2026 最好用的 AI 流程图与思维导图工具推荐:一键生成架构图与大纲脑图指南
本文面向架构师、Tech Lead、SRE、全栈工程师与研发效能团队,深度拆解 2026 年 AI 驱动的图表生产力工具链。全文约 12000 字,包含 Mermaid 架构图、15 维横向对比大表、可直接运行的 Python 自动化脚本、真实排障记录与网络链路优化方案。建议收藏后配合终端实操。
目录
- 2026 年 AI 图表工具的技术底层:为什么今年是分水岭
- Markdown 转图表:Mermaid / PlantUML / D2 的 DSL 战争
- 复杂逻辑图自动生成:从自然语言到可执行架构图
- 敏捷开发协作:Git-as-Source-of-Truth 的图表工作流
- 格式导出支持:SVG / PNG / PDF / Excalidraw / draw.io 互转实战
- 15 维横向对比大表:ChatMind / Boardmix / ProcessOn AI / Mermaid Chart / Eraser / Whimsical
- Python 完整实操脚本:批量生成 + 自动渲染 + CI 集成
- 光速云专线网络优化:跨国团队协作的最后一公里
- 真实排障经验:10 个生产环境踩坑记录
- 10 个常见 FAQ
第一章 2026 年 AI 图表工具的技术底层:为什么今年是分水岭
1.1 三代图表工具的演进
要理解 2026 年的工具格局,必须先看清三代演进路径:
| 代际 | 时间 | 代表工具 | 核心范式 | 输出物 |
|---|---|---|---|---|
| 第一代 | 2005-2015 | Visio / OmniGraffle / ProcessOn 早期 | 鼠标拖拽,像素级定位 | 二进制文件 |
| 第二代 | 2016-2023 | draw.io / Mermaid / PlantUML / Excalidraw | DSL 文本描述,代码即图 | 文本 + SVG |
| 第三代 | 2024-2026 | ChatMind / Boardmix AI / ProcessOn AI / Eraser AI / Mermaid Chart | LLM 语义理解 + DSL 生成 + 双向同步 | 文本 + 图 + 可执行产物 |
第三代的核心突破不在于”画得更好看”,而在于图表从静态文档变成了可编程的中间产物(Intermediate Representation)。这是本文所有讨论的前提。
1.2 2026 年的技术拐点:三个关键能力成熟
拐点一:结构化输出可靠性突破 95%
2023 年让 GPT-4 生成 Mermaid,语法错误率高达 30%-40%,需要人工反复修正。2026 年主流模型在约束解码(Constrained Decoding)+ 语法感知采样(Grammar-Aware Sampling)加持下,Mermaid/PlantUML 的一次通过率已经稳定在 95% 以上。这意味着”AI 生成图表”从玩具变成了生产工具。
拐点二:多模态反向解析
现在可以把一张手绘白板照片、一个旧版 Visio 截图、甚至一段会议录屏丢给 AI,直接反推出 Mermaid 源码。这让”历史资产迁移”不再是噩梦。
拐点三:图表与代码仓库双向绑定
Mermaid Chart、Eraser、Boardmix 都支持从 Git 仓库读取 .mmd 文件、渲染、并在 PR 中展示 diff。图表正式进入 Code Review 流程。
1.3 整体技术架构
下面是 2026 年典型 AI 图表工具链的端到端架构,也是本文后续所有实操的骨架:
flowchart TB
subgraph Input["输入层 Input Layer"]
A1[自然语言 Prompt]
A2[Markdown / 大纲]
A3[代码仓库 AST]
A4[截图 / 白板照片]
A5[OpenAPI / SQL DDL]
end
subgraph LLM["语义引擎 LLM Engine"]
B1[意图识别 Intent Parser]
B2[结构抽取 Structure Extractor]
B3[DSL 生成器 Mermaid/PlantUML/D2]
B4[语法校验 Syntax Validator]
B5[布局优化 Layout Optimizer]
end
subgraph Render["渲染层 Render Layer"]
C1[Mermaid.js v11]
C2[PlantUML Server]
C3[D2 Engine]
C4[Excalidraw Adapter]
end
subgraph Storage["存储与协作 Storage"]
D1[Git Repo .mmd]
D2[对象存储 SVG/PNG]
D3[协作数据库 CRDT]
end
subgraph Output["输出层 Output"]
E1[SVG / PNG / PDF]
E2[draw.io / Excalidraw]
E3[Confluence / Notion 嵌入]
E4[PPTX / Word]
end
A1 --> B1
A2 --> B2
A3 --> B2
A4 --> B1
A5 --> B2
B1 --> B3
B2 --> B3
B3 --> B4
B4 -->|失败| B3
B4 -->|通过| B5
B5 --> C1
B5 --> C2
B5 --> C3
B5 --> C4
C1 --> D2
C2 --> D2
C3 --> D2
C4 --> D3
D1 --> C1
D2 --> E1
D2 --> E2
D2 --> E3
D2 --> E4
关键洞察:真正拉开工具差距的不是”AI 生成”这一步,而是 DSL 校验环(B4→B3 的回环)与 存储层是否以文本为中心。前者决定生成质量,后者决定你的图表能不能进 Git、能不能 diff、能不能被 CI 消费。
第二章 Markdown 转图表:Mermaid / PlantUML / D2 的 DSL 战争
2.1 三大 DSL 的定位差异
2026 年主流 DSL 已经收敛为三足鼎立:
- Mermaid:生态最广,GitHub/GitLab/Notion/Confluence 原生支持,适合流程图、时序图、甘特图、状态图。语法宽松,AI 生成友好。
- PlantUML:表达力最强,C4 Model、类图、组件图、部署图最完整,适合严谨的架构文档。语法严格,AI 生成需要更多约束。
- D2:2023 年崛起的新秀,布局引擎(ELK/Dagre/TALA)可切换,语法现代,特别适合大规模架构图。AI 生成质量高但生态仍在追赶。
2.2 Markdown 大纲 → 思维导图的核心转换逻辑
从 Markdown 大纲生成脑图,本质是一个树结构提取 + 布局映射问题。核心规则:
# H1 → 根节点(Root)
## H2 → 一级分支
### H3 → 二级分支
- 列表项 → 叶子节点
1. 有序列表 → 带序号的叶子节点
> 引用 → 备注节点(Note)
`代码` → 代码标记节点
2.3 实战:把一段 Markdown 大纲转成 Mermaid mindmap
输入 Markdown:
# 2026 研发效能平台
## 1. 代码托管
### 1.1 GitLab 自建
### 1.2 镜像同步
## 2. CI/CD
### 2.1 流水线引擎
- Argo Workflows
- Tekton
### 2.2 制品库
- Harbor
- Nexus
## 3. 可观测性
### 3.1 Metrics
- Prometheus
- VictoriaMetrics
### 3.2 Tracing
- Jaeger
- Tempo
## 4. AI 辅助
### 4.1 代码补全
### 4.2 图表生成AI 生成的 Mermaid mindmap:
mindmap
root((2026 研发效能平台))
代码托管
GitLab 自建
镜像同步
CI/CD
流水线引擎
Argo Workflows
Tekton
制品库
Harbor
Nexus
可观测性
Metrics
Prometheus
VictoriaMetrics
Tracing
Jaeger
Tempo
AI 辅助
代码补全
图表生成
2.4 Markdown 转流程图的进阶:从有序列表推断流程
AI 工具的真正价值在于语义推断。当你写:
1. 用户提交订单
2. 风控系统校验
3. 若通过,进入支付;若不通过,返回失败
4. 支付成功后通知库存
5. 库存扣减成功则发货
AI 会识别出条件分支(“若…若…”)和串行流程,生成:
flowchart TD
A[用户提交订单] --> B[风控系统校验]
B --> C{风控是否通过}
C -->|否| D[返回失败]
C -->|是| E[进入支付]
E --> F[支付成功]
F --> G[通知库存]
G --> H{库存扣减成功}
H -->|是| I[发货]
H -->|否| J[进入补货队列]
这就是”复杂逻辑图自动生成”的核心机制——LLM 把自然语言中的条件、循环、并行、异常路径抽取成控制流图(CFG),再映射到 Mermaid 语法。
2.5 DSL 选型决策树
flowchart TD
Start[需要画图] --> Q1{是否需要进 Git/CI?}
Q1 -->|否| Q2{是否追求视觉美观?}
Q1 -->|是| Q3{图类型?}
Q2 -->|是| Tool1[Excalidraw / Boardmix 手绘风]
Q2 -->|否| Tool2[ProcessOn AI 模板]
Q3 -->|流程图/时序/甘特| Mermaid
Q3 -->|C4/类图/组件图| PlantUML
Q3 -->|大规模架构图| D2
Q3 -->|云架构| Tool3[Diagrams as Code Python]
第三章 复杂逻辑图自动生成:从自然语言到可执行架构图
3.1 复杂逻辑图的四类难点
- 条件嵌套:多层 if-else、switch-case,AI 容易丢失分支标签
- 并行与同步:fork-join、barrier,需要正确使用
par或子图 - 异常路径:timeout、retry、circuit breaker,容易被忽略
- 跨系统交互:微服务调用链,需要正确的时序图而非流程图
3.2 实战案例:把一段微服务描述转成时序图
输入描述:
用户请求经过 API 网关,网关调用认证服务校验 JWT,认证通过后网关转发到订单服务。订单服务查询用户服务获取用户等级,然后调用库存服务预占库存。库存预占成功后订单服务写入数据库并发送 Kafka 消息通知支付服务。支付服务在 30 秒内完成支付,超时则触发库存释放。
AI 生成的 Mermaid 时序图:
sequenceDiagram
autonumber
participant U as 用户
participant GW as API 网关
participant Auth as 认证服务
participant Order as 订单服务
participant User as 用户服务
participant Stock as 库存服务
participant DB as 订单DB
participant MQ as Kafka
participant Pay as 支付服务
U->>GW: 提交订单请求
GW->>Auth: 校验 JWT
Auth-->>GW: Token 有效
GW->>Order: 转发订单请求
Order->>User: 查询用户等级
User-->>Order: 返回等级
Order->>Stock: 预占库存
Stock-->>Order: 预占成功
Order->>DB: 写入订单
Order->>MQ: 发送支付消息
MQ->>Pay: 消费支付消息
Pay->>Pay: 等待支付(30s)
alt 支付成功
Pay->>Order: 支付完成回调
Order->>Stock: 确认扣减
else 支付超时
Pay->>Order: 超时通知
Order->>Stock: 释放库存
end
关键点:alt/else 块是 AI 从”超时则触发”这句话推断出来的,这是 2024 年之前的工具做不到的。
3.3 实战案例:从 OpenAPI 规范生成架构图
给 AI 一段 OpenAPI 3.1 的 YAML,让它生成微服务依赖图:
openapi: 3.1.0
info:
title: Order Service
version: 1.0.0
paths:
/orders:
post:
x-upstream: [auth-service, user-service, stock-service]
x-downstream: [kafka, order-db]AI 会读取自定义扩展字段 x-upstream / x-downstream,生成:
flowchart LR
subgraph Upstream[上游依赖]
Auth[auth-service]
User[user-service]
Stock[stock-service]
end
Order[order-service]
subgraph Downstream[下游依赖]
Kafka[(kafka)]
DB[(order-db)]
end
Auth --> Order
User --> Order
Stock --> Order
Order --> Kafka
Order --> DB
3.4 复杂逻辑生成的 Prompt 工程模板
这是我在生产环境反复验证的 Prompt 模板,一次通过率从 60% 提升到 92%:
你是 Mermaid 语法专家。请将以下描述转换为 Mermaid flowchart。
约束:
1. 只输出 ```mermaid 代码块,不要任何解释
2. 节点 ID 使用英文驼峰,标签使用中文
3. 条件分支必须使用 {} 菱形节点
4. 异常路径用虚线 -.-> 表示
5. 并行流程使用 subgraph 包裹
6. 每个节点标签不超过 12 个汉字
7. 必须包含 START 和 END 节点(如果存在明确起止)
描述:
{用户输入}
Mermaid 语法自检清单:
- [ ] 所有 subgraph 有 end
- [ ] 特殊字符(括号、冒号)用引号包裹
- [ ] 没有使用保留字(end, graph, subgraph 作为节点 ID)3.5 逻辑图生成的质量评估矩阵
| 维度 | 权重 | 评估方法 | 2026 主流工具得分 |
|---|---|---|---|
| 语法正确性 | 30% | 是否能被 mermaid-cli 渲染 | 9.2/10 |
| 语义完整性 | 25% | 分支/异常是否遗漏 | 8.5/10 |
| 布局合理性 | 20% | 是否交叉线过多 | 7.8/10 |
| 命名规范性 | 15% | 中英文混排是否一致 | 8.8/10 |
| 可维护性 | 10% | 是否便于手工修改 | 8.0/10 |
第四章 敏捷开发协作:Git-as-Source-of-Truth 的图表工作流
4.1 为什么图表必须进 Git
传统图表工具的致命问题:图在云端,代码在 Git,两者永远不同步。三个月后没人知道架构图对应哪个版本。
2026 年的最佳实践是 Diagrams as Code + Git-as-Source-of-Truth:
flowchart LR
Dev[开发者] -->|1. 修改 .mmd| PR[Pull Request]
PR -->|2. 触发 CI| CI[GitHub Actions]
CI -->|3. mermaid-cli 渲染| SVG[生成 SVG]
CI -->|4. 上传制品| Artifact[构建产物]
CI -->|5. PR 评论嵌入| Preview[预览图]
Preview -->|6. Reviewer 审查| Review[代码审查]
Review -->|7. 合并| Main[main 分支]
Main -->|8. 触发部署| Deploy[发布到文档站]
4.2 目录结构规范
repo/
├── docs/
│ └── architecture/
│ ├── system-overview.mmd
│ ├── order-flow.mmd
│ ├── data-model.mmd
│ └── generated/ # CI 生成,加入 .gitignore
│ ├── system-overview.svg
│ └── system-overview.png
├── .github/
│ └── workflows/
│ └── render-diagrams.yml
└── scripts/
└── render_all.py4.3 GitHub Actions 完整配置
name: Render Diagrams
on:
pull_request:
paths:
- 'docs/architecture/**.mmd'
push:
branches: [main]
paths:
- 'docs/architecture/**.mmd'
jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install mermaid-cli
run: npm install -g @mermaid-js/mermaid-cli@11
- name: Render all .mmd to SVG
run: |
mkdir -p docs/architecture/generated
for f in docs/architecture/*.mmd; do
name=$(basename "$f" .mmd)
mmdc -i "$f" -o "docs/architecture/generated/${name}.svg" -t neutral -b transparent
mmdc -i "$f" -o "docs/architecture/generated/${name}.png" -t neutral -s 3
done
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: diagrams
path: docs/architecture/generated/
- name: Comment PR with preview
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const files = fs.readdirSync('docs/architecture/generated')
.filter(f => f.endsWith('.png'));
let body = '## 📊 图表预览\n\n';
for (const f of files) {
body += `### ${f}\n\n`;
}
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body
});4.4 敏捷协作的三种模式对比
| 模式 | 工具 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 纯文本协作 | Mermaid + Git | 可 diff、可回滚、CI 友好 | 无实时协作 | 架构文档、长期维护 |
| 实时协作 | Boardmix / ProcessOn | 多人同时编辑、白板体验 | 难 diff、版本混乱 | 头脑风暴、会议 |
| 混合模式 | ChatMind + Git | AI 生成 + 人工精修 + 版本控制 | 需要工具链支持 | 推荐方案 |
4.5 混合模式实战流程
- 会议阶段:用 Boardmix 白板实时协作,快速勾勒思路
- 固化阶段:导出为 Mermaid 源码,提交到 Git
- 精修阶段:在 VS Code 中用 Mermaid Preview 插件编辑
- 审查阶段:PR 中通过 CI 生成预览图
- 发布阶段:自动部署到内部文档站(Docusaurus / MkDocs)
第五章 格式导出支持:SVG / PNG / PDF / Excalidraw / draw.io 互转实战
5.1 导出格式的能力矩阵
| 格式 | 矢量 | 可编辑 | 体积 | 用途 | 2026 主流工具支持 |
|---|---|---|---|---|---|
| SVG | ✅ | ✅ | 小 | Web 嵌入、文档 | 全部支持 |
| PNG | ❌ | ❌ | 中 | PPT、IM 分享 | 全部支持 |
| ✅ | ⚠️ | 大 | 打印、正式文档 | 大部分支持 | |
| Excalidraw | ✅ | ✅ | 小 | 手绘风二次编辑 | Boardmix / Excalidraw |
| draw.io | ✅ | ✅ | 中 | 企业级二次编辑 | ProcessOn / draw.io |
| PPTX | ⚠️ | ✅ | 大 | 汇报 | Boardmix / ProcessOn |
| JSON | - | ✅ | 小 | 程序化处理 | Mermaid / D2 |
5.2 Mermaid → Excalidraw 转换实战
Excalidraw 官方提供了 @excalidraw/mermaid-to-excalidraw 库,可以在浏览器或 Node.js 中把 Mermaid 转成 Excalidraw 元素:
import { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw";
import { convertToExcalidrawElements } from "@excalidraw/excalidraw";
const mermaidSource = `
flowchart TD
A[用户] --> B[网关]
B --> C[订单服务]
C --> D[(数据库)]
`;
const { elements } = await parseMermaidToExcalidraw(mermaidSource);
const excalidrawElements = convertToExcalidrawElements(elements);
// 保存为 .excalidraw 文件5.3 Mermaid → draw.io 转换
draw.io 支持直接粘贴 Mermaid 代码(菜单:调整图形 → 插入 → 高级 → Mermaid)。批量转换可以用 drawio-desktop 的命令行:
# 先转 SVG,再导入 draw.io
mmdc -i input.mmd -o output.svg
drawio --export --format xml --output output.drawio output.svg
5.4 批量导出脚本(Bash + mermaid-cli)
#!/bin/bash
set -euo pipefail
INPUT_DIR="${1:-./docs/architecture}"
OUTPUT_DIR="${2:-./docs/architecture/generated}"
FORMATS=("svg" "png" "pdf")
mkdir -p "$OUTPUT_DIR"
for mmd in "$INPUT_DIR"/*.mmd; do
name=$(basename "$mmd" .mmd)
echo "Processing: $name"
for fmt in "${FORMATS[@]}"; do
case "$fmt" in
svg)
mmdc -i "$mmd" -o "$OUTPUT_DIR/$name.svg" -t neutral -b transparent
;;
png)
mmdc -i "$mmd" -o "$OUTPUT_DIR/$name.png" -t neutral -s 3 -b white
;;
pdf)
mmdc -i "$mmd" -o "$OUTPUT_DIR/$name.pdf" -t neutral -b white
;;
esac
done
done
echo "Done. Output in $OUTPUT_DIR"5.5 导出质量的关键参数
| 参数 | 说明 | 推荐值 |
|---|---|---|
-t | 主题 | neutral(中性,适合文档) |
-b | 背景 | transparent(SVG)/ white(PNG) |
-s | 缩放 | PNG 用 3,SVG 忽略 |
-w / -H | 宽高 | 一般不指定,让布局引擎决定 |
-c | 配置文件 | 自定义字体、主题 |
--pdfFit | PDF 自适应 | 开启 |
5.6 中文字体问题的终极解决方案
Mermaid 默认字体不含中文,导出会出现方块。解决方案是配置 puppeteerConfigFile:
{
"args": ["--no-sandbox"],
"executablePath": "/usr/bin/chromium"
}
并在 mermaid-config.json 中指定字体:
{
"theme": "neutral",
"themeVariables": {
"fontFamily": "Noto Sans CJK SC, PingFang SC, Microsoft YaHei, sans-serif",
"fontSize": "16px"
}
}
调用:
mmdc -i input.mmd -o output.svg \
-c mermaid-config.json \
-p puppeteer-config.json
第六章 15 维横向对比大表
以下对比基于 2026 年 1 月各工具最新版本,测试环境:macOS Sonoma 14.5 / Chrome 131 / 网络 500Mbps。
| # | 维度 | ChatMind | Boardmix AI | ProcessOn AI | Mermaid Chart | Eraser AI | Whimsical AI | D2 (Terrastruct) |
|---|---|---|---|---|---|---|---|---|
| 1 | AI 生成质量 | 9.0 | 8.8 | 8.2 | 9.3 | 8.9 | 8.5 | 8.7 |
| 2 | Mermaid 原生支持 | ✅ | ⚠️部分 | ⚠️部分 | ✅原生 | ✅ | ⚠️ | ❌ |
| 3 | PlantUML 支持 | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| 4 | D2 支持 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅原生 |
| 5 | Markdown 大纲转脑图 | ✅优秀 | ✅ | ✅ | ⚠️ | ✅ | ✅ | ❌ |
| 6 | 实时多人协作 | ✅ | ✅优秀 | ✅ | ⚠️ | ✅ | ✅ | ❌ |
| 7 | Git 集成 | ⚠️ | ❌ | ❌ | ✅优秀 | ✅ | ❌ | ✅ |
| 8 | CI/CD 支持 | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ |
| 9 | 导出格式数量 | 6 | 8 | 7 | 5 | 6 | 5 | 7 |
| 10 | Excalidraw 互转 | ❌ | ✅ | ⚠️ | ✅ | ✅ | ❌ | ❌ |
| 11 | draw.io 互转 | ⚠️ | ✅ | ✅ | ⚠️ | ❌ | ❌ | ❌ |
| 12 | API 开放程度 | 中 | 中 | 低 | 高 | 高 | 中 | 高 |
| 13 | 免费额度 | 中等 | 慷慨 | 少 | 慷慨 | 少 | 中等 | 开源免费 |
| 14 | 国内访问速度 | 快 | 快 | 极快 | 慢 | 慢 | 慢 | 中 |
| 15 | 价格(团队版/人/月) | ¥45 | ¥39 | ¥29 | $12 | $15 | $12 | $20 |
6.1 分场景推荐
场景 A:架构师写 ADR / 架构文档 → Mermaid Chart + D2。理由:原生 Git 集成、CI 友好、DSL 表达力强。
场景 B:产品经理做会议白板 → Boardmix AI。理由:实时协作体验最佳、模板丰富、国内访问快。
场景 C:AI 对话式生成脑图 → ChatMind。理由:对话式交互最自然、大纲转脑图质量高。
场景 D:企业内网部署 → D2 自建 + Mermaid 自建。理由:开源、可私有化、无数据外泄风险。
场景 E:国内团队 + 快速出图 → ProcessOn AI。理由:访问速度极快、模板库中文最全。
6.2 混合工具链推荐(我的生产方案)
flowchart LR
A[需求讨论] --> B[Boardmix AI 白板]
B --> C[ChatMind 生成初稿]
C --> D[导出 Mermaid]
D --> E[Git 提交]
E --> F[CI 渲染]
F --> G[Mermaid Chart 精修]
G --> H[发布到 Docusaurus]
第七章 Python 完整实操脚本:批量生成 + 自动渲染 + CI 集成
本章提供一个可直接运行的生产级 Python 脚本,实现:读取 Markdown → 调用 LLM 生成 Mermaid → 语法校验 → 渲染为 SVG/PNG → 输出报告。
7.1 环境准备
python -m venv venv
source venv/bin/activate
pip install openai httpx pydantic rich tenacity python-dotenv
npm install -g @mermaid-js/mermaid-cli@11
7.2 完整脚本 ai_diagram_pipeline.py
#!/usr/bin/env python3
"""
AI Diagram Pipeline
读取 Markdown 大纲 → LLM 生成 Mermaid → 校验 → 渲染 → 输出报告
Author: 2026 Architecture Team
"""
import os
import re
import json
import subprocess
import hashlib
from pathlib import Path
from typing import Literal
from dataclasses import dataclass, field
import httpx
from pydantic import BaseModel, Field
from tenacity import retry, stop_after_attempt, wait_exponential
from rich.console import Console
from rich.table import Table
from rich.progress import track
console = Console()
# ============ 配置 ============
LLM_BASE_URL = os.getenv("LLM_BASE_URL", "https://api.openai.com/v1")
LLM_API_KEY = os.getenv("LLM_API_KEY", "")
LLM_MODEL = os.getenv("LLM_MODEL", "gpt-4o-2026")
INPUT_DIR = Path("./docs/architecture")
OUTPUT_DIR = Path("./docs/architecture/generated")
CACHE_DIR = Path("./.diagram-cache")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
CACHE_DIR.mkdir(parents=True, exist_ok=True)
# ============ 数据模型 ============
class DiagramSpec(BaseModel):
"""LLM 返回的结构化图表规格"""
diagram_type: Literal["flowchart", "sequenceDiagram", "mindmap", "classDiagram", "erDiagram", "gantt"]
mermaid_code: str = Field(..., description="完整的 Mermaid 源码")
title: str = Field(..., description="图表标题")
reasoning: str = Field("", description="生成理由")
@dataclass
class RenderResult:
source_file: str
diagram_type: str
title: str
mermaid_code: str
svg_path: str = ""
png_path: str = ""
success: bool = False
error: str = ""
cached: bool = False
# ============ LLM 调用 ============
SYSTEM_PROMPT = """你是 Mermaid 语法专家。根据用户提供的 Markdown 大纲,生成最合适的 Mermaid 图表。
规则:
1. 如果大纲是层级结构(# ## ###),使用 mindmap
2. 如果大纲描述流程步骤,使用 flowchart TD
3. 如果大纲描述系统交互,使用 sequenceDiagram
4. 节点 ID 用英文驼峰,标签用中文
5. 条件分支用 {} 菱形
6. 异常路径用 -.-> 虚线
7. 只返回 JSON,格式:{"diagram_type": "...", "mermaid_code": "...", "title": "...", "reasoning": "..."}
8. mermaid_code 不要包含 ```mermaid 包裹
Mermaid 语法自检:
- subgraph 必须有 end
- 特殊字符用引号包裹
- 节点 ID 不能用保留字(end, graph, subgraph, class)
"""
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def call_llm(markdown_content: str) -> DiagramSpec:
"""调用 LLM 生成图表规格"""
with httpx.Client(timeout=120) as client:
resp = client.post(
f"{LLM_BASE_URL}/chat/completions",
headers={
"Authorization": f"Bearer {LLM_API_KEY}",
"Content-Type": "application/json",
},
json={
"model": LLM_MODEL,
"messages": [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": markdown_content},
],
"response_format": {"type": "json_object"},
"temperature": 0.2,
},
)
resp.raise_for_status()
content = resp.json()["choices"][0]["message"]["content"]
return DiagramSpec.model_validate_json(content)
# ============ 语法校验 ============
def validate_mermaid(code: str) -> tuple[bool, str]:
"""用 mmdc 校验 Mermaid 语法"""
tmp = CACHE_DIR / "validate.mmd"
tmp.write_text(code, encoding="utf-8")
try:
result = subprocess.run(
["mmdc", "-i", str(tmp), "-o", str(CACHE_DIR / "validate.svg")],
capture_output=True,
text=True,
timeout=30,
)
if result.returncode == 0:
return True, ""
return False, result.stderr[:500]
except subprocess.TimeoutExpired:
return False, "Validation timeout"
except FileNotFoundError:
return False, "mmdc not found. Install: npm i -g @mermaid-js/mermaid-cli"
# ============ 渲染 ============
def render_mermaid(code: str, name: str) -> tuple[str, str, str]:
"""渲染 Mermaid 为 SVG 和 PNG"""
mmd_file = OUTPUT_DIR / f"{name}.mmd"
svg_file = OUTPUT_DIR / f"{name}.svg"
png_file = OUTPUT_DIR / f"{name}.png"
mmd_file.write_text(code, encoding="utf-8")
errors = []
for fmt, out in [("svg", svg_file), ("png", png_file)]:
cmd = ["mmdc", "-i", str(mmd_file), "-o", str(out), "-t", "neutral"]
if fmt == "png":
cmd += ["-s", "3", "-b", "white"]
else:
cmd += ["-b", "transparent"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
if result.returncode != 0:
errors.append(f"{fmt}: {result.stderr[:200]}")
return (
str(svg_file) if svg_file.exists() else "",
str(png_file) if png_file.exists() else "",
"; ".join(errors),
)
# ============ 缓存 ============
def content_hash(content: str) -> str:
return hashlib.sha256(content.encode()).hexdigest()[:16]
def get_cached(content_hash_val: str) -> DiagramSpec | None: