乐于分享
好东西不私藏

CodeWiki-Plus开篇:从代码文档到AI知识引擎

CodeWiki-Plus开篇:从代码文档到AI知识引擎

作者: WanderingBug

项目地址: https://github.com/mambo-wang/CodeWiki-Plus
CodeWiki 是 FPT Software AI4Code 团队开源的代码知识库生成工具,通过 Tree-sitter AST 解析自动为代码仓库生成模块化 Wiki。CodeWiki-Plus 在其基础上进行了深度改造:五周内新增 35000+ 行代码,将搜索性能提升 3-5 倍,并构建了完整的知识管理层和跨服务调用分析能力。本文介绍改造的动机、核心设计选择和阶段性收益。

一、为什么要 Fork:原版 CodeWiki 的三个短板

CodeWiki 的核心思路很好——用 AST 解析提取代码结构,用 LLM 生成结构化文档,比人工维护文档高效得多。
最初要改造这个项目,是因为CodeWiki 原始设计需要用户自行配置 LLM API(API Key + base_url),然后通过 CLI 一键生成文档。这带来两个问题:
1. 配置门槛:用户需要申请 API Key、了解 provider 差异、处理模型兼容性
2. 灵活性不足:生成过程是黑盒的,用户无法在过程中干预聚类策略或文档风格
改造目标:将 CodeWiki 退化为纯工具链 MCP Server,由 AI IDE(CodeBuddy、Cursor 等)的 Agent 全权驱动 Wiki 生成流水线,实现零 LLM 配置,具体改造过程见之前的文章。
在实际使用中,另外还遇到了三个无法回避的问题:
短板一:大项目跑不动。 原版将所有组件数据存放在内存字典中,搜索引擎是纯 Python 遍历 JSON 文件,没有持久化缓存,每次会话都从零开始。一个 500+ 文件的 Java 项目,首次分析需要十几分钟,分析结果不保留,下次打开 IDE 又得重来。对于日常开发中"改了几行代码想更新一下文档"的场景,这个成本完全不可接受。
短板二:MCP 协议支持粗糙。 原版有两个基础的 MCP Server,但只有工具定义,没有 Server Instructions、没有 Prompt 模板、没有 Resource。Agent 连上之后不知道该怎么用——先调什么、后调什么、输出放在哪里、怎么判断是否需要更新——全靠猜。在实际工作流中,这意味着必须额外编写 Skill 来编排调用顺序,MCP 本身的价值被大幅削弱。
短板三:知识没有管理。 生成的 Wiki 是一堆平铺的 Markdown 文件,没有分类、没有关联、没有生命周期。外部设计文档、会议纪要、API 规范无法纳入统一管理。文档生成完之后,好不好、对不对、过没过期,没有度量手段。更关键的是,原版只能看到单仓库内部的依赖关系,对于微服务架构中跨仓库、跨服务的调用关系完全是盲区。
这三个问题分别对应性能、协议和知识三个层面的改造。下面逐一展开。

二、性能重构:从"跑不动"到"秒级增量"

性能改造的目标很明确:让大型项目的日常使用体验从"等十几分钟"变成"等几秒"。改造分四个层次推进。

2.1 SQLite 持久化缓存

借鉴 codegraph 的架构思路,我们引入了 SQLite 作为统一的持久化层(WAL 模式)。所有组件索引、文件指纹、依赖关系、BM25 搜索索引、符号映射都落入数据库,跨会话共享同一个 SQLite 文件。
设计选择:使用内容哈希(SHA-256 前 64KB)加文件修改时间的双重变更检测,而不是单纯依赖 Git diff。原因是很多使用场景下用户并没有 commit 就希望更新文档(比如 IDE 里改了几行想看看效果),纯 Git diff 会漏掉 unstaged 的变更。
引入缓存后,第一次分析完成后的后续会话几乎是秒级响应——不需要重新解析,直接从 SQLite 加载组件数据和搜索索引。同时实现了 LazyComponentStore,用 LRU 策略按需加载组件完整数据,避免一次性将数万个组件全部读入内存。

