ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Understand-Anything 的 /understand 流水线 Token 成本削减:C1–C5 五项优化的实施蓝图与仓库落地

2026/9/6 17:43:38 拓冰建站 浏览量
Understand-Anything 的 /understand 流水线 Token 成本削减:C1–C5 五项优化的实施蓝图与仓库落地 Understand-Anything 的 /understand 流水线 Token 成本削减C1–C5 五项优化的实施蓝图与仓库落地【免费下载链接】Understand-AnythingGraphs that teach graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.项目地址: https://gitcode.com/GitHub_Trending/un/Understand-Anything本文基于 Understand-Anything 仓库中的实施计划 2026-03-27-token-reduction-impl.md 展开解析该计划如何通过导入预解析、批次合并、附录移除、payload 瘦身和 LLM 审核器门控这五项改动将/understand命令在大型代码库上的 token 成本削减约 85%。读完本文你将掌握每一项优化C1–C5的具体任务拆解、参数变更与验证手段并能对照当前仓库源码了解这些机制如importMap、batchImportData、--review门控、内联校验脚本最终在代码中的实际形态。1. 背景/understand 的 token 成本花在了哪里/understand是 Understand-Anything 的核心技能它扫描整个代码库分阶段Phase 0–7调度多个 LLM 子代理file-analyzer、architecture-analyzer、tour-builder、graph-reviewer 等最终产出一个可交互的知识图knowledge-graph.json供 dashboard 展示。整个流水线由 SKILL.md 这份 Markdown 编排文件驱动。该计划配套的设计文档 2026-03-27-token-reduction-design.md计划中引用路径docs/plans/2026-03-27-token-reduction-design.md已随目录迁移实际位于docs/superpowers/specs/给出了一个 500 文件 TypeScriptReact 项目的基线 token 拆解来源阶段Token输入占比allProjectFiles列表 × 67 个批次Phase 2~167,000~50%file-analyzer-prompt.md模板 × 67 个批次Phase 2~134,000~40%语言/框架附录 × 67 个批次Phase 2~68,000~20%Tour builder payload全量节点边Phase 5~80,000~24%Graph reviewer完整图文件清单Phase 6~58,000~17%Architecture analyzer payloadPhase 4~22,000~7%合计~529,000根因一句话概括Phase 2 以每批 5–10 个文件切出 67 个批次而每个批次都被独立注入了完整的 500 文件列表仅用于各自的导入路径解析——同一份数据被重复发送了 67 次而这份解析工作本身是完全确定性的。优化目标因此设定为在 500 文件项目上削减 85% 输入 token同时不降低图谱质量、保留--full/增量/scope 参数、保持knowledge-graph.json输出 schema 向后兼容。2. 优化总览五项改动与实施顺序计划把方案拆成五个相互独立、可单独发布的改动C1–C5并按风险从低到高的顺序上线改动内容针对的浪费预估节省C5LLM graph-reviewer 改为--review门控默认走内联确定性校验每次运行固定支付 ~58,500 token 的审核成本~58,500C4瘦身 Phase 4架构分析与 Phase 5tour 构建的注入 payload全量节点/全类型边/完整 layer 对象被注入~121,500C3从 file-analyzer 批次中移除语言/框架附录改用内联速查表每个批次重复注入 ~1,300 token 附录~23,000C1扫描器预解析导入importMap写入scan-result.json批次只收batchImportData切片全量文件列表 × N 批次~154,100C2批量大小 5–10 → 20–30 文件并发 3 → 5模板与调度开销随批次数线性放大~94,000叠加 C1计划将全部工作组织为 9 个任务每个任务独立提交各带一条perf(understand): ...或chore提交信息风险分布与依赖关系如下表源自计划末尾的 Summary 小节任务改动风险Task 1C5: 门控 reviewer低Task 2C4a: 瘦身 Phase 4 payload低Task 3C4b: 瘦身 Phase 5 payload低Task 4C3: 批次去附录低Task 5C1a: 扫描器导入解析中Task 6C1b: file-analyzer 改用 batchImportData中Task 7C1cC2: SKILL.md 编排 批量大小中Task 8版本号同步低Task 9冒烟测试—其中 Tasks 1–4 彼此独立可与 Tasks 5–7 分开发布而 Task 5、6、7 构成一条紧耦合的链路扫描器产出importMap→ SKILL.md 按批次切出batchImportData→ file-analyzer 直接消费必须一起上线。3. C5Task 1把 LLM 审核器关进--review门后面3.1 动机Phase 6REVIEW原本总是调度 LLM graph-reviewer 子代理去读取完整的 assembled graph~500 节点、全部边、layers、tour做质量审核。但设计文档指出这个审核流程的Phase 1其实完全是一个确定性脚本Phase 2只是一个阈值判断——issues.length 0就通过。Happy path 上没有任何需要 LLM 判断的地方却要为它支付约 58,000 输入 500 输出的 token。3.2 方案默认内联校验 --review才走 LLM计划修改 SKILL.md 的 Phase 6检查$ARGUMENTS中是否有--review标志然后走两条路径之一。默认路径无--review写入并执行一个内联 Node.js 校验脚本输出{ issues, warnings, stats }到review.json。计划给出的完整脚本逻辑如下核心校验项#!/usr/bin/env node const fs require(fs); const graphPath process.argv[2]; const outputPath process.argv[3]; try { const graph JSON.parse(fs.readFileSync(graphPath, utf8)); const issues [], warnings []; const nodeIds new Set(); const seen new Map(); // 1) 节点必填字段id / type / name / summary / tags 缺一记为 issue graph.nodes.forEach((n, i) { if (!n.id) { issues.push(Node[${i}] missing id); return; } if (!n.type) issues.push(Node[${i}] ${n.id} missing type); if (!n.name) issues.push(Node[${i}] ${n.id} missing name); if (!n.summary) issues.push(Node[${i}] ${n.id} missing summary); if (!n.tags || !n.tags.length) issues.push(Node[${i}] ${n.id} missing tags); if (seen.has(n.id)) issues.push(Duplicate node ID ${n.id} at indices ${seen.get(n.id)} and ${i}); else seen.set(n.id, i); nodeIds.add(n.id); }); // 2) 边的 source/target 必须指向真实存在的节点 graph.edges.forEach((e, i) { if (!nodeIds.has(e.source)) issues.push(Edge[${i}] source ${e.source} not found); if (!nodeIds.has(e.target)) issues.push(Edge[${i}] target ${e.target} not found); }); // 3) 文件级节点必须恰好属于一个 layer缺层 / 多层冲突均记 issue // 4) tour 每一步引用的 nodeId 必须存在 // 5) 无边的节点记为 warningorphan不阻塞 const stats { totalNodes, totalEdges, totalLayers, tourSteps, nodeTypes, edgeTypes }; fs.writeFileSync(outputPath, JSON.stringify({ issues, warnings, stats }, null, 2)); process.exit(0); } catch (err) { process.stderr.write(err.message \n); process.exit(1); }执行命令与失败处理策略node $PROJECT_ROOT/.understand-anything/tmp/ua-inline-validate.js \ $PROJECT_ROOT/.understand-anything/intermediate/assembled-graph.json \ $PROJECT_ROOT/.understand-anything/intermediate/review.json脚本非零退出时读取 stderr、修复脚本并重试一次。--review路径则保持原样读取 graph-reviewer 提示模板附加 Phase 1 文件清单{path, sizeLines}列表与 Phase 2–5 累积的警告并要求子代理做交叉验证——扫描清单中的每个文件都应有对应file:节点图中filePath不在清单里的节点也要被标记。两条路径共用后处理逻辑若issues非空执行自动修复删除悬空边、用合理默认值填充缺失字段——空tags→[untagged]、空summary→No summary available、删除非法类型节点修复后重跑校验若一次修复后仍有严重问题则照常保存图谱但在最终报告中带上警告并跳过 dashboard 自动启动。3.3 仓库中的现状当前仓库的 SKILL.md 中--review已是一级选项Run full LLM graph-reviewer instead of inline deterministic validationPhase 6SKILL.md#L572-L731与计划完全同构且有两点后续演进值得注意内联脚本落盘文件名从计划中的ua-inline-validate.js变为ua-inline-validate.cjs数据目录也泛化为$UA_DIR.ua/或已存在时沿用旧的.understand-anything/文件级节点的判定从仅type file扩展为一个类型集合[file, config, document, service, pipeline, table, schema, resource, endpoint]——因为节点体系后来扩展到了 13 种类型配置、文档、基础设施文件同样要求必须恰好属于一个 layer。4. C4Task 2–3瘦身 Phase 4 与 Phase 5 的注入 payload4.1 C4aPhase 4 节点字段裁剪Phase 4architecture-analyzer负责架构分层。计划将其 dispatch prompt 中的文件节点格式从[list of {id, name, filePath, summary, tags} for all file-type nodes]改为[list of {id, filePath, summary, tags} for all file-type nodes — omit name, complexity, languageNotes]理由name恒等于filePath的 basename可推导complexity与languageNotes对分层决策无用。预计每个节点少 15–20% tokenPhase 4 合计省 3,000–5,000 token。4.2 C4bPhase 5 三处裁剪最大单项收益Phase 5tour-builder原本收到全部节点含 function/class、全部边类型、完整 layer 对象含nodeIds数组。计划做了三处裁剪数据改造前改造后节点全量500 文件项目约 1,500 节点~67,500 token仅 file 类型500 节点~15,000 token节点字段{id, name, filePath, summary, type, tags, complexity, languageNotes?}{id, name, filePath, summary, type}边全部类型3,000 条~60,000 token仅imports与calls~400–800 条~12,000 tokenLayers{id, name, description, nodeIds: [...]}{id, name, description}丢弃 nodeIds依据是 tour 本身只在文件粒度导航步骤引用的是file:节点 IDBFS 遍历只走imports/calls边layer 数据只用于叙事弧线的先后顺序——nodeIds大数组对 tour 设计没有价值。Phase 5 合计从 ~132,500 降到 ~27,500 token单项节省 ~105,000。计划同时要求同步更新tour-builder-prompt.md的输入 schema 示例layers 去掉nodeIds、nodes 标注 file-type only并在 Node Summary Index 一节补一句说明输入节点仅含 file 类型索引表也只含文件节点。仓库现状提示模板文件已演化为 agent 定义文件tour-builder.md 等。从当前 SKILL.md#L518-L539 看Phase 5 payload 保持了不注入 function/class 节点、layers 省略 nodeIds这两条核心裁剪但节点范围从仅file:类型扩大到所有文件级节点config、document、service 等边也改回注入全部类型——这是计划落地后针对知识图覆盖非代码资产这一新能力做出的后续平衡调整说明 payload 瘦身与图谱完整度之间经历了二次调参。5. C3Task 4移除批次附录换成一次性速查表5.1 动机languages/typescript.md~600 token与frameworks/react.md~700 token这类附录文件原本被注入到每一个file-analyzer 批次的 prompt 里成本是 ~1,300 token × N 批次。而模型对这些主流语言已有深入训练知识逐批次重复注入是低效的。5.2 方案SKILL.md Phase 2的 Build the combined prompt template 块从三步读基础模板 → 按语言注入./languages/id.md→ 按框架注入./frameworks/id.md收缩为一步——只读基础模板明确Phase 2 批次禁止追加附录文件附录保留给 Phase 4只有一次子代理调用成本可接受。dispatch 的附加上下文里也删除 Frameworks detected 行。file-analyzer-prompt.md在 Critical Constraints 之前插入紧凑的 Language and Framework Quick Reference 段~150 token只付一次用两张速查表捕捉附录里最高信号量的模式Tag 信号信号应打的标签文件在hooks/下导出以use开头的函数hook,service文件在contexts/或context/下导出 Provider 组件service,state文件在pages/或views/下ui,routing文件在store/、slices/、reducers/、state/下state文件在services/、api/、client/下service包根目录带再导出的__init__.pyentry-point,barrel项目根的manage.pyentry-point目录中的mod.rsbarrelcmd/子目录下的main.goentry-pointEdge 信号模式应建的边React 组件在 JSX 中渲染另一组件父→子contains组件/hook 调用自定义 hookuseX消费方→hook 文件depends_onContext provider 包裹组件provider→context 定义publishes组件调用useContext或自定义 context hook消费方→context 定义subscribesPythonfrom x import yx 为项目内文件imports与 JS/TS 同规则Goimport内部包路径指向解析文件的imports验证要求Phase 2 的附录注入步骤必须彻底消失而 Phase 4 的同名块必须保持不变——仓库现状印证了这一点SKILL.md#L420-L424 的 Phase 4 仍然完整执行语言上下文注入与框架附录注入。6. C1Task 5–6扫描器预解析导入importMap 贯穿全流程这是整个方案中数据流改动最大的一项导入解析只应做一次在 Phase 1且是确定性工作而不是在 67 个批次里各做一次。6.1 C1a扫描器新增 Step 8 — Import Resolution计划为扫描脚本要求新增一步对每个源文件抽取并解析相对导入产出importMap写进scan-result.json。各语言的抽取模式语言导入模式TypeScript/JavaScriptimport ... from ./.../../require(./...)Python仅相对导入from .x import y、from ..x import yGoimport (...)块中以go.modmodule 路径开头者Rustuse crate::、use super::、mod xJava/Kotlin无法按路径解析——跳过Rubyrequire_relative ...解析规则相对导入从导入方所在目录解析无扩展名时按序尝试.ts、.tsx、.js、.jsx、/index.ts、/index.js、/index.tsx、/index.jsx、.py、.go、.rs、.rb解析结果必须存在于已发现文件列表中才记录否则视为外部/动态导入而跳过。输出格式与约束importMap: { src/index.ts: [src/utils.ts, src/config.ts], src/utils.ts: [], src/components/App.tsx: [src/hooks/useAuth.ts, src/store/index.ts] }键为项目相对路径与files[*].path对齐值为已解析的项目内路径文件清单中的每个文件都必须有键无导入则为[]外部包一律不出现。同时要求最终组装阶段不得丢弃importMap原 IMPORTANT 注记追加所有其他字段——包括importMap——必须原样保留。6.2 C1bfile-analyzer 输入 schema 换血file-analyzer 的输入从全量文件列表 本批文件变为本批文件 本批预解析导入Before{ projectRoot: /path/to/project, allProjectFiles: [src/index.ts, src/utils.ts, ...], batchFiles: [ {path: src/index.ts, language: typescript, sizeLines: 150} ] }After{ projectRoot: /path/to/project, batchFiles: [ {path: src/index.ts, language: typescript, sizeLines: 150}, {path: src/utils.ts, language: typescript, sizeLines: 80} ], batchImportData: { src/index.ts: [src/utils.ts, src/config.ts], src/utils.ts: [] } }配套改动包括抽取脚本不再解析导入输出格式中删除imports数组保留metrics.importCount改由batchImportData[path].length直接得出建边规则改为对batchImportData[filePath]中每个已解析路径建imports边禁止自行重新解析Critical Constraints 中关于resolvedPath的旧措辞一并替换。仓库现状这条链路如今是仓库中最工程化的部分。计划里让 LLM 照着散文描述写解析脚本的 Step 8后来被一个完全确定性的捆绑脚本 extract-import-map.mjs 取代——其文件头注释直言此前运行时 LLM 产出的脚本质量不一、只靠正则、语言覆盖稀疏。该脚本基于understand-anything/core的 TreeSitterPlugin 抽取原始导入再按语言执行解析规则支持面远超计划初版TS/JS相对导入 tsconfig 路径别名按 importer 向上找最近的 tsconfigmonorepo 友好扩展名探测顺序见 TS_EXT_PROBES并额外处理 NodeNext/ESM 约定下源码导入./config.js但磁盘上只有./config.ts的改写NODENEXT_REWRITES注释注明这是 issue #294 的修复——否则 ESM-TS 项目会产出一张几乎没有边的图Go多模块 monorepo 支持按 importer 向上找最近go.mod剥离 module 前缀包级导入展开为该目录下全部.go文件Python相对导入按前导点数上溯绝对导入把每个祖先目录都当作候选 root 探测天然适配多服务仓库Java/Kotlin/Scala/C#点分 FQN → 后缀索引匹配PHP走 composer.json PSR-4 自动加载Swift解析 Package.swift target 声明单文件失败只降级为importMap[path] []并发 stderr 警告不中断整体。project-scanner.md 的 Step C 规定importMap必须逐字合并进scan-result.json不得编辑、重排或过滤且明确列出了 13 种受支持语言、集合之外的语言得到空数组、没有 LLM 回退。回归测试见 test_extract_import_map.test.mjs。6.3 C1c C2Task 7SKILL.md 编排接线Phase 1 读到的scan-result.json清单中新增一项 importMap每个文件的预解析项目内导入并明确存为内存变量$IMPORT_MAP供 Phase 2 使用。Phase 2 的派发块在 dispatch 前按批次切片batchImportData {} for each file in this batch: batchImportData[file.path] $IMPORT_MAP[file.path] ?? []dispatch prompt 中allProjectFiles整段删除替换为本批预解析导入数据建imports边直接用禁止从源码重新解析。增量更新路径同步注明变更文件同样走 20–30/批、5 并发、batchImportData构造流程。C2同任务完成两项参数调整批量大小从每批5–10 文件改为每批20–30 文件目标 ~25/批并发上限从3提到5。计划的权衡表很直白小批次旧大批次新500 文件的批次数~67~20模板重复次数67×20×质量风险低聚焦略高并发35质量风险被评估为低抽取脚本对批次大小不敏感每个子代理操作互不重叠的文件组20–30 个文件仍远在上下文窗口内。C1C2 叠加后Phase 2 从 ~301,500 降到 ~53,500 token~82%。仓库现状批量策略已从固定 20–30 文件演进为语义批处理。SKILL.md 新增 Phase 1.5运行捆绑脚本 compute-batches.mjs读取scan-result.json的importMap在导入图上跑Louvain 社区发现runLouvain把互相紧耦合的文件聚进同一批次再为每批补上batchImportData与neighborMap跨批邻居文件及其导出符号供跨批边置信度使用输出batches.json。并发上限保持计划的值——SKILL.md#L303Run up to5 subagents concurrently。file-analyzer.md 则把计划的直接用batchImportData建边强化成硬性自检输出中imports边数必须等于本批所有batchImportData[file].length之和不是 90%不是有意义的那些是全部merge-batch-graphs.py的后处理恢复通道只作为兜底。相关测试见 test_compute_batches.test.mjs。7. Task 8版本同步按项目约定插件版本在四个文件中保持同步计划执行 patch bump1.2.1→1.2.2属内部优化、无 API 变更understand-anything-plugin/package.json.claude-plugin/marketplace.jsonplugins[0]的version.claude-plugin/plugin.json.cursor-plugin/plugin.json验证方式是对四个文件grep version确认全部显示新版本。当前仓库中 package.json 的版本已演进到2.9.4说明这套降本方案落地后插件又经历了多轮迭代。8. Task 9构建与端到端冒烟验证计划以真实项目跑/understand --full做整体验证检查清单值得任何改造 LLM 流水线的工程直接借鉴构建pnpm --filter understand-anything/core build与 skill 包构建零错误本地构建拷入插件缓存~/.claude/plugins/cache/understand-anything/understand-anything/version。小项目~20 文件Phase 0–7 无错误、knowledge-graph.json生成、节点/边数量合理、layers 与 tour 齐全、输出中不出现allProjectFiles或附录相关报错。大项目100 文件批次数应降到 ~4–6不再是 10–20scan-result.json中importMap存在且完整图谱质量与改造前持平summary 有信息量、分层正确。--review路径/understand --full --review应确实派发 LLM graph-reviewer而非内联脚本review.json含approved字段流水线正常完成。如有修复单独提交fix(understand): smoke test fixes for token reduction changes。9. 收益汇总与结论计划给出的合计账目500 文件 TypeScriptReact 项目改动改造前改造后节省C1C2import map 批次合并~301,500~53,500~248,000C3去附录~26,000~3,000~23,000C4Phase 45 瘦身~154,500~33,000~121,500C5默认门控 reviewer~58,500~0~58,500合计~540,500~89,500~451,000~83%并指出节省随项目规模放大1,000 文件项目的批次数更多C1C2 消除的重复量更大。计划还列出主要风险与缓解扫描器漏解析复杂再导出/动态导入→ 漏边行为与旧版一致、可接受大批次降低 summary 质量 → 影响仅限单文件分析深度、风险低tour 剥离 function/class 节点 → 现有 tour 步骤只引用file:ID无兼容性问题默认去掉 LLM reviewer → 内联脚本覆盖全部关键结构问题悬空引用、缺层、重复 IDLLM 的增量价值是孤儿节点、笼统 summary 这类非阻塞性质量警告。方法论上这份计划的价值在于三个可复用的模式其一把每批次重复注入的确定性数据上移到流水线最早的一次性阶段importMap下游只做切片消费其二用门控 默认确定性路径替代无条件的 LLM 调用--review把质量审核降级为 opt-in其三LLM 编排中的散文式脚本要求最终都收敛为确定性捆绑脚本 回归测试extract-import-map.mjs、compute-batches.mjs从提示词工程走向提示词 代码的双轨实现——这正是计划蓝图2026-03-27与当前仓库插件 2.9.4之间的主要演化轨迹。【免费下载链接】Understand-AnythingGraphs that teach graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.项目地址: https://gitcode.com/GitHub_Trending/un/Understand-Anything创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考