Dify一键生成饼状图:从工作流到ECharts的完整指南

发布时间:2026/8/30 5:36:46
Dify一键生成饼状图:从工作流到ECharts的完整指南 在做企业内部数据答疑机器人的时候我有一个很深的体会很多业务方并不满足于“回答是什么”而是希望AI直接给出可视化结果。比如“各地区销售额占比怎么样”这类问题如果能直接回一张饼状图沟通效率会高很多。这个需求看着简单实际落地时却在 Dify 里卡了很久——网上资料大多在讲 RAG 和 Agent真正讲“如何稳定输出一张饼状图”的内容很少。本文就从零梳理在 Dify 中一键生成饼状图的几种落地路线覆盖工作流、代码节点、数据分析 Agent 和前端 ECharts 集成附上完整代码和踩坑记录适合正在用 Dify 搭建报表类应用的开发者参考。1. 背景与核心概念1.1 Dify 是什么Dify 是一个开源的 LLM 应用开发平台提供了从模型管理、Prompt 编排、知识库到工作流、Agent、API 发布的一整套能力。你可以把它理解成一个“大模型应用的后台”不用从零编写前端页面也不用自己维护复杂的会话状态就能快速搭建聊天助手、智能客服、数据分析助手这类应用。在数据分析场景中Dify 的价值主要体现在两点一是把“用户输入—模型理解—工具调用—结果输出”的完整链路可视化地串起来二是通过工作流和代码节点把传统脚本里的数据处理逻辑嵌入到 AI 应用流程中。1.2 一键生成饼状图的业务场景饼状图在业务分析里非常高频常见场景包括用户上传一份销售明细希望看到各产品线销售额占比。运营人员输入几个分类和数值想快速得到预算分配比例。企业报表机器人需要定时生成部门人数、渠道来源、费用结构等占比图。前端集成需求AI 通过对话得出结构化数据再由自研系统渲染成交互式图表。这些场景的共同点是用户不想手动复制数据到 Excel也不愿意在报表工具里重新配置数据源。通过 Dify我们可以把“数据解析、占比计算、绘图展示”封装成一条自动化链路。1.3 三条常用技术路线对比实现方案输出形式交互性适用场景工作流 代码节点静态图片 / base64低Dify 聊天窗口内直接展示数据分析 Agent图片 / 文字分析中上传 CSV、Excel 文件后自然语言生成图表JSON 数据 前端 ECharts结构化数据高自研前端页面需要图例交互、联动筛选三条路线并不冲突。在同一个项目里可以先在 Dify 中用代码节点验证效果后续再切换到 Agent 或前端渲染方案。后面我会逐一展开。2. 环境准备与平台说明2.1 准备条件在开始之前你需要准备好以下环境Dify 实例社区版 Docker 部署、企业版或云端 SaaS 均可。模型供应商 API Key用于创建 Agent 或 LLM 节点推荐选择支持工具调用的模型。工作流创建权限至少能创建一个空白工作流应用。测试数据建议准备 JSON 格式的占比数据也可以准备 CSV 文件。需要注意的是不同 Dify 版本的节点类型、工具名称、API 端点会有差异。本文不会绑定某个具体版本以“自托管 较新版本”为例重点说明配置思路和通用写法。如果你使用的是云端免费版部分自定义依赖可能受限需要根据你的实际环境调整。2.2 测试数据准备为了方便演示我们先准备一份 JSON 格式的数据结构非常简单包含分类名称和数值[ {name: 华东区域, value: 320}, {name: 华南区域, value: 260}, {name: 华北区域, value: 180}, {name: 西南区域, value: 90} ]如果你更习惯用表格文件也可以用 CSV区域,销售额 华东,320 华南,260 华北,180 西南,90本文后面的示例都基于这份数据。实际项目中数据可能来自数据库、Excel 导入或用户对话但核心处理逻辑是一样的把不同来源的数据统一成[{name, value}]这样的结构再交给绘图环节。2.3 关键技术约束说明在 Dify 中生成饼状图最大的技术约束是代码节点的沙箱环境。Dify 的代码节点运行在独立的沙箱容器中和本地 Python 环境并不完全一致。沙箱默认提供基础 Python 库但第三方库并不一定齐全。比如你想直接import matplotlib需要确认当前部署镜像中是否安装了 matplotlib。如果用的是自托管 Docker 部署可以通过修改镜像或安装依赖解决如果用的是云端托管版本则可能需要改用数据分析 Agent 或自定义工具。理解这一点后面遇到ModuleNotFoundError时就不会慌。3. 核心原理拆解3.1 生成饼状图的本质饼状图本质上是一个“数据映射”问题你需要有分类字段和数值字段然后由绘图库把数值转换成角度。所以不管 Dify 的方案怎么变核心步骤都是固定的接收原始数据。清洗并解析数据。计算占比一般由绘图库自动完成。渲染成图片或结构化数据。返回给用户或前端系统。Dify 的工作流非常适合承载这套流程。开始节点负责接收输入代码节点负责数据处理和绘图输出节点负责展示结果。3.2 图片输出的三种形式在 Dify 中把图片展示给用户常见有三种形式base64 Data URL把图片编码成data:image/png;base64,xxx可以直接塞进 Markdown 的![]()语法中适合小尺寸图片。文件输出如果你的 Dify 版本支持文件类节点可以把图片作为文件返回用户可以直接下载。外部 URL把图片上传到对象存储或图床返回一个可访问的 URL适合大图和跨端展示。base64 方式实现最简单但也最容易踩坑。图片过大时聊天消息会变得很长部分前端渲染可能不稳定。我们会在后面常见问题部分专门说明。3.3 Dify 代码节点的执行逻辑Dify 工作流中的代码节点入口函数通常命名为main参数来自上游节点返回值是一个字典字典中的字段会成为该节点的输出变量。了解这个逻辑后写代码节点时就不会手足无措。代码节点适合做三件事数据格式转换、数据清洗、调用绘图库生成图片。但要注意代码节点不是万能的它不适合做重量级模型调用也不适合执行需要访问内网数据的操作。如果业务复杂建议把能力封装成自定义工具而不是把大量逻辑堆在代码节点里。4. 实战方案一工作流 代码节点绘制饼状图4.1 创建应用与开始节点登录 Dify 控制台选择“工作流”类型创建一个新的工作流应用。进入工作流画布后先配置“开始”节点。这个节点负责接收外部传入的参数。我们定义两个输入字段字段名类型必填说明datastring是JSON 数组格式为[{name:分类,value:数值}]titlestring否图表标题默认“数据分布”从语义上讲data是绘图的核心数据源title只是辅助展示后续代码节点会用到。4.2 编写绘图代码节点在画布中添加一个“代码”节点将开始节点作为上游。代码节点的参数映射中把开始节点的data和title传入。绘图的代码如下可以直接复制到 Dify 代码节点的编辑器中import json import base64 from io import BytesIO def main(data: str, title: str) - dict: # 1. 解析 JSON 数据 try: items json.loads(data) except Exception as e: return {error: fJSON解析失败{e}} if not isinstance(items, list) or len(items) 0: return {error: 数据不能为空且必须是列表} # 2. 提取分类和数值 names [] values [] for item in items: names.append(str(item.get(name, ))) values.append(float(item.get(value, 0))) # 3. 使用 matplotlib 绘制饼状图 try: import matplotlib matplotlib.use(Agg) import matplotlib.pyplot as plt # 字体设置避免中文乱码 plt.rcParams[font.sans-serif] [SimHei, Arial Unicode MS, DejaVu Sans] plt.rcParams[axes.unicode_minus] False fig, ax plt.subplots(figsize(6, 5)) ax.pie(values, labelsnames, autopct%1.1f%%, startangle90) ax.axis(equal) ax.set_title(title or 数据分布) # 4. 转成 base64 字符串 buf BytesIO() fig.savefig(buf, formatpng, dpi120, bbox_inchestight) buf.seek(0) img_base64 base64.b64encode(buf.read()).decode(utf-8) plt.close(fig) total sum(values) return { image_base64: img_base64, data_url: fdata:image/png;base64,{img_base64}, total: round(total, 2) } except ModuleNotFoundError as e: return {error: f当前沙箱缺少绘图依赖{e}请改用数据分析 Agent 或自定义工具}代码里有几个关键点matplotlib.use(Agg)是必须的。Dify 代码节点运行在无图形界面的服务器上只有使用 Agg 这种非交互式后端savefig才能正常导出 PNG 图片。中文字体设置了多个候选因为不同系统内置字体不一样。如果仍然乱码说明环境中没有这些中文字体可以改用英文标签或通过自定义工具补齐字体文件。try-except包裹绘图逻辑是为了在沙箱缺少依赖时返回友好的错误信息而不是让整个工作流直接失败。返回的data_url是一个可直接用于 Markdown 图片的 Data URL省去前端拼接的步骤。4.3 配置输出节点添加一个“输出”节点输出类型选择 Markdown。在输出内容中引用代码节点的输出变量## 饼状图 ![饼状图](data:image/png;base64,{{#代码节点ID.image_base64#}}) 数据总量{{#代码节点ID.total#}}需要注意代码节点ID要替换成你画布中实际节点的 ID变量引用方式可以参考 Dify 工作流编辑器提供的变量提示。Dify 在画布中会直接显示可用的输出变量不需要手动记忆节点 ID。如果你希望图片可下载而不是嵌入聊天可以尝试在输出节点中返回文件类型但这依赖你的 Dify 版本是否提供文件输出节点。基础用法还是推荐 Markdown base64 方式。4.4 运行与验证点击右上角的“运行”按钮输入下面的测试数据[ {name: 华东区域, value: 320}, {name: 华南区域, value: 260}, {name: 华北区域, value: 180}, {name: 西南区域, value: 90} ]运行后预期输出是一张饼状图四个区域会按数值比例显示同时给出数据总量。如果一切正常你已经实现了“一键生成饼状图”的最小闭环。4.5 加入 LLM 节点支持自然语言输入代码节点目前要求输入必须是标准 JSON对用户不够友好。如果希望用户直接输入“华东 320华南 260华北 180西南 90”可以在代码节点前面加一个 LLM 节点让模型把自然语言转成 JSON。LLM 节点的 Prompt 可以这样设计请从用户输入中提取饼状图需要的分类和数值。 输出格式必须为 JSON 数组例如 [{name:华东,value:320}] 只输出 JSON不要输出其他解释。 用户输入{{#开始节点.query#}}但大模型输出的 JSON 不一定完全规范所以仍然需要在代码节点中做json.loads容错。这也是“模型负责理解、代码负责稳定”的典型分工。5. 实战方案二数据分析 Agent 一键生成饼状图5.1 适用场景方案一的缺点是用户必须按固定格式录入数据而且绘图依赖沙箱中的 matplotlib。如果业务方希望直接上传 Excel 或 CSV再由 AI 自动完成分析和绘图方案二会更合适。这是典型的数据分析 Agent 场景用户上传文件Agent 调用代码解释器或数据分析工具读取文件、理解列名、绘制图表。整个过程不需要用户关心 JSON 格式也不需要预先设计工作流分支。5.2 创建 Agent 与配置工具在 Dify 控制台创建一个“Agent”应用选择支持工具调用的模型然后在工具列表中启用代码执行类工具。不同版本的工具名称可能不同有的叫“数据分析”有的叫“代码解释器”请以你的环境为准。如果工具列表里没有可以查看是否支持安装自定义工具或插件把绘图能力封装成一个工具后在 Agent 中启用。这个方案适合自托管部署的场景云端版本受限于平台能力需要关注当前版本的特性说明。5.3 设计提示词数据分析 Agent 的提示词很重要直接影响模型理解和执行效果。推荐下面这个模板你是一名数据分析师。请根据用户上传的数据文件完成以下任务 1. 理解数据中的分类字段和数值字段。 2. 如果用户要求生成饼状图请选择合适的字段。 3. 使用代码解释器绘制饼状图并返回图片。 4. 如果分类过多只展示占比最大的前 N 项其余合并为“其他”。 5. 最终用简洁的中文说明数据结论并指出占比最高的分类。这段提示词做了三件事明确角色、限定输出、处理极值情况。第 4 条尤其重要因为当分类太多时直接画饼状图会变成一个密密麻麻的圆环可读性很差。让 Agent 自动合并“其他”是最实用的工程技巧。5.4 执行流程与注意事项用户上传文件后Agent 会经历以下流程分析文件结构识别列名。根据用户问题选择分类列和数值列。调用代码解释器用 Python 绘制饼状图。返回图片和文字分析。在使用时有几个问题需要提前考虑中文列名模型可能无法准确识别类似“区域-销售额”这样的字段建议在 Prompt 中要求模型先输出字段识别结果再继续绘图。数据脱敏如果文件包含客户姓名、手机号等敏感信息建议先过滤后再上传。数值字段类型如果列中混有空值或非数字模型需要先做清洗。你也可以在 Prompt 中强制要求“先处理缺失值再绘图”。在私有化部署的环境中上传文件不会离开内网安全性相对可控。如果使用云端版本涉及敏感业务数据时务必确认平台的数据保护方案。6. 实战方案三输出 JSON 数据 前端 ECharts 渲染6.1 适用场景与整体架构方案一和方案二生成的图片是静态的用户无法悬停查看精确数值也无法点击某个扇区做下钻。如果 Dify 只是后端能力的一部分最终页面在自己的业务系统里更推荐方案三Dify 负责生成结构化数据前端使用 ECharts 渲染交互式饼图。整体架构如下用户输入 → Dify 工作流 → 代码节点清洗数据 → 输出 JSON → 业务后端调用 Dify API → 前端 ECharts 渲染这种方案把“AI 能力”和“前端展示”解耦Dify 不直接输出图片而是输出一张“数据加工单”。6.2 Dify 工作流返回结构化数据在 Dify 工作流中代码节点只需要负责清洗和格式化数据不需要调用 matplotlib。示例代码如下import json def main(data: str) - dict: items json.loads(data) # 清洗非法数据 cleaned [] for i in items: name str(i.get(name, )) value i.get(value) if name and value is not None: try: cleaned.append({ name: name, value: float(value) }) except ValueError: continue return { chart_data: json.dumps(cleaned, ensure_asciiFalse) }输出节点直接返回chart_data字段内容是一个标准 JSON 数组。前端拿到就能直接使用不需要再做二次解析。如果你希望在 Dify 聊天窗口里做预览也可以加一个 Markdown 输出节点把 JSON 以代码块形式展示。6.3 调用 Dify API 获取结果如果前端需要主动触发生成图表通常通过后端调用 Dify 的开放 API。这里给一个 Python 调用示例需要注意的是不同应用类型的 API 端点不同工作流应用一般使用/v1/workflows/run聊天助手应用使用/v1/chat-messages以你环境中的 API 文档为准import requests URL http://your-dify.example.com/v1/workflows/run API_KEY app-xxxx payload { inputs: { data: [{name:华东,value:320},{name:华南,value:260}] }, response_mode: blocking, user: demo-user } headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } resp requests.post(URL, jsonpayload, headersheaders, timeout60) print(resp.status_code) print(resp.json())接口返回结果中会携带工作流输出字段你需要根据实际响应结构解析出chart_data。如果响应超时可以把response_mode改为streaming用流式方式逐步读取。6.4 前端 ECharts 展示前端拿到chart_data后用 ECharts 渲染非常方便。下面是一个可直接运行的 HTML 示例!DOCTYPE html html langzh-CN head meta charsetUTF-8 title饼图示例/title script srchttps://cdn.jsdelivr.net/npm/echarts5/dist/echarts.min.js/script /head body div idchart stylewidth: 600px; height: 400px;/div script // 实际项目中这里的数据来自 Dify API 返回的 chart_data const data [ { name: 华东区域, value: 320 }, { name: 华南区域, value: 260 }, { name: 华北区域, value: 180 }, { name: 西南区域, value: 90 } ]; const chart echarts.init(document.getElementById(chart)); chart.setOption({ tooltip: { trigger: item }, legend: { bottom: 0 }, series: [{ type: pie, radius: 60%, data: data, label: { formatter: {b}: {d}% }, emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: rgba(0, 0, 0, 0.5) } } }] }); /script /body /htmlECharts 的好处是交互能力强用户可以 hover 查看百分比、点击图例筛选分类更适合正式的业务系统。相比静态图片这种方案也更适合做下钻分析比如点击“华东区域”后继续展示该区域下的城市分布。7. 常见问题与排查思路7.1 高频问题速查表问题现象常见原因解决思路代码节点报错ModuleNotFoundError: No module named matplotlib沙箱环境未安装绘图库使用数据分析 Agent 或自定义工具自托管时在沙箱镜像中安装依赖生成的图片不显示只看到一长串 base64前端不支持过长 Data URL缩小图片尺寸改用文件节点或对象存储 URL图片中文标签乱码matplotlib 缺少中文字体配置中文字体或使用英文标签JSON 解析失败大模型输出不是标准 JSON代码节点中做容错增加 LLM 节点前的数据清洗饼图扇区太多无法阅读分类数量过多只展示前 N 项其余合并为“其他”工作流输出变量引用不生效节点 ID 或字段名写错在画布中通过变量面板确认引用名Agent 无法识别上传文件的列名列名是中文且有歧义在 Prompt 中要求先输出字段识别结果再绘图7.2 依赖缺失问题的排查流程如果你在代码节点中遇到依赖缺失可以按下面的顺序排查先查看报错日志确认是ModuleNotFoundError还是ImportError。如果你使用的是 Dify 社区版 Docker 部署找到沙箱镜像确认是否进入容器执行过pip list。如果缺依赖可以在自定义镜像中补充安装。如果你使用的是云端版本代码节点无法修改环境建议改用数据分析 Agent 或自定义工具而不是继续折腾沙箱。如果业务必须使用 matplotlib但环境不支持可以考虑将绘图逻辑下沉到独立服务通过 HTTP 请求节点调用。7.3 base64 图片过长问题base64 图片本质上是把二进制文件转成纯文本体积会比原图增加约 33%。当图片达到几 MB 时聊天消息会非常卡顿。解决方法主要有降低dpi到 96 或 72减小figsize优先保证清晰度够用。使用 PNG 压缩参数或在savefig中设置optimizeTrue。改用文件输出或对象存储 URL适合需要长期保存的报表。如果只是临时预览可以接受较低分辨率。8. 最佳实践与工程建议8.1 输入数据严格校验无论是工作流代码节点还是 Agent输入数据都可能来自用户自由输入。校验是第一步也是最重要的一步。我们在绘图代码中要检查数据类型、空列表、None 值、负数等情况。如果数据不合法返回一个明确的错误信息而不是让工作流崩溃。if not items: return {error: 数据为空请检查输入} if any(v 0 for v in values): return {error: 饼状图不支持负数请检查数值字段}这种“提前失败”的设计可以显著降低后续排查成本。8.2 图片输出优化控制图片体积figsize和dpi不要盲目调大6x5 英寸、120 dpi 已经足够聊天窗口展示。设置中文字体把字体配置统一封装成公共代码避免每个工作流都重复编写。数据过多时截断只画 Top 10其余合并为“其他”保证可读性。尽量在 Python 中完成百分比格式化避免前端或模型二次处理。8.3 绘图逻辑复用与自定义工具在一个实际项目中多个工作流可能都需要生成饼状图。如果每个工作流都复制一份绘图代码后续维护会非常痛苦。推荐的做法是把绘图逻辑封装成 Dify 的自定义工具。工具内部可以包含更复杂的 Python 代码、字体资源、依赖管理工作流只需要传入数据和参数即可。如果你不想马上做自定义工具至少可以把公共代码集中在一个代码节点中通过上游节点把参数传入减少重复。8.4 安全与权限建议上传到 Dify 的数据可能包含敏感信息在进入工作流之前做好脱敏。如果使用云端 SaaS避免把涉及客户隐私、财务明细的文件直接上传。调用 Dify API 时使用最小权限的 API Key不要使用管理员密钥。如果要在聊天窗口中展示 HTML 或图片注意过滤用户输入避免恶意内容注入。私有化部署是数据合规性要求较高时的首选方案。这些建议同样适用于其他 Dify 应用不只是饼状图场景。9. 总结与后续学习方向本文围绕 Dify 一键生成饼状图介绍了三条完整落地路线工作流 代码节点适合在 Dify 聊天窗口内快速展示静态图片通过 base64 输出。数据分析 Agent适合用户直接上传 CSV、Excel 文件由模型自动完成分析和绘图。JSON 数据 ECharts适合自研前端系统通过 Dify API 获取结构化数据再由 ECharts 渲染交互式图表。实际项目里没有绝对最优的方案。如果让我重新做一次我会先确认部署环境的沙箱依赖再决定是用代码节点还是 Agent最后根据前端需求选择静态图片还是交互式图表。不同 Dify 版本对代码节点、工具、API 端点的支持存在差异强烈建议你在自己的环境中先用示例数据跑一遍确认沙箱依赖和变量引用方式后再应用到业务数据。如果这篇内容对你有帮助可以收藏备用。后续如果对 Dify 自定义工具、Agent 配置或前端集成有更多疑问也欢迎继续交流。