从能画图到画对图:LakeMind ECharts 可视化体系的三周进化史
引子:会查数的 Agent,不一定会画图
做过 Data Agent 的人大概都有同感:让 LLM 写 SQL 查数只是前半程,真正的"最后一公里"是把结果呈现给人看。表格适合精确读数,但趋势、占比、对比这些诉求,只有图表能回答。
问题在于,大多数 Agent 产品的图表能力是"一次性"的:后端拼一个图表配置,前端渲染出来,故事就结束了。图丑、图错、图看不懂,都没人管。
LakeMind 走了一条不同的路:把图表当作一个需要持续进化的产品能力来做。从 2026 年 6 月 27 日第一次提交 render_chart 工具,到 7 月 12 日修复流式渲染下的图表重建风暴,仓库里留下了二十多条 chart 相关的提交记录。这篇文章就顺着这些提交,复盘一套 AI 图表体系是如何从"能画"进化到"画对"的。
一、第一版先解决"有没有":render_chart 落地(6 月 27 日)
第一版的设计很克制。提交 3df43c9 引入了 render_chart 工具和前端 ChartSegment 组件:Agent 在对话中生成柱状图、折线图、饼图、散点图四种基础图表,每个图表段还带一个可折叠的 SQL 区块,让用户随时能看"这张图的数据是怎么算出来的"。
这一版有一个重要的设计决策:图表类型不是 LLM 一锤定音的。基础类型之间允许用户手动切换——Agent 给了柱状图,用户觉得折线图更合适,点一下 tab 就能换。这个决策背后的判断是:LLM 对"哪种图更合适"的判断经常不稳定,与其赌单次准确率,不如把纠偏权交给用户。
二、当天连环打磨:ECharts 默认配置只适合做 Demo
有意思的是,第一版落地当天就迎来了连环打磨,几条提交把"能画"往"能看"推了一大步:
- 6185cf3:图表类型切换 tab 上的 emoji 换成统一风格的 SVG 图标,去掉 hover 边框和多余标题,让图表段在对话流里不那么"跳戏";
- 1369bf2:为深色主题定制高对比度色板,坐标轴、tooltip、文字、图例全部统一适配,柱状图加圆角、折线加粗;
- 2524764:修复两类经典布局事故——图例与坐标轴重叠(改为根据图例行数动态计算 bottom 留白),以及饼图被标题遮挡(整体下移)。
这几条提交看似琐碎,其实指向同一个经验:ECharts 的默认配置是为 Demo 设计的,拿到真实产品里,配色、留白、层级全都要重新过一遍。尤其是 Agent 场景,图是嵌在对话流里的,视觉噪音比普通报表页面更致命。
三、画图之前,先回答"要不要画"
图表能力上线后很快暴露另一个问题:Agent 太爱画图了,什么问题都先甩一张图,哪怕答案明明是一行数字。
提交 8f15356 在系统提示词(PREAMBLE)中加入了可视化判断准则:明确"何时用表格、何时用图表",避免每次都画图。同一天的 1a038db 和 ea7f8ac 则建立了图表类型治理:新增漏斗图和仪表盘两类特殊图表,用于转化漏斗分析与单值指标展示,但它们不参与基础类型切换——特殊图表是 Agent 基于分析场景的刻意选择,不该被用户误切成饼图。
“基础类型随便切,特殊类型听 Agent 的”,这条规则把自由度和确定性划开了。
四、桌面端的特殊需求:全屏与高清导出(7 月 10 日)
进入 7 月,图表体系开始补桌面端特有的能力。提交 67cd552 一次性加入全屏查看与高清图片导出;3758587 让全屏浮层里也能切换图表类型;70dead6 针对 macOS 优化全屏渲染与布局。
其中 7383b24 值得单独说:保存图片最初走的是浏览器下载 API,但在 Tauri 桌面应用里,Webview 的下载行为并不可靠,这条提交改为调用 Tauri 后端命令唤起系统原生保存对话框(后端新增约 50 行命令代码)。这是桌面应用与 Web 应用差异的一个缩影——许多 Web 上"理所当然"的能力,到了桌面端都得重新走一遍原生链路。
五、表达的正确性:双 Y 轴与单位(7 月 11 日)
真正让图表从"好看"走向"正确"的,是 7 月 11 日的两条提交。
2d9a8f2 解决的是经典的量纲碾压问题:当"销售额"和"转化率"放在同一张图上时,共享 Y 轴会把转化率压成贴着零的一条线。这条提交给 render_chart 增加了 right_y_fields 参数,让 LLM 可以把不同量纲的序列放到右侧 Y 轴,单轴还是双轴由分析场景决定;同时右轴隐藏分割线、网格右侧加宽,轴名称自动取自该轴上的序列。
3876dfd 则补上了单位:新增 y_field_labels 参数(列名到带单位可读标签的映射),让图例和轴名称直接显示单位。提交信息里有一句话说得很直白:双 Y 轴图如果没有单位,读者根本无法判断右轴是百分比还是 0-1 小数。
更值得注意的是这两条提交的配套动作:它们不只改了代码,还同步更新了 PREAMBLE 和 tenets 准则库中的>六、主题重构与流式渲染的性能坑(7 月 11 日—12 日)
7 月 11 日 LakeMind 整体重构了浅色主题,图表跟着重做了一版浅色风格(17d6057),全屏浮层与头部也补齐了浅色适配。
7 月 12 日的 abcf732 则是整个进化史里技术含量最高的一条修复。背景是内联图表引用机制上线后(Agent 可以在文字总结里用 {{chart:}} 标记把已生成的图表嵌进正文,这部分机制此前已有专文分析),流式输出期间出现了严重卡顿。
排查结论很有代表性:流式追加文本时,前端状态每个 token 都会产生新的数组引用,导致图表块的 memo 重算、每次 map 都生成全新的块对象;而 SolidJS 的 For 组件是按对象引用做 key 的,引用一变就销毁重建——等于每个 token 都在对所有内联图表执行一次 echarts.dispose() 加 echarts.init()。
修复思路是给解析结果做引用级缓存:以图表标记为 key 缓存已解析的块对象,只要引用未变就复用同一个对象,For 组件便不再重建。修复后,图表在标记闭合的瞬间就能出现在流式文本中间,且全程零重建。这条提交还顺手修了一个细节:未闭合的标记会显示一个占位徽章,而不是把原始花括号泄漏到正文里。
七、复盘:三条可以带走的经验
回头看这三周、二十多条提交,有三条经验对做 AI 产品的同学应该有参考价值。
第一,图表库的默认配置只够做 Demo。配色、留白、图例位置、主题适配,每一项都要按真实产品标准重新过一遍,而且这是一项持续工作,不是一次性装修。
第二,可视化准则要"编码"进系统,而不是靠提示词口头叮嘱。LakeMind 的做法是把准则拆成三层:工具参数层(right_y_fields、y_field_labels 让正确性变成接口约束)、提示词层(PREAMBLE 里的判断规则)、准则库层(tenets 中可检索的>