2.2 SHA-256 增量选择性重解析

有了缓存之后,下一步是"只处理变化的部分"。增量更新时,系统先通过双重检测确定变更文件集合,然后对未变更文件直接加载缓存中的组件数据,跳过 AST 解析和 LLM 调用。
实现上,skip_file_paths 参数贯穿整个分析链路——从 DependencyGraphBuilder 到 DependencyParser 到 AnalysisService 到 CallGraphAnalyzer——确保未变更文件在任何阶段都不会被重复处理。写入缓存时使用 INSERT OR REPLACE 替代原来的 DELETE all + INSERT,避免增量场景下的数据丢失。
另一个关键改进是 Overview stale 精确判定。原版在增量更新后无条件标记 overview 需要重新生成,即使变更的模块和 overview 毫无关系。现在系统会解析 overview.md 中的 wiki-links 和 markdown links,建立引用关系图,只有当受影响的模块确实在 overview 的引用列表中时,才标记为 stale。这避免了大量不必要的级联刷新。

2.3 SQLite 倒排索引替代 JSON 搜索

原版的搜索引擎将全部文档存储在一个 JSON 文件中,每次查询时 Python 逐候选遍历计算 BM25 分数。文档数量少时问题不大,但当 Wiki 页面达到数百篇时,搜索延迟明显可感知。
重写后的方案使用三张表:search_index(文档元数据)、search_token_index(token → doc 倒排)、search_stats(全局统计)。BM25 评分通过 CTE + JOIN + GROUP BY 在 SQL 层完成,Python 端只负责结果格式化。
实测性能对比:
文档规模原版耗时新版耗时提升倍数
100 篇基准-60%2.5x
500 篇基准-74%3.8x
2000 篇基准-79%4.8x
同时引入了 Frontmatter 搜索加权:tags 和 aliases 获得 3 倍权重,title 和 description 获得 2 倍权重。这解决了一个实际痛点——用户经常用缩写或别名搜索(比如用"OMS"搜"订单管理服务"),纯正文匹配命中率很低,加权后显著改善。

2.4 大项目输出优化

大型项目全量输出组件列表时,原版返回的 JSON 可达 15MB 以上,远超 MCP 协议的输出限制,也严重浪费 Agent 的 token 预算。
引入 summary 模式后,list_components 支持按文件聚合组件,返回每个文件的组件数量、类型分布和类名列表,输出体积从约 15MB 降到约 2MB。Agent 在聚类阶段使用摘要概览判断模块划分,需要精确信息时再按 file_prefix 过滤获取特定文件的完整组件数据。
另一个实际问题是 analyze_repo 的响应体积。原版一次性返回全部分析结果,大项目直接触发 MCP 的 maxOutputLength 溢出。改为分页响应后,Agent 可以按需获取,不再被协议限制卡住。

三、MCP 协议规范化:从"能连上"到"自主工作"

MCP 协议的价值在于让 Agent 能够自主发现和使用工具。但如果 Server 只提供了工具定义而没有使用指南,Agent 的调用准确率会很低——它不知道 analyze_repo 之后应该调 generate_docs 还是 get_module_tree,不知道 query_wiki 的 scope 参数该怎么填,不知道什么时候该用增量更新而不是全量重建。
参考我们在 CodingHub 项目中的 MCP 最佳实践,对 CodeWiki-Plus 的 MCP Server 进行了四个层面的升级。

3.1 Server Instructions

添加了 1624 字符的全局指引,包含能力概览、推荐工作流和约束说明。Agent 连上 MCP 后首先读到这段指引,就能理解"这个 Server 能做什么、典型的使用流程是什么、哪些操作有前置条件"。
实际效果:不安装任何 Skill 的情况下,Agent 仅凭 Instructions 就能自主完成"分析仓库 → 生成文档 → 搜索知识 → 增量更新"的完整流程。这大幅降低了使用门槛——用户只需要在 IDE 中配置 MCP 连接,不需要额外编写编排逻辑。

