1. 项目概述为Dify注入图表与文档生成能力如果你正在使用Dify构建AI应用并且希望让AI不仅能生成文字还能直接输出流程图、思维导图、PPT甚至试卷那么这个项目合集就是为你准备的。brightwang/dify-tool-service是一个开源工具集它通过一系列独立的Flask微服务将Mermaid、Markmap、Marp和Quiz生成能力封装成Dify可调用的工具Tool从而极大地扩展了Dify Agent的“动手能力”。简单来说它解决了这样一个核心痛点在Dify的工作流或Agent中当LLM大语言模型构思出需要图表或结构化文档来表达的内容时我们不再需要手动复制文本、打开外部工具、生成图表、再上传回系统。整个过程可以完全自动化。例如你可以创建一个“技术方案设计Agent”用户输入需求Agent不仅生成方案描述还能自动附上清晰的系统架构流程图Mermaid和项目计划甘特图或者一个“学习助手Agent”能根据教材内容自动生成配套的思维导图Markmap和测验试卷Quiz。这个项目源自B站UP主“AI带路党Pro”的系列实战教程提供了从服务部署、Dify工具配置到最终应用集成的完整解决方案。每个服务都设计为轻量、独立的容器可以按需启用与你的Dify环境无缝集成。接下来我将为你详细拆解每个服务的原理、部署细节、以及在Dify中配置的关键技巧和避坑指南。2. 核心架构与设计思路解析2.1 为什么选择“微服务工具”模式在深入实操之前理解其设计哲学至关重要。Dify的核心优势在于编排LLM、工具和知识库。这里的“工具”是一个广义概念可以是搜索引擎API、数据库查询也可以是任何能通过HTTP调用的功能。dify-tool-service项目采用“微服务工具”模式正是基于以下几点考量解耦与灵活性将图表生成、文档渲染这类计算或资源密集型任务从Dify核心中剥离出来作为独立服务运行。这样Dify服务器只需专注于AI编排逻辑而图表渲染服务可以独立扩缩容甚至部署在性能更强的机器上。某个服务如Marp的崩溃不会影响Mermaid服务的正常运行。技术栈适配Mermaid图表、Markmap思维导图、MarpPPT各自有最适合的渲染引擎或运行环境通常是Node.js。通过Flask包装我们为这些异构的技术栈提供了一个统一的、基于HTTP RESTful API的调用接口使得Dify这个Python/Go主导的平台能够轻松地调用它们。标准化集成Dify对“工具”有明确的定义规范主要支持OpenAPI Schema格式。每个Flask服务都精心设计了符合规范的API端点如/generate并提供了对应的OpenAPI描述文件openapi.json。这使得在Dify中通过“自定义工具”功能导入时Dify能自动识别出工具的输入参数、输出格式极大地简化了配置过程。数据流清晰整个数据流非常清晰Dify工作流中的LLM节点生成特定格式的文本如Mermaid代码、Markdown内容 - 通过HTTP请求调用对应的工具服务 - 工具服务在后台执行渲染将文本转换为SVG、HTML或PDF文件 - 文件被保存并通过URL返回 - Dify将URL嵌入最终答案中返回给用户。这种设计保证了每个环节职责单一易于调试和维护。2.2 项目结构全景图仓库中包含四个独立的子服务每个都是一个完整的、可独立运行的Docker项目dify-mermaid-flask-service: 负责将Mermaid文本代码渲染为SVG矢量图。Mermaid是一种基于文本的图表定义语言可以绘制流程图、序列图、甘特图、类图等。dify-markmap-flask-service: 负责将嵌套的Markdown列表渲染为交互式思维导图HTML文件。Markmap是一个将Markdown转化为思维导图的库。dify-marp-flask-service: 负责将Markdown文本渲染为幻灯片PPT并最终生成可访问的HTML演示文稿。它包含两个容器一个Flask服务用于接收内容和调用Marp引擎一个Marp CLI容器用于实际的PPT渲染。dify-quiz-flask-service: 负责将结构化的试卷数据通常是JSON格式渲染为美观的HTML格式试卷方便在线查看或打印。每个服务的目录结构基本一致以mermaid-flask-service为例mermaid-flask-service/ ├── app/ │ ├── __init__.py │ ├── main.py # Flask应用主入口定义API路由 │ └── services/ │ └── mermaid.py # 核心渲染逻辑调用mermaid-cli或py-mermaid ├── data/ # 挂载卷用于持久化生成的图表文件 ├── Dockerfile # 定义服务构建的镜像 ├── requirements.txt # Python依赖包列表 ├── openapi.json # 工具的OpenAPI描述文件 └── docker-compose.yaml # 可选用于独立测试该服务的编排文件这种一致性降低了学习和维护成本部署一个服务后其他服务可以举一反三。3. 环境准备与前置条件在开始部署前请确保你的基础环境已经就绪。这套工具集是围绕Dify设计的因此一个正在运行的Dify环境是前提。3.1 基础环境要求Dify 环境你需要一个已经通过Docker Compose成功部署的Dify实例。建议使用官方最新稳定版。你需要拥有Dify所在服务器的操作权限并熟悉基本的Docker和Docker Compose操作。Docker Docker Compose这是部署的基石。确保Docker守护进程正在运行并且docker和docker-compose命令可用。Git用于克隆项目仓库。网络规划所有新增的服务都需要与Dify的Docker网络互通。从提供的docker-compose.yaml片段可以看到服务都加入了ssrf_proxy_network和default网络。ssrf_proxy_network是Dify官方Docker部署中创建的一个用于内部服务通信的网络确保工具服务能通过服务名如mermaid-flask-service被Dify容器访问到。3.2 获取项目代码通过Git将项目克隆到你的Dify服务器上建议放在与Dify的docker目录同级或子目录方便管理。git clone https://github.com/brightwang/dify-tool-service.git cd dify-tool-service克隆后你会看到四个子目录分别对应四个服务。注意请仔细检查你克隆的仓库是否包含所有子模块如果有的话。虽然本项目目前看起来是平铺结构但良好的习惯是确认一下。不过根据项目结构直接使用即可。3.3 理解Dify的Docker目录结构假设你的Dify是通过官方docker-compose.yaml部署在/opt/dify目录下其结构可能如下/opt/dify/ ├── docker-compose.yaml ├── .env ├── storage/ ├── mongodb_data/ └── ...你需要将工具服务目录如mermaid-flask-service复制到/opt/dify/目录下使其成为Dify项目的一部分。这样修改主docker-compose.yaml时路径引用如./mermaid-flask-service才会正确。4. 服务部署详解以Mermaid为例我们将以dify-mermaid-flask-service作为第一个例子详细走一遍部署和集成流程。其他服务的流程高度相似主要区别在于配置细节。4.1 部署Mermaid图表服务第一步复制服务目录将mermaid-flask-service整个目录复制到你的Dify的Docker compose项目根目录下。cp -r dify-mermaid-flask-service/mermaid-flask-service /opt/dify/第二步修改主docker-compose.yaml这是最关键的一步。用文本编辑器如vim或nano打开Dify的主docker-compose.yaml文件位于/opt/dify/docker-compose.yaml。 找到services:部分在现有服务如api、worker、web的后面添加新的服务定义。你需要将项目README中的配置片段整合进去。注意不能直接无脑粘贴需要确保格式正确缩进对齐。通常所有服务都在services:下并列。添加后相关部分看起来像这样services: api: ... # Dify原有api服务配置 worker: ... # Dify原有worker服务配置 web: ... # Dify原有web服务配置 # 以下是新增的mermaid服务 mermaid-flask-service: build: ./mermaid-flask-service container_name: mermaid-flask-service restart: always volumes: - ./mermaid-flask-service/data:/app/data ports: - 5002:5002 networks: - ssrf_proxy_network - default关键配置解析build: ./mermaid-flask-service: 告诉Docker Compose基于该目录下的Dockerfile构建镜像。volumes: 将宿主机的./mermaid-flask-service/data目录挂载到容器的/app/data。这是持久化存储的关键生成的SVG图片文件会保存在这里即使容器重启也不会丢失。ports: - 5002:5002: 将容器的5002端口映射到宿主机的5002端口。这里有一个重要避坑点确保端口5002在你的服务器上没有其他程序占用。如果已被占用需要修改左边的宿主机端口例如- 5003:5002但后续在Dify中配置工具URL时也要相应更改。networks: 让该容器加入ssrf_proxy_network和default网络这是它能被Dify其他容器特别是api服务访问到的前提。第三步启动服务在/opt/dify目录下执行docker-compose up -d mermaid-flask-service-d表示后台运行。使用docker-compose logs -f mermaid-flask-service可以查看实时日志确认服务是否启动成功。你应该能看到类似* Running on http://0.0.0.0:5002/的输出。第四步验证服务通过curl命令或浏览器测试服务是否正常。首先获取你服务器的IP地址或使用localhost如果在本机测试。curl -X POST http://你的服务器IP:5002/generate \ -H Content-Type: application/json \ -d {code: graph TD; A--B; A--C; B--D; C--D;}如果返回一个包含svg_url的JSON响应例如{svg_url: http://你的服务器IP:5002/data/xxxxx.svg}并且用浏览器打开这个URL能看到一个流程图说明服务部署成功。4.2 在Dify中配置Mermaid工具服务跑起来后它只是一个HTTP API。接下来要让它成为Dify认识的一个“工具”。第一步导入工具定义登录你的Dify控制台。进入“工具” - “自定义工具”。点击“导入工具”。选择文件mermaid-flask-service目录中或项目仓库提供的mermaid作图工具.yml文件。导入后你会看到一个新工具其OpenAPI Schema已经指向了http://mermaid-flask-service:5002/openapi.json。注意这里使用的是Docker服务名mermaid-flask-service和容器内端口5002这是Dify容器网络内部的调用方式不需要经过宿主机端口映射。第二步发布工作流并创建工具这是原指南中容易让人困惑的一步。mermaid作图工具.yml导入后实际上创建了一个工作流而不是直接可用的工具。进入“工作流”页面找到刚刚导入的名为“Mermaid作图工具”的工作流。点击该工作流进入编辑界面。你可以浏览其结构通常包含一个“HTTP请求”节点其URL配置为{{#sys.variables.mermaid_service_url}}/generate这意味着它依赖于一个叫mermaid_service_url的变量。这个变量在工具被调用时会由Dify传入。关键操作点击右上角的“发布”。在发布对话框中选择“发布为工具”。在工具配置界面将工具名称设置为mermaid_service描述设置为save mermain content and get svg url描述很重要Agent会参考它来决定何时调用此工具。然后点击“发布”。发布成功后在“工具” - “自定义工具”页面你应该能看到一个名为mermaid_service的工具。它的图标可能是一个齿轮点击可以查看其详情确认其API端点等信息。第三步配置并使用Agent导入项目提供的mermaid_agent.yml文件在“助手”-“导入”中操作。这会创建一个预配置的Agent。进入这个新导入的Agent的编辑界面。在“工具”配置部分你需要删除可能已经失效的旧工具引用如果存在然后点击“添加工具”从列表中选择你刚刚发布的mermaid_service工具。保存Agent配置。现在你可以测试这个Agent了。在对话窗口输入“帮我画一个用户登录的流程图”Agent应该会理解你的意图调用Mermaid工具并最终返回一个包含SVG图片链接的答案。实操心得很多人在“发布为工具”这一步出错误以为导入YAML后工具就直接可用了。务必理解Dify的机制YAML定义的工作流是“蓝图”发布后才生成真正的“工具实例”。另外工具的描述Description是Agent决定是否调用的关键依据用英文清晰描述其功能如“save mermaid content and get svg url”能显著提高工具调用的准确率。5. 其他服务部署要点与差异处理掌握了Mermaid服务的部署其他服务大同小异。下面重点讲解它们各自的特殊之处和需要注意的细节。5.1 Markmap思维导图服务部署步骤与Mermaid完全一致。复制markmap-flask-service到Dify目录。在主docker-compose.yaml的services:下添加对应配置注意端口改为5003。docker-compose up -d markmap-flask-service。验证服务curl -X POST http://localhost:5003/generate -H Content-Type: application/json -d {markdown: - Central Idea\n - Main Topic 1\n - Subtopic 1.1\n - Main Topic 2}Dify集成关键导入markmap思维导图工具.yml这会创建一个工作流。将该工作流发布为工具工具名设为save_markmap描述改为save markmap content and get url。导入markmap_agent.yml在Agent中删除旧工具引用添加新的save_markmap工具。技术细节Markmap服务接收一个嵌套的Markdown列表字符串在服务端使用markmap-lib库将其转换为一个包含d3.js和markmap-view的独立HTML文件。生成的HTML文件具有交互性缩放、折叠节点。5.2 Marp PPT服务这是最复杂的一个服务因为它涉及两个协同工作的容器。部署步骤复制marp-flask-service到Dify目录。修改主docker-compose.yaml需要添加两个服务定义marp-flask-service: build: ./marp-flask-service container_name: marp-flask-service restart: always volumes: - ./marp-flask-service/data:/app/data ports: - 5004:5004 networks: - ssrf_proxy_network - default marp: image: marpteam/marp-cli:latest container_name: marp restart: always volumes: - ./marp-flask-service/data:/home/marp/app # 注意挂载到同一个数据卷 ports: - 5005:8080 environment: - LANG${LANG} command: -s . networks: - ssrf_proxy_network - default启动服务docker-compose up -d marp-flask-service marp。架构解析marp-flask-service作为前端接口接收Markdown格式的PPT内容将其保存为.md文件到共享数据卷./marp-flask-service/data。marp使用官方的Marp CLI镜像。它挂载了同一个数据卷并运行marp -s .命令启动一个HTTP服务器端口8080实时渲染该数据卷目录下的Markdown文件为PPT网页。当Flask服务需要生成PPT时它保存文件后会构造一个指向marp容器服务的URL如http://marp:8080/presentation.md。这个URL最终返回给用户。Dify集成关键导入marp的PPT工具.yml发布为工具名字设为save_marp_content描述为保存marp ppt内容并获得ppt链接。导入marp_agent.yml在Agent中更新工具引用。重要避坑点确保两个容器挂载的卷路径指向宿主机的同一目录./marp-flask-service/data这是它们共享文件的基础。另外marp容器的端口映射5005:8080是为了让你能从宿主机外部浏览器预览PPT内部调用从Flask服务构造URL使用的是容器名marp和端口8080。5.3 Quiz试卷服务部署步骤与Mermaid类似是最简单的服务之一。复制quiz-flask-service。在主docker-compose.yaml添加配置端口5006。docker-compose up -d quiz-flask-service。Dify集成关键导入创建试卷工作流.yml发布为工具名字设为save_quiz_and_get_url描述为保存试卷并获取试卷url。导入保存试卷agent.yml更新工具引用。功能特点该服务期望接收一个结构化的JSON数据包含试卷标题、题目列表题干、选项、答案等然后使用Jinja2模板引擎渲染成一个美观的、适合打印的HTML页面。这意味着前序的LLM节点需要输出格式非常规范的JSON。6. 深度配置、优化与故障排查6.1 网络与连接问题排查问题Dify Agent无法调用工具提示连接失败或超时。这是最常见的问题。请按以下步骤排查检查服务是否运行docker-compose ps确认所有新增服务状态为Up。检查容器内网络互通# 进入Dify的api容器 docker-compose exec api sh # 在容器内尝试curl工具服务 curl -v http://mermaid-flask-service:5002/health # 每个服务应有一个健康检查端点如果容器内无法连通检查docker-compose.yaml中所有相关服务是否都加入了相同的网络ssrf_proxy_network和default。可以运行docker network inspect dify_ssrf_proxy_network查看有哪些容器连接。检查工具配置的URL在Dify的“自定义工具”页面点击工具详情查看其“服务器URL”。必须使用Docker服务名和容器端口例如http://mermaid-flask-service:5002。绝对不要使用localhost或宿主机IP因为从Dify容器内部看localhost指的是它自己。检查端口冲突如果宿主机端口如5002被占用服务可能启动失败。修改docker-compose.yaml中的宿主机端口映射并确保Dify工具配置中的URL如果从外部测试需要也相应更改。6.2 文件存储与权限问题问题服务日志显示无法写入/app/data目录或生成的图片URL访问不到。目录权限确保宿主机上的./xxx-flask-service/data目录存在且对Docker进程可写。通常需要mkdir -p /opt/dify/mermaid-flask-service/data chmod 777 /opt/dify/mermaid-flask-service/data # 简单粗暴但有效生产环境建议配置特定用户UID卷挂载路径确认docker-compose.yaml中volumes映射的路径正确无误。相对路径./是基于docker-compose.yaml文件所在目录的。URL可访问性服务返回的URL如http://your-server:5002/data/xxx.svg是从外部访问的视角。这个URL依赖宿主机端口映射。确保服务器的防火墙/安全组开放了对应的端口5002-5006。如果Dify和用户在同一内网这没问题。如果服务需要被公网用户访问你需要配置公网IP或域名并可能需要调整Flask服务中生成URL的逻辑例如通过环境变量设置外部可访问的BASE_URL。6.3 性能优化与安全考量资源限制对于Marp这类可能渲染复杂PPT的服务可以考虑为容器添加资源限制防止其占用过多CPU/内存影响Dify主服务。deploy: resources: limits: cpus: 1 memory: 1G启用健康检查可以在docker-compose.yaml中为每个服务添加健康检查便于Docker Compose或编排系统管理。healthcheck: test: [CMD, curl, -f, http://localhost:5002/health] interval: 30s timeout: 10s retries: 3 start_period: 40s你需要在Flask应用中实现一个/health端点。安全加固非公开服务这些工具服务通常不应直接对公网暴露。确保只有Dify所在的内部网络或通过反向代理如Nginx才能访问它们。输入验证虽然Flask服务已有基础验证但在生产环境中应对传入的Mermaid/Markdown代码进行更严格的清洗和沙箱化处理防止代码注入攻击尽管风险较低。使用环境变量将服务器URL、密钥等配置信息从代码中抽离通过Docker环境变量注入。6.4 自定义与扩展这套框架的威力在于其可扩展性。如果你需要集成其他生成服务例如生成ECharts图表、生成PDF报告完全可以仿照现有服务创建一个新的flask-service。创建新服务的通用步骤创建Flask应用编写一个Flask应用暴露一个或多个API端点如/generate接收参数调用后端渲染引擎可能是Python库、Node.js脚本或系统命令将结果保存到文件并返回访问URL。编写Dockerfile定义包含所有依赖的运行环境。提供OpenAPI描述创建openapi.json文件精确定义工具的输入输出。这是Dify能正确识别和调用工具的关键。创建Dify工作流YAML设计一个调用你服务的工作流并可以发布为工具。集成到主编排文件将新服务添加到docker-compose.yaml中。7. 实战应用场景与提示词设计部署好工具后如何让Agent聪明地使用它们这很大程度上取决于你的提示词Prompt设计。场景一技术文档助手Agent目标根据用户描述生成系统设计文档并附带架构图。提示词要点在系统指令中明确说明“你拥有绘制图表的能力。当需要描述系统架构、流程或序列时请使用Mermaid语法生成图表代码并调用mermaid_service工具来生成图表。”在Few-shot示例中展示完整的交互过程用户提问 - Agent思考决定画图- 调用工具 - 将图片URL嵌入Markdown格式回答中。示例对话用户请设计一个简单的用户登录验证流程。Agent思考这个问题适合用序列图表示。我将生成Mermaid代码并调用工具。sequenceDiagram participant U as 用户 participant C as 客户端 participant S as 服务器 participant D as 数据库 U-C: 输入用户名/密码 C-S: 发送登录请求 S-D: 验证用户凭证 D--S: 返回验证结果 alt 验证成功 S--C: 返回Token及成功信息 C--U: 登录成功跳转首页 else 验证失败 S--C: 返回错误信息 C--U: 提示用户名或密码错误 end调用mermaid_service工具 这是您要求的用户登录验证流程图场景二会议纪要与知识梳理助手Agent目标总结会议录音或长篇文档并生成思维导图。提示词要点指令中强调“当你需要梳理复杂信息的结构、层次关系时请使用嵌套的Markdown列表格式组织内容并调用save_markmap工具生成交互式思维导图。”要求Agent先输出文本摘要再说明“以下是本次会议核心内容的思维导图”并附上工具调用结果。提示词设计核心原则明确工具能力在系统提示词中清晰列出可用的工具及其用途。规定输出格式告诉Agent在什么情况下、以何种格式Mermaid代码、特定JSON结构来准备工具所需的输入。提供示例一两个完整的、包含工具调用的对话示例能极大地提升Agent使用工具的准确率。引导最终呈现指示Agent如何将工具返回的结果通常是URL优雅地整合到最终回答中如使用Markdown图片语法或链接。通过以上步骤你不仅能成功部署这套强大的Dify扩展工具集还能理解其背后的设计原理掌握排查问题的方法并最终设计出能自动生成丰富多媒体内容的智能Agent。这标志着你的Dify应用从“文本对话”迈向了“内容创作自动化”的新阶段。