这两年 AI 写代码的能力已经足够让团队产出速度翻倍但有一个问题我见很多人没讲清楚AI 造代码的速度越快项目的“架构理解成本”就越高。生成一个新函数很容易但要搞清楚这个函数该放哪个模块、它会被谁调用、改了它会不会把订单服务搞挂靠人肉看几十万行代码成本极高。于是工具链里出现了两个值得关注的方向一类是终端里的 AI 代理解决“怎么让机器按指令干活”另一类是架构分析与归档工具解决“让存量代码变成可检索、可解释、可演进的结构化资产”。我习惯把它们合称tt-a1i / archify这样的组合——前者负责自动化任务后者负责把代码仓库变成一个“活文档”。这篇内容不打算写成一个具体产品的完整评测原因很简单关于这两个名字的公开资料非常有限硬要编一个“官方文档式”的教程反而没价值。更稳妥的做法是把它当成一个技术方向来拆解AI 辅助架构分析到底要解决什么问题怎么落地有哪些坑以及一套可以照着跑的最小原型。读完你会知道这类工具适合用在哪、不适合用在哪也能在自己的项目里快速验证“代码归档 AI 摘要”这条链路是否值得投入。1. 这篇文章真正要解决的问题先抛一个判断AI 辅助开发的下半场不是“写代码”而是“理解代码”。现在很多团队已经接受了 AI 结对编程提交速度确实快了。但代码合并只是第一步。三周后你要改一个核心模块却发现不知道哪些服务依赖它六个月后新人入职光是用 IDE 逐层跳转理解业务链路就需要两到三周一年后架构腐化严重谁都不敢动老代码因为改动一个工具方法可能牵连十几个线上服务。这些问题恰恰是 AI 编程助手没有解决的。Copilot 能告诉你“这段代码怎么写”但它不会主动告诉你“你正在写的这段代码和三个月前那个紧急修复之间有什么微妙关系”。这和“能写”是两码事。tt-a1i / archify这类组合本质上是想补上这个缺口tt-a1i这类终端 AI 代理负责把“人用自然语言下达的命令”变成“可重复执行的工程任务”比如扫描代码、生成报告、定位模块边界。archify这类架构归档引擎负责把仓库里的文件、模块、依赖、调用关系抽取成结构化数据再生成人类可读的架构文档。换句话说它们要解决的核心问题是让项目从“只有代码能说话”变成“代码 结构化档案 AI 解释一起说话”。什么样的读者最该关注这条链路负责遗留系统维护的工程师每天要做大量代码考古。微服务团队的架构师想知道服务边界是否还清晰。做工程效能的人想减少新人 onboarding 成本。以及所有正在使用 AI 生成大量代码、担心技术债失控的开发者。2. 基础概念与核心原理2.1 什么是“架构归档”传统意义的“归档”是打包存档但这里不是。archify代表的“架构归档”是把一个项目的结构信息抽取出来变成可持久化、可检索、可对比的资产。一次完整的架构归档至少包含四层信息层级内容示例文件层目录结构、文件规模、语言类型src/main/java/com/example/OrderService.java依赖层模块间的 import、require、调用关系OrderService - PaymentClient逻辑层主要的类、函数、接口、路由定义POST /order/{id}/pay - OrderController.pay()语义层模块职责、调用意图、关注点支付模块负责订单支付状态流转与第三方渠道对接前两层是静态分析就能拿到的难度低第三层需要更精细的 AST 分析第四层过去基本靠人写文档现在可以交给 AI 模型生成初步摘要再由人来确认。2.2 什么是“终端 AI 代理”tt-a1i在我理解中是一个更通用的“终端任务代理”。它不是某个具体的命令行工具而是一类设计模式接收自然语言目标比如“找出 order 模块里没有被任何接口引用的死代码”。拆解为可执行步骤扫描目录、解析依赖、分析调用链、生成报告。调用本地工具或外部模型完成子任务。把结果整理成人类可读的结论并记录执行过程方便复现。这里真正容易踩坑的地方是很多人把终端 AI 代理理解成“用自然语言包装 shell 命令”以为能执行几条命令就算完成。实际上它最难的部分是“目标拆解”和“结果验证”。AI 告诉你“这个模块没有外部引用”你怎么确认它说的是对的这就需要 archify 提供结构化的调用关系数据让 AI 的结论可以被交叉验证。2.3 两者结合的价值没有tt-a1i时archify 的分析结果需要一个工程师读懂报告再决定下一步动作没有archify时AI 代理只能凭大概印象回答“这个项目是干什么的”基本上是在猜。两者结合形成一条闭环代码仓库 - 静态扫描 - 结构化归档 - AI 摘要 - 人工确认 - 知识沉淀这也是我判断这类工具组合会越来越重要的原因它把“AI 生成结论”和“代码真实结构”绑定在一起让 AI 的每个判断都有据可查而不是只靠模型记忆。3. 适用场景与边界3.1 最适合用在哪遗留系统维护。我见过很多老项目文档早就过期了唯一可信的信息源就是代码本身。但几十万行代码靠人读不现实。用 archify 先扫描出模块依赖再让 AI 逐个模块生成职责摘要最后有一位熟悉业务的人核对一遍两周的代码考古可以压缩到两三天。新人 onboarding。新人进组最痛苦的不是看不懂某个语法而是不知道“业务入口在哪、核心链路怎么走”。把架构归档报告作为培训材料效果比散落的 wiki 好得多因为它是直接从当前代码生成的不会有过期问题。AI 生成代码的审计。既然 AI 在快速生成代码我们就需要一种同样快速的“逆向工程”能力。每次 AI 生成一批代码跑一次归档扫描看看它引入了多少新的依赖、是否把不该耦合的模块挂在了一起。没有这一步AI 生成代码越多架构腐化越快。3.2 它不适合解决什么问题不能替代代码 review。AI 生成的摘要可能有幻觉尤其当我们用外部大模型时模型可能写出它“认为合理”但实际不存在的逻辑。不能替代真正的运行时观测。静态分析只能看到“代码里写了什么”看不到运行时 QPS、延迟、异常率这些真实健康度指标。不能自动修复架构问题。它会告诉你“这里出现了循环依赖”但怎么拆还是要人来决策。4. 环境准备与前置条件接下来我们用一个小型 Python 项目示范“架构扫描 AI 摘要 归档报告”的核心流程。你可以把它当成archify这个方向的轻量原型跑通之后再迁移到完整工程化实现。4.1 运行环境操作系统Windows / macOS / Linux 均可以下命令以 macOS 和 Ubuntu 为准。Python3.10 及以上。建议使用虚拟环境避免污染系统 Python。包管理工具pip 即可。AI 模型服务可选如果你本地有 Ollama或者有 OpenAI 兼容接口可以跑通“AI 摘要”部分没有也不影响基础归档功能。4.2 项目初始化mkdir archify-demo cd archify-demo python3 -m venv .venv source .venv/bin/activate创建一个需求文件# 文件路径requirements.txt rich13.0.0 requests2.31.0这里rich用于终端彩色输出requests用于调用 AI 模型接口。如果只是观察目录结构和依赖关系甚至不需要这两个依赖但加上它们能让演示更接近真实工具。安装依赖pip install -r requirements.txt版本以实际安装为准本文重点演示通用思路不绑定某个特定版本组合。4.3 准备一个待分析的示例项目我们要分析的对象不能太简单。先在archify-demo下创建一个sample_project目录模拟一个电商项目的最小结构sample_project/ ├── README.md ├── app/ │ ├── __init__.py │ ├── main.py │ ├── order/ │ │ ├── __init__.py │ │ ├── models.py │ │ ├── service.py │ │ └── views.py │ └── payment/ │ ├── __init__.py │ ├── client.py │ └── webhook.py ├── libs/ │ └── common/ │ ├── __init__.py │ ├── utils.py │ └── logger.py └── tests/ ├── test_order.py └── test_payment.py这里的核心依赖关系预期是order/service.py引用payment/client.py。payment/webhook.py引用order/models.py。app/main.py引用order/service.py和payment/webhook.py。这样就有了一个足够复杂、包含跨模块依赖和小循环引用的示例。5. 核心流程拆解架构归档工具的核心流程可以分成四步扫描、解析、归档、生成摘要。下面逐一拆解。5.1 扫描文件树第一步把项目目录里所有需要关注的文件找出来。这里的关键是支持忽略规则否则会把.venv、node_modules、__pycache__这种目录扫进来报告会非常脏。关键逻辑递归遍历目录。跳过隐藏目录、常见虚拟环境目录和缓存目录。按文件后缀过滤只保留 Python 源码也可以扩展为支持 Java、TS、Go。这一步做错会出现的问题把虚拟环境或构建产物当成业务代码依赖分析时产生大量噪音。真实项目中必须维护一份合理的.archifyignore文件类似.gitignore的语义。5.2 解析导入关系Python 项目可以通过 AST 解析源码找出import x和from x import y语句确定模块之间的依赖。这是最核心的一步。这里有一个重要的替代方案生产级工具建议使用tree-sitter或jedi等成熟的解析库而不是正则表达式。正则只能应付简单场景遇到多行导入、动态导入、别名导入会漏掉大量关系。我们下面给出的最小原型为了减少依赖先用正则配合 AST 做基础解析并明确标注“示例级实现”。5.3 结构化归档把上一步的依赖关系整理成 JSON 或 Markdown形成报告的原始数据。JSON 适合机器读取和后续对比Markdown 适合人类阅读。真实工具通常两者都生成。归档文件需要包含以下字段项目路径和快照时间。文件清单。每个文件的依赖项。模块之间的总依赖矩阵。循环依赖提示如果发现 A 依赖 B、B 又依赖 A。这一步的价值是“可复现”。今天扫一次三个月后再扫一次两份 JSON 对比就能看出依赖新增了多少、有没有出现可疑的跨层调用。5.4 调用 AI 生成模块摘要有了结构化数据可以把文件清单、依赖关系、关键函数列表拼接成提示词调用本地或云端大模型生成“模块职责摘要”。这里要特别提醒安全边界不要把未脱敏的代码直接发给外部 API。如果你的项目属于公司核心业务、涉及敏感逻辑优先使用本地模型如 Ollama 部署的 Qwen、Llama 系列或者对代码做变量名脱敏后再发送。从工程实践看模块摘要任务对模型的推理能力要求不高只需要理解“这个模块在业务链路上大概处于哪个位置”用 7B 到 14B 的本地模型通常就能完成。6. 完整示例代码实现下面给出一个可以直接运行的简化版archify.py。它实现扫描、AST 依赖解析、JSON 和 Markdown 报告生成并预留 AI 摘要接口。# 文件路径archify-demo/archify.py import argparse import ast import json import os from datetime import datetime, timezone from pathlib import Path from typing import Dict, List, Set # 默认忽略目录 IGNORE_DIRS { .git, .svn, .hg, .venv, venv, env, __pycache__, node_modules, dist, build, .idea, .vscode, } # 需要分析的源码后缀 SOURCE_SUFFIX {.py} def scan_files(root: Path) - List[Path]: 递归扫描项目目录返回所有源码文件路径。 files [] for dirpath, dirnames, filenames in os.walk(root): # 就地过滤忽略目录 dirnames[:] [d for d in dirnames if d not in IGNORE_DIRS] for filename in filenames: path Path(dirpath) / filename if path.suffix in SOURCE_SUFFIX: files.append(path) return sorted(files) def parse_imports(file_path: Path) - Set[str]: 用 AST 解析 Python 文件中的 import 语句返回模块名集合。 imports set() try: tree ast.parse(file_path.read_text(encodingutf-8)) except (SyntaxError, UnicodeDecodeError) as exc: # 解析失败时记录提示但不中断整个归档过程 print(f [warn] 无法解析 {file_path}: {exc}) return imports for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: imports.add(alias.name) elif isinstance(node, ast.ImportFrom): if node.module: imports.add(node.module) # 处理 from . import xxx 这种相对导入 if node.level: imports.add(. * node.level (node.module or )) return imports def build_dependency_map(files: List[Path], root: Path) - Dict[str, Set[str]]: 构建 文件路径 - 依赖文件路径 的映射。 deps: Dict[str, Set[str]] {} module_to_file: Dict[str, List[str]] {} # 第一遍建立模块名到文件路径的索引 for file in files: rel file.relative_to(root) # 把路径当作模块名例如 app/order/service.py - app.order.service module_name ..join(rel.with_suffix().parts) module_to_file.setdefault(module_name, []).append(str(rel)) # 同时支持包目录下的 __init__.py 映射到包名 if file.name __init__.py: pkg_module ..join(rel.parent.parts) module_to_file.setdefault(pkg_module, []).append(str(rel)) # 第二遍逐个文件解析 import转成文件级依赖 for file in files: rel file.relative_to(root) deps[str(rel)] set() imported_modules parse_imports(file) for mod in imported_modules: # 只保留项目内能被解析到的依赖 if mod in module_to_file: for target_file in module_to_file[mod]: deps[str(rel)].add(target_file) return deps def find_cycles(deps: Dict[str, Set[str]]) - List[List[str]]: 简单检测两点间的循环依赖A 依赖 B 且 B 依赖 A。 cycles [] items list(deps.keys()) for i, a in enumerate(items): for b in items[i 1:]: if b in deps.get(a, set()) and a in deps.get(b, set()): cycles.append([a, b]) return cycles def generate_markdown_report( root: Path, deps: Dict[str, Set[str]], cycles: List[List[str]], summary: Dict[str, str], ) - str: 生成人类可读的 Markdown 归档报告。 lines [] lines.append(f# 架构归档报告) lines.append() lines.append(f- 项目路径{root}) lines.append(f- 生成时间{datetime.now(timezone.utc).isoformat()}) lines.append(f- 源码文件数{len(deps)}) lines.append() lines.append(## 依赖概览) lines.append() lines.append(| 文件 | 依赖 |) lines.append(| --- | --- |) for file in sorted(deps): dep_str , .join(sorted(deps[file])) if deps[file] else - lines.append(f| {file} | {dep_str} |) lines.append() lines.append(## 循环依赖提示) lines.append() if cycles: for a, b in cycles: lines.append(f- {a} - {b}) else: lines.append(- 未检测到两点循环依赖。) lines.append() if summary: lines.append(## AI 模块摘要) lines.append() for module, desc in summary.items(): lines.append(f### {module}) lines.append() lines.append(desc) lines.append() return \n.join(lines) def call_ai_summary(deps: Dict[str, Set[str]], base_url: str, api_key: str, model: str) - Dict[str, str]: 调用 OpenAI 兼容接口生成模块摘要。 如果 base_url 或 api_key 为空则跳过返回空字典。 实际接入时可以把文件头部注释、关键函数签名拼进 prompt。 if not base_url or not api_key: print([info] 未配置 AI 服务跳过摘要生成。) return {} import requests summary: Dict[str, str] {} modules list(deps.keys())[:5] # 示例中只处理前 5 个文件避免耗时过长 for mod in modules: prompt ( f你是一名资深架构师。请用不超过 80 个字概括模块 {mod} 的职责。 f它的直接依赖是{list(deps[mod]) or 无}。 输出格式职责描述。 ) try: resp requests.post( f{base_url}/chat/completions, headers{Authorization: fBearer {api_key}}, json{ model: model, messages: [ {role: user, content: prompt}, ], temperature: 0.2, }, timeout15, ) resp.raise_for_status() data resp.json() summary[mod] data[choices][0][message][content].strip() except Exception as exc: print(f [warn] 生成摘要失败 {mod}: {exc}) return summary def main() - None: parser argparse.ArgumentParser(description轻量级 AI 架构归档工具) parser.add_argument(project, help要分析的项目目录) parser.add_argument(--output, default./archify-report, help报告输出目录) parser.add_argument(--ai-base-url, default, helpOpenAI 兼容接口地址例如 http://localhost:11434/v1) parser.add_argument(--ai-api-key, defaultollama, helpAPI Key本地 Ollama 可填 ollama) parser.add_argument(--ai-model, defaultqwen2.5:7b, help模型名称) args parser.parse_args() root Path(args.project).resolve() if not root.exists(): print(f[error] 项目目录不存在: {root}) return print(f[1/4] 扫描目录: {root}) files scan_files(root) print(f 共发现 {len(files)} 个源码文件) print([2/4] 解析依赖关系...) deps build_dependency_map(files, root) cycles find_cycles(deps) print([3/4] 生成架构摘要...) summary call_ai_summary( deps, base_urlargs.ai_base_url, api_keyargs.ai_api_key, modelargs.ai_model, ) print([4/4] 生成归档报告...) output_dir Path(args.output).resolve() output_dir.mkdir(parentsTrue, exist_okTrue) # 生成 JSON 结构化数据 json_data { project: str(root), generated_at: datetime.now(timezone.utc).isoformat(), files: [str(f.relative_to(root)) for f in files], dependencies: {k: sorted(v) for k, v in deps.items()}, cycles: cycles, summary: summary, } json_path output_dir / archify-report.json json_path.write_text(json.dumps(json_data, ensure_asciiFalse, indent2), encodingutf-8) # 生成 Markdown 报告 md_content generate_markdown_report(root, deps, cycles, summary) md_path output_dir / archify-report.md md_path.write_text(md_content, encodingutf-8) print(f 报告已生成) print(f - JSON: {json_path}) print(f - Markdown: {md_path}) if __name__ __main__: main()代码的关键逻辑说明scan_files通过os.walk遍历目录并利用dirnames[:] ...实现就地过滤效率比二次判断更高。parse_imports使用 Python 标准库ast能正确处理绝大多数 import 写法包括from x import y和相对导入。build_dependency_map先用遍历建立“模块名到文件路径”的索引再反向解析保证只保留项目内的依赖外部包依赖不会混入报告。call_ai_summary没有硬编码外部服务而是采用 OpenAI 兼容协议。如果你本地有 Ollama启动后把--ai-base-url指到http://localhost:11434/v1即可。报告同时输出 JSON 和 Markdown前者便于工具链读取后者方便阅读。7. 运行结果与效果验证先不接 AI 服务跑一次纯本地归档验证核心扫描逻辑是否正确。python archify.py sample_project --output ./report预期输出[1/4] 扫描目录: /Users/you/archify-demo/sample_project 共发现 10 个源码文件 [2/4] 解析依赖关系... [3/4] 生成架构摘要... [info] 未配置 AI 服务跳过摘要生成。 [4/4] 生成归档报告... 报告已生成 - JSON: /Users/you/archify-demo/report/archify-report.json - Markdown: /Users/you/archify-demo/report/archify-report.md然后打开report/archify-report.json重点检查dependencies中是否出现了app/order/service.py - app/payment/client.py。dependencies中是否出现了app/payment/webhook.py - app/order/models.py。cycles是否能检测出这两个文件之间的双向依赖。如果期望的依赖关系出现在 JSON 里说明核心解析逻辑跑通了。如果失败先按下面顺序排查确认sample_project目录存在且目录名拼写正确。确认当前 shell 在虚拟环境中python能导入rich如果安装失败可以先删除rich相关代码再跑。确认.venv没有被误扫。正常情况下IGNORE_DIRS已经排除了.venv。接下来验证 AI 摘要能力。假设本地启动了 Ollama并且已经拉取qwen2.5:7b模型python archify.py sample_project \ --output ./report \ --ai-base-url http://localhost:11434/v1 \ --ai-api-key ollama \ --ai-model qwen2.5:7b这时会在终端看到生成摘要的日志。打开archify-report.md在“AI 模块摘要”部分检查每个模块的职责描述是否与实际代码一致。AI 可能给出模棱两可的表述属于正常现象。真正需要警惕的是它描述得“过于具体”但代码里根本不存在相关逻辑这是模型幻觉需要人工校对。8. 常见问题与排查思路问题现象可能原因排查方式解决方案扫描到大量无关注释目录忽略规则不全查看 JSON 里files列表补充 IGNORE_DIRS或引入独立 ignore 文件import 解析不出依赖文件里有语法错误或动态 import查看终端 warn 日志先修复项目内语法错误或换 tree-sitter 做容错解析报告里出现外部包依赖模块名索引匹配错误对比module_to_file索引只保留能在项目内解析到的模块AI 摘要内容明显不正确模型幻觉 / 提示词缺少上下文查看该文件实际代码和依赖在 prompt 中加入文件头部注释、函数签名降低 temperature大型仓库扫描很慢全部文件都走 AST 解析统计文件数分析耗时分布按目录分片分析或只分析指定 diff 范围调用外部 API 超时模型服务未启动 / 网络不稳用 curl 测试接口连通性本地模型优先或增加超时和重试机制这里最容易犯的一个错是把 AI 摘要当成权威结果直接写进团队文档。我的建议是AI 生成的摘要必须带上“生成时间”和“模型名称”并且明确标注“AI 生成仅供参考”。一旦发现摘要和代码不一致立即修正避免错误知识在团队中扩散。9. 最佳实践与工程建议如果要把这类能力放进真实项目下面这几点建议值得参考。9.1 归档文件要纳入版本控制很多人觉得“报告是生成物不需要提交”但架构归档报告恰恰相反。它应该像package-lock.json一样被提交到仓库这样每次架构变更都能通过 diff 看到。比如一次重构后依赖矩阵变化了多少、循环依赖是否减少这些信息都在 git 历史里比事后补文档可靠得多。9.2 与 CI 流程集成更进一步的玩法是在 CI 中增加一个“架构检查”任务每次 MR 生成一份新的架构归档 JSON。与主干分支的归档对比。如果出现新增的跨层依赖、循环依赖或文件数量异常增加就自动失败或提醒 reviewer。这个机制能把架构治理前置到代码评审阶段而不是等架构腐化到不可收拾时才去补救。9.3 安全边界要前置如果你打算调用云端大模型做摘要第一原则是“先脱敏再上传”。可以做一个简单的脱敏步骤把代码里的变量名替换为var_001这类占位符。去掉字符串字面量尤其是 URL、数据库连接串、公网 IP。只发送文件路径、依赖关系、函数签名不发送函数实现。如果团队有合规要求更稳妥的做法是全部走本地模型。9.4 AI 代理的每一步都要可追溯这也是tt-a1i这类终端 AI 代理最需要注意的地方。它执行完一个任务后不能只给出“已完成”的结论必须输出执行了哪些命令。修改了哪些文件。生成了哪些数据。哪些结论来自代码分析哪些来自模型推断。否则AI 代理引入的“自动化”反而会变成新的黑盒出了问题没人知道它是怎么得出这个结论的。9.5 从小范围试点开始不要一上来就给全公司所有仓库部署。选择一个中等规模、有明确架构痛点且团队愿意配合的项目先跑两周第一周只生成归档报告不改变任何流程。第二周让两位维护者对照报告回答业务问题验证报告是否准确、够用。两周后根据反馈调整忽略规则、摘要粒度再决定是否推广。10. 总结与后续学习方向从tt-a1i / archify这个组合里我能看到一个明确的技术趋势AI 编程工具正在从“帮你补全代码”走向“帮你理解、治理和沉淀代码”。终端 AI 代理解决的是任务的自动化执行架构归档引擎解决的是代码结构的信息化表达两者结合才可能真正解决“AI 造代码越快架构越难维护”这个悖论。如果你也想在自己的项目里验证这条链路最务实的路径是先把架构扫描跑起来生成一份 JSON 归档然后接入本地模型生成模块摘要最后让团队里最熟悉业务的同事校对一遍。不要一开始就追求什么自动生成整套架构文档先把“代码结构可见”这件事做到位。下一阶段值得深入的方向包括用 tree-sitter 替换正则与 AST支持 Java、TypeScript、Go 等多语言解析。把归档结果接入 IDE 插件实现“点击模块即可查看依赖图谱和 AI 摘要”。在 CI 中建立架构 diff 检查让每次 MR 都自动评估架构影响面。把多模块、多服务的归档结果汇总成企业级系统架构资产配合运行时指标做成架构健康度看板。先说这么多建议收藏备用。真正的难点不在于写一个扫描工具而在于让一个团队长期坚持“代码提交后生成归档、评审时看架构影响面”这个习惯。工具只是把这件事变得足够便宜最终能不能起作用还是取决于流程和人的配合。