flint-chart-author · git:20260804.9cab05a · 2026-08-04 · sha256 3041b5e68322f153
flint-chart-author git:20260804.9cab05aA
Immutable. This exact content never changes and is served at /api/v1/blob/3041b5e68322f153.
---
name: flint-chart-author
description: >
从结构化、表格或查询结果生成数据图表:选择适合对比、趋势、分布、相关性或层级关系的图型,
生成、修复、解释或校验 Flint 图表规格,输出可直接渲染的 ```flint 围栏块。
Trigger on: "画图", "画个图", "可视化", "出个图表", "flint", "chart", "visualize",
"plot this", "graph these numbers", "对比一下…(给出多行数据时)", "趋势", "分布",
"占比", "相关性", 或用户已给出表格/查询结果并要求"看得更直观"。
也在需要**修复**一个渲染失败的 ```flint 块、或**解释**某个 flint 规格含义时使用。
---
# flint-chart-author — Flint 图表规格作者
你把**已经拿到手的结构化数据**变成一个合法的 ` ```flint ` 围栏块。
[Flint](https://github.com/microsoft/flint-chart) 是微软研究院的可视化中间语言:给它
「数据 + 图型 + 编码」,它自己推导刻度、轴、标签、图例、布局——所以你**不需要**写任何
Vega-Lite / ECharts 的底层配置,写多了反而会被丢弃。
图型清单、通道语义、语义类型表、完整示例与失败模式对照见
[`references/flint-spec.md`](references/flint-spec.md),**按需载入**。
## 边界
| | |
|---|---|
| **输入** | 已有的结构化数据、表格、或查询结果(对象数组形态) |
| **职责** | 选图型与编码 · 必要时先聚合 · 生成 / 修复 / 解释 / 校验 flint 规格 |
| **输出** | 一个 ` ```flint ` 围栏块(JSON),块外配一句人话说明它在说什么 |
| **不负责** | 数据库连接与取数权限 · 知识库/wiki 维护 · markdown 存放在哪一页 · 浏览器端渲染 |
数据从哪来、图放到哪儿去,都由调用你的那条工作流决定;你只对**「这段 JSON 合法且画出来是对的」**负责。
## 工作流
### 1. 先看数据,再选图
看三件事:**行数**、**每列的类型**(数值 / 类别 / 日期)、**你想让读者看出什么**。
最后一件决定图型——参考的图型表按用途分组(对比 / 趋势 / 分布 / 相关 / 构成层级 / 流向 / 时间安排)。
拿不准就选最朴素的那个:类别比大小用 `Bar Chart`,随时间变化用 `Line Chart`,两个数值的关系用
`Scatter Plot`。**朴素的图被读懂的概率远高于花哨的图。**
### 2. 必要时先聚合——这是你的活,不是 flint 的
flint **不做聚合**(`encodings.*.aggregate` 只在部分模板生效,别指望)。原始明细表要先自己算成
结论性的聚合结果再内联:`GROUP BY` 之后的几行、十几行,而不是几百行明细。
> 判据:**这张图要说的那句话,需要几行数据才够?** 只要那几行。
> 搬原始表进来既撞行数上限,也让读者自己去找结论——那是表格的活,不是图的活。
### 3. 写块
最小形态(`semantic_types` 可整段省略,flint 会自行推断):
````markdown
```flint
{"data":{"values":[{"模型":"model-a","评测得分":72.4},{"模型":"model-b","评测得分":81.9}]},
"chart_spec":{"chartType":"Bar Chart",
"encodings":{"x":{"field":"模型"},"y":{"field":"评测得分"}}}}
```
````
写清楚一点(推荐):加 `semantic_types` 让刻度/格式/排序更合理,加 `baseSize` 定尺寸。
字段名用**数据里的原名**(中文列名完全可以)。想让轴上显示得更好看,就**在数据里把列名改好**——
flint 0.4.1 没有「显示名」这种字段(写了不报错也不生效)。
### 4. 自校验(**每次输出前逐条过,不要跳**)
- [ ] 整块是**合法 JSON**(不是 YAML、没有注释、没有尾逗号、没有单引号)
- [ ] 顶层只有 `data` / `semantic_types` / `chart_spec` / `options` 之内(别的键一律被丢弃)
- [ ] `data.values` 是**对象数组**且**非空**;**没有** `data.url`(渲染端一律拒绝,图不会出现)
- [ ] 每个单元格是**标量**(字符串 / 数字 / 布尔)——不放嵌套对象或数组
- [ ] 行数 **≤ 1000**
- [ ] **类别数别太多**:`color` / `column` / `row` 上的取值超出图表容量时,flint 会**整批丢掉**多余的,
渲染端据此拒渲并显示「数据被截断」——先做 Top-N 聚合,别把几十个类别硬塞进一张图
- [ ] `chart_spec.chartType` 与参考里的写法**逐字符一致**(**大小写敏感**:`Bar Chart` 对,`Bar chart` 错)
- [ ] 每个 `encodings.*.field` 都能在数据列里找到(**任一行**有即可)
- [ ] 数据形状与图型匹配(`Histogram` 的 `x` 必须是数值列、`Calendar Heatmap` 的 `x` 必须是日期串……见参考)
- [ ] 若写了 `baseSize`:宽高都是**有限正数**(`baseSize` 是**基准不是上限**——flint 会按类别数/
分面数把它放大,实测 `420×260` 在多序列下会长到 `657×514`)。**不必**为了栏宽去调它:
渲染端会按正文栏宽让 flint **重新编译**一遍;只有大到离谱(宽 >1600 或高 >1200 仍收不住)
才会被判「数据过大」
### 5. 块外补一句人话
图是**取数那一刻的快照**,不会自己刷新。所以在块外正文写一句:这张图在说什么,数据来自哪、口径是什么、
什么时候取的。这是通用建议、**不是** flint 规格的一部分——不要试图把来源塞进 JSON,任何自定义字段都会被丢弃。
## 修复一个画不出来的块
按这个顺序查,命中率从高到低(都是实测出来的失败模式,详见参考的对照表):
1. **JSON 语法**——最常见,先 parse 一遍。
2. **`chartType` 大小写**——写错会直接抛 `Unknown ECharts chart type: …`。
3. **列名对不上**——`encodings.*.field` 写了数据里没有的列。**这种最坏:不报错,画出一张空图**。
4. **数据形状不匹配图型**——列名全对也可能空,例如给 `Histogram` 喂了类别列当 `x`。
5. **该图型的「必给」通道缺了**——flint 会**静默回吐一个不是 ECharts 图的中间态**,渲染端只能判失败。
实测 `Sunburst Chart` 缺 `color` 即如此(见参考第 2 节的备注列)。
6. **超限**——行数 / 块体积 / 画布过大,渲染端保留源码并显示「数据过大」。
7. **类别太多**——`color`/`column`/`row` 的取值被 flint 整批丢弃,渲染端显示「数据被截断」。
注意这条**不是**「图太大」:删行没用,要减的是**类别数**。
修完**重跑第 4 步的整份清单**,不要只验你刚改的那一条。
## 三条纪律
- **数据必须内联。** 图要能只靠这段 markdown 重建;引用外部 URL 的块不会被渲染。
- **不画装饰图。** 一张图对应一个结论。没有结论就不画——一段话比一张没有话说的图强。
- **失败要看得见。** 拿不准某个图型能不能成,就退回 `Bar Chart`/`Line Chart`,别赌。