AI agent skill · by @jin-bo
Flint Chart Author
从结构化、表格或查询结果生成数据图表:选择适合对比、趋势、分布、相关性或层级关系的图型, 生成、修复、解释或校验 Flint 图表规格,输出可直接渲染的 ```flint 围栏块。 Trigger on: "画图", "画个图", "可视化", "出个图表", "flint", "chart", "visualize", "plot this", "graph these numbers", "对比一下…(给出多行数据时)", "趋势", "分布", "占比", "相关性", 或用户已给出表格/查询结果并要求"看得更直观"。 也在需要**修复**一个渲染失败的 ```flint 块、或**解释**某个 flint 规格含义时使用。
Archived 2026-10-23 · Source updated 2026-09-19 · License: MIT. Check the original repository for the latest version.
SKILL.md instructions
# 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` 定尺寸。
字段名用**数据里的原名**(中文列名完全可以),不要为了图去改名——要改显示名用 `field_display_names`。
### 4. 自校验(**每次输出前逐条过,不要跳**)
- [ ] 整块是**合法 JSON**(不是 YAML、没有注释、没有尾逗号、没有单引号)
- [ ] 顶层只有 `data` / `semantic_types` / `chart_spec` / `field_display_names` / `options` 五个键之内
- [ ] `data.values` 是**对象数组**且**非空**;**没有** `data.url`
(flint 的类型接受 url,但渲染端一般拒绝取远端数据,图不会出现)
- [ ] 每个单元格是**标量**(字符串 / 数字 / 布尔)——不放嵌套对象或数组
- [ ] 行数 **≤ 1000**(这是**宿主渲染端**的上限、不是 flint 的规格;换宿主时按那边确认。
不过真要画到接近上限,多半是第 2 步的聚合没做够)
- [ ] `chart_spec.chartType` 与参考里的写法**逐字符一致**(**大小写敏感**:`Bar Chart` 对,`Bar chart` 错)
- [ ] 每个 `encodings.*.field` 都能在数据列里找到(**任一行**有即可)
- [ ] 数据形状与图型匹配(`Histogram` 的 `x` 必须是数值列、`Calendar Heatmap` 的 `x` 必须是日期串……见参考)
- [ ] 若写了 `baseSize`:宽高都是**有限正数**、且在 **160–1600** × **120–1200** 内
(注意:`baseSize` 是**基准不是上限**——flint 会按类别数/分面数把它**放大**,实测 `420×260`
在多序列下会长到 `657×514`。渲染端卡的是**放大后**的尺寸,所以类别特别多时要么减少类别、
要么用 `canvasSize` 给一个硬上限,它是真会生效的钳制)
### 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. **超限**——行数 / 块体积 / 画布尺寸越界,渲染端会保留源码并显示「数据过大」。
(这一类的具体阈值由**宿主渲染端**定,不是 flint 规格的一部分。)
修完**重跑第 4 步的整份清单**,不要只验你刚改的那一条。
## 三条纪律
- **数据必须内联。** 图要能只靠这段 markdown 重建;引用外部 URL 的块不会被渲染。
- **不画装饰图。** 一张图对应一个结论。没有结论就不画——一段话比一张没有话说的图强。
- **失败要看得见。** 拿不准某个图型能不能成,就退回 `Bar Chart`/`Line Chart`,别赌。