先问大家一个问题:当你在 AI 对话里说“帮我画一张销量趋势图”时,你希望 AI 直接给出一段能运行的 ECharts 代码,还是给你一张已经渲染好的图表页面?很多人的实际体验是:AI 能写代码,但代码经常跑不起来;能识别数据,但生成的图表样式完全不在线;甚至同一个 Skill 在 A 客户端能用,换到 B 客户端就失效。这篇文章要讲的,就是我自己在 GitHub 上开源的一个高星图表 Skill 项目的大版本更新。我会从 Skill 的设计理念、目录结构、配置方式、核心流程、常见坑位和工程实践几个维度展开,尽量让读者既能理解 Skill 是什么,也能直接照着配置一个属于自己的图表生成能力。
如果你是 AI Agent 的开发者、知识库搭建者,或者日常用 Claude、ChatGPT 等工具做数据可视化,这篇文章会比较适合你。读完你可以掌握 Skill 的基本规范,学会如何把图表生成能力拆成可复用的 Skill 文件,并了解这个开源项目更新后新增了哪些能力、解决了哪些旧版本痛点。
2. 了解 Skill,先搞清楚它解决什么问题
Skill 这个概念在 AI 应用圈子里越来越热,尤其是 Claude 的 Skills、ChatGPT 的 GPT Actions、各类 Agent 框架里的 Plugin,本质上都是一种“把特定能力封装成可复用单元”的思路。简单来讲,Skill 就是给大模型提供的一套“说明书 + 工具集合”,告诉模型在什么场景下调用什么脚本、按什么流程输出什么格式的内容。
图表 Skill 则是专门用于“数据可视化”的 Skill。它解决的问题是:大模型本身并不擅长精确控制图形位置、颜色、动画和交互,但它擅长理解自然语言意图、分析数据结构、选择图表类型。通过 Skill,我们可以把“理解用户需求”、“选择图表类型”、“生成图表配置”、“输出可运行代码”这几个步骤固定下来,让每次生成的结果都稳定可复现。
比如传统方式让 AI 画图,模型可能随机发挥,这次的代码用 ECharts,下次用 Chart.js,再下次直接给一段 SVG。而图表 Skill 会约定好输出格式、代码模板、数据字段映射规则,最终用户拿到的是风格统一、配置完整、能直接预览的方案。
2.1 图表 Skill 和普通提示词的区别
很多人会问:我不就是用一段提示词让 AI 画图吗?为什么要多此一举搞一个 Skill?这里有一个非常关键的区别:提示词是一次性的,Skill 是结构化的。
普通提示词是你在对话里说的话,模型只能基于当前上下文理解;而 Skill 是一个文件目录,里面包含说明文档、示例代码、校验脚本、依赖配置。模型在执行任务前会先读取 Skill 目录下的SKILL.md,了解你预先定义的规则,再调用你准备好的工具脚本。这意味着:
- 规则可以长期复用,不用每次重复描述。
- 代码生成逻辑可以被版本管理,团队可以协作维护。
- 可以加入自动化校验,比如 JSON 配置合法性检查。
- 输出格式高度可控,适合接入自动化流水线。
2.2 图表 Skill 的典型应用场景
结合项目里收到的用户反馈,图表 Skill 最常见的应用场景有这么几类:
- 数据分析报告自动生成:从数据库读取指标,自动产出趋势图、占比图、雷达图。
- 运营周报可视化:给出一组 Excel 或 CSV 数据,快速生成适合公众号、飞书文档里的图表。
- 教学课件制作:老师用自然语言描述成绩分布,Skill 生成适合演示的饼图、柱状图。
- 大屏可视化设计:结合 ECharts 的科技感样式,生成带动态线条、中心占比的炫酷大屏组件。
- 低代码平台图表组件对接:Skill 输出标准化 JSON,让低代码平台直接解析渲染。
这次大更新正是围绕这些场景做了很多针对性优化。
3. 大更新之前,先回顾旧版的设计思路
在介绍新功能之前,我想先简单回顾一下这个项目早期的设计。这个 Skill 最初是我在解决一个具体问题时的产物:我当时频繁使用 AI 生成图表,但发现每次都要在提示词里写一堆要求,比如“用 ECharts,要求折线图,颜色不要超过三种,字体要显示中文”,而且换一个对话窗口就得重新说一遍。痛定思痛,我把这套“要求”沉淀成了文档和模板,放进一个统一的 Skill 目录里。
旧版的设计大致是这样:
chart-skill/ ├── SKILL.md ├── templates/ │ ├── bar_chart.json │ ├── line_chart.json │ ├── pie_chart.json │ └── radar_chart.json ├── examples/ │ ├── demo_data.csv │ └── generated_demo.html └── scripts/ └── validate_chart.pySKILL.md是核心入口,告诉模型“你是图表生成助手,请按以下规则输出”;templates文件夹存放各种图表的 JSON 模板,模型参考模板生成配置;examples提供输入示例和预期输出;scripts/validate_chart.py用来校验生成的 JSON 是否符合 ECharts 配置规范。
旧版上线后,GitHub 上的关注度超出了我的预期。很多人通过这个 Skill 解决了“AI 生成的图表代码跑不起来”的痛点。但与此同时,用户也反馈了很多问题,这些问题构成了这次大更新的核心驱动力。
3.1 旧版的主要痛点
用户反馈比较集中的问题有四个。
第一,模板机制太僵硬。旧版依赖固定 JSON 模板,遇到用户描述“我想做一个中心显示数字、周围散发动态线条的图”这种需求时,模板匹配逻辑无法覆盖,模型只能在固定模板上硬改,生成结果经常出现配置冲突。
第二,数据处理能力弱。旧版只把 CSV 数据原样交给模型,模型经常搞错字段类型,比如把销售额读成字符串,导致图表坐标轴数值异常。
第三,缺少代码级验证。validate_chart.py只能校验 JSON 语法,校验不了配置项的浏览器兼容性,比如某些高版本特性在低版本 ECharts 里根本不支持。
第四,对多端输出适配不足。不同平台渲染环境不一样,有的需要完整 HTML,有的只需要 option 配置,有的要适配移动端。旧版没有做输出分层,用户拿到的成品经常需要手动调整。
4. 大更新整体架构:从“模板匹配”到“生成管线”
这次大更新没有在旧代码上面打补丁,而是把整体架构重新梳理了一遍,核心思路从“模板匹配”转变成了“生成管线”。所谓生成管线,就是把图表生成过程拆成几个固定阶段,每个阶段由 Skill 里的独立模块负责,模型按照管线顺序执行。
新的项目结构长这样:
chart-skill/ ├── SKILL.md ├── config/ │ ├── skill.yaml │ └── chart_register.json ├── modules/ │ ├── data_parser.py │ ├── chart_selector.py │ ├── option_builder.py │ ├── style_engine.py │ └── output_renderer.py ├── presets/ │ ├── default_theme.json │ ├── tech_dark_theme.json │ ├── business_light_theme.json │ └── minimal_theme.json ├── examples/ │ ├── sales_data.csv │ ├── user_requests.txt │ └── expected_output/ └── scripts/ ├── run_pipeline.py ├── validate_option.py └── create_skill_package.py这个结构把原来只有“模板+校验”的 Skill 扩展成了“解析-选择-构建-美化-输出”的五段式管线。下面我会逐个模块解释它的作用和更新思路。
4.1 SKILL.md 的重新设计
SKILL.md是整个 Skill 的灵魂文件,模型执行任务前首先读取它。新版不再是一段简短的“你是图表专家”提示词,而是写成了结构化指令文档,包含元信息、执行流程、输出规范和边界约束。
我们先来看SKILL.md的关键片段:
--- name: chart-skill description: 根据用户描述和数据文件生成 ECharts 可视化方案 version: 2.0.0 author: your-name license: MIT --- # 图表生成 Skill ## 角色定义 你是一名资深前端可视化工程师,擅长 ECharts 图表设计与实现。 ## 执行流程 当你收到用户的图表需求时,必须按以下顺序执行: 1. 调用 modules/data_parser.py 解析输入数据。 2. 调用 modules/chart_selector.py 判断最佳图表类型。 3. 调用 modules/option_builder.py 构建 ECharts option。 4. 调用 modules/style_engine.py 应用主题样式。 5. 调用 modules/output_renderer.py 输出最终结果。 ## 输出规范 - 所有输出必须包含完整可运行的 ECharts option。 - 输出格式根据用户要求,支持三种: - json:只输出 option 配置。 - html:输出带完整引入 ECharts CDN 的 HTML 文件。 - vue:输出 Vue 组件中的 option 片段。 ## 边界约束 - 不要修改原始数据文件。 - 如果数据字段无法识别,必须向用户询问,不得自行猜测。 - 禁止使用自定义图形注册方式生成图表,统一使用 ECharts 标准配置。注意新版SKILL.md里的version、author、license信息,这是为了让 Skill 本身也能被版本管理。如果你在团队内部通过 Git 仓库分发,版本号会帮助你追踪变更。
4.2 配置层:skill.yaml 和 chart_register.json
Skill 的行为不能全部写死在提示词里,因为提示词越长,模型越容易遗漏细节。所以新版引入了配置层,把“哪些图表类型可用”“各类型对应什么模板”这类信息放到结构化文件里。
config/skill.yaml内容示例:
name: chart-skill version: 2.0.0 default_theme: business_light supported_charts: - line - bar - pie - radar - scatter - funnel - gauge - hexagon output_formats: - json - html - vue max_data_rows: 5000 locale: zh-CN这里的supported_charts指定了 Skill 支持的图表类型,模型在chart_selector阶段会参考这个列表做选择题。hexagon是这次新增的“六边形图表”类型,是很多用户催更的功能,后面我会专门介绍。
config/chart_register.json则维护图表类型和配置模块的映射关系:
{ "line": { "module": "option_builder", "method": "build_line", "requires": ["xAxis", "yAxis", "series"] }, "bar": { "module": "option_builder", "method": "build_bar", "requires": ["xAxis", "yAxis", "series"] }, "pie": { "module": "option_builder", "method": "build_pie", "requires": ["series"] }, "hexagon": { "module": "option_builder", "method": "build_hexagon", "requires": ["indicator", "series"] } }这样做的好处是,模型只需要根据chart_register.json找到对应方法,而不需要记忆每个图表的全部配置细节。模板和逻辑分离,后续新增图表类型只需要注册一个方法。
4.3 数据解析模块:从“无脑读取”到“智能识别”
旧版直接让模型读 CSV,结果经常把数值列读成字符串。新版增加了data_parser.py,专门做数据清洗和类型推断。
下面是一个简化版示例,演示如何解析带表头的 CSV 并推断字段类型:
# 文件路径:modules/data_parser.py import csv import json from datetime import datetime def parse_csv(file_path): """解析 CSV 文件,推断字段类型,输出标准化数据结构。""" with open(file_path, "r", encoding="utf-8") as f: reader = csv.DictReader(f) rows = list(reader) if not rows: raise ValueError("CSV 文件为空") columns = list(rows[0].keys()) parsed = {col: [] for col in columns} for row in rows: for col in columns: raw_value = row[col].strip() parsed[col].append(convert_value(raw_value)) return { "columns": columns, "rows": parsed, "row_count": len(rows), "column_types": infer_types(parsed) } def convert_value(raw_value): """尝试转换值类型,失败则返回原始字符串。""" # 处理空值 if raw_value == "" or raw_value.lower() == "null": return None # 尝试整数 try: return int(raw_value) except ValueError: pass # 尝试浮点数(注意处理千分位逗号) try: return float(raw_value.replace(",", "")) except ValueError: pass # 尝试日期 try: return datetime.strptime(raw_value, "%Y-%m-%d").date().isoformat() except ValueError: pass return raw_value def infer_types(parsed_data): """根据实际值推断每一列的类型。""" type_map = {} for col, values in parsed_data.items(): non_null = [v for v in values if v is not None] if not non_null: type_map[col] = "empty" elif all(isinstance(v, int) for v in non_null): type_map[col] = "integer" elif all(isinstance(v, float) for v in non_null): type_map[col] = "float" elif all(isinstance(v, str) for v in non_null): type_map[col] = "string" elif all(hasattr(v, "isoformat") for v in non_null): type_map[col] = "date" else: type_map[col] = "mixed" return type_map if __name__ == "__main__": # 简单测试 sample = "examples/sales_data.csv" result = parse_csv(sample) print(json.dumps(result, ensure_ascii=False, indent=2, default=str))在SKILL.md的执行流程中,模型会先调用这个脚本解析数据,然后根据column_types来决定哪些列适合做 X 轴、哪些适合做 Y 轴、哪些适合做维度。这比直接把原始文件丢给模型要可靠得多。
4.4 图表选择模块:根据数据结构自动推荐类型
图表类型的选择容易踩坑。用户说“我要对比几个部门的预算”,模型可能随手生成一个折线图,但实际上数据是离散的类别对比,柱状图更合适。chart_selector.py的目标是提供一套启发式规则,让模型“先判断,再作图”。
# 文件路径:modules/chart_selector.py def select_chart_type(data, user_hint=None): """ 根据数据结构和用户意图推荐图表类型。 返回推荐类型和理由说明。 """ column_types = data["column_types"] row_count = data["row_count"] # 低于 30 行的数据,优先考虑柱状图或饼图;超过 30 行,折线图更合适 if row_count > 30: return { "chart_type": "line", "reason": "数据行数超过 30,折线图更适合展示连续趋势。" } # 如果所有数值列只有一列,且描述中包含"占比""份额"等关键词,选择饼图 value_cols = [c for c, t in column_types.items() if t in ("integer", "float")] category_cols = [c for c, t in column_types.items() if t in ("string", "date")] if user_hint: hint = user_hint.lower() if "占比" in hint or "份额" in hint or "比例" in hint: return {"chart_type": "pie", "reason": "用户明确提到占比/份额,使用饼图。"} if "趋势" in hint or "变化" in hint: return {"chart_type": "line", "reason": "用户明确提到趋势/变化,使用折线图。"} if "对比" in hint or "排名" in hint: return {"chart_type": "bar", "reason": "用户明确提到对比/排名,使用柱状图。"} if "六边形" in hint or "能力" in hint: return {"chart_type": "hexagon", "reason": "用户明确提到六边形/能力,使用六边形图。"} # 缺省逻辑 if len(value_cols) >= 1 and len(category_cols) >= 1: return {"chart_type": "bar", "reason": "存在类别维度和数值指标,柱状图是通用对比方案。"} return {"chart_type": "pie", "reason": "默认使用饼图展示构成关系。"}这个模块不追求十全十美,但能显著减少模型“乱选类型”的问题。用户如果对自己的需求有明确倾向,也可以通过提示词覆盖自动推荐结果。
4.5 样式引擎:这次更新的重头戏
旧版的最大短板是视觉风格不稳定。同一个图表,这次生成出来是蓝白配色,下次变成红黑配色,再下次可能用了很奇怪的渐变。
新版引入了style_engine.py和presets/目录。预设主题包括:
default_theme.json:默认主题,适合大多数场景。business_light.json:商务浅色,适合 PPT 和报告。tech_dark.json:科技深色,适合大屏,带发光效果和动态线条。minimal_theme.json:极简风格,干净留白。
我们看一个简化版的style_engine.py:
# 文件路径:modules/style_engine.py import json import os def load_theme(theme_name): """加载预设主题文件。""" preset_dir = os.path.join(os.path.dirname(__file__), "..", "presets") theme_path = os.path.join(preset_dir, f"{theme_name}.json") if not os.path.exists(theme_path): raise FileNotFoundError(f"主题 {theme_name} 不存在") with open(theme_path, "r", encoding="utf-8") as f: return json.load(f) def apply_theme(option, theme_name="business_light"): """ 将主题应用到 ECharts option 上。 会合并 color、backgroundColor、textStyle 等字段。 """ theme = load_theme(theme_name) # 合并颜色 if "color" in theme: option["color"] = theme["color"] # 合并背景色 if "backgroundColor" in theme: option["backgroundColor"] = theme["backgroundColor"] # 合并文本样式 if "textStyle" in theme: text_style = option.get("textStyle", {}) text_style.update(theme["textStyle"]) option["textStyle"] = text_style # 处理标题样式 if "title" in theme and "title" in option: option["title"].update(theme["title"]) # 处理图例样式 if "legend" in theme and "legend" in option: option["legend"].update(theme["legend"]) return option用户反馈里提到的“中心是数字占比,周围散发长短不一的动态线条”效果,我在tech_dark主题里做了专门优化。这个效果本质上是把series配置成pie和lines组合,中心用graphic元素显示数字,外围用lines系列生成随机长短的动画线条。如果你需要独立实现这个效果,可以参考下面的 ECharts 核心片段:
option = { backgroundColor: '#0f1c2e', graphic: [ { type: 'text', left: 'center', top: '42%', style: { text: '68%', textAlign: 'center', fill: '#ffffff', fontSize: 48, fontWeight: 'bold' } } ], series: [ { type: 'pie', radius: ['55%', '70%'], center: ['50%', '50%'], label: { show: false }, data: [ { value: 68, name: '完成率', itemStyle: { color: '#3fa7ff' } }, { value: 32, name: '缺口', itemStyle: { color: '#1a3455' } } ] }, { type: 'lines', coordinateSystem: 'polar', data: generateRandomLines(24), lineStyle: { color: '#3fa7ff', width: 1, opacity: 0.6, curveness: 0.2 }, effect: { show: true, period: 4, trailLength: 0.6, symbol: 'circle', symbolSize: 3 } } ], polar: { center: ['50%', '50%'], radius: '65%' } }; function generateRandomLines(count) { const lines = []; for (let i = 0; i < count; i++) { lines.push({ coords: [ [0, 0], [Math.random() * 10 + 5, Math.random() * 360] ] }); } return lines; }这段代码在 ECharts 5.x 中可以直接运行。如果你部署在大屏上,配合tech_dark主题的动态感会更强。
4.6 多格式输出:json、html、vue 三端适配
新版在输出层做了很大的调整。output_renderer.py负责根据用户需求输出不同格式:
json:只输出纯 ECharts option,方便嵌入已有项目。html:输出完整 HTML 文件,包含 ECharts CDN 引入和初始化逻辑。vue:输出 Vue 3 组件里的options数据和mounted初始化代码。
以html输出为例,渲染逻辑大致是这样的:
# 文件路径:modules/output_renderer.py HTML_TEMPLATE = """<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>{title}</title> <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script> <style> body {{ margin: 0; padding: 20px; background: {background}; }} #chart {{ width: 100%; height: 600px; }} </style> </head> <body> <div id="chart"></div> <script> const chart = echarts.init(document.getElementById('chart')); const option = {option_json}; chart.setOption(option); window.addEventListener('resize', () => chart.resize()); </script> </body> </html> """ def render_html(option, title="Chart"): background = option.get("backgroundColor", "#ffffff") option_json = json.dumps(option, ensure_ascii=False, indent=2) return HTML_TEMPLATE.format( title=title, background=background, option_json=option_json )这个模板看起来简单,但解决了几个常见问题:自动添加resize监听、自动适配背景色、CDN 版本固定。用户不会再因为window.resize漏写导致页面缩放图表不跟着变。
5. 完整实战:从 GitHub 拉取 Skill 到生成第一张图表
前面讲了架构,现在带大家实操一遍完整的流程。我会以“获取项目、配置环境、运行管线、生成图表”四个步骤为例。
5.1 从 GitHub 获取项目
开源项目一般托管在 GitHub 上。如果你是用git clone方式获取,命令如下:
git clone https://github.com/your-name/chart-skill.git cd chart-skill如果你项目的目录名不叫chart-skill,以实际仓库名为准。国内访问 GitHub 速度不理想时,可以使用 GitHub 镜像站或加速下载工具。这里强调一点:下载开源项目请尽量从原始仓库地址获取,避免使用不明来源的二次打包文件,防止代码被篡改。
5.2 环境准备
这个项目的核心代码使用 Python 3 编写,不依赖第三方包,标准库即可运行。也就是说,只要你的电脑安装了 Python 3.8 及以上版本,就能直接跑通数据解析和管线脚本。
可以用下面的命令检查 Python 版本:
python3 --version如果你在 Windows 环境,可能需要使用python而不是python3,根据你的环境变量设置调整即可。
5.3 准备演示数据
examples/目录下我放了一份示例销售数据sales_data.csv,内容大致如下:
月份,销售额,订单量,客户数 2024-01,128000,342,58 2024-02,142000,378,64 2024-03,156000,401,69 2024-04,138000,366,61 2024-05,172000,421,77 2024-06,188000,458,83 2024-07,195000,472,86 2024-08,210000,503,92 2024-09,226000,531,98 2024-10,218000,517,95 2024-11,254000,589,106 2024-12,276000,632,114这份数据包含日期、金额、数量、客户数四个字段,适合测试柱状图、折线图和混合图。
5.4 运行数据解析模块
先直接运行数据解析模块,看看结果:
python modules/data_parser.py预期输出会显示字段类型推断结果。如果你看到月份被推断为string而不是date,是正常的,因为2024-01这个格式默认没有转换成日期,我建议保留为字符串类型,在 ECharts 中直接用类目轴显示会更直观。
5.5 调用 Skill 生成图表
Skill 的常规使用方式是在支持 Skill 的 AI 客户端中引用SKILL.md路径。假设你使用的是 Claude Desktop、Cherry Studio 或类似的 Skill 客户端,你需要在当前会话中加载这个目录。
加载后,你可以直接输入需求:
用 examples/sales_data.csv 的数据画一张月度销售额柱状图,使用 business_light 主题,输出 html 格式。
模型会按照SKILL.md的执行流程调用各模块,最终生成一个 HTML 文件。如果你不希望依赖 AI 客户端,也可以直接运行管线脚本:
python scripts/run_pipeline.py \ --data examples/sales_data.csv \ --chart bar \ --theme business_light \ --format html \ --output output/sales_bar.htmlrun_pipeline.py是一个简化版的调度脚本,它把数据解析、图表选择、配置构建、样式应用、输出渲染串联起来。脚本执行完成后,会在output/目录生成一个可打开的 HTML 图表文件。
5.6 验证生成的图表配置
为了减少“代码跑不起来”的问题,新版增加了validate_option.py校验脚本:
python scripts/validate_option.py output/option.json它会递归检查 option 中是否有未定义的系列类型、是否缺少必填字段、series 长度是否匹配。校验通过后,才建议把配置投入生产。
6. 新增亮点:六边形图表与个性化图表生成
这次更新有一个让我印象很深的需求:很多用户希望生成“六边形图表”,用于能力评估、技能画像、综合素质展示。六边形图表本质上是 ECharts 的雷达图(radar),但做了一些视觉定制:指标点放在六边形的顶点上,连线形成封闭多边形,中心位置可以显示综合评分。
为了这个功能,我在chart_register.json里新增了hexagon类型,并在option_builder.py中实现了build_hexagon方法。核心逻辑是让模型把多列数值归一化到 0-100 区间,然后生成雷达图配置。
下面是一个六边形图表的 option 示例:
{ "radar": { "indicator": [ { "name": "技术深度", "max": 100 }, { "name": "业务理解", "max": 100 }, { "name": "沟通协作", "max": 100 }, { "name": "学习能力", "max": 100 }, { "name": "抗压能力", "max": 100 }, { "name": "创新能力", "max": 100 } ], "radius": "65%", "shape": "polygon", "splitNumber": 5, "axisName": { "color": "#333", "fontSize": 14 }, "splitArea": { "areaStyle": { "color": ["rgba(63, 167, 255, 0.02)", "rgba(63, 167, 255, 0.04)"] } } }, "series": [ { "type": "radar", "data": [ { "value": [92, 78, 85, 88, 90, 82], "name": "当前员工", "areaStyle": { "color": "rgba(63, 167, 255, 0.3)" }, "lineStyle": { "color": "#3fa7ff", "width": 2 } }, { "value": [80, 75, 80, 85, 82, 78], "name": "团队平均", "areaStyle": { "color": "rgba(255, 159, 64, 0.2)" }, "lineStyle": { "color": "#ff9f40", "width": 2, "type": "dashed" } } ] } ] }如果你在 AI 对话里提到了“六边形”、“能力雷达”、“员工画像”这些词,chart_selector.py会优先推荐hexagon类型,不再需要用户手写完整 radar 配置。
7. 常见问题与排查清单
新版本上线后,用户咨询的问题集中在几个固定场景。我把高频问题的排查方案整理成表格,方便你直接对照处理。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| Skill 加载后在 AI 客户端中不生效 | 客户端不支持读取本地目录,或路径含中文/空格 | 确认客户端支持 Skill 功能,路径建议使用纯英文;或把 Skill 打包为插件格式 |
| 生成的图表中文乱码 | HTML 缺少charset=utf-8或 ECharts CDN 加载失败 | 检查输出 HTML 模板是否包含 meta charset;优先使用 jsdelivr 等稳定 CDN |
下载项目后没有SKILL.md | 仓库默认分支不是 main,或克隆不完整 | 检查分支名,使用git clone -b main指定分支;确认仓库根目录文件完整 |
run_pipeline.py提示找不到模块 | 当前工作目录不在项目根目录 | 先执行cd到项目根目录,再运行脚本 |
| 生成的 option 在 ECharts 中报错 | series 类型或字段名错误 | 使用validate_option.py校验;对照 ECharts 官方文档确认版本兼容性 |
| 大屏图表动态效果不明显 | 未使用tech_dark主题,或 effect 配置未开启 | 指定--theme tech_dark;检查effect.show是否为 true |
| 想把 Skill 集成到自己的 Agent 项目 | 缺少环境变量或配置映射 | 阅读config/skill.yaml,将supported_charts与 Agent 的意图识别模块对接 |
除了表格里的问题,还有一个非常容易踩的坑:在 Python 脚本中直接使用from modules.xxx import导入模块时,不同系统对当前路径的处理方式不同。如果你在 Windows 的 PowerShell 下执行,务必先确认当前目录是项目根目录。如果你在 VS Code 里调试,建议先把工作目录设置为项目根目录。
8. 最佳实践与工程建议
前面把功能都过了一遍,这一节我想分享一些从项目维护和社区反馈中沉淀下来的工程建议,这些建议在你自己开发 Skill 时同样适用。
8.1 把提示词和可执行代码分开管理
这是 Skill 设计中最重要的一条原则。SKILL.md里写清楚“做什么”,scripts/和modules/里写清楚“怎么做”。如果你把所有逻辑都塞进提示词,模型每次运行时都要处理大量文本,容易出错且执行不稳定。更好的做法是提示词只描述流程和边界,具体的数据处理、校验、渲染交给脚本。
8.2 为每个 Skill 维护一份版本元信息
我建议在 Skill 项目根目录或者config/skill.yaml里写清楚版本号、依赖环境、作者、许可证。如果不写版本,团队里多个人同时维护时,很容易出现“这个脚本改了但不知道是哪个版本”的问题。引入 Git 标签或者 GitHub Release 也是很好的做法。
8.3 数据安全边界要提前划清
图表 Skill 通常需要读取数据文件,这里要特别强调:不要在 Skill 里内置“读取任意路径文件”的能力,更不要允许模型自动修改原始数据文件。在SKILL.md的边界约束里明确写出“禁止修改原始数据”,并让脚本在读取文件时校验文件扩展名和大小。涉及敏感数据时,建议在沙箱环境运行,并做好脱敏处理。
8.4 输出结果要做两级校验
第一级是语法校验,即 JSON 是否能被正确解析;第二级是业务校验,即图表是否适合表达当前数据。如果你的 Skill 有能力运行 ECharts 的 SSR 渲染,可以把生成的配置用echarts的 nodejs 端渲染一次,确认没有运行时错误。如果不具备条件,至少保留validate_option.py之类的静态校验脚本。
8.5 不要迷信某一个 CDN
国内访问 ECharts CDN 有时不稳定,尤其是公共服务器的网络波动。在输出 HTML 时,可以考虑提供多个 CDN 源备用,或者提示用户下载 ECharts 到本地。不过 CDN 选择属于部署细节,建议把可用性测试纳入 Skill 的验收流程。
8.6 考虑输出分层和二次编辑需求
用户拿到图表的最终目的往往不是“看一次”,而是“放进报告里再改改”。如果 Skill 输出的 HTML 是纯静态的,后续修改会很麻烦。我在新版中加入了“配置导出”按钮,用户可以在页面上调整颜色、标题后直接导出 JSON。类似思路可以引用到你自己的项目里:不要只输出一次性的结果,给用户留一条可编辑的路径。
8.7 遇到类型推断不准时,给用户纠错入口
即使是精心设计的数据解析模块,也无法覆盖所有真实数据场景。我的做法是:当column_types中存在mixed类型时,在输出中提示用户手动指定字段类型,而不是让模型擅自处理。如果你在生成管道中发现了同样的现象,建议参考这个处理策略。
9. 后续规划与可复用思路
这次大更新并不是终点,项目迭代的方向会集中在三个方面。
第一是支持更多图表类型和视觉主题,计划补充桑基图、关系图、仪表盘图等,同时增加暗黑科技、渐变玻璃拟态等主题风格。第二是增加“数据源对接”能力,不再局限于 CSV 文件,支持直接连接 MySQL、PostgreSQL、SQLite 等数据库,让 Skill 能直接查询指标生成图表。第三是完善多语言支持,让 Skill 的说明文档和输出内容能适配英文、日文等场景。
如果你也想开发类似的 Skill,我的建议是:不要一开始追求大而全,先从一个痛点场景出发。比如你先做“销售周报图表生成”这个细分能力,跑通后沉淀出data_parser、chart_selector、output_renderer这些通用模块,再逐步扩展到更多场景。这个开源项目就是这么一步步走过来的。
实际去动手配置一次,你才会更清楚地理解“提示词”和“Skill”之间的差别。如果你用它生成了不错的图表,或者后续自己封装了新的图表类型,也欢迎分享出来一起迭代。