
在接手一个不熟悉的中大型项目时很多人都有过这样的经历一边翻代码一边开绘图工具手动拖出一个个模块框再用箭头连来连去。这个过程的痛不是“画图”本身而是你得先靠人肉把代码读明白。等你终于画完大概率会发现两个问题一是图里画的模块边界和真实代码并不完全一致二是代码一迭代这张图很快就过期了。AI 编程助手在过去两年里快速普及读代码、解释代码、生成代码已经成了基本操作。但真正容易被忽略的是它们在“代码理解”之外的一种新能力——Skill。Skill 本质上是把提示词、脚本、规则和参考文档打包成一个可复用的技能目录让 AI 在特定任务中按一套固定工作流执行。把它用在“生成架构图”这件事上会产生一个非常实用的效果让 AI 边读代码边出图你只需要负责确认和微调。这篇文章会先讲清楚 Skill 到底是什么、为什么它适合用来生成架构图然后手把手写一个“扫描代码—提取依赖—输出架构图”的完整 Skill最后给出实际项目中常见的坑和工程化建议。就算你之前没有接触过 Skill读完也能在自己本机跑通整个流程。1. 这篇文章真正要解决的问题先说一个判断手动画架构图真正消耗时间的环节不是“拖框连线”而是“读代码”。一张合格的架构图至少需要回答几个问题系统分为哪几个模块模块之间如何调用数据大致如何流转有没有循环依赖有没有公共底座这些问题如果靠人肉去代码里找答案成本极高。以几万行代码的仓库为例理清模块边界通常需要半天到几天不等而且结果严重依赖读代码的人的经验。新手容易把图画成“目录结构图”老人容易把图画成“理想设计图”两者都可能和真实代码偏离。用 AI 生成架构图的思路本质上是在改变“谁来读代码”这个环节。常规做法是让 AI 直接阅读整个仓库并输出一张图。对于小型 demo 项目这种方式效果很好但一旦代码量变大AI 的上下文窗口会被大量文件内容填满生成结果开始出现遗漏、幻觉和过度概括。这篇文章要解决的正是这个核心矛盾如何在代码量较大的工程里既让 AI 理解项目结构又不让 AI 被海量源码淹没最终稳定地产出一张与代码同步的架构图。解决办法是两条腿走路用确定性的脚本扫描代码拿到真实的模块清单和依赖关系用 AI 理解扫描结果补充业务语义生成结构清晰的架构图。这种方式对以下几类读者最有用需要快速上手陌生项目的后端开发需要为团队整理架构文档的技术负责人做微服务拆分或模块治理的架构师以及想给项目补充文档、又不想手工维护图形的开源维护者。2. 基础概念Skill、架构图与 AI 编程助手2.1 什么是 SkillSkill 是 AI 编程助手中一种可复用的“技能包”机制。它不是一个独立的编程语言或框架更像是一套给 AI 使用的标准化操作手册。一个 Skill 通常表现为一个目录目录里有SKILL.md描述这个技能的用途、触发条件、执行步骤脚本文件完成具体的机械性工作参考模板给 AI 提供输出格式示例规则说明约束 AI 在什么情况下应当怎么表现。当用户在对话中触发了某个 Skill 的描述场景时AI 会自动读取对应的SKILL.md然后按照里面定义的步骤工作。和直接写一段提示词相比Skill 的价值在于“标准化”它把一次性的任务流程固化下来团队任何人都能复用同一套方法。2.2 架构图到底是什么架构图是对软件系统结构化关系的可视化表达。常见的有图类型表达内容典型问题系统上下文图系统与外部用户、外部系统的边界系统边界在哪容器图应用、服务、数据库等可部署单元有哪些服务、存储组件图容器内部的主要模块与调用关系模块之间如何依赖部署图进程在物理/云环境中的分布服务部署在哪、如何通信近几年 C4 模型在团队文档中越来越常见原因是它把复杂的系统按“层级放大”的方式拆开每一层都只用少量元素表达。C4 模型恰好也是 Skill 生成架构图时的理想输出框架第一层先画系统边界第二层再画服务和存储第三层再深入到具体模块。2.3 为什么 Skill 适合做架构图生成如果只是临时用 AI 生成一张图直接写提示词就够了。但架构图是团队文档的一部分需要反复生成、更新、统一风格。Skill 的优势恰恰在于每次都用同一套扫描规则输出不会飘忽不定脚本部分可以保证“图里的内容来自真实代码”而不是 AI 的想象团队可以共享同一个 Skill拉齐所有人的出图标准。这就把“一次性问答”升级成了“可持续维护的文档生产流程”。3. 核心原理为什么“边读代码边出图”是可行的3.1 传统静态分析的局限静态分析工具很早就出现了。通过解析 import 语句、函数调用、类依赖关系工具可以自动生成调用关系图或依赖图。这种做法的优势是结果精确不会骗人。但它有两个明显的限制粒度难以控制工具默认把所有依赖都视为平等关系无法区分“业务模块依赖”和“基础设施依赖”生成的图经常信息爆炸缺少业务语义静态分析能告诉你 A 模块 import 了 B 模块但无法告诉你 A 和 B 的边界为什么这样划分用户真正想看的“模块职责”得靠人解释。3.2 纯 AI 读代码的局限让 AI 直接读整个代码仓库是很多人尝试过的方案。在小型项目里效果惊艳但一旦仓库变大问题就出现了上下文窗口有限几万个文件不可能全部塞进对话幻觉风险上升AI 在记不全文件时会倾向于“脑补”出不存在的模块或调用关系结果不可复现同一个问题问两次答案可能不一样。3.3 脚本扫描 AI 理解各取所长这正是 Skill 方案最值得借鉴的架构思路把“确定性工作”交给脚本把“理解性工作”交给 AI。代码仓库 │ ▼ 脚本扫描确定性的 ──► 结构化的 JSON 数据 │ │ ▼ ▼ AI 理解与加工 ◄── SKILL.md 引导 ──┘ │ ▼ 架构图定义文本 │ ▼ 渲染成图形 / 导入文档脚本负责回答“代码里到底有什么”哪些文件、哪些模块、哪些依赖。AI 负责回答“这些东西该怎么组织”哪些模块应该归到同一层、哪些依赖应该被忽略、模块之间的职责边界怎么描述。两件事分开后幻觉空间被压到了最小。这也是本文要强调的一个点好的 AI 架构图工具不是让 AI 凭空画图而是让 AI 在真实数据的基础上画图。4. 环境准备与前置条件在开始编写 Skill 之前先确认本机环境。4.1 运行环境本文示例以 Python 3 编写扫描脚本完全使用标准库不需要安装第三方依赖。只要机器上有 Python 3.8 及以上版本即可运行。验证方式python3 --version如果没有输出或版本过低请先安装合适的 Python 版本。4.2 AI 编程助手Skill 需要运行在支持 Skill 机制的 AI 编程助手中。目前主流做法是把 Skill 放在个人配置目录下的 skills 文件夹或者项目根目录下的专用目录中。不同工具的目录位置略有差异但通用原理一致让 AI 能在对话中检索到SKILL.md。以常见做法为例先在当前项目下创建一个目录结构mkdir -p .claude/skills/arch-gen touch .claude/skills/arch-gen/SKILL.md如果你的工具不识别.claude目录也可以将 Skill 放到工具的全局 skill 目录。本文示例放在项目目录下原因是架构图生成和具体代码仓库强相关跟随项目走更方便团队共享。4.3 前置知识阅读本文只需要两个基础能力会运行命令行工具对 Python 语法有最基本的了解能看懂 import 和函数。不需要提前掌握任何深度学习或 NLP 知识。5. 完整示例从零编写一个自动出图 Skill下面我们来写一个完整的 Skill名字叫arch-gen。它的功能是扫描当前仓库的 Python 代码提取模块和依赖关系生成结构化数据再由 AI 基于这份数据输出架构图描述文本。5.1 编写 SKILL.mdSKILL.md是这个 Skill 的核心它告诉 AI 在什么情况下使用、按什么步骤执行。文件路径.claude/skills/arch-gen/SKILL.md--- name: arch-gen description: 扫描当前代码仓库提取模块结构、依赖关系与数据流向生成项目架构图。当用户要求“生成架构图”“梳理模块关系”“分析项目结构”“导出依赖图”时使用。 --- # arch-gen 你是一名架构分析助手。你的任务是基于代码扫描脚本输出的结构化数据结合对代码仓库的理解生成一份清晰的架构图描述文本。 ## 执行步骤 1. 运行扫描脚本 python3 scan_structure.py . structure.json先拿到代码的真实结构。 2. 读取 structure.json关注模块列表、依赖关系、顶层目录划分。 3. 结合仓库中的 README、目录名、入口文件判断模块的业务职责。 4. 过滤明显属于基础设施的依赖如标准库、第三方 SDK。 5. 输出架构图描述文本按以下格式组织 - 第一层系统边界和主要子系统 - 第二层模块之间的依赖关系 - 第三层值得注意的循环依赖或高风险耦合。 6. 如果代码量过大先输出整体结构再针对用户关心的局部模块深入分析。 ## 输出约定 - 图描述文本使用节点和箭头的文本格式例如 模块A -- 模块B - 每个箭头上尽量补充一行简短说明解释为什么存在该依赖 - 对循环依赖问题用“风险提示”单独标记 - 不要编造代码中不存在的模块。5.2 编写代码结构扫描脚本扫描脚本的作用是解析代码文件提取 import 关系。以 Python 项目为例可以用标准库ast解析语法树。文件路径.claude/skills/arch-gen/scan_structure.py#!/usr/bin/env python3 scan_structure.py - 扫描代码目录提取模块与依赖关系 import ast import json import sys from pathlib import Path def scan_python_file(file_path: Path): 解析 Python 文件提取 import 语句 try: tree ast.parse(file_path.read_text(encodingutf-8)) except (SyntaxError, UnicodeDecodeError): # 语法错误或编码异常的文件直接跳过不影响整体扫描 return None imports [] for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: imports.append(alias.name) elif isinstance(node, ast.ImportFrom): module node.module or imports.append(module) return { file: str(file_path), imports: sorted(set(imports)), } def main(root_dir: str): result {modules: [], dependencies: []} ignore_dirs {venv, .venv, __pycache__, node_modules, .git, dist, build} for path in Path(root_dir).rglob(*): if not path.is_file() or path.suffix ! .py: continue if any(part in ignore_dirs for part in path.parts): continue parsed scan_python_file(path) if parsed: result[modules].append(parsed) print(json.dumps(result, indent2, ensure_asciiFalse)) if __name__ __main__: root sys.argv[1] if len(sys.argv) 1 else . main(root)这个脚本做了四件事遍历目录、跳过常见依赖目录、解析每个 Python 文件的 import、把结果输出成 JSON。它的优势是零依赖、速度足够快几万行的仓库通常几秒内就能扫完。5.3 编写架构图生成脚本拿到structure.json之后可以用第二个脚本把 JSON 转换成节点和边的文本描述。这个描述既可以作为给 AI 的输入也可以直接被支持文本导入的绘图工具识别。文件路径.claude/skills/arch-gen/generate_arch.py#!/usr/bin/env python3 generate_arch.py - 读取扫描结果生成架构图文本描述 import json import sys from collections import defaultdict def normalize_module(import_name: str) - str: 把 import 名归一为顶层模块 if not import_name: return unknown return import_name.split(.)[0] def generate(json_path: str): with open(json_path, encodingutf-8) as f: data json.load(f) edges defaultdict(set) modules set() for item in data.get(modules, []): file item[file] # 以仓库根目录第一级目录作为模块边界 module file.split(/)[0] modules.add(module) for imp in item.get(imports, []): target normalize_module(imp) if target and target ! module: edges[module].add(target) lines [] lines.append(# 模块节点) for m in sorted(modules): lines.append(fnode {m}) lines.append() lines.append(# 依赖关系) for src, targets in edges.items(): for tgt in sorted(targets): if tgt in modules: lines.append(fedge {src} -- {tgt}) else: lines.append(fedge {src} -- EXTERNAL ({tgt})) print(\n.join(lines)) if __name__ __main__: generate(sys.argv[1])这个脚本先把 import 名归一成顶层模块再判断被依赖的模块是内部模块还是外部依赖最后输出统一格式的文本。注意这里的模块边界定义是“仓库根目录下的第一级目录”这是一个简单但有效的默认规则你可以根据项目情况改成包名、分层目录或业务子域。5.4 在 AI 编程助手中加载并使用 Skill完成以上三个文件后Skill 目录结构如下.claude/skills/arch-gen/ ├── SKILL.md ├── scan_structure.py └── generate_arch.py在项目根目录启动 AI 编程助手然后直接提问使用 arch-gen 技能分析当前项目的整体架构生成一张架构图如果 AI 支持自动触发 Skill它会读取SKILL.md先运行扫描脚本再读取 JSON 结果最后输出架构图描述。为了确认脚本真的被调用也可以在对话里手动指定执行步骤python3 scan_structure.py . structure.json python3 generate_arch.py structure.json arch.txtarch.txt就是脚本侧的确定性产物。AI 只需要在这个文本基础上做业务语义补充就能生成比“纯读代码”更靠谱的架构描述。6. 运行结果与效果验证6.1 预期输出假设项目根目录下有api、core、worker、common四个模块且api依赖corecore依赖common扫描脚本生成的structure.json片段大致如下{ modules: [ { file: api/main.py, imports: [core.service, fastapi] }, { file: core/service.py, imports: [common.utils, sqlalchemy] } ], dependencies: [] }generate_arch.py输出的arch.txt大致如下# 模块节点 node api node common node core # 依赖关系 edge api -- core edge core -- common edge api -- EXTERNAL (fastapi) edge core -- EXTERNAL (sqlalchemy)AI 拿到这份文本后会补上模块职责说明并输出类似这样的一张图系统边界 - api对外提供 HTTP 接口 - core核心业务逻辑 - worker异步任务处理 - common公共工具与配置 依赖关系 - api -- core接口层调用业务层 - core -- common业务层使用公共工具 - worker -- core任务处理复用业务能力这种格式已经可以直接粘贴到支持节点边文本的文档工具中渲染也可以交给其他绘图工具转换成项目团队习惯的模型格式。6.2 如何判断生成结果是否正确验证架构图是否靠谱重点不在图形是否美观而在三点模块是否和代码真实结构一致对照structure.json确认图里的模块都能在仓库中找到依赖方向是否准确顺着代码调用关系抽查几条关键箭头确认方向没有反没有幻觉模块图里不应出现代码中不存在的服务或中间件。如果 AI 在输出里添加了代码中不存在的模块请让它删除并把这种情况反馈到SKILL.md的约束规则里下次避免。6.3 验证失败时的第一步排查如果脚本执行失败先看两个方面是否在当前正确目录下运行脚本默认扫描当前目录请在代码仓库根目录执行是否真的有 Python 文件如果项目是 Java、Go 或前端项目本示例脚本不适用需要把scan_structure.py换成对应语言的解析脚本。7. 常见问题与排查思路问题现象可能原因排查方式解决方案AI 没有触发 Skilldescription里没有覆盖用户问法或工具不支持自动触发检查SKILL.md的描述字段查看工具是否已识别技能目录在提问中显式写出技能名或调整描述加入更多触发词架构图缺少关键模块扫描脚本忽略了某些目录或语言打开structure.json查看模块列表调整扫描范围支持更多文件后缀补充分层规则依赖关系过于杂乱第三方库和内部模块没有区分查看arch.txt中EXTERNAL标记的数量在生成脚本中维护一张内部模块白名单过滤基础设施依赖输出与代码不一致AI 在补充语义时脑补了不存在的模块对照structure.json逐条核对在SKILL.md中强调“所有节点必须来自扫描结果”扫描大仓库耗时过长扫描了依赖目录或无关文件查看脚本是否遍历了 ignore 目录完善 ignore_dirs把构建产物、缓存放进忽略列表动态 import 无法解析Python 动态加载的模块不在静态 import 中检查代码是否存在__import__、importlib用法在SKILL.md中要求 AI 结合代码行为补充动态依赖说明8. 最佳实践与工程建议8.1 扫描脚本保持零依赖架构图 Skill 的脚本越简单越好。最理想的状态是完全使用标准库实现这样任何人克隆仓库后都能立刻运行不用安装额外依赖。凡是能用正则、语法树和文件遍历解决的问题尽量不要引入第三方库。8.2 分层输出先整体后局部大项目的架构图不应该“一张图画完”。更合理的做法是让 AI 按照 C4 模型逐层输出先出系统上下文再出容器图最后深入到模块组件层。每一层控制在 7 到 10 个节点以内超出部分继续往下钻取。这比一张巨图更容易维护也更容易审查。8.3 架构图定义文本应收录进代码仓库架构图应该和代码放在同一个仓库并且每一次重新生成后都提交一次变更。这样做了之后架构图的变更记录和代码变更记录对齐Code Review 时可以直接看到“这次改动影响了哪些模块依赖”。这比把图存在共享文档里更能反映真实系统状态。8.4 对 AI 的约束要写进行规则SKILL.md中关于“不要编造模块”的约束必须明确。AI 生成架构图时最常见的错误不是分析能力不足而是“过度补全”。建议在规则中明确所有节点必须能在扫描结果中找到所有箭头必须有代码依据无法确定的关系标注为“待确认”不要默认成立。8.5 关注循环依赖和耦合风险架构图的价值不只是展示现状更重要的是暴露问题。团队可以约定在SKILL.md中要求 AI 特别标注循环依赖、双向依赖和“上帝模块”。这些信息对架构治理非常有用也是人工画图时最难持续跟踪的部分。8.6 安全与权限边界scan_structure.py是只读操作不会修改任何源文件。引入到 CI 流程时建议使用最小权限的只读账号运行并限制扫描目录范围避免扫描到敏感配置目录。架构图生成结果如果包含内部系统名称、数据库信息和部署节点注意不要发布到公开场合。9. 总结与后续学习方向这篇文章的核心观点可以概括成一句话架构图自动化不应该依赖 AI 凭空生成而应该让 AI 在脚本扫描出的真实数据之上进行理解和组织。动手实践时建议从一个小项目开始按下面三步走复制SKILL.md和两个 Python 脚本到个人项目的.claude/skills/arch-gen/目录在一个 10 到 20 个文件的模块上跑通扫描流程图对比手画架构图与 AI 输出的差异把生成结果提交到仓库下次代码迭代后再生成一次感受“图随代码更新”的维护成本变化。如果你想继续深入可以从这几个方向展开为 Java 项目编写基于字节码分析的扫描脚本用依赖图算法做模块耦合度量化把架构图生成接入 CI在每次合并请求中自动更新架构文档或者把架构分析结果和索引服务打通实现全仓库的实时可视化。架构图永远不是一次性的交付物而是一个不断演化的系统最直接的结构快照。让 AI 帮你读代码、出草图、标风险你才有精力做更重要的判断这个架构该往哪里走哪些债务该还了。