这个概念是什么,例如 Q5_K、RoPE、KV cache?
如何把这个项目整理成可问答的 Wiki、RAG 与代码知识图
本科生最需要的不是“把所有日志塞进聊天框”,而是能快速回答四种问题:
目标
本科生最需要的不是“把所有日志塞进聊天框”,而是能快速回答四种问题:
这个模块负责什么,输入输出在哪里?
一条命令或一次运行实际经过了哪些文件?
某个结论来自哪份代码、manifest 或 transcript?
Wiki 负责稳定阅读路径;RAG 负责在大量页面中找相关片段;代码理解图负责回答跨模块依赖。三者互补,不能互相替代。
flowchart LR
Source[源代码 / JSON / 协议] --> Wiki[人工可读 Wiki]
Source --> Index[分块 + metadata 索引]
Source --> Graph[模块/接口/产物关系图]
Wiki --> Student[按章节学习]
Index --> RAG[按问题检索原文片段]
Graph --> Trace[跨模块追踪]
RAG --> Answer[带来源链接的回答]
Trace --> Answer1. 最值得借用的 Wiki 方法
目录式 Wiki:借用 MkDocs Material 或 Docusaurus 的组织方式
这类工具解决“怎么读”,不是“怎么回答”。可借用的做法是:左侧按学习顺序导航、每页一个明确问题、页面之间用链接串起来、表格和 Mermaid 直接渲染。
| Wiki 页面类型 | 这个项目的页面例子 | 应包含的固定字段 |
|---|---|---|
| 概念页 | token、BPE、Q5_K、RoPE、KV cache | 一句话定义、类比、简化公式、对应模块、常见误解。 |
| 模块页 | tokenizer、Host、HLS、PS、board | 职责、输入、内部步骤、输出、接口、上下游。 |
| 接口页 | UART 协议、C API、HLS port | 调用格式、参数、返回、调用者、被调用者。 |
| 流程页 | GGUF 到 UART transcript | Mermaid 时序/流程、每一步读写文件。 |
| 产物页 | golden、fixture、manifest | 谁生成、保存什么、如何复核、可回答什么。 |
本知识库已经按此结构生成 HTML。未来可以迁移到 MkDocs Material 或 Docusaurus;迁移只改变站点生成方式,不改变内容模型。
自动代码 Wiki:借用 DeepWiki / CodeWiki 一类的“入口优先”方法
自动代码 Wiki 的核心不是“自动总结所有文件”,而是先找到能启动或连接模块的入口:main、CLI、协议 parser、顶层 HLS 函数、构建脚本。然后从入口画出调用链,并在每个结论旁边保留源文件路径。
在这个项目中,应优先索引:
| 类别 | 首要入口 |
|---|---|
| PS 应用 | ZCU106/ps_app/nl_uart_app/src/nl_uart_app.c 的 main 与 dispatch |
| tokenizer | q25_nl_tokenizer_bundle.h 的公开函数 |
| HLS | 每个 src/*.h 中的 extern "C" 顶层函数 |
| Host | scripts/run_golden.py 的 main 与参数定义 |
| 板级 | run_q25_nl_board_acceptance.ps1 与 transcript validator |
2. RAG:该检索什么,不该检索什么
RAG 的基本流程是“把问题转成检索,再把检索到的原文交给模型回答”。它不自动保证正确;最重要的是把正确范围的材料检索出来,并把来源展示给读者。
sequenceDiagram
participant U as 学生问题
participant Q as Query rewrite
participant R as Hybrid retrieval
participant F as Metadata filter
participant L as LLM answer
participant C as 引用
U->>Q: Q5_K 在哪个 HLS kernel 使用?
Q->>R: Q5_K + HLS + kernel
R->>F: 过滤 domain=hls
F-->>L: 源码摘要、模块页、接口页
L-->>C: 回答 + 路径/片段
C-->>U: 可回查的解释推荐:混合检索,而不是只做向量检索
| 检索层 | 擅长的问题 | 例子 |
|---|---|---|
| 关键词/BM25 | 精确文件名、函数名、错误码、Q25TOKRT | “q25_nl_tokenizer_runtime_image_open 谁调用?” |
| 向量检索 | 自然语言同义问法、概念解释 | “板上是怎么把文字变成 token 的?” |
| metadata filter | 限定模型、模块、执行层或产物类型 | 只看 domain=hls、model=qwen2p5。 |
| reranker | 多个候选片段很相似时排序 | 让接口定义排在日志前面。 |
| 引用输出 | 防止答案悬空 | 回答附 path、标题、chunk id。 |
可借用的组件:FAISS/Chroma/Qdrant 做向量索引;BM25 或数据库全文检索做关键词;LlamaIndex/LangChain 只作为连接器和流程编排。它们不是知识本身,知识仍来自文档、代码和产物。
RAG chunk 的正确切法
不要按每 500 个字符硬切。硬件/软件项目最适合按语义边界切块。
| chunk 类型 | 一块应包含什么 | metadata 示例 |
|---|---|---|
| 概念 chunk | 定义、类比、公式、关联模块 | kind=concept, topic=rope |
| 模块 chunk | 职责、输入、输出、接口 | kind=module, domain=ps_uart |
| 函数 chunk | 签名、参数、返回、调用关系 | kind=api, symbol=q25_nl_tokenizer_runtime_image_open |
| 流程 chunk | 起点到终点的 Mermaid 和步骤 | kind=flow, flow=text_prompt |
| 产物 chunk | producer、consumer、hash/manifest 路径 | kind=artifact, artifact=golden |
建议固定 metadata:source_path、title、kind、domain、model、stage、symbols、produces、consumes、updated_at。检索答案必须返回 source_path 和标题。
3. GraphRAG:什么时候值得用
普通 RAG 很适合“Q25TOKRT 是什么”;当问题跨越三层以上时,图关系更清楚,例如“用户输入中文后,到底经过 tokenizer、PS、HLS 和 board 哪些模块?”
GraphRAG 的最小图不需要先做复杂社区算法。先维护三类节点和五类边即可。
flowchart LR
M[模块] -->|calls| A[API]
M -->|produces| P[产物]
M -->|reads| D[数据]
A -->|implemented_by| F[源文件]
P -->|validated_by| V[验证器]| 节点 | 例子 |
|---|---|
| 模块 | tokenizer、Host reference、HLS kernel、PS UART、board runner |
| API | TEXT_PROMPT、q25_nl_tokenizer_bundle_encode_bpe_bounded、smollm2_attention_core |
| 数据/产物 | Q25TOKRT、tensor payload、golden JSON、fixture、UART transcript |
| 边 | 例子 |
|---|---|
calls | TEXT_PROMPT -> q25_nl_tokenizer_bundle_encode_bpe_bounded |
produces | tokenizer exporter -> tokens.jsonl |
consumes | HLS kernel -> fixture BIN |
validates | transcript validator -> UART transcript |
implements | nl_uart_app.c -> UART protocol |
Microsoft GraphRAG 的“实体、关系、社区摘要”思路可以借用在跨模块问答上;但这个项目的第一版只需事实边。不要把猜测性的“可能调用”写入图中。
4. 代码理解的四层方法
这比让模型直接“读完整个仓库”可靠得多。
| 层 | 做法 | 本项目例子 |
|---|---|---|
| 目录层 | 给每个顶层目录一个职责 | models/、scripts/、ZCU106/hls/、ZCU106/ps_app/。 |
| 入口层 | 找真正启动点和公开 API | Python main、C main、extern "C" HLS top。 |
| 数据层 | 追踪谁生成、谁读取每种文件 | GGUF -> tensor BIN -> fixture -> HLS result。 |
| 运行层 | 画一次真实命令的调用/时序 | UART TEXT_PROMPT -> tokenizer image -> token ids。 |
可以用 AST、LSP 或 CodeQL 建立函数/包含关系;用 rg 搜索字符串协议和文件路径;用 manifest 和脚本参数确认数据关系。自动抽取得到的是候选关系,关键接口应由人工或测试复核。
5. 适合这个项目的落地顺序
flowchart TD
A[HTML Wiki: 先让人能读] --> B[统一 metadata]
B --> C[BM25 + vector hybrid RAG]
C --> D[回答附 source_path]
D --> E[添加模块/API/产物图]
E --> F[跨模块 GraphRAG 问答]先维护本次生成的 HTML Wiki,任何人都能按章节阅读。
给每页、每个接口和每个产物补齐 metadata。
对 HTML/Markdown 正文和源代码摘要建立混合检索。
强制回答带来源路径;不能检索到来源时回答“不确定”。
最后再建立模块/API/产物关系图,专门处理跨层问题。
6. 不建议的做法
| 做法 | 问题 | 更好的替代 |
|---|---|---|
| 把所有 Vitis 工作目录、二进制、原始日志直接向量化 | 噪声大,检索会被生成文件淹没。 | 只索引源码、协议、manifest、人工摘要和关键报告。 |
| 只靠向量相似度找函数 | 函数名、错误码、路径容易被漏掉。 | 与 BM25/全文检索并用。 |
| 没有来源就让 LLM 自由解释状态 | 容易把 stub、Host、HLS、board 混为一谈。 | 回答必须带模块范围与来源。 |
| 先做复杂 GraphRAG 再写文档 | 图节点没有稳定定义,维护成本高。 | 先有模块页和接口表,再抽取事实关系。 |
结论
对这个项目,最实际的组合是:HTML Wiki 负责学习路径,混合 RAG 负责按问题找原文,事实关系图负责跨模块追踪。 这三层都要把结果链接回真实文件和明确模块,才能让解释既好懂又可核查。