10 KiB
知识库后端当前实现说明
本文档只记录当前分支中 src/main/services/knowledge 已经落地的后端分层、调用边界和 workflow 行为。
v2-refactor-temp 下的文档是临时工作笔记。当前 canonical 文档是:
本文不覆盖旧的 src/main/knowledge / knowledge-base:* 通道。
1. 当前架构图
UI / preload IPC / main-side workflow
-> KnowledgeService
-> KnowledgeWorkflowService
-> JobManager
-> knowledge.prepare-root
-> knowledge.index-documents
-> knowledge.delete-subtree
-> knowledge.reindex-subtree
-> KnowledgeLockManager
-> KnowledgeBaseService / KnowledgeItemService
-> KnowledgeVectorStoreService / FileManager
UI Data API reads / patch
-> Data API knowledge handlers
-> KnowledgeBaseService / KnowledgeItemService
当前没有 KnowledgeRuntimeService,也没有 Knowledge 自己维护的 in-memory queue。持久化调度、retry、timeout、cancel 和 startup recovery 由 JobManager 负责。
2. 当前职责边界
KnowledgeBaseService / KnowledgeItemService:
- 负责 SQLite 业务表读写。
- 负责
knowledge_item.status/error的持久化更新。 - 负责
knowledge_item.data与type的一致性校验。 - 负责 container item 的子项状态向上聚合。
- 不负责 reader、embedding、向量库写入、JobManager 调度或 caller-facing IPC。
Data API knowledge handlers:
- 只暴露数据库可直接满足的读和 base metadata/config 更新。
- 不负责 runtime mutation,不创建或删除 vector store artifacts。
KnowledgeService:
- 负责 caller-facing
knowledge-runtime:*IPC。 - 负责 create/delete/restore base workflow。
- 注册 Knowledge JobManager handlers。
- 持有
KnowledgeWorkflowService和KnowledgeLockManager。 - 对 delete / reindex / chunk 操作做入口 guard。
- 不直接执行 reader / chunk / embed / vector write。
KnowledgeWorkflowService:
- 负责
addItems/deleteItems/reindexItems的 workflow 分支。 - 负责
scheduleItem(baseId, itemId)。 - 将
directory分派为knowledge.prepare-root。 - 将
file/note/url分派为knowledge.index-documents。 - 负责 add/reindex 调度失败后的状态补偿。
KnowledgeLockManager:
- 负责同一 base 下的进程内 mutation 串行化。
- 保护 vector replace/delete、FileRef cleanup、item status writes 和 destructive cleanup/reset。
- 不能替代
DbService.withWriteTx;主 SQLite 写事务仍必须走DbService.withWriteTx。
3. 当前调用边界与调用方契约
UI / preload 当前调用模型:
UI
|
+--> Data API
| -> list/get knowledge bases
| -> patch base metadata/config
| -> list/get knowledge items
|
\--> preload knowledgeRuntime IPC
-> create/delete/restore base
-> add/delete/reindex items
-> search
-> list/delete chunks
添加 file / url / note / directory 时,调用方直接走:
caller
-> preload IPC add-items(item payloads)
调用方不应先通过 Data API 创建 item,再把 created item ids 传给 runtime addItems。
Leaf item 当前链路:
add-items(leaf payloads)
-> create leaf item rows
-> status = processing
-> enqueue knowledge.index-documents
Container item 当前链路:
add-items(directory payloads)
-> create root item rows
-> status = preparing
-> enqueue knowledge.prepare-root
-> prepare-root expands owner
-> prepare-root creates child rows
-> workflowService.scheduleItem(child)
prepare-root 创建出的 child 可以继续是 directory,由 workflow service 再次分派为 knowledge.prepare-root。递归展开不由 reader 或 leaf indexing 分支处理。
4. JobManager 模型
当前 Knowledge job types:
knowledge.prepare-rootknowledge.index-documentsknowledge.delete-subtreeknowledge.reindex-subtree
每个 base 使用独立队列:
base.${baseId}
JobManager 负责:
- job 持久化。
- dispatch。
- retry / timeout。
- cancel。
- startup recovery。
Knowledge 不再维护 entries map、controller、runPromise、interruptError 或其他 in-memory queue 状态。
5. 当前索引执行链路
knowledge.index-documents 当前流程:
handler.execute
-> load base and item
-> skip missing / deleting / already completed item
-> under base mutation lock:
rebuild source file refs
status = reading
-> read documents
-> chunk documents
-> under base mutation lock:
status = embedding
-> embed chunks
-> under base mutation lock:
re-read item
skip vector write if item is deleting
vectorStore.replaceByExternalId(itemId, nodes)
status = completed
如果 reader 返回空 documents,或 chunk 后没有可索引 chunks,index-documents 仍视为成功:写入 replaceByExternalId(itemId, []) 清空该 item 的旧 chunks,然后把 item 标记为 completed。
非中断错误由 JobManager retry。Retry 耗尽或 job cancel 时,handler onSettled 把对应 item 标记为 failed,但如果 item 已经是 deleting 则跳过失败回写。
6. Delete / Reindex 当前链路
delete-items 当前流程:
delete-items(baseId, itemIds)
-> collapse to top-level roots
-> under base mutation lock:
mark selected root subtrees deleting
-> enqueue knowledge.delete-subtree
knowledge.delete-subtree:
-> resolve still-deleting subtree
-> cancel active jobs touching subtree
-> under base mutation lock:
delete vectors for leaf items
clear Knowledge FileRef rows for full subtree
delete knowledge_item rows
file_ref.sourceId 是 polymorphic,没有 FK 指向 knowledge_item。因此最终 hard delete 必须先展开完整 subtree 清理 Knowledge FileRef,再删除 rows;仅删除显式 root id 对应 refs 会留下 descendant orphan refs。
reindex-items 当前流程:
reindex-items(baseId, itemIds)
-> collapse to top-level roots
-> reject unless every selected subtree item is completed or failed
-> enqueue knowledge.reindex-subtree
knowledge.reindex-subtree:
-> skip if delete already marked any subtree item deleting
-> under base mutation lock:
re-check deleting guard
delete old vectors
delete expanded descendants for selected container roots
reset selected roots to preparing / processing
-> workflowService.scheduleItem(root)
Reindex 不是 cancellation primitive。Active subtree 只能 delete,不能 reindex。
7. knowledge_item.status 当前边界
当前 status 表达业务生命周期和粗粒度运行进度:
idlepreparingprocessingreadingembeddingcompletedfaileddeleting
当前不再保留单独 phase 字段。status 是持久业务状态,不由 JobManager progress 反推。
状态语义:
preparing:directory正在 expand / create children。processing:leaf 已接受但尚未进入 reading,或 container 仍有 active children。reading:leaf 正在读取 source documents。embedding:leaf 正在 embedding。completed:leaf indexing 完成,或 container 没有 active children。failed:index/preparation/scheduling compensation 失败。deleting:用户不可见,等待后台 cleanup。
8. Base workflow
createBase(dto) 当前流程:
IPC create-base(CreateKnowledgeBaseDto)
-> KnowledgeBaseService.create(dto)
-> KnowledgeVectorStoreService.createStore(base)
-> return created base
如果 vector store 初始化失败,orchestration 会调用 KnowledgeBaseService.delete(base.id) 回滚刚创建的 SQLite base,然后把原始错误抛给调用方。
deleteBase(baseId) 当前流程:
IPC delete-base(baseId)
-> cancel active Knowledge jobs in base queue
-> under base mutation lock:
KnowledgeVectorStoreService.deleteStore(baseId)
KnowledgeBaseService.delete(baseId)
Artifact 删除失败时 SQLite 行保留,用户可从 UI 重试。SQLite 删除失败时已删除 artifacts 不会恢复,orchestration 抛出 invalidOperation。
restoreBase(dto) 当前流程:
IPC restore-base(sourceBaseId, embeddingModelId, dimensions)
-> load source base
-> load source root items
-> create new base with source config and requested embedding contract
-> add source root item payloads to restored base
Restore 允许 failed base,也允许 completed base;即使 completed source base 的 embeddingModelId 和 dimensions 未变化,也允许创建同配置 clone/rebuild。
9. Search / Chunk 当前边界
search(baseId, query) 当前流程:
- 拒绝 failed base。
- 拒绝没有 searchable token 的 query。
- 使用 base embedding model 生成 query embedding。
- 查询 sqlite-vec vector store。
- 过滤 missing / other-base / deleting source item 的结果。
- 如果配置了 rerank model,执行 rerank。
- 应用 threshold 并写入 rank。
list-item-chunks / delete-item-chunk 当前规则:
- 拒绝 failed base。
- 要求目标 item 自身为
completed。 - 对 completed
directorylist 请求,如果 subtree 仍含deletingdescendant,则拒绝。
10. 当前明确不做的内容
- 不使用旧
KnowledgeRuntimeService。 - 不维护 Knowledge 自己的 in-memory queue。
- 不使用
index-leafjob type;当前 leaf indexing job 是knowledge.index-documents。 - 不保留单独
phase字段。 - 不把 restore same embedding config 视为 no-op 并拒绝。
- 不主动 permanent-delete detached
FileEntryrows。 - Round 1 不接入 FileProcessing;
knowledge_base.fileProcessorId当前对 indexing inert。
11. 后续更新本文档时的原则
- 如果 canonical 文档已经覆盖事实,优先更新 canonical 文档,再在本文保留短摘要或链接。
- 不再新增大段逐实现复制,避免
v2-refactor-temp与 canonical docs 漂移。 - 如果当前实现与 RFC 目标不同,必须明确写“当前实现”还是“目标设计”。