3.2 Prompt 模板

提供 6 个 MCP Prompt 模板,覆盖典型使用场景:
Prompt用途
generate-wiki引导 Agent 完成从分析到生成的完整流程
extract-knowledge从代码中提取设计知识并写入 Wiki
search-wiki按主题搜索已有知识
quality-check执行文档质量审计
incremental-update检测变更并增量刷新
workspace-analysis多仓库工作区联合分析
每个 Prompt 不是简单的指令文本,而是一段 USER 消息脚本,引导 Agent 按步骤完成任务。例如 generate-wiki 会先引导 Agent 调用 analyze_repo 获取项目结构,再根据模块数量决定生成策略,最后执行 generate_docs 并验证输出。

3.3 Resource 与 ResourceTemplate

注册了 3 个静态 Resource(wiki-catalog、module-tree、index-status)和 3 个 ResourceTemplate。IDE 可以直接浏览 Wiki 的目录结构、模块树和索引状态,不需要调用工具就能快速了解项目文档的现状。这对于"我想看看这个项目的文档覆盖情况"这类轻量查询非常有用。

3.4 工具描述全面重写

21 个工具的描述全部重写,加入了工作流上下文("通常在 analyze_repo 之后使用")、跨工具引用("输出可作为 generate_docs 的输入")、行为约束("scope 参数支持三重匹配:stem/路径前缀/路径组件")和枚举值说明。
这些看似琐碎的改动对 Agent 的调用准确率影响很大。MCP 协议下,Agent 完全依赖工具描述来决定何时调用、如何传参。描述越精确,Agent 的试错成本越低。

四、LLM Wiki 知识层:从文档堆到知识图谱

原版 CodeWiki 的输出是一堆平铺的 Markdown 文件。生成完就放在那里,没有分类体系、没有页面关联、没有质量度量、没有外部文档管理能力。这不是一个"知识库",只是一个"文档目录"。
受 llm_wiki(Obsidian 知识管理插件)和 WeKnora(腾讯开源的文档智能平台)的设计启发,我们构建了一套完整的知识管理层。

4.1 结构化页面体系

定义了 6 种页面类型,分目录组织:
页面类型目录用途
modulewiki/modules/代码模块文档(自动生成)
entitywiki/entities/领域实体、数据模型
conceptwiki/concepts/技术概念、设计模式
sourcewiki/sources/外部摄入的文档
comparisonwiki/comparisons/方案对比、技术选型
querywiki/queries/查询结果快照
统一的路由引擎(page_router.py)根据 page_type 自动分发到正确目录。写入方不需要关心文件该放在哪里,系统自动处理。这解决了原版中"Agent 经常把文件写错位置"的问题。

4.2 Wikilink 知识图谱

页面之间通过 Wikilink 建立有向关联,存储在 SQLite 的 wiki_links 表中。基于这个图结构,实现了多跳搜索:搜到一个模块后,可以沿着依赖关系做 BFS 扩展,带衰减权重(decay 参数控制每跳的权重衰减比例),避免无限发散。
搜索结果现在附带 related 字段,包含通过图谱扩展发现的关联页面。Agent 在调研一个模块时,不需要反复手动搜索相关概念,系统自动推荐。
同时实现了 Wikilink 到 Markdown 链接的自动转换——Wiki 页面中的 \[\[页面名]] 语法在输出时自动转为可点击的相对路径链接,方便在 IDE 和 GitHub 中直接跳转。

4.3 外部文档管理

通过 ingest_source / retract_source 管理第三方文档的完整生命周期。设计文档、API 规范、技术方案、会议纪要都可以纳入知识库,和自动生成的代码文档统一管理。source_registry.json 注册表追踪每份外部文档的导入状态、来源 URL 和最后验证时间。
配合 batch_ingest 工具,可以一次性将一个目录下的多份文档批量导入。我们在实践中用这个能力将 OpenSpec 框架的 schema.yaml(方法论文档)、specs 目录下的 46 个能力规格(实体知识)和 changes/archive 中的 29 个变更设计文档(架构决策)全部摄入 Wiki,形成了项目级的完整知识体系。

