docs: specify knowledge retrieval enhancements
This commit is contained in:
@@ -29,7 +29,7 @@ Keep Electron security boundaries intact:
|
||||
|
||||
## Runtime Behavior
|
||||
|
||||
- Ask and Plan modes must remain read-only at the runtime boundary.
|
||||
- Ask mode must remain read-only at the runtime boundary.
|
||||
- Execute mode may use tools only through the existing approval controls.
|
||||
- Preserve cancellation, timeout, bounded-output, and shutdown behavior.
|
||||
- Treat OpenCode and Continue as untrusted child runtimes. Preserve environment
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
- [x] **知识图谱**:支持规则、模型和混合抽取,以及实体、关系、别名和证据维护。
|
||||
- [x] **向量模型配置与检索**:可配置兼容 Embeddings 接口并用于语义检索。
|
||||
- [x] **向量诊断与索引任务**:提供真实向量生成诊断、按文档重建进度、取消、失败状态与重启后结果恢复;每篇成功文档立即可用于检索。
|
||||
- [x] **混合检索测试台**:支持全文、中文词组、向量和图谱通道诊断,可调 Top K、阈值、权重、本地或学习型重排及上下文预算。
|
||||
- [x] **上下文分块与离线评估**:保留标题、页码、标题层级和块类型用于上下文索引,并提供双语 Recall、MRR、nDCG、上下文精度/召回和无答案误报评估。
|
||||
- [x] **高级分块与维护**:支持固定、结构化和父子分块,以及分块搜索、编辑、停用、删除、文档重建和可取消的全库重建。
|
||||
- [x] **受控知识本体**:每个知识库可定义实体、关系、别名和端点约束,保留证据偏移、置信度和抽取来源,并显式提示图谱重建。
|
||||
- [x] **强制检索与引用上下文**:对话可按需或每次先检索,显示零结果、降级、失败与取消状态,并可查看引用上下文或安全打开来源。
|
||||
- [x] **魔法笔记 / Magic Notes**:提供本地优先的笔记与待办工作台、范围管理、编辑、筛选和受控 AI 评论;创建、保存和评论结果使用统一应用通知。
|
||||
- [ ] **MCP Server Control Plane**(规划中):扩展 MCP Agent Runtime Broker,统一生命周期、健康检查、重连、Schema 缓存、按项目或任务隔离、审批和审计,并受控接入 OpenCode、Continue。
|
||||
|
||||
|
||||
@@ -93,7 +93,10 @@ GoodBuddy 不绑定特定模型厂商。用户可以通过 OpenAI Responses、Op
|
||||
|
||||

