DeerFlow chart-visualization 技能解析:从 26 种图表智能选型到 Node.js 渲染管线
本篇技术文章基于 DeerFlow 仓库中的 skills/public/chart-visualization 技能包展开,完整讲解该技能“智能选图 → 参数提取 → 脚本生成 → 结果回传”的四步工作流,深入剖析 scripts/generate.js 的图表类型映射、服务端环境变量与地图类图表的特殊调用链,并结合 references/ 目录下的字段规范说明如何构造可复制、可运行的生成载荷。读完本文,你将能够在 DeerFlow 中准确使用这一技能完成数据可视化,并理解其在技能加载体系中的位置。
1. 技能定位与整体工作流
chart-visualization 是 DeerFlow 内置的公共技能之一,位于 skills/public/chart-visualization/SKILL.md。它的元数据声明如下(来自 SKILL.md 的 frontmatter):
name: chart-visualization
description: This skill should be used when the user wants to visualize data.
It intelligently selects the most suitable chart type from 26 available
options, extracts parameters based on detailed specifications, and
generates a chart image using a JavaScript script.
compatibility:
nodejs: ">=18.0.0"
从 frontmatter 可以看出三点关键事实:该技能面向“用户想要可视化数据”的场景触发;提供 26 种可选图表类型;运行依赖 Node.js >= 18.0.0(脚本使用了原生 fetch API,这也是要求 Node 18+ 的原因)。
技能的整体目录结构为:
skills/public/chart-visualization/
├── SKILL.md # 技能主文档,定义四步工作流
├── references/ # 26 份图表字段规范文档(每种图表一个 .md)
│ ├── generate_line_chart.md
│ ├── generate_bar_chart.md
│ ├── generate_district_map.md
│ └── ...
└── scripts/
└── generate.js # 图表生成执行脚本
SKILL.md 定义的标准工作流分为四步:智能图表选型(Intelligent Chart Selection)→ 参数提取(Parameter Extraction)→ 图表生成(Chart Generation)→ 结果回传(Result Return)。下文按该骨架逐节展开。
2. 第一步:智能图表选型——26 种类型的数据特征匹配
选型阶段的核心逻辑是“分析数据特征,匹配最合适的图表类型”。SKILL.md 给出了六大类匹配指南,这也是 Agent 决策时的依据:
| 数据特征 | 推荐图表类型 |
|---|---|
| 时间序列 | generate_line_chart(趋势)或 generate_area_chart(累积趋势);两个不同量纲用 generate_dual_axes_chart |
| 对比类 | generate_bar_chart(类别)或 generate_column_chart;频率分布用 generate_histogram_chart |
| 部分与整体 | generate_pie_chart 或 generate_treemap_chart(层级结构) |
| 关系与流向 | generate_scatter_chart(相关性)、generate_sankey_chart(流量)、generate_venn_chart(重叠) |
| 地图 | generate_district_map(行政区)、generate_pin_map(点位)、generate_path_map(路线) |
| 层级与树状 | generate_organization_chart(组织图)或 generate_mind_map(思维导图) |
除上述六类外,SKILL.md 还列出了 11 种专用图表:
generate_radar_chart:多维对比generate_funnel_chart:流程阶段转化generate_liquid_chart:百分比/进度generate_word_cloud_chart:文本词频generate_boxplot_chart或generate_violin_chart:统计分布generate_network_graph:复杂节点-边关系generate_fishbone_diagram:因果分析generate_flow_diagram:流程图generate_spreadsheet:表格/透视表,用于结构化数据的交叉汇总
值得注意的是,references/ 目录下 26 个规范文件与上述 26 种图表工具一一对应,例如 references/generate_line_chart.md、references/generate_district_map.md。这种“文档即 Schema”的组织方式让 Agent 在选图之后可以按需读取单一规范文件,而无需一次性加载全部 26 份规范。
3. 第二步:参数提取——以 references 为字段的 Single Source of Truth
选型完成后,SKILL.md 要求读取对应图表的 reference 文档来确认必填/可选字段,再把用户输入的数据映射为期望的 args 格式。以折线图为例,references/generate_line_chart.md 定义了:
必填字段
data: array<object>,每条记录包含time(string)与value(number),多系列时附带group(string)
可选字段
style.lineWidth: number,自定义折线线宽style.backgroundColor: string,背景色style.palette: string[],指定系列颜色style.texture: string,默认default,可选default/roughtheme: string,默认default,可选default/academy/darkwidth: number,默认600;height: number,默认400title、axisXTitle、axisYTitle: string,默认空字符串
此外该文档还给出使用建议:所有系列的时间点应对齐,时间建议按 ISO 格式(如 2025-01-01 或 2025-W01),高频数据应先聚合到日/周粒度避免过密。
再看两个有代表性的规范差异:
条形图(references/generate_bar_chart.md)引入了两个互斥的分组开关:group(默认 false,并排展示,要求 stack=false)与 stack(默认 true,堆叠展示,要求 group=false),二者均要求数据中包含 group 字段。构造载荷时若同时开启两者,语义上是矛盾的,应按需只保留其一。
电子表格/透视表(references/generate_spreadsheet.md)则展示了同一工具内的模式切换:必填仅 data(每行为一个对象,键即列名),但当提供 rows 或 values 字段时自动渲染为数据透视表(交叉表),columns 用于指定列顺序或列分组。
饼/环图(references/generate_pie_chart.md)的关键可选参数是 innerRadius(范围 [0,1],默认 0,设为 0.6 即生成环图),并建议在类别数超过 6 个时聚合为“其它”。
行政区地图(references/generate_district_map.md)是所有图表中约束最强的:title 必填且不超过 16 字;data.name 必须是中国境内精确到省/市/区/县的行政区关键词;可选字段包括 data.colors(色带,默认 10 色列表)、data.dataType(number/enum 决定颜色映射方式)、data.subdistricts[](下钻子区域,需同时开启 showAllSubdistricts);宽高默认值为 1600×1000(大于普通图表的 600×400)。该文档还指出:地图只支持中国境内且依赖高德数据;若配置了 SERVICE_ID 环境变量,生成记录会同步到“我的地图”小程序。
4. 第三步:图表生成——generate.js 源码级剖析
生成阶段调用 scripts/generate.js,载荷格式与执行命令在 SKILL.md 中定义为:
{
"tool": "generate_chart_type_name",
"args": {
"data": [...],
"title": "...",
"theme": "...",
"style": { }
}
}
node ./scripts/generate.js '<payload_json>'
深入源码可以看到以下实现细节:
(1)图表类型映射表。 脚本开头定义了 CHART_TYPE_MAP,将 25 个 generate_* 工具名映射为服务端识别的短类型名,例如 generate_line_chart → "line"、generate_district_map → "district-map"、generate_spreadsheet 不在其中——因为地图与表格类走不同的分支逻辑。源码注释标明该映射“consistent with src/utils/callTool.ts”,说明它是与上游 chart-visualization 项目共享的契约。
(2)服务端与鉴权环境变量。 脚本支持两个环境变量:
VIS_REQUEST_SERVER:图表生成服务地址,未设置时默认回退到脚本内内置的 AntV 公共服务端点;SERVICE_ID:服务标识,仅在地图类调用链中作为serviceId随请求发送,用于生成记录归属(对应行政区地图文档中“我的地图”的同步行为)。
(3)普通图表与地图的两条请求路径。 这是源码中最值得注意的分支:
- 普通图表(
generateChartUrl):将args展开为请求体,附加type(短类型名)与source: "chart-visualization-creator",POST 后校验data.success,成功则直接返回data.resultObj——即一张图表图片的 URL; - 地图类工具(
generate_district_map、generate_pin_map、generate_path_map,由isMapChartTool列表判定):走generateMap分支,请求体结构不同(携带serviceId、tool、input),响应结构也更深:脚本会遍历result.content,把type === "text"的条目逐条打印,而非直接输出 URL。这解释了为什么地图类工具在返回形态上与其他 25 种图表不一致。
(4)单条与批量两种输入。 main() 入口允许第一个参数是 内联 JSON 字符串或 JSON 文件路径(通过 fs.existsSync 判断);解析后的 spec 若为数组则视为批量任务,逐个执行。每个 spec 缺少 tool 字段或工具名无法映射时仅打印错误并 continue,不会中断后续任务;单个图表生成失败也只记录错误(Error generating chart for ${tool})而不影响其他图表。这种“容错式批处理”设计适合 Agent 一次性生成多张图的场景。
(5)可测试性。 脚本末尾通过 module.exports 导出 generateChartUrl、generateMap、httpPost、CHART_TYPE_MAP,便于单元测试对 HTTP 层进行 mock。
// 批量生成的最小示例(内联 JSON,两个 spec)
node ./scripts/generate.js '[
{"tool":"generate_line_chart","args":{"title":"月度销售","data":[{"time":"2025-01","value":120},{"time":"2025-02","value":150}]}},
{"tool":"generate_pie_chart","args":{"data":[{"category":"华东","value":40},{"category":"华南","value":35}], "innerRadius":0.6}}
]'
5. 第四步:结果回传与 _meta.spec
按 SKILL.md 约定,脚本成功后标准输出图表图片 URL,Agent 需要向用户同时返回两项内容:图片 URL 与 完整的 args(即用于生成的规格说明)。各 reference 文档的“返回结果”一节进一步说明:服务端在响应的 _meta.spec 字段中回传完整输入规格,供后续编辑与复用——这意味着 Agent 在拿到 URL 后,可以把 _meta.spec 作为可追溯、可再生的“图表源码”一并展示给用户,而不只是给出一张静态图片。
6. 在 DeerFlow 技能体系中的位置
chart-visualization 属于 skills/public/ 下的公共技能目录,与 deep-research、ppt-generation、data-analysis 等技能并列。从后端源码结构看,公共技能的目录即技能清单的来源,测试用例 backend/tests/test_skill_catalog.py 中即以 chart-visualization 作为技能目录的样例数据,并验证了按关键词(如输入 chart)能匹配到 chart-visualization 这一条目,说明技能选择是“按名称模糊匹配 + 描述信息”驱动的——这也解释了为什么 SKILL.md 的 description 字段要精确描述触发场景(“user wants to visualize data”)。前端文档 frontend/src/content/zh/harness/skills.mdx 与英文版 en/harness/skills.mdx 也提及该技能,作为技能体系的介绍示例。
因此,一次完整的调用链为:用户提出可视化需求 → Agent 依据 SKILL.md 的选型指南选定工具并读取对应 reference 提取参数 → 在技能目录下执行 node ./scripts/generate.js '<payload_json>'(要求 Node.js >= 18)→ 脚本 POST 到 VIS_REQUEST_SERVER 指向的服务 → 脚本打印图片 URL → Agent 将 URL 与完整 args 一并返回用户。
7. 使用要点与限制小结
- 运行环境:需要 Node.js >= 18(SKILL.md frontmatter 的
compatibility声明),脚本依赖原生fetch; - 26 种工具与 references 一一对应:选图后务必读取对应
references/generate_*.md确认必填字段,尤其注意行政区地图的强约束(标题 ≤16 字、行政区名精确到省/市/区/县、仅支持中国境内); - 分组参数互斥:条形图的
group与stack语义互斥,不能同时开启; - 网络依赖:生成动作本身是远程服务调用(默认 AntV 公共端点,可用
VIS_REQUEST_SERVER覆盖),失败时脚本以HTTP <status>或errorMessage形式抛出; - 地图类返回结构不同:三种地图工具走
generateMap分支,输出为content文本条目而非裸 URL,展示时需要相应处理; - 可复用性:利用
_meta.spec回传的完整规格,可对同一图表做二次调整(改主题、改配色、改尺寸),而无需重新提取参数。
综上,DeerFlow 的 chart-visualization 技能通过“SKILL.md 定流程、references 定 Schema、generate.js 定执行”的三层结构,把 26 种图表能力封装为一条可被 Agent 稳定复用的可视化管线:选型有指南、参数有规范、生成有脚本、结果可追溯。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00