4.4 质量治理

lint_wiki 从原版的 5 项检查扩展到 10 项:
检查项含义
broken_links引用了不存在的页面
missing_frontmatter缺少必要的元数据
duplicate_titles标题重复
empty_pages空页面
outdated_refs引用了已删除的组件
orphan_pages没有任何入链的孤立页面
no_outlinks没有出链的页面(知识孤岛)
missing_aliases缺少别名定义(影响搜索命中率)
stale_sources外部文档超过验证周期
overview_stale概览文档引用的模块已变更
health_score 用 0-100 分综合评估文档质量,按 error(-10)、warning(-3)、info(-1)三级扣分。分数低于阈值时,Agent 在执行知识查询前会先建议运行质量修复。

4.5 零配置启动

所有写入工具自动创建 output_dir 及 .meta/ 子目录。空项目不需要先跑一遍 analyze_repo 就能开始积累知识笔记——直接调用 ingest_note 写入设计决策、踩坑记录,Wiki 结构自动生长。
这个改动的动机来自实际使用场景:很多时候项目还在早期设计阶段,代码量很少,但设计决策和技术选型已经产生了大量值得沉淀的知识。零配置让知识积累不必等到代码"足够多"才开始。

五、跨服务调用分析:看见微服务全貌

真实的生产系统很少是单仓库单服务的。一个电商系统可能有订单服务、支付服务、用户服务、通知服务,分布在不同仓库或同一 Monorepo 的不同目录下。原版 CodeWiki 只能看到单个仓库内部的函数调用关系,跨服务的 HTTP 调用、RPC 调用完全是盲区。
这意味着:当 Agent 要修改订单服务的取消逻辑时,它不知道支付服务的退款接口依赖了这个逻辑的返回值;当架构师要评估一个 API 变更的影响面时,他需要人工翻阅所有下游服务的代码。

5.1 核心思路:Route 节点间接匹配

直接匹配跨仓库的函数调用是不可能的——两个仓库的代码不在同一个 AST 中。借鉴 codebase-memory-mcp 的 Route 节点机制,我们采用协议无关的间接匹配策略:不匹配函数调用,而是提取每个服务暴露和消费的路由(HTTP 端点),通过路径匹配建立跨服务关联。
数据流:每个仓库的 analyze_repo 在 AST 解析管线中新增 Route 提取 pass → Route 节点持久化到该仓库的 SQLite 缓存 → analyze_workspace 汇总所有仓库的 Route → CrossServiceMatcher 执行四阶段匹配 → 匹配结果渲染为 Mermaid 拓扑图 + Markdown 表格。

5.2 多语言 Route 提取

Route 提取作为现有语言分析器的后处理 pass 运行,不侵入现有解析逻辑。目前支持四种语言和主流框架:
语言服务端检测客户端检测
PythonFastAPI 装饰器、Flask route、Django urlpatternsrequests、httpx、aiohttp
JavaSpring MVC 注解、JAX-RSRestTemplate、WebClient、Feign
TypeScript/JSExpress、NestJS 装饰器axios、fetch
GoGin、Chi、net/httpnet/http client
路径规范化是匹配准确性的关键。不同框架的参数语法不同(:id、\{id}、\、$\{id}),统一规范化为 \{} 后再比较。同时处理尾随斜杠、大小写等边界情况。

5.3 四阶段匹配引擎

CrossServiceMatcher 的匹配策略:
1. 精确匹配:route_key(METHOD + 规范化路径)完全一致
2. 模板降级:具体路径与模板路径逐段比较,\{} 段匹配任意非空段
3. 同仓库过滤:跳过同一仓库内的 client-server 匹配(那是内部调用,不是跨服务)
4. 置信度评分:精确匹配置信度 1.0,模板降级匹配按匹配段比例衰减

