检索机制
KaaS 使用 LLM 迭代式检索 —— 无需 embedding,无需向量数据库。由 LLM 自身导航编译好的 Wiki,找到相关内容后生成带引用的答案。
工作原理
检索过程分六步,单次完成:
1. 用户提问
用户通过 Chat 界面(或 MCP ask 工具)发送自然语言问题。
2. 读取 Master-Index
后端加载 master-index —— 一个 Markdown 文件,列出所有 Wiki 文章的标题、路径和一行摘要。这是编译流水线的 Index 阶段自动维护的目录。
3. LLM 选择相关页面
将用户问题和完整的 master-index 目录一起发送给 LLM。LLM 返回最可能包含答案的页面路径列表。这是一次 单轮决策 —— 不做迭代循环或重排序。
4. 读取全文
后端从 Wiki 存储中读取每个选中页面的完整 Markdown 内容。
5. 生成带引用的答案
将文章全文加上原始问题发送给 LLM。LLM 生成带 内联引用 的答案 —— 每个论断都标注来源文章的标题和路径(如 [文章标题](path))。
6. SSE 流式推送
答案通过 Server-Sent Events(SSE)流式返回给用户。前端渲染引用标记,可点击跳转到对应 Wiki 文章。
为什么不用向量检索?
传统 RAG 系统将文档切块、生成 embedding 向量、通过余弦相似度检索。KaaS 采用根本不同的方法:
| 维度 | 传统向量 RAG | KaaS LLM 迭代式 |
|---|---|---|
| 预处理 | 切块 + 对所有内容做 embedding | 编译成结构化 Wiki + 维护索引 |
| 索引 | 向量数据库(chromadb、pinecone 等) | 纯 Markdown 文件(master-index.md) |
| 检索 | 向量余弦相似度 | LLM 阅读目录,通过推理选页 |
| 上下文质量 | 原始文本块(常在段落中间截断) | 完整的结构化文章 |
| 依赖 | Embedding 模型 + 向量数据库 | 除 LLM 本身外无其他依赖 |
| 维护 | 每次内容变更都要重新 embed | 编译时索引自动更新 |
核心优势
零基础设施 —— 不需要部署 embedding 模型,不需要运维向量数据库。"索引" 就是一个任何文本编辑器都能打开的 Markdown 文件。
全文上下文 —— 不是检索碎片化的 512-token 文本块,而是让 LLM 阅读完整的、结构良好的文章。这产生更连贯的答案。
编译时质量保障 —— 重活在编译阶段完成(去重、去噪、合并、结构化)。到检索时,内容已经干净且有组织。
透明导航 —— 你可以直接打开
master-index.md看到 LLM 选页时看到的内容。没有不透明的相似度分数。
权衡
- 目录大小限制 —— master-index 必须能放进 LLM 的上下文窗口。对于大多数个人/团队 Wiki(数百篇文章),这不是问题。对于超大规模语料库(数万篇文章),可能需要层级索引(topic-index → master-index)或未来引入向量辅助预筛选。
- 每次查询的 LLM 开销 —— 每次检索涉及两次 LLM 调用(选页 + 生成答案)。对于高流量部署,这比简单的相似度查找更昂贵。
可选增强
KaaS 支持两个可选功能来提升检索质量:
- Query Rewrite(
/rewrite)—— 在选页之前重写用户问题,提升检索清晰度。 - 追问建议(
/suggest)—— 回答后建议用户可能想问的相关问题。
两者默认关闭,可按请求启用。
实现参考
检索逻辑位于 py/src/kb_ai/retrieve.py。编排检索 + 答案生成的 chat 流程位于 py/src/kb_ai/server_chat.py。