|
||||
|
||||
- SQLite FTS5 全文检索与有界上下文召回。
|
||||
- SQLite FTS5、中文词组、向量和图谱混合检索,并提供可调权重、本地重排与有界上下文。
|
||||
- 检索测试工作台展示候选数量、通道降级、耗时、排名、分数和实际送入模型的上下文。
|
||||
- 支持固定长度、结构化和父子分块,以及分块搜索、编辑、停用、删除和可取消重建。
|
||||
- 对话可选择由模型按需检索或每次先检索,并展示检索状态与可打开上下文的来源引用。
|
||||
- 支持规则、模型和混合图谱抽取。
|
||||
- 支持实体、关系、别名、证据与来源位置追溯。
|
||||
- 图谱可搜索、筛选、缩放和拖动节点。
|
||||
|
||||
@@ -0,0 +1,591 @@
|
||||
# 知识库检索与分块增强 PRD
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 实施中 |
|
||||
| 版本 | 0.1 |
|
||||
| 日期 | 2026-08-11 |
|
||||
| 适用产品 | GoodBuddy 桌面端 |
|
||||
| 实施范围 | 第一阶段:可用、可见、可诊断;第二阶段:可调、可优化、可维护 |
|
||||
|
||||
## 1. 背景
|
||||
|
||||
GoodBuddy 已具备本地多知识库、文件与目录同步、网页导入、SQLite FTS5、
|
||||
OpenAI 兼容向量模型、RRF 混合检索、知识图谱、任务状态和来源引用。现有实现
|
||||
优先建立了本地数据主权、安全边界和跨 Runtime 工具授权,但用户仍难以稳定
|
||||
获得“导入资料后即可准确问答”的体验。
|
||||
|
||||
当前主要问题不是缺少知识图谱,而是基础 RAG 链路缺少完整闭环:
|
||||
|
||||
1. 在对话中启用知识库只会开放搜索工具,是否检索仍由模型自行决定。
|
||||
2. 默认向量检索关闭,中文全文检索对自然语言问法和同义表达的召回不足。
|
||||
3. 向量请求失败会降级为全文检索,但知识库页面仍可能显示索引完成。
|
||||
4. 大于 5,000 个向量分块的知识库会跳过向量召回。
|
||||
5. 用户不能独立测试召回、查看各通道得分或确认实际送入模型的上下文。
|
||||
6. 分块参数固定,缺少结构化、父子分块、分块预览和人工修正。
|
||||
7. 引用只能阅读片段,不能查看完整上下文或打开原始来源。
|
||||
|
||||
本项目先完成稳定性和可观测性,再增加高级分块、重排与维护能力。知识图谱
|
||||
继续作为可选召回通道,但不替代全文和向量检索的基础质量。
|
||||
|
||||
## 2. 已确认的产品决策
|
||||
|
||||
1. 保持本地优先,不引入必须联网的托管知识库服务。
|
||||
2. 保持 Electron Main、Preload、Renderer 的安全边界,Renderer 不直接读取
|
||||
数据库、原文件或向量。
|
||||
3. 保留“模型按需检索”,并新增“每次先检索”模式。后者必须由 Main 进程
|
||||
预检索,不能只依赖提示词要求模型调用工具。
|
||||
4. 知识库新建后不默认启用全部已有知识库;对话中的范围继续由用户显式选择。
|
||||
5. 向量服务不可用时保留全文检索,但必须返回明确降级状态。
|
||||
6. 中文召回使用应用内可控的 CJK n-gram 索引,不新增远程服务依赖。
|
||||
7. 混合检索保留 RRF 候选融合,并增加本地确定性重排、可选的
|
||||
Cohere/Jina 兼容学习型重排、最低相关度和上下文预算。学习型重排失败时
|
||||
安全降级,不影响全文、向量和图谱召回。
|
||||
8. 向量搜索取消 5,000 分块静默失效,使用有界内存的分页扫描。在没有稳定
|
||||
跨平台向量扩展前,接受本地 CPU 线性扫描,并持续显示性能诊断。
|
||||
9. 向量索引兼容性同时校验 Provider、Model、维度和 Provider Fingerprint。
|
||||
同名模型切换端点后,旧向量不能继续参与召回。
|
||||
10. 失败或取消的重建不能停用上一版已就绪索引。新索引只有完整校验成功后才
|
||||
原子替换当前服务版本。
|
||||
11. 分块设置属于知识库,修改后不会伪装为立即生效。用户需要显式重建索引。
|
||||
12. 分块允许预览、编辑、启用、停用和删除。来源再次同步可能覆盖人工修改,
|
||||
UI 必须在修改前持续说明该行为。
|
||||
13. 第一阶段和第二阶段均不新增付费或外部模型调用。现有 Embeddings 调用仍由
|
||||
用户配置决定。
|
||||
14. Ask 的运行时边界保持只读。知识库内容始终被标记为不可信证据,
|
||||
不能成为系统指令。
|
||||
|
||||
## 3. 目标
|
||||
|
||||
### 3.1 用户目标
|
||||
|
||||
- 明确知道本次回答是否检索、检索了哪些知识库,以及是否发生降级。
|
||||
- 在知识库页面输入真实问题,查看命中分块、通道、得分和最终上下文。
|
||||
- 为不同文档选择适合的分块模式,并在导入前理解影响。
|
||||
- 查看和修正错误分块,不需要删除并重新导入整个来源。
|
||||
- 从回答引用查看完整上下文,并打开对应本地文件或网页。
|
||||
- 在向量、解析或图谱失败时获得可恢复的状态和明确操作。
|
||||
|
||||
### 3.2 产品目标
|
||||
|
||||
- 默认中文问法在没有向量模型时仍具有可用的关键词召回。
|
||||
- 向量服务故障、大知识库和模型变更不再产生静默空结果。
|
||||
- 建立可复现的检索调试入口,支持固定问题进行回归测试。
|
||||
- 将解析、全文、向量和图谱状态拆分,避免“索引完成”误导。
|
||||
- 为后续元数据过滤、远程 Rerank Provider 和自动评测保留稳定契约。
|
||||
|
||||
### 3.3 质量目标
|
||||
|
||||
- 中文同义改写测试集的 Recall@5 相比现有全文检索基线提升至少 30%。
|
||||
- 检索测试结果必须在本机重复执行时保持稳定排序。
|
||||
- 任意向量失败都必须在检索诊断或任务状态中可见。
|
||||
- 10,000 个分块的知识库不得因固定上限返回空向量结果。
|
||||
- 每条展示引用都能找到仍存在且属于已授权知识库的分块和文档。
|
||||
- 检索输出和上下文拼装均遵守字符、结果数和 IPC 大小上限。
|
||||
|
||||
## 4. 非目标
|
||||
|
||||
本项目不包含:
|
||||
|
||||
- 团队共享知识库、SSO、SCIM 或跨设备同步。
|
||||
- 企业级 ACL、文档级角色继承和远程权限同步。
|
||||
- 云端网站爬虫、Notion、飞书、语雀等第三方连接器。
|
||||
- MinerU、PaddleOCR-VL 或其他远程文档解析服务。
|
||||
- 专用向量数据库、外部 Elasticsearch 或打包平台原生向量扩展。
|
||||
- 托管重排服务账户、计费或供应商绑定;仅提供通用兼容接口配置。
|
||||
- 自动问题生成、FAQ 生成和训练数据标注平台。
|
||||
- 完整 RAG 离线评测平台。第二阶段只提供手动检索测试与可导出的诊断信息。
|
||||
- 在应用内高保真渲染所有原始 Office 和 PDF 文档。
|
||||
|
||||
## 5. 竞品基线与 GoodBuddy 定位
|
||||
|
||||
截至 2026-08-11,Dify、FastGPT 和 RAGFlow 的公开文档均把检索测试、可配置
|
||||
分块和可调检索参数作为知识库基础能力:
|
||||
|
||||
| 能力 | Dify | FastGPT | RAGFlow | GoodBuddy 本期 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 检索测试 | 支持 | 支持 | 支持 | 第一阶段支持 |
|
||||
| Top K / 阈值 | 支持 | 支持 | 支持 | 第一阶段支持 |
|
||||
| 全文 + 向量 | 支持 | 支持 | 支持 | 已有,第一阶段增强中文 |
|
||||
| Rerank | 模型 Rerank | 模型 Rerank | 模型 Rerank | 本地确定性与可选兼容模型重排 |
|
||||
| 父子分块 | 支持 | 可通过索引与大分块组合 | 支持多种切分策略 | 第二阶段支持 |
|
||||
| 分块维护 | 支持内容维护 | 支持数据维护 | 支持块级检查 | 第二阶段支持 |
|
||||
| 深度文档理解 | 中等 | 中等 | 强 | 继续复用本地解析与 OCR |
|
||||
| 本地目录监听 | 非核心 | 非核心 | 非核心 | GoodBuddy 差异化能力 |
|
||||
| 本地可编辑图谱 | 非核心 | 非核心 | 部分版本支持 GraphRAG | GoodBuddy 差异化能力 |
|
||||
|
||||
本期不复制竞品的云端工作流平台,而是将其成熟 RAG 交互映射为桌面、本地、
|
||||
受控的数据链路。
|
||||
|
||||
参考公开文档:
|
||||
|
||||
- Dify Knowledge:
|
||||
<https://docs.dify.ai/en/use-dify/knowledge/readme>
|
||||
- Dify 检索测试:
|
||||
<https://docs.dify.ai/en/use-dify/knowledge/test-retrieval>
|
||||
- Dify 分块设置:
|
||||
<https://docs.dify.ai/en/use-dify/knowledge/create-knowledge/chunking-and-cleaning>
|
||||
- FastGPT 知识库搜索方案和参数:
|
||||
<https://doc.fastgpt.io/docs/introduction/guide/knowledge_base/dataset_engine>
|
||||
- RAGFlow Dataset 配置:
|
||||
<https://ragflow.io/docs/configure_knowledge_base>
|
||||
- RAGFlow 检索测试:
|
||||
<https://ragflow.io/docs/run_retrieval_test>
|
||||
|
||||
## 6. 信息架构
|
||||
|
||||
知识工作区继续使用主从布局和现有四个页签:
|
||||
|
||||
```text
|
||||
知识库
|
||||
├─ 文档与来源
|
||||
│ ├─ 来源管理
|
||||
│ ├─ 检索测试入口
|
||||
│ ├─ 文档状态
|
||||
│ └─ 分块查看与维护
|
||||
├─ 知识图谱
|
||||
├─ 任务中心
|
||||
└─ 设置
|
||||
├─ 检索设置
|
||||
├─ 分块设置
|
||||
└─ 图谱设置
|
||||
```
|
||||
|
||||
“检索测试”是当前知识库的高频诊断操作,通过知识库标题区次操作打开独立
|
||||
工作台,不新增第五个一级页签。
|
||||
|
||||
对话输入区的知识范围弹层包含:
|
||||
|
||||
1. 已启用知识库多选。
|
||||
2. 检索方式:模型按需检索、每次先检索。
|
||||
3. 当前范围为空、索引降级或向量未配置时的短说明。
|
||||
|
||||
## 7. 第一阶段:可用、可见、可诊断
|
||||
|
||||
### 7.1 检索方式
|
||||
|
||||
新增请求级 `knowledgeRetrievalMode`:
|
||||
|
||||
| 值 | 用户文案 | 行为 |
|
||||
| --- | --- | --- |
|
||||
| `auto` | 模型按需检索 | 保留当前 `knowledge_search` 工具,由模型决定是否调用 |
|
||||
| `always` | 每次先检索 | Main 在启动 Runtime 前使用原始用户问题检索一次,再把有界证据作为不可信上下文提供给 Runtime |
|
||||
|
||||
规则:
|
||||
|
||||
- 没有启用知识库时不显示为“已检索”。
|
||||
- `always` 预检索后仍保留 `knowledge_search`,模型可以改写查询再次检索。
|
||||
- 预检索零结果不阻止回答,但必须显示“已检索,未找到相关内容”。
|
||||
- 预检索失败不得自动扩大范围或访问未选知识库。
|
||||
- 图片生成能力不执行知识预检索。
|
||||
- Ask 和 Execute 使用相同的只读检索范围。
|
||||
|
||||
### 7.2 中文全文检索
|
||||
|
||||
在现有 `unicode61` FTS 之外增加本地 CJK n-gram 检索文本:
|
||||
|
||||
- 连续汉字生成二元词组,保留必要的单字符短查询回退。
|
||||
- 拉丁字母和数字使用 NFKC、大小写归一化和现有 FTS。
|
||||
- 多个查询词使用召回优先的 OR 候选,再通过覆盖率和短语命中重排。
|
||||
- 不把整句中文问题转换成“所有汉字必须同时出现”的条件。
|
||||
- 索引更新、分块编辑、停用和删除必须同步更新 CJK 索引。
|
||||
- 数据库迁移必须为已有分块有界回填,不要求用户重新导入。
|
||||
|
||||
### 7.3 检索设置
|
||||
|
||||
每个知识库保存以下设置:
|
||||
|
||||
| 字段 | 范围 | 默认值 |
|
||||
| --- | --- | --- |
|
||||
| `topK` | 1 至 20 | 6 |
|
||||
| `minimumVectorSimilarity` | 0 至 1 | 0(不过滤低相似度结果) |
|
||||
| `ftsWeight` | 0 至 2 | 1 |
|
||||
| `vectorWeight` | 0 至 2 | 1 |
|
||||
| `graphWeight` | 0 至 2 | 0.8 |
|
||||
| `candidateMultiplier` | 2 至 10 | 4 |
|
||||
| `contextMaxCharacters` | 2,000 至 48,000 | 16,000 |
|
||||
| `adjacentChunkCount` | 0 至 2 | 0 |
|
||||
| `localRerankEnabled` | 布尔值 | false |
|
||||
|
||||
至少一个召回通道权重大于 0。图谱未启用时,图谱权重只读显示为不可用。
|
||||
向量模型未启用或索引不兼容时,向量权重保留但当前请求降级。
|
||||
|
||||
### 7.4 检索测试工作台
|
||||
|
||||
用户输入最多 4,000 字符的问题,工作台显示:
|
||||
|
||||
- 当前知识库和生效设置。
|
||||
- 总耗时、各通道耗时和候选数。
|
||||
- 请求通道、实际使用通道和降级原因。
|
||||
- 最终结果序号、文档、定位、片段和最终相关度。
|
||||
- FTS、CJK、向量、图谱的独立排名与向量相似度。
|
||||
- 本地重排前后排名。
|
||||
- 相邻分块或父块合并后的实际上下文。
|
||||
- “查看分块”“打开来源”操作。
|
||||
|
||||
检索测试不创建聊天消息、不写入会话历史、不调用 LLM,也不改变知识库内容。
|
||||
|
||||
### 7.5 可扩展向量搜索
|
||||
|
||||
移除“超过 5,000 个候选则返回空结果”的逻辑:
|
||||
|
||||
1. 按稳定游标分页读取同一知识库、Provider、Model 和维度的向量。
|
||||
2. 每批计算余弦相似度。
|
||||
3. 内存中只保留候选上限所需的最佳结果。
|
||||
4. 支持取消和应用关闭。
|
||||
5. 维度、校验和或索引状态不匹配的向量不参与结果。
|
||||
6. 诊断返回扫描数量和向量耗时。
|
||||
7. Provider Fingerprint 不匹配时标记索引不兼容,不回退到同名旧模型向量。
|
||||
|
||||
线性扫描是本期跨平台保底实现。后续接入稳定向量扩展时不得改变上层契约。
|
||||
|
||||
### 7.6 状态与降级
|
||||
|
||||
文档状态拆分为:
|
||||
|
||||
| 状态 | 含义 |
|
||||
| --- | --- |
|
||||
| 解析 | 等待、运行、完成、失败 |
|
||||
| 全文索引 | 等待、完成、失败 |
|
||||
| 向量索引 | 未启用、等待、运行、完成、失败、不兼容 |
|
||||
| 图谱 | 未启用、按需、等待、运行、完成、失败 |
|
||||
|
||||
知识库汇总不得仅以“文档 metadata 不是 failed”计算完成。UI 至少显示:
|
||||
|
||||
- 可用于全文检索的文档数。
|
||||
- 已完成向量化的文档数。
|
||||
- 失败文档数。
|
||||
- 当前向量模型与索引是否兼容。
|
||||
|
||||
降级事件包括:
|
||||
|
||||
- 未配置向量模型。
|
||||
- 查询向量生成失败。
|
||||
- 当前模型没有匹配索引。
|
||||
- 部分文档向量失败。
|
||||
- 图谱关闭或没有证据。
|
||||
- 结果被相关度或上下文预算过滤。
|
||||
|
||||
### 7.7 引用查看
|
||||
|
||||
每条引用增加稳定 `chunkId`、最终相关度和检索通道。用户展开引用后可以:
|
||||
|
||||
1. 查看命中分块。
|
||||
2. 查看相邻分块或父块形成的完整上下文。
|
||||
3. 查看知识库、文档、来源和定位。
|
||||
4. 对本地文件调用 Main 校验后的 `shell.openPath`。
|
||||
5. 对 HTTP(S) 来源调用 Main 校验后的外部打开。
|
||||
|
||||
Renderer 不能提交任意路径或 URL。Main 必须根据 `libraryId`、`documentId` 和
|
||||
`chunkId` 重新读取已保存来源并验证归属。
|
||||
|
||||
界面把该列表描述为“本次检索证据”或“已查阅来源”,不把仅被召回的片段
|
||||
自动宣称为回答中某个句子的精确出处。后续只有经过稳定 Citation ID 校验的
|
||||
句级标注才能使用更强的“该句引用”语义。
|
||||
|
||||
## 8. 第二阶段:可调、可优化、可维护
|
||||
|
||||
### 8.1 分块模式
|
||||
|
||||
每个知识库选择一种模式:
|
||||
|
||||
| 模式 | 行为 | 适用内容 |
|
||||
| --- | --- | --- |
|
||||
| 固定分块 | 按目标长度、重叠和自然边界切分 | 普通文本、日志、代码 |
|
||||
| 结构分块 | 优先保持解析 section、Markdown 标题和段落结构 | 手册、制度、长文档 |
|
||||
| 父子分块 | 小块用于召回,大块用于模型上下文 | 长篇说明、合同、研究资料 |
|
||||
|
||||
设置:
|
||||
|
||||
| 字段 | 范围 | 默认值 |
|
||||
| --- | --- | --- |
|
||||
| `mode` | `fixed` / `structure` / `parent-child` | `structure` |
|
||||
| `targetCharacters` | 400 至 8,000 | 1,600 |
|
||||
| `overlapCharacters` | 0 至目标长度的 40% | 160 |
|
||||
| `parentCharacters` | 1,600 至 16,000 | 4,800 |
|
||||
| `childCharacters` | 300 至 4,000 | 900 |
|
||||
|
||||
父子分块要求:
|
||||
|
||||
- 父块只作为上下文,不进入 FTS、CJK 或向量候选。
|
||||
- 子块用于召回,并保存父块关联。
|
||||
- 引用默认突出子块,同时允许查看父块全文。
|
||||
- 父块和子块总输出仍受上下文预算限制。
|
||||
|
||||
### 8.2 本地与学习型重排
|
||||
|
||||
第二阶段提供不调用外部模型的可选本地重排。评分特征包括:
|
||||
|
||||
- 原始 RRF 排名。
|
||||
- 中文和拉丁词覆盖率。
|
||||
- 完整短语命中。
|
||||
- 文档标题、分块标题和路径命中。
|
||||
- 向量相似度。
|
||||
- 同文档重复结果惩罚。
|
||||
|
||||
重排结果必须:
|
||||
|
||||
- 归一化为 0 至 1 的 `relevance`。
|
||||
- 对相同输入和索引保持确定性。
|
||||
- 保留重排前排名和各特征得分用于诊断。
|
||||
- 在关闭时完全保留原有 RRF 排序。
|
||||
|
||||
学习型模式使用 Main 进程中的 Cohere/Jina 兼容客户端,凭据只进入加密设置和
|
||||
Main 进程。请求限制为 100 个候选、每个候选 8,000 字符,并具有 15 秒默认
|
||||
超时、取消传播和有界响应。失败时可回退本地重排或 RRF,并只返回脱敏诊断。
|
||||
|
||||
### 8.3 相邻分块合并与上下文预算
|
||||
|
||||
- 对最终候选按文档和 ordinal 合并相邻分块。
|
||||
- 不把同一分块重复放入上下文。
|
||||
- 保留每个命中分块的引用定位。
|
||||
- 按相关度从高到低消耗 `contextMaxCharacters`。
|
||||
- 单个超长父块按安全边界截断并标记 `truncated`。
|
||||
- 不允许低排名结果挤掉已经选中的高排名证据。
|
||||
|
||||
### 8.4 分块管理
|
||||
|
||||
文档行提供“查看分块”,打开分块管理对话框:
|
||||
|
||||
- 显示 ordinal、角色、标题、定位、字符数、启用状态和内容预览。
|
||||
- 支持分页和文档内搜索。
|
||||
- 支持编辑内容。
|
||||
- 支持启用或停用。
|
||||
- 支持删除,并说明来源同步可能重新创建分块。
|
||||
- 编辑后更新 FTS 和 CJK 索引,并使旧向量失效。
|
||||
- 已配置向量模型时,编辑操作完成后为该文档重建向量。
|
||||
- 删除最后一个可检索分块时,文档显示“无可检索内容”,不能显示完全就绪。
|
||||
|
||||
高影响删除使用具体确认文案。普通启停使用共享 Switch,并声明
|
||||
`role="switch"`。
|
||||
|
||||
### 8.5 单文档与全库重建
|
||||
|
||||
- 单文档重建重新读取来源、解析、分块、全文索引、向量和图谱。
|
||||
- 全库重建按来源顺序执行,并显示文档级进度。
|
||||
- 修改分块模式或关键参数后,知识库显示“设置已更新,等待重建”。
|
||||
- 重建采用文档级原子替换,失败时保留上一版可用分块和向量。
|
||||
- 用户可以取消全库重建;已经成功替换的文档保持可用。
|
||||
- 文件不存在、网页失败或 OCR 不可用时保留可重试错误。
|
||||
- 单来源允许的 2,000 个文件必须全部参与增量同步、删除检测和校验和跳过,
|
||||
不受普通页面 500 项列表上限影响。
|
||||
|
||||
## 9. 数据模型与兼容性
|
||||
|
||||
### 9.1 KnowledgeBase
|
||||
|
||||
知识库增加版本化设置:
|
||||
|
||||
```ts
|
||||
type KnowledgeRetrievalSettings = {
|
||||
version: 1
|
||||
topK: number
|
||||
minimumVectorSimilarity: number
|
||||
ftsWeight: number
|
||||
vectorWeight: number
|
||||
graphWeight: number
|
||||
candidateMultiplier: number
|
||||
contextMaxCharacters: number
|
||||
adjacentChunkCount: number
|
||||
localRerankEnabled: boolean
|
||||
}
|
||||
|
||||
type KnowledgeChunkingSettings = {
|
||||
version: 1
|
||||
mode: 'fixed' | 'structure' | 'parent-child'
|
||||
targetCharacters: number
|
||||
overlapCharacters: number
|
||||
parentCharacters: number
|
||||
childCharacters: number
|
||||
}
|
||||
```
|
||||
|
||||
SQLite 使用 JSON 列保存设置,读写均经过共享 Zod Schema。迁移后的旧知识库使用
|
||||
与当前行为接近的兼容默认值,不自动重建已有分块。
|
||||
|
||||
### 9.2 Chunk
|
||||
|
||||
分块增加以下语义:
|
||||
|
||||
```ts
|
||||
type KnowledgeChunkRole = 'standalone' | 'parent' | 'child'
|
||||
|
||||
type KnowledgeChunkState = {
|
||||
enabled: boolean
|
||||
role: KnowledgeChunkRole
|
||||
parentChunkId?: string
|
||||
manuallyEdited: boolean
|
||||
updatedAt?: string
|
||||
}
|
||||
```
|
||||
|
||||
实现可以使用显式列或受校验 metadata,但查询必须为旧数据提供默认值:
|
||||
|
||||
- 缺少 `enabled` 时视为 `true`。
|
||||
- 缺少 `role` 时视为 `standalone`。
|
||||
- 父块不参与召回索引。
|
||||
|
||||
### 9.3 检索响应
|
||||
|
||||
```ts
|
||||
type KnowledgeRetrievalResponse = {
|
||||
query: string
|
||||
durationMs: number
|
||||
settings: KnowledgeRetrievalSettings
|
||||
diagnostics: {
|
||||
requestedChannels: KnowledgeRetrievalChannel[]
|
||||
usedChannels: KnowledgeRetrievalChannel[]
|
||||
degradedChannels: Array<{
|
||||
channel: KnowledgeRetrievalChannel
|
||||
reason: string
|
||||
}>
|
||||
candidateCounts: Partial<Record<KnowledgeRetrievalChannel, number>>
|
||||
}
|
||||
results: KnowledgeRetrievalResult[]
|
||||
context: {
|
||||
characterCount: number
|
||||
truncated: boolean
|
||||
groups: KnowledgeContextGroup[]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
错误、诊断和引用不得包含 API Key、Authorization Header、完整私人文档或未经
|
||||
限制的 Provider 响应。
|
||||
|
||||
## 10. IPC 与安全边界
|
||||
|
||||
新增或扩展的 IPC:
|
||||
|
||||
- `knowledge:retrieve`
|
||||
- `knowledge:settings:update`
|
||||
- `knowledge:document:rebuild`
|
||||
- `knowledge:library:rebuild`
|
||||
- `knowledge:chunks:list`
|
||||
- `knowledge:chunk:update`
|
||||
- `knowledge:chunk:delete`
|
||||
- `knowledge:reference:context`
|
||||
- `knowledge:reference:open`
|
||||
|
||||
要求:
|
||||
|
||||
- 所有输入由共享 Zod Schema 校验。
|
||||
- 所有处理器校验可信 Renderer sender。
|
||||
- ID 必须重新检查知识库、来源、文档和分块归属。
|
||||
- 列表使用有界分页,单次最多返回 200 个分块。
|
||||
- 内容编辑限制单块最大字符数。
|
||||
- 外部打开只接受数据库已保存的本地普通文件或 HTTP(S) URL。
|
||||
- 不向 Preload 暴露原始数据库、Electron `shell` 或文件系统 API。
|
||||
- 更新与重建遵守取消、超时、应用关闭和有界错误规则。
|
||||
|
||||
## 11. 交互与无障碍
|
||||
|
||||
- 复用 `PageTabs`、`SegmentedControl`、共享 Switch 和应用通知。
|
||||
- 检索方式是互斥选项,使用 `SegmentedControl` 或语义化单选组。
|
||||
- 分块启停是持久二元状态,使用 `role="switch"`。
|
||||
- 检索结果列表使用可访问名称,得分不得只用颜色表达。
|
||||
- 检索工作台打开后焦点进入问题输入框,关闭后返回触发按钮。
|
||||
- 分块编辑和删除对话框遵守焦点陷阱、Escape 和焦点恢复。
|
||||
- 异步成功使用应用通知;字段错误、检索进度和可就地恢复错误保留在工作台。
|
||||
- 窄窗口下检索结果改为单列,配置摘要保持可读,不隐藏降级状态。
|
||||
|
||||
## 12. 失败与恢复
|
||||
|
||||
| 场景 | 行为 |
|
||||
| --- | --- |
|
||||
| 向量查询失败 | 继续全文和图谱检索,显示降级原因 |
|
||||
| 部分文档无向量 | 使用可用文档,显示完成数和失败数 |
|
||||
| CJK 索引迁移失败 | 回滚迁移,不损坏旧 FTS |
|
||||
| 重排失败 | 回退 RRF 排序并显示诊断 |
|
||||
| 分块编辑后向量失败 | 保留编辑和全文索引,标记向量失败 |
|
||||
| 单文档重建失败 | 保留上一版可用索引 |
|
||||
| 同名模型端点变化 | 旧 Fingerprint 索引标记不兼容,等待重建 |
|
||||
| 新向量重建失败 | 保留上一版就绪向量继续服务,单独记录失败尝试 |
|
||||
| 原文件已移动 | 显示来源不可用,提供重试或移除 |
|
||||
| 引用对象已删除 | 显示引用已失效,不打开任意替代路径 |
|
||||
| 上下文超预算 | 按排名截断并明确标记 |
|
||||
| 请求取消或应用关闭 | 停止新批次,释放句柄,不留下半替换索引 |
|
||||
|
||||
## 13. 埋点与评测
|
||||
|
||||
GoodBuddy 不上传私人检索查询或文档内容。本地诊断至少记录有界统计:
|
||||
|
||||
- 检索模式。
|
||||
- 启用知识库数量。
|
||||
- 各通道候选数和耗时。
|
||||
- 是否发生降级。
|
||||
- 最终结果数和上下文字符数。
|
||||
- 重建文档数、成功数、失败数和取消状态。
|
||||
|
||||
手动验收使用仓库内不含私人内容的固定样例集,覆盖:
|
||||
|
||||
- 中文自然语言改写和同义词。
|
||||
- 中英文混合产品名。
|
||||
- 精确编号、路径和代码标识。
|
||||
- 多文档冲突信息。
|
||||
- 无答案问题。
|
||||
- 10,000 个以上分块。
|
||||
- 向量服务断开和模型维度变化。
|
||||
|
||||
## 14. 实施顺序
|
||||
|
||||
### 14.1 第一阶段
|
||||
|
||||
1. 共享设置、请求和检索响应契约。
|
||||
2. SQLite 迁移和 CJK 索引。
|
||||
3. 可扩展向量扫描、检索诊断和状态模型。
|
||||
4. 检索设置与工作台。
|
||||
5. 对话“每次先检索”。
|
||||
6. 引用上下文和打开来源。
|
||||
7. 第一阶段单元、IPC 和 Renderer 测试。
|
||||
|
||||
### 14.2 第二阶段
|
||||
|
||||
1. 结构分块和父子分块。
|
||||
2. 本地重排与相关度。
|
||||
3. 相邻块合并和上下文预算。
|
||||
4. 分块预览、编辑、启停和删除。
|
||||
5. 单文档与全库重建。
|
||||
6. 第二阶段回归、性能和生产构建验证。
|
||||
|
||||
## 15. 验收标准
|
||||
|
||||
### 15.1 第一阶段
|
||||
|
||||
- 用户可在对话中选择“模型按需检索”或“每次先检索”。
|
||||
- “每次先检索”在 Runtime 启动前产生检索诊断和引用,即使模型未调用工具。
|
||||
- 未配置向量模型时,中文改写问题仍能通过 CJK 索引召回相关分块。
|
||||
- 向量查询失败时回答可继续,界面明确显示已降级。
|
||||
- 10,000 个分块的向量测试能够返回正确 Top K,不出现固定上限空结果。
|
||||
- 同名模型切换端点后,不会读取 Fingerprint 不匹配的旧向量。
|
||||
- 重建失败时,上一版已就绪向量仍能继续召回。
|
||||
- 包含 2,000 个文件的目录同步能够处理第 501 至 2,000 个文档的修改与删除。
|
||||
- 检索测试展示通道、候选数、排名、相关度、上下文和降级原因。
|
||||
- 引用可以查看完整上下文并打开 Main 校验后的来源。
|
||||
- 查询长度在共享契约、IPC、MCP 和数据库层保持一致。
|
||||
|
||||
### 15.2 第二阶段
|
||||
|
||||
- 用户可选择固定、结构或父子分块并显式重建。
|
||||
- 父块不参与召回,子块命中后可提供父块上下文。
|
||||
- 本地重排可以开启或关闭,并显示重排前后排名。
|
||||
- 上下文严格遵守字符预算,重复和相邻片段按规则合并。
|
||||
- 用户可预览、编辑、启停和删除分块。
|
||||
- 分块修改后 FTS、CJK 和向量状态保持一致。
|
||||
- 单文档重建失败不会破坏上一版可用索引。
|
||||
- 所有新增操作可用键盘完成,并在浅色、深色和窄窗口下可用。
|
||||
|
||||
### 15.3 工程验证
|
||||
|
||||
所有源代码变更完成后必须通过:
|
||||
|
||||
```text
|
||||
npm test
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm run build
|
||||
```
|
||||
|
||||
外部或付费模型调用不属于自动验证,只有获得明确授权后才运行。
|
||||
@@ -0,0 +1,523 @@
|
||||
# 知识库检索与分块增强 User Stories
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 实施中 |
|
||||
| 版本 | 0.1 |
|
||||
| 日期 | 2026-08-11 |
|
||||
| 关联 PRD | [知识库检索与分块增强 PRD](knowledge-rag-enhancement-prd.md) |
|
||||
|
||||
## 1. 角色
|
||||
|
||||
### 1.1 普通知识使用者
|
||||
|
||||
已经导入公司制度、产品手册或项目资料,希望直接提问并得到稳定、带来源的回答,
|
||||
不需要理解向量、RRF 或分块算法。
|
||||
|
||||
### 1.2 知识库维护者
|
||||
|
||||
负责导入、同步和清理资料,需要知道哪些文档成功、哪些索引失败,以及如何修复
|
||||
错误解析或错误分块。
|
||||
|
||||
### 1.3 RAG 调试者
|
||||
|
||||
需要用真实问题验证召回,比较不同参数和通道,定位“文档里有但没有命中”的
|
||||
原因。
|
||||
|
||||
### 1.4 本地与内网用户
|
||||
|
||||
不能把资料上传到外部知识库服务,希望全文检索、分块、重排和诊断均在本机
|
||||
完成,只在显式配置 Embeddings 后发送有界文本。
|
||||
|
||||
## 2. Epic A:明确控制是否检索
|
||||
|
||||
### US-A1 模型按需检索
|
||||
|
||||
作为普通知识使用者,我希望保留由模型判断是否需要检索的模式,以便一般闲聊
|
||||
不会产生不必要的知识搜索。
|
||||
|
||||
验收:
|
||||
|
||||
- Given 当前启用了至少一个知识库并选择“模型按需检索”
|
||||
- When 用户发送问题
|
||||
- Then Main 只向本次请求开放已选知识库的只读搜索能力
|
||||
- And 模型没有调用知识搜索时,不显示虚假的“已检索”
|
||||
- And 未选中的知识库不可被工具参数扩大范围
|
||||
|
||||
### US-A2 每次先检索
|
||||
|
||||
作为普通知识使用者,我希望选择“每次先检索”,以便模型不能跳过已启用的
|
||||
知识库。
|
||||
|
||||
验收:
|
||||
|
||||
- Given 当前启用了至少一个知识库并选择“每次先检索”
|
||||
- When 用户发送文本问题
|
||||
- Then Main 在 Runtime 启动前使用原始问题执行一次有界检索
|
||||
- And 命中证据以不可信上下文进入 Runtime
|
||||
- And 模型仍可通过只读工具执行后续改写检索
|
||||
- And 页面明确显示“已预检索”“零结果”或“已降级”
|
||||
- And 图片生成请求不执行知识预检索
|
||||
|
||||
### US-A3 请求级范围
|
||||
|
||||
作为普通知识使用者,我希望每次请求只使用我勾选的知识库,以免不相关资料
|
||||
干扰回答。
|
||||
|
||||
验收:
|
||||
|
||||
- 新建知识库后只新增该知识库到当前选择,不自动重新启用已取消的知识库
|
||||
- 删除知识库后从当前范围中移除对应 ID
|
||||
- 同一请求最多启用 20 个知识库
|
||||
- 对话输入区持续显示已选数量和检索方式
|
||||
- 范围为空时检索方式不产生误导状态
|
||||
|
||||
## 3. Epic B:检索可见、可诊断
|
||||
|
||||
### US-B1 打开检索测试
|
||||
|
||||
作为 RAG 调试者,我希望在当前知识库直接输入问题并测试,以便不通过聊天模型
|
||||
也能验证索引。
|
||||
|
||||
验收:
|
||||
|
||||
- 知识库标题区提供“测试检索”次操作
|
||||
- 工作台打开后焦点进入查询输入框
|
||||
- 查询最多 4,000 字符
|
||||
- 测试不创建聊天消息、任务成果或模型调用
|
||||
- 关闭工作台后焦点返回触发按钮
|
||||
|
||||
### US-B2 查看通道诊断
|
||||
|
||||
作为 RAG 调试者,我希望看到每种检索通道的结果和降级原因,以便判断问题来自
|
||||
全文、向量还是图谱。
|
||||
|
||||
验收:
|
||||
|
||||
- 结果显示请求通道和实际使用通道
|
||||
- 结果显示 FTS/CJK、向量和图谱候选数
|
||||
- 结果显示总耗时和有界通道耗时
|
||||
- 向量未配置、请求失败或索引不兼容时显示明确原因
|
||||
- 不在错误或诊断中显示 API Key、Authorization 或完整文档
|
||||
|
||||
### US-B3 查看排名与上下文
|
||||
|
||||
作为 RAG 调试者,我希望看到候选排名、最终相关度和送入模型的上下文,以便
|
||||
解释最终回答为什么使用这些资料。
|
||||
|
||||
验收:
|
||||
|
||||
- 每条结果显示文档、定位、片段和最终排名
|
||||
- 可用时显示全文、向量、图谱独立排名和向量相似度
|
||||
- 启用本地重排后显示重排前排名
|
||||
- 展示相邻块或父块合并后的上下文
|
||||
- 展示上下文字符数、预算和截断状态
|
||||
|
||||
### US-B4 零结果诊断
|
||||
|
||||
作为普通知识使用者,我希望零结果时获得具体原因,而不是只有空列表。
|
||||
|
||||
验收:
|
||||
|
||||
- 区分“知识库为空”“索引不可用”“查询无命中”“被阈值过滤”
|
||||
- 提供修改关键词、检查状态或调整阈值的下一步说明
|
||||
- 零结果不显示为首次使用空状态
|
||||
- 检索测试保留原查询和设置,方便再次执行
|
||||
|
||||
## 4. Epic C:中文与混合检索
|
||||
|
||||
### US-C1 中文自然语言召回
|
||||
|
||||
作为中文用户,我希望不用输入原文中的连续短语,也能找到表达相同意思的内容。
|
||||
|
||||
验收:
|
||||
|
||||
- 中文索引生成连续二元词组
|
||||
- 中文查询不会要求所有不同汉字同时出现
|
||||
- 短查询具有有界单字回退
|
||||
- 中英文、数字和产品标识混合查询仍能召回
|
||||
- 相同查询和索引产生稳定排序
|
||||
|
||||
### US-C2 向量服务降级
|
||||
|
||||
作为本地与内网用户,我希望向量服务断开时仍可使用全文搜索,同时清楚知道
|
||||
语义召回不可用。
|
||||
|
||||
验收:
|
||||
|
||||
- 查询向量失败不阻止 FTS/CJK 和图谱检索
|
||||
- 检索响应包含向量降级原因
|
||||
- 文档状态不把向量失败显示成全部完成
|
||||
- 同名模型切换端点后,Fingerprint 不匹配的旧向量不得参与召回
|
||||
- 重建失败时,上一版已就绪向量继续服务
|
||||
- 修复配置并重建后,降级状态消失
|
||||
- 故障信息经过脱敏
|
||||
|
||||
### US-C3 大知识库向量检索
|
||||
|
||||
作为知识库维护者,我希望超过 5,000 个分块后语义搜索仍然工作。
|
||||
|
||||
验收:
|
||||
|
||||
- 向量分批扫描没有固定 5,000 分块空结果
|
||||
- 只保留所需最佳候选,内存不会随全库候选等比例增长
|
||||
- 扫描支持取消和应用关闭
|
||||
- 10,000 个以上分块的测试返回正确 Top K
|
||||
- 诊断显示扫描数量与耗时
|
||||
|
||||
### US-C4 大目录完整同步
|
||||
|
||||
作为知识库维护者,我希望包含 2,000 个文件的目录也能完整增量同步,以免后半
|
||||
部分文档长期保留旧内容。
|
||||
|
||||
验收:
|
||||
|
||||
- 第 501 至 2,000 个文档参与校验和比较
|
||||
- 未变化文档不会重复解析和向量化
|
||||
- 已删除文件对应文档会被移除
|
||||
- 页面分页上限不影响后台同步完整性
|
||||
|
||||
### US-C5 调整召回参数
|
||||
|
||||
作为 RAG 调试者,我希望调整 Top K、最低相关度和通道权重,以便适配不同知识
|
||||
类型。
|
||||
|
||||
验收:
|
||||
|
||||
- Top K、阈值、候选倍数和权重具有明确范围和默认值
|
||||
- 至少一个召回通道权重大于 0
|
||||
- 图谱关闭时图谱权重不可生效并说明原因
|
||||
- 设置持久化到当前知识库,不影响其他知识库
|
||||
- 非法输入不能跨 IPC
|
||||
|
||||
## 5. Epic D:真实索引状态
|
||||
|
||||
### US-D1 查看分阶段状态
|
||||
|
||||
作为知识库维护者,我希望分别看到解析、全文、向量和图谱状态,以便准确判断
|
||||
文档能否使用。
|
||||
|
||||
验收:
|
||||
|
||||
- 文档不再用单个“ready”代表所有索引完成
|
||||
- 全文完成但向量失败时,明确显示“全文可用、向量失败”
|
||||
- 向量未启用与向量失败是不同状态
|
||||
- 图谱按需、未启用和失败是不同状态
|
||||
- 汇总显示全文可用数、向量完成数和失败数
|
||||
|
||||
### US-D2 修复失败文档
|
||||
|
||||
作为知识库维护者,我希望单独重建失败文档,而不是重新同步整个目录。
|
||||
|
||||
验收:
|
||||
|
||||
- 文档行提供“重建文档”
|
||||
- 重建重新执行解析、分块、全文、向量和图谱
|
||||
- 失败时保留上一版可用索引
|
||||
- 完成后更新任务和状态
|
||||
- 原文件不存在时保留可重试错误
|
||||
|
||||
### US-D3 修改设置后重建
|
||||
|
||||
作为知识库维护者,我希望分块设置修改后明确提示需要重建,以免误以为旧文档
|
||||
已经使用新设置。
|
||||
|
||||
验收:
|
||||
|
||||
- 保存关键分块设置后显示“等待重建”
|
||||
- 设置保存本身不删除现有索引
|
||||
- 用户可选择全库重建
|
||||
- 全库重建可取消
|
||||
- 已成功替换的文档继续可用
|
||||
|
||||
## 6. Epic E:高级分块
|
||||
|
||||
### US-E1 固定分块
|
||||
|
||||
作为知识库维护者,我希望配置目标长度和重叠,以便处理日志、代码或简单文本。
|
||||
|
||||
验收:
|
||||
|
||||
- 目标长度为 400 至 8,000 字符
|
||||
- 重叠不超过目标长度的 40%
|
||||
- 优先在自然边界切分
|
||||
- 每个块保留来源 section、定位和 ordinal
|
||||
- 旧知识库迁移后不自动改变已有分块
|
||||
|
||||
### US-E2 结构分块
|
||||
|
||||
作为知识库维护者,我希望分块尽量保持标题和段落结构,以便命中片段保留语义。
|
||||
|
||||
验收:
|
||||
|
||||
- 优先保持解析 section
|
||||
- Markdown 标题能够成为分块 heading
|
||||
- 标题随子段落进入索引元数据
|
||||
- 超长 section 仍按有界规则继续切分
|
||||
- 空标题和空段落不创建分块
|
||||
|
||||
### US-E3 父子分块
|
||||
|
||||
作为 RAG 调试者,我希望小块负责准确召回、大块负责完整上下文,以便兼顾精度
|
||||
和完整性。
|
||||
|
||||
验收:
|
||||
|
||||
- 父块和子块具有稳定关系
|
||||
- 父块不直接进入 FTS/CJK/向量候选
|
||||
- 子块命中后可返回父块上下文
|
||||
- 引用突出实际命中的子块
|
||||
- 父块输出仍受上下文预算和截断限制
|
||||
|
||||
## 7. Epic F:重排与上下文
|
||||
|
||||
### US-F1 本地重排
|
||||
|
||||
作为本地与内网用户,我希望在不调用外部模型的情况下改善候选排序。
|
||||
|
||||
验收:
|
||||
|
||||
- 本地重排默认关闭并可按知识库开启
|
||||
- 使用 RRF、词覆盖、短语、标题、路径、向量和重复惩罚等确定性特征
|
||||
- 结果相关度归一化到 0 至 1
|
||||
- 检索测试显示重排前后排名
|
||||
- 关闭时保持原 RRF 行为
|
||||
- UI 不把本地算法描述为 AI Rerank 模型
|
||||
|
||||
### US-F1.1 学习型重排
|
||||
|
||||
作为需要更高排序质量的用户,我希望可选择兼容的学习型重排模型,并在服务
|
||||
不可用时继续获得本地结果。
|
||||
|
||||
验收:
|
||||
|
||||
- 模式明确区分关闭、本地规则和学习型重排
|
||||
- Main 最多发送 100 个候选,每个候选不超过 8,000 字符
|
||||
- API Key 仅通过环境变量或 Main 加密存储使用,不进入 Renderer
|
||||
- 超时、无效响应和服务错误回退本地重排,并显示脱敏诊断
|
||||
- 用户取消和应用关闭必须终止请求,不得按普通降级吞掉
|
||||
|
||||
### US-F2 相邻分块合并
|
||||
|
||||
作为普通知识使用者,我希望命中片段包含必要的上下文,而不是孤立半句话。
|
||||
|
||||
验收:
|
||||
|
||||
- 可配置向前、向后相邻 0 至 2 个块
|
||||
- 只合并同文档且 ordinal 连续的启用分块
|
||||
- 同一块不会重复输出
|
||||
- 每个原命中仍保留引用定位
|
||||
- 合并结果遵守上下文预算
|
||||
|
||||
### US-F3 上下文预算
|
||||
|
||||
作为普通知识使用者,我希望低质量内容不会挤占模型上下文。
|
||||
|
||||
验收:
|
||||
|
||||
- 按最终相关度从高到低选择上下文
|
||||
- 已选择的高排名证据不会被低排名证据替换
|
||||
- 超预算时明确标记截断
|
||||
- 预算范围为 2,000 至 48,000 字符
|
||||
- IPC 和 Runtime 输入继续受总大小限制
|
||||
|
||||
### US-F4 上下文索引
|
||||
|
||||
作为知识库维护者,我希望检索可以利用文档结构,而引用仍忠于原文。
|
||||
|
||||
验收:
|
||||
|
||||
- 可按知识库启用上下文索引,并在修改后提示显式重建
|
||||
- 标题、标题层级、页码和块类型使用有界确定性前缀进入 FTS、CJK 和向量文本
|
||||
- 原始分块、引用、模型上下文和图谱证据不显示生成前缀
|
||||
- FTS、CJK、向量和内容校验使用同一规范索引文本
|
||||
|
||||
## 7.1 Epic F+:受控本体与检索评估
|
||||
|
||||
### US-F5 每库受控本体
|
||||
|
||||
作为知识库维护者,我希望控制可用实体和关系类型,以便图谱保持一致。
|
||||
|
||||
验收:
|
||||
|
||||
- 每库保存实体类型、关系类型、双语名称、别名和可选端点约束
|
||||
- 手工编辑使用受控选择器并拒绝未知类型或不兼容端点
|
||||
- 图谱抽取按类型解析实体,保留人工锁定字段和跨类型边界
|
||||
- 证据保存原文偏移、置信度、抽取来源和有界 provenance
|
||||
- 本体或启用中的图谱策略变化标记需要重建
|
||||
|
||||
### US-F6 离线检索评估
|
||||
|
||||
作为 RAG 维护者,我希望用固定双语样本检测召回回归,而不读取用户数据或调用
|
||||
网络服务。
|
||||
|
||||
验收:
|
||||
|
||||
- `npm run eval:retrieval` 使用临时 SQLite 和确定性内存 Provider
|
||||
- 报告 Recall@5/10、MRR@10、nDCG@10、上下文精度/召回、无答案误报和延迟
|
||||
- 提供词法、确定性向量、混合及本地重排消融
|
||||
- 质量门槛按中英文分别检查,报告不包含原文、查询、端点、模型名或凭据
|
||||
- 可选报告路径仅允许工作区内非符号链接文件
|
||||
|
||||
## 8. Epic G:分块维护
|
||||
|
||||
### US-G1 查看分块
|
||||
|
||||
作为知识库维护者,我希望查看某篇文档实际生成的分块,以便确认解析和切分质量。
|
||||
|
||||
验收:
|
||||
|
||||
- 文档行提供“查看分块”
|
||||
- 列表显示序号、角色、标题、定位、字符数和启用状态
|
||||
- 支持有界分页和文档内搜索
|
||||
- 可查看完整单块内容
|
||||
- 父子块关系可辨认但不只靠颜色表达
|
||||
|
||||
### US-G2 编辑分块
|
||||
|
||||
作为知识库维护者,我希望修正错误文本,以便问答使用正确内容。
|
||||
|
||||
验收:
|
||||
|
||||
- 编辑限制单块最大字符数
|
||||
- 保存后同步更新全文和 CJK 索引
|
||||
- 旧向量立即失效并触发当前文档重建
|
||||
- 编辑块标记为人工修改
|
||||
- UI 说明来源再次同步可能覆盖修改
|
||||
- 保存失败保留用户草稿
|
||||
|
||||
### US-G3 启停分块
|
||||
|
||||
作为知识库维护者,我希望暂时停用有害或无关片段,而不永久删除它。
|
||||
|
||||
验收:
|
||||
|
||||
- 使用共享 Switch 和 `role="switch"`
|
||||
- 停用块不参与任何召回通道
|
||||
- 重新启用后恢复全文索引,并按需重建向量
|
||||
- 状态更新失败时保留最后确认状态
|
||||
- 引用已停用块时显示引用已失效
|
||||
|
||||
### US-G4 删除分块
|
||||
|
||||
作为知识库维护者,我希望删除确定无用的分块,以便避免错误召回。
|
||||
|
||||
验收:
|
||||
|
||||
- 删除前说明来源同步可能重新创建该块
|
||||
- 删除使用具体动作和对象文案
|
||||
- 删除联动清理全文、CJK、向量和图谱证据
|
||||
- 删除最后一个可检索块后文档显示“无可检索内容”
|
||||
- 不删除原始文件
|
||||
|
||||
## 9. Epic H:引用和来源
|
||||
|
||||
### US-H1 查看完整引用上下文
|
||||
|
||||
作为普通知识使用者,我希望从回答引用查看完整上下文,以便验证回答是否忠于
|
||||
资料。
|
||||
|
||||
验收:
|
||||
|
||||
- 引用携带稳定 `libraryId`、`documentId` 和 `chunkId`
|
||||
- 点击引用由 Main 重新校验对象归属
|
||||
- 展示命中分块、相邻块或父块
|
||||
- 展示知识库、文档、来源和定位
|
||||
- 对已删除对象显示明确失效状态
|
||||
|
||||
### US-H2 打开原始来源
|
||||
|
||||
作为普通知识使用者,我希望从引用打开原文件或网页,以便继续阅读。
|
||||
|
||||
验收:
|
||||
|
||||
- 本地来源只通过数据库保存的普通文件路径打开
|
||||
- 网页来源只允许数据库保存的 HTTP(S) URL
|
||||
- Renderer 不能传入任意待打开路径或 URL
|
||||
- 文件已移动时显示可恢复错误
|
||||
- 不能跨平台精确跳页时仍显示原定位信息
|
||||
|
||||
### US-H3 引用与回答一致
|
||||
|
||||
作为普通知识使用者,我希望引用列表只显示本次实际检索到的内容。
|
||||
|
||||
验收:
|
||||
|
||||
- Main 只收集本次 capability token 产生的引用
|
||||
- 预检索和模型后续检索引用去重
|
||||
- 引用顺序遵循最终相关度和首次使用顺序
|
||||
- 单消息引用数和序列化大小有明确上限
|
||||
- 不把未检索文档显示为来源
|
||||
|
||||
## 10. Epic I:迁移、安全和兼容
|
||||
|
||||
### US-I1 无损迁移
|
||||
|
||||
作为现有用户,我希望升级后保留知识库、来源、分块、图谱和向量。
|
||||
|
||||
验收:
|
||||
|
||||
- SQLite 迁移在事务中执行
|
||||
- 旧分块默认启用并视为 standalone
|
||||
- 旧知识库获得兼容检索和分块设置
|
||||
- CJK 索引回填失败时回滚迁移
|
||||
- 升级不自动删除或重建原有内容
|
||||
|
||||
### US-I2 安全边界
|
||||
|
||||
作为本地用户,我希望新增功能不扩大 Renderer 和子 Runtime 权限。
|
||||
|
||||
验收:
|
||||
|
||||
- 新增 IPC 全部校验可信 sender 和共享 Schema
|
||||
- Main 重新检查知识库、文档、分块和来源归属
|
||||
- Renderer 不访问 SQLite、文件系统、Electron shell 或凭据
|
||||
- 知识内容标记为不可信证据
|
||||
- Ask 不获得写工具
|
||||
- 错误和日志不包含密钥、授权头和未限制正文
|
||||
|
||||
### US-I3 取消和关闭
|
||||
|
||||
作为用户,我希望大库检索或重建可以停止,不留下损坏索引。
|
||||
|
||||
验收:
|
||||
|
||||
- 长向量扫描、单文档重建和全库重建响应 AbortSignal
|
||||
- 应用关闭停止新批次并等待有界清理
|
||||
- 文档级替换成功前继续使用上一版索引
|
||||
- 取消状态区别于失败
|
||||
- 取消不会删除原文件或用户维护的其他文档
|
||||
|
||||
## 11. 优先级映射
|
||||
|
||||
### 第一阶段
|
||||
|
||||
- US-A1、US-A2、US-A3
|
||||
- US-B1、US-B2、US-B3、US-B4
|
||||
- US-C1、US-C2、US-C3、US-C4、US-C5
|
||||
- US-D1
|
||||
- US-H1、US-H2、US-H3
|
||||
- US-I1、US-I2
|
||||
|
||||
### 第二阶段
|
||||
|
||||
- US-D2、US-D3
|
||||
- US-E1、US-E2、US-E3
|
||||
- US-F1、US-F2、US-F3
|
||||
- US-G1、US-G2、US-G3、US-G4
|
||||
- US-I3
|
||||
|
||||
## 12. Definition of Done
|
||||
|
||||
每个 User Story 只有在以下条件全部满足时才完成:
|
||||
|
||||
1. Main、Preload、Renderer 和共享契约保持明确边界。
|
||||
2. 行为有聚焦的单元、IPC 或组件回归测试。
|
||||
3. 中英文文案同时更新。
|
||||
4. 浅色、深色、键盘和窄窗口核心流程可用。
|
||||
5. 失败、取消、空结果和降级状态均有独立表现。
|
||||
6. 不覆盖用户现有未提交或未跟踪文件。
|
||||
7. `npm test`、`npm run typecheck`、`npm run lint` 和 `npm run build`
|
||||
全部通过。
|
||||
@@ -0,0 +1,112 @@
|
||||
# Knowledge retrieval evaluation
|
||||
|
||||
GoodBuddy's retrieval evaluation is an offline Vitest suite that exercises the
|
||||
real `KnowledgeService` and `KnowledgeDatabase` retrieval path without changing
|
||||
production data. Run it with:
|
||||
|
||||
```text
|
||||
npm run eval:retrieval
|
||||
```
|
||||
|
||||
By default the suite returns the report only to its tests and leaves no file.
|
||||
To retain a JSON report, set `GOODBUDDY_RETRIEVAL_EVAL_OUTPUT` to a
|
||||
workspace-relative file path. Absolute paths and paths escaping the workspace
|
||||
are rejected.
|
||||
|
||||
## Corpus and labels
|
||||
|
||||
The committed `synthetic-bilingual-v1` fixture is wholly synthetic, bilingual
|
||||
(Simplified Chinese and English), and CC0. Stable document, chunk, and query IDs
|
||||
make changes reviewable. The strict Zod schema bounds every field and rejects
|
||||
unknown fields, duplicate or dangling IDs, inexact annotations, and
|
||||
path/endpoint/secret-like values. It also rejects degenerate label sets: each
|
||||
language must contain both an answerable and a no-answer query.
|
||||
|
||||
Each answerable query has graded chunk judgments:
|
||||
|
||||
- `3`: directly answers the question.
|
||||
- `2`: substantially answers it.
|
||||
- `1`: useful supporting evidence.
|
||||
|
||||
Every judgment also contains one or more exact, verbatim answer spans from its
|
||||
chunk. A no-answer query has no judgments. When adding labels, two reviewers
|
||||
should independently check relevance grades and exact spans, resolve
|
||||
disagreements, then update the fixture version or ID when the corpus meaning
|
||||
changes.
|
||||
|
||||
## Evaluation design
|
||||
|
||||
Each run creates a temporary SQLite database and directly seeds the production
|
||||
knowledge classes with stable IDs. It uses deterministic in-memory embedding
|
||||
providers with stable fingerprints; it does not read API keys, environment
|
||||
provider settings, user databases, or network resources. Five ablations use
|
||||
the same corpus:
|
||||
|
||||
1. lexical retrieval only;
|
||||
2. topic-agnostic deterministic token-hash vector retrieval;
|
||||
3. handcrafted-alias vector retrieval;
|
||||
4. lexical/vector hybrid retrieval;
|
||||
5. hybrid retrieval with the local heuristic reranker.
|
||||
|
||||
The token-hash provider hashes normalized input tokens without topic-specific
|
||||
knowledge, so it is a transparent lexical-overlap vector ablation. The
|
||||
handcrafted bilingual alias provider exists only as **regression plumbing** to
|
||||
exercise vector, hybrid, and rerank production paths with stable cross-language
|
||||
matches. It is fixture-aware and is not an embedding-quality model or a claim
|
||||
about real provider quality.
|
||||
|
||||
The suite runs twice and compares the deterministic projection (IDs, hashes,
|
||||
rank metrics, and failures). Wall-clock latency is intentionally excluded from
|
||||
that equality check.
|
||||
|
||||
## Metrics
|
||||
|
||||
- **Recall@5 / Recall@10:** fraction of all annotated relevant chunks returned
|
||||
within the cutoff, macro-averaged over answerable queries.
|
||||
- **MRR@10:** reciprocal rank of the first relevant chunk, with zero when none
|
||||
appears in the first ten.
|
||||
- **Graded nDCG@10:** discounted cumulative gain using `2^grade - 1`, divided
|
||||
by the ideal graded ordering.
|
||||
- **Context precision:** characters in exact annotated spans found in returned
|
||||
context divided by all returned context characters.
|
||||
- **Context recall:** characters in exact annotated spans found in returned
|
||||
context divided by all annotated span characters.
|
||||
- **No-answer false-positive rate:** no-answer queries that return any result
|
||||
divided by all no-answer queries.
|
||||
- **Latency:** count, minimum, median, p95, maximum, and arithmetic mean in
|
||||
milliseconds for each ablation. These are diagnostic, not deterministic
|
||||
gates.
|
||||
|
||||
Rankings are deduplicated by chunk ID before cutoffs and ranking metrics are
|
||||
computed. Overlapping or nested exact evidence spans are unioned, so duplicate
|
||||
rank entries and overlapping annotations cannot inflate context precision or
|
||||
recall. Aggregate metrics are also emitted per language.
|
||||
|
||||
## Privacy
|
||||
|
||||
Reports contain only fixture/query/ablation IDs, a SHA-256 corpus hash, an
|
||||
evaluation-definition hash, a hash of provider definitions, aggregate metrics,
|
||||
latency summaries, and ID-based actionable failures. The
|
||||
`evaluationDefinitionHash` covers fixture version/ID, raw queries, judgments,
|
||||
retrieval settings, ablations, provider definitions, and metric version; it
|
||||
changes when the evaluated contract changes without disclosing that contract.
|
||||
Reports omit raw queries, document titles, corpus text, snippets/context,
|
||||
source paths, endpoints, fingerprints, model names, credentials, metadata, and
|
||||
vectors. The integration test checks every fixture title, chunk, query, and
|
||||
private provider identifier against the serialized report.
|
||||
|
||||
Retained report paths must be workspace-relative. Resolution uses async
|
||||
filesystem APIs, rejects absolute/traversal paths and null bytes, checks each
|
||||
parent component, and refuses symlink traversal or a symlink destination. The
|
||||
report is first written to a same-directory temporary file and then renamed.
|
||||
|
||||
## Quality gates
|
||||
|
||||
The integration test gates stable lexical, topic-agnostic token-hash,
|
||||
regression-vector, hybrid, context-precision/context-recall, and per-language
|
||||
baselines. It also requires reranked MRR@10 of at least 0.78, reranked nDCG@10
|
||||
of at least 0.75, no-answer false positives no higher than 0.34, and prevents
|
||||
local reranking from reducing hybrid nDCG@10 by more than 0.05. Exact nDCG
|
||||
arithmetic has a focused unit test. Gates are fixture baselines rather than
|
||||
universal production-SLA claims; adjust them only with a reviewed fixture or
|
||||
justified retrieval behavior change.
|
||||
@@ -95,12 +95,6 @@ GoodBuddy 应能够:
|
||||
- 允许读取明确授权的上下文。
|
||||
- 禁止文件写入、命令执行和外部副作用。
|
||||
|
||||
#### Plan
|
||||
|
||||
- Runtime 可读取上下文并生成结构化计划。
|
||||
- 用户确认计划后才能进入 Execute。
|
||||
- 计划变更需要重新确认。
|
||||
|
||||
#### Execute
|
||||
|
||||
- 允许按现有逐工具审批机制执行。
|
||||
|
||||
Reference in New Issue
Block a user