5.4 Monorepo 支持

对于单仓库多服务的 Monorepo 场景,系统通过 5 阶段启发式检测识别子服务边界:docker-compose 服务定义 → Dockerfile 分布 → 构建清单(pom.xml / package.json)→ 约定目录结构 → Spring Boot 启动类。
检测到子服务后,为每个子服务分配独立标签,复用同一套 CrossServiceMatcher 引擎。增量模式下,从 SQLite 缓存加载全量路由再重新标记,避免只看到新增文件的路由而遗漏已有服务。

5.5 输出产物

最终输出写入 workspace 级别的 overview.md:
Mermaid 服务拓扑图:服务为节点,API 调用为边,标注 HTTP 方法和路径
跨服务调用表:Method、Path、Client Service、Client Function、Server Service、Server Function
未匹配路由表:标注为外部 API 或待确认的孤立路由
对于理解微服务架构全貌、评估变更影响面、辅助 Agent 做跨服务的代码修改,这个能力填补了原版最大的功能空白。

六、文档生成策略优化

6.1 doc_type 机制

不是所有代码都需要同等对待。一个 DTO 类和一个核心业务 Service 的文档价值完全不同。引入 doc_type 机制后,支持两种文档类型:
business:面向业务工作流、状态转换、领域规则的文档
design:面向技术设计、接口契约、设计决策的文档(默认)
两种类型使用不同的提示词策略。同时 overview 级别和 module 级别的提示词也做了分离——overview 关注模块间关系和系统全貌,module 关注内部实现细节和业务约束。

6.2 schema.yaml 约束注入

每个项目可以在 schema.yaml 中定义文档规范要求(必选章节、命名规则、描述粒度等)。这些约束在 get_prompt 阶段自动注入 LLM 提示词,确保生成的文档遵循项目特定规范。analyze_repo 的响应中也会返回当前生效的 schema 信息,方便 Agent 了解项目的文档标准。

6.3 Frontmatter 标准化

所有生成的 Wiki 文件统一添加 OKF 规范的 YAML frontmatter(title、type、tags、description、aliases、severity)。这些元数据既服务于搜索加权(如前文所述),也为后续的知识消费协议和质量治理提供基础。

七、阶段性收益

五周时间,86 个文件变更,35000+ 行新增代码。核心收益:
维度改造前改造后
大项目首次分析十几分钟,不可复用首次完成后,后续秒级加载
增量更新全量重跑SHA-256 选择性重解析,分钟级完成
搜索性能(2000 篇)基准4.8 倍提升
MCP 可用性需额外 Skill 编排零 Skill 自主完成全流程
知识管理平铺文件,无关联6 类页面 + 图谱 + 10 项质量检查
架构视野单仓库内部跨服务拓扑 + Monorepo 子服务检测
使用门槛需配置 session零配置启动,开箱即用

八、正在推进的方向

优化不会停在这里。参考高德技术团队《CodeWiki: 为 LLM 自动生成代码知识库的工程实践》和阿里技术团队《分解一座冰山:后端系统 AI 知识库体系建设实践》两篇文章的思路,我们整理了四阶段演进路线,目前正在逐步推进。

知识表达与消费优化

Evidence-Based 业务断言。 当前 prompt 是通用"生成文档"指令,LLM 输出的业务描述无法区分"有代码依据的事实"和"推测"。计划在提示词中要求每条业务规则附带 evidence(代码引用 + 推理依据)和 confidence 评分,无证据的断言标记为 candidate。高德团队的实践表明,这一机制虽然不能消除幻觉,但可以显著减少无依据断言,并让错误更容易审查。
渐进式消费协议。 当前 query_wiki 是单次搜索返回 snippet,没有"先概览→再定位→后精读"的渐进结构。计划为 query_wiki 新增 mode 参数(overview / directory / detail),让 Agent 按需获取不同粒度的信息。目标是 overview 模式控制在 500 token 以内,directory 模式控制在 800 token 以内,大幅降低 LLM 消费知识库的 token 成本。
知识来源标注。 query_wiki 混合返回自动生成文档和人工笔记,LLM 无法判断信息的可信度和时效性。计划为每条结果添加 source_type 字段(auto_generated / developer_note / ingested_source),并在 Wiki 页面 frontmatter 中记录生成时的代码版本 SHA,支持长期追溯。

