技术架构与创新点
技术架构 创新点 系统设计
系统架构、核心组件、数据流与创新技术点深度分析
系统架构概览
整体架构图
┌─────────────────────────────────────────────────────────────────┐
│ 用户自然语言输入 │
│ "创建展示 AG-UI 协议事件流的 Excalidraw 图表" │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ Claude Code + SKILL.md │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 设计方法论引擎(24KB 核心指令) │ │
│ │ - 深度评估(简单 vs 综合) │ │
│ │ - 研究强制要求(查找真实规范) │ │
│ │ - 视觉模式映射(扇出、收敛、时间线等) │ │
│ │ - 分区块构建策略 │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 参考文件层 (references/) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │color-palette │ │element- │ │json-schema │ │
│ │.md │ │templates.md │ │.md │ │
│ │品牌颜色配置 │ │元素 JSON 模板 │ │Excalidraw格式 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ .excalidraw JSON 文件生成 │
│ { type: "excalidraw", version: 2, elements: [...], ... } │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 渲染验证管道 (render_excalidraw.py) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Playwright │ → │ headless │ → │ PNG 输出 │ │
│ │ Chromium │ │ Chromium │ │ 视觉检查 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 迭代修复循环 │
│ JSON → 渲染 → 检查 → 修复 → 重新渲染 → ... │
└─────────────────────────────────────────────────────────────────┘
技术栈分解
| 层级 | 技术 | 版本 | 用途 |
|---|---|---|---|
| Skill 定义 | Markdown + YAML frontmatter | - | Claude Code 技能注册 |
| 依赖管理 | uv + pyproject.toml | Python 3.11+ | 轻量级 Python 包管理 |
| 渲染引擎 | Playwright | ≥1.40.0 | 无头浏览器自动化 |
| 浏览器 | Chromium | - | SVG 渲染 |
| Excalidraw 库 | @excalidraw/excalidraw | CDN (esm.sh) | SVG 导出功能 |
| 集成目标 | .claude/skills/ | - | Claude Code、OpenCode |
核心组件详解
1. SKILL.md(技能定义文件 - 24KB)
这是项目的核心大脑,包含完整的设计方法论和执行工作流。
结构分析:
# Excalidraw Diagram Creator
## Customization → 指向 color-palette.md 为唯一品牌配置点
## Core Philosophy → "Diagrams that argue, not display"
## Depth Assessment → 简单/综合图表决策框架
## Research Mandate → 技术图表必须先研究真实规范
## Evidence Artifacts → 证据工件类型表(代码片段、JSON 示例等)
## Multi-Zoom Architecture→ 三层次设计方法论
## Design Process → 6 步工作流(理解→映射→草图→JSON→验证)
## Large Diagram Strategy → 分区块 JSON 构建策略
## Visual Pattern Library → 扇出、收敛、时间线等模式库
## Shape Meaning → 语义形状映射
## Color as Meaning → 颜色语义系统
## Modern Aesthetics → 粗糙度、线宽、透明度指南
## Layout Principles → 层级、留白、连接
## JSON Structure → Excalidraw 格式要求
## Render & Validate → 强制渲染验证循环
## Quality Checklist → 27 点验证清单
关键设计决策:
| 设计选择 | 原因 | 影响 |
|---|---|---|
| Markdown 而非 JSON/YAML | 可读性高,便于 AI 理解 | 文件大小但语义清晰 |
| 24KB 详细指令 | 覆盖所有边缘情况和设计原则 | 确保输出质量一致性 |
| 强制渲染验证 | JSON 无法直观判断视觉缺陷 | 防止生成不可用的图表 |
| 单一品牌配置点 | 降低定制门槛 | 非技术用户也能改颜色 |
2. 参考文件层
color-palette.md(品牌颜色配置)
三套颜色系统:
# 形状颜色(语义编码)
Semantic Purpose → Fill/Stroke Pair:
Start/Trigger: fill: #fed7aa, stroke: #c2410c
End/Success: fill: #a7f3d0, stroke: #047857
Decision: fill: #fef3c7, stroke: #b45309
AI/LLM: fill: #ddd6fe, stroke: #6d28d9
Error: fill: #fecaca, stroke: #b91c1c
Primary/Neutral: fill: #3b82f6, stroke: #1e3a5f
# 文本层级颜色(替代容器)
Text Hierarchy:
Title: #1e40af (章节标题)
Subtitle: #3b82f6 (副标题)
Body/Detail: #64748b (描述文本)
# 证据工件颜色(代码片段主题)
Evidence Artifacts:
Code snippet background: #1e293b
JSON/data text: #22c55e (green)
创新点: 颜色不是装饰,而是信息编码。每个语义目的都有固定的填充/描边对,确保图表一致性。
element-templates.md(元素模板库)
提供 6 种核心 Excalidraw 元素的复制粘贴模板:
- 自由浮动文本(无容器)
- 结构线(非箭头,用于时间线/树结构)
- 标记点(10-20px 椭圆)
- 矩形(带圆角
roundness: {type: 3}) - 容器内文本(带
containerId) - 箭头(带
startBinding/endBinding和points数组)
每个模板包含所有必需的 Excalidraw 属性(seed、version、versionNonce 等),AI 只需替换坐标和颜色。
json-schema.md(格式参考)
Excalidraw JSON 格式的速查手册,包含:
- 元素类型定义(rectangle、ellipse、diamond、arrow、text、line、frame)
- 通用属性(id、x/y、width/height、颜色、填充/描边样式)
- 文本专用属性(fontSize、fontFamily、textAlign、containerId)
- 箭头专用属性(points 数组、binding 格式、箭头类型)
3. 渲染管道(render_excalidraw.py)
6.6KB Python 脚本,实现 JSON → PNG 的完整渲染流程。
核心函数:
| 函数 | 行数 | 功能 |
|---|---|---|
validate_excalidraw(data) | ~15 | 验证 JSON 结构(type=excalidraw、elements 数组非空) |
compute_bounding_box(elements) | ~30 | 计算所有元素的包围盒(处理箭头的 points 相对坐标) |
render(...) | ~80 | 主渲染逻辑:启动 Playwright → 加载模板 → 调用 renderDiagram → 截图 |
main() | ~20 | CLI 入口(argparse 处理—output、—scale、—width 参数) |
渲染流程详解:
# 1. 读取并验证 JSON
raw = excalidraw_path.read_text()
data = json.loads(raw)
errors = validate_excalidraw(data) # 提前失败,避免无效渲染
# 2. 计算视口大小
min_x, min_y, max_x, max_y = compute_bounding_box(elements)
padding = 80
vp_width = min(max_x - min_x + padding * 2, 1920) # capped at 1920
vp_height = max(max_y - min_y + padding * 2, 600)
# 3. 启动无头 Chromium
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page(
viewport={"width": vp_width, "height": vp_height},
device_scale_factor=scale # 默认 2x 分辨率
)
# 4. 加载 HTML 模板(包含 Excalidraw 库从 esm.sh CDN)
page.goto(template_url)
page.wait_for_function("window.__moduleReady === true", timeout=30000)
# 5. 注入 JSON 并渲染
result = page.evaluate(f"window.renderDiagram({json_str})")
page.wait_for_function("window.__renderComplete === true", timeout=15000)
# 6. 截图 SVG 元素
svg_el = page.query_selector("#root svg")
svg_el.screenshot(path=str(output_path))
创新设计:
- 提前验证 - 在启动浏览器前验证 JSON 结构,避免浪费资源
- 动态视口计算 - 根据内容自动调整大小,而非固定尺寸
- 信号驱动等待 - 使用
__moduleReady和__renderComplete信号,而非固定延迟 - SVG 直接截图 - 截图 SVG 元素而非整个页面,确保输出纯净
4. HTML 模板(render_template.html)
1.7KB 单文件,提供浏览器渲染环境。
关键实现:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Excalidraw Render</title>
<style>#root { width: 100%; height: 100vh; }</style>
</head>
<body>
<div id="root"></div>
<script type="module">
// 从 CDN 加载 Excalidraw 库(bundle 版本包含所有导出函数)
import { exportToSvg } from "https://esm.sh/@excalidraw/excalidraw?bundle";
// 暴露全局函数供 Python 调用
window.renderDiagram = async function(jsonData) {
const svg = await exportToSvg({
elements: jsonData.elements,
appState: {
viewBackgroundColor: "#ffffff",
exportBackground: true,
gridSize: 20
},
files: jsonData.files,
});
document.getElementById("root").appendChild(svg);
window.__renderComplete = true; // 信号通知完成
};
window.__moduleReady = true; // 信号通知模块加载完成
</script>
</body>
</html>
设计亮点:
- 零构建步骤 - 直接从 esm.sh CDN 加载,无需 npm install
- 全局函数暴露 -
window.renderDiagram供 Playwright 调用 - 信号机制 -
__moduleReady和__renderComplete实现异步同步
数据流分析
端到端流程
1. 用户输入
↓
"创建展示微服务架构的图表"
2. AI 理解(SKILL.md 指导)
↓
- 深度评估:这是综合技术图表 → 需要证据工件
- 研究 mandate:查找真实微服务组件名、API 格式
- 视觉模式:扇出(API Gateway→Services)、收敛(Services→DB)
3. 颜色选择(color-palette.md)
↓
- API Gateway: Primary (fill: #3b82f6, stroke: #1e3a5f)
- Services: Secondary (fill: #60a5fa)
- Database: End/Success (fill: #a7f3d0, stroke: #047857)
4. 元素生成(element-templates.md)
↓
- 复制矩形模板,替换坐标、颜色、文本
- 复制箭头模板,设置 startBinding/endBinding
- 添加自由浮动文本(标题、描述)
5. JSON 构建(分区块策略)
↓
第一遍:基础结构 + Section 1(入口点)
第二遍:Section 2(决策/路由)
第三遍:Section 3(主内容区)
...
6. 渲染验证
↓
render_excalidraw.py diagram.excalidraw → diagram.png
↓
AI 读取 PNG 检查:
- 文本是否溢出容器?
- 箭头是否交叉元素?
- 间距是否均匀?
↓
如有问题 → 修复 JSON → 重新渲染
7. 输出
↓
- diagram.excalidraw(可编辑)
- diagram.png(预览)
JSON 结构详解
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{
"id": "trigger_rect", // 描述性 ID(非随机)
"type": "rectangle",
"x": 100, "y": 100,
"width": 180, "height": 90,
"strokeColor": "#1e3a5f", // 来自 color-palette.md
"backgroundColor": "#3b82f6",
"fillStyle": "solid",
"strokeWidth": 2,
"strokeStyle": "solid",
"roughness": 0, // 0=现代简洁,1=手绘风格
"opacity": 100, // 始终 100(用颜色/大小创建层级)
"angle": 0,
"seed": 100001, // 按区命名空间(100xxx, 200xxx)
"version": 1,
"versionNonce": 67890,
"isDeleted": false,
"groupIds": [],
"boundElements": [ // 绑定到此元素的子元素(如文本)
{"id": "trigger_text", "type": "text"}
],
"link": null,
"locked": false,
"roundness": {"type": 3} // 圆角
},
{
"id": "trigger_text",
"type": "text",
"x": 130, "y": 132,
"width": 120, "height": 25,
"text": "API Gateway",
"originalText": "API Gateway",
"fontSize": 16,
"fontFamily": 3, // 3=等宽字体
"textAlign": "center",
"verticalAlign": "middle",
"strokeColor": "#1e3a5f",
"backgroundColor": "transparent",
"containerId": "trigger_rect", // 容器绑定
"lineHeight": 1.25
},
{
"id": "arrow_to_service",
"type": "arrow",
"x": 282, "y": 145,
"points": [[0, 0], [118, 0]], // 相对坐标路径
"startBinding": {
"elementId": "trigger_rect",
"focus": 0,
"gap": 2
},
"endBinding": {
"elementId": "service_rect",
"focus": 0,
"gap": 2
},
"startArrowhead": null,
"endArrowhead": "arrow"
}
],
"appState": {
"viewBackgroundColor": "#ffffff",
"gridSize": 20
},
"files": {}
}
创新技术点
1. 分区块 JSON 构建策略
问题: LLM 单次输出有~32K token 限制,综合图表 JSON 轻松超限。
解决方案:
第一遍:创建基础文件包装器 + Section 1 元素
第二遍:追加 Section 2 元素
第三遍:追加 Section 3 元素
...
最终遍:审查跨区绑定、更新 boundElements
关键技巧:
- 使用描述性字符串 ID(
"trigger_rect"而非"elem_1")便于跨区引用 - 按区命名空间 seed 值(Section 1: 100xxx, Section 2: 200xxx)避免碰撞
- 每追加新区时,同步更新前区的 cross-section binding
优势:
- 规避 token 限制
- 每区可专注设计,质量更高
- 便于调试(单区问题不影响全局)
2. 渲染 - 视图 - 修复循环
核心理念: JSON 无法直观判断视觉缺陷,必须渲染后检查。
循环流程:
生成 JSON → render_excalidraw.py → 读取 PNG → 检查缺陷 → 修复 JSON → 重新渲染 → ...
检查清单:
- 文本是否被容器裁剪?
- 元素是否重叠?
- 箭头是否穿过元素而非绕过?
- 标签是否模糊(未明确锚定到描述对象)?
- 间距是否均匀?
- 整体构图是否平衡?
典型迭代次数: 2-4 次
优势:
- 防止交付有视觉缺陷的图表
- AI 可从渲染结果学习改进
- 用户可看到中间结果并提供反馈
3. 语义化颜色系统
传统做法: 随意选择颜色,或基于美学。
本项目做法: 颜色编码语义,每个目的有固定填充/描边对。
Start/Trigger → fill: #fed7aa, stroke: #c2410c(暖色=起点)
End/Success → fill: #a7f3d0, stroke: #047857(绿色=完成)
Decision → fill: #fef3c7, stroke: #b45309(黄色=注意)
AI/LLM → fill: #ddd6fe, stroke: #6d28d9(紫色=智能)
Error → fill: #fecaca, stroke: #b91c1c(红色=错误)
优势:
- 跨图表一致性
- 降低认知负荷(颜色=含义)
- 非技术用户只需改 color-palette.md 即可定制品牌
4. <30% 容器化原则
观察: 传统图表过度使用容器(每个文本都在框内)。
本项目原则:
- 默认使用自由浮动文本
- 仅当以下情况添加容器:
- 是章节焦点
- 需要视觉分组
- 箭头需要连接
- 形状本身承载语义(决策菱形等)
实现技巧:
- 用字号/颜色创建层级(标题 28px #1e40af,副标题 20px #3b82f6,正文 16px #64748b)
- 用结构线(line 类型)替代框(时间线、树结构)
- 用小标记点(10-20px 椭圆)替代大形状
目标: <30% 的文本元素在容器内
本章小结
架构亮点:
- 分层设计 - Skill 定义层、参考文件层、渲染管道层职责清晰
- 提前验证 - JSON 结构验证在渲染前完成,避免资源浪费
- 信号驱动 - 使用
__moduleReady/__renderComplete实现异步同步 - 零构建步骤 - CDN 加载 Excalidraw 库,无需 npm install
创新点总结:
- 分区块 JSON 构建(规避 LLM token 限制)
- 渲染验证循环(强制视觉质量)
- 语义化颜色系统(颜色=信息)
- <30% 容器化原则(自由浮动文本优先)
下一章将深入分析实现细节和设计模式。