生成引擎增强

规则引擎路由。 DTO、VO、Config、Mapper 等样板代码消耗大量 LLM token 生成低价值描述。计划在组件解析阶段自动分类(boilerplate / business / infra),样板代码由模板生成,业务代码走完整 LLM 流程。高德团队在中等规模仓库上的实践数据是约 40% 的代码单元可以由规则引擎处理,我们预期类似比例的 token 节省。
知识飞轮与状态流转。 当前 ingest_note 无门槛,LLM 自主决定沉淀内容,可能写入错误或重复知识。计划引入 candidate → confirmed → rejected 的状态机制,LLM 沉淀的知识默认为候选状态,经研发确认后才升级为正式知识。query_wiki 默认只返回已确认的知识,候选知识标注"\[未确认]"。
方法级增量检测。 当前增量检测是文件级,改一个方法整个文件重新处理。计划在 SQLite 缓存中为每个组件存储内容哈希,文件变化后逐组件比较,只标记真正变化的组件为 stale,并级联标记受影响的 Wiki 页面为 needs_refresh。

知识内容扩展与生态

系统约束 / Policy。 CodeWiki-Plus 能描述"API 做了什么",但无法表达"API 的 field X 绝对不能删除"。计划支持 YAML 格式定义结构化约束规则,作为 Agent 修改代码时的"红线"优先注入上下文。
业务层知识。 当前完全没有业务层,无法回答"退款体验优化涉及哪些服务"这类业务驱动的问题。计划新增业务元语(概念定义、领域术语)、业务场景(用户操作→技术链路映射)、设计决策(为什么这样做)三类业务知识。
任务路由。 Agent 接到任务后需自行判断"改数据库应该看哪些页面"。计划支持按任务类型(add_api / modify_database / fix_bug)定义知识预加载规则,Agent 识别任务类型后自动聚合相关知识片段。
运行时配置语义注入。 大量业务逻辑依赖配置(application.yml、@Value、Nacos/Apollo),当前只能说"读取了某项配置",无法说明配置的业务含义。计划分阶段实现配置项提取、语义化摘要和敏感配置脱敏。

九、结语

CodeWiki-Plus 的五周改造,核心命题只有一个:让 AI Coding 工具链中的"知识层"真正可用。
性能重构解决的是"能不能日常用"的问题——如果每次更新文档都要等十几分钟,没有人会用。MCP 协议规范化解决的是"Agent 能不能自主用"的问题——如果需要人工编排每一步调用,自动化就无从谈起。知识管理层解决的是"知识能不能积累"的问题——如果生成的文档没有结构、没有关联、没有质量度量,它就只是一堆会过期的文件。跨服务分析解决的是"视野够不够宽"的问题——微服务架构下,单仓库视角看不到系统全貌。
高德团队在文章中提出了一个很好的定位:CodeWiki 的目标不是让模型一次读取更多源码,而是把分散的代码事实和隐性的领域规则转化为可追溯、可评审、可持续更新的知识资产。CodeWiki-Plus 认同这个方向,并正在沿着"代码文档生成器 → 可信知识生成器 → AI Coding 知识平台"的路径演进。
当前阶段的工作证明了这条路是可行的。但系统的长期价值仍需要通过更多真实项目验证——特别是知识新鲜度治理、跨仓库影响面分析和端到端的需求实现质量。这些是下一阶段的重点。
项目已在 GitHub 开源:https://github.com/mambo-wang/CodeWiki-Plus ,欢迎 Star、Issue 和 PR。如果你也在探索 AI Coding 工具链中的知识管理问题,欢迎交流。