Files
CherryHQ-cherry-studio/v2-refactor-temp/docs/knowledge/knowledge-backend-decisions.md

10 KiB
Raw Permalink Blame History

知识库后端当前实现说明

本文档只记录当前分支中 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

  1. 负责 SQLite 业务表读写。
  2. 负责 knowledge_item.status / error 的持久化更新。
  3. 负责 knowledge_item.datatype 的一致性校验。
  4. 负责 container item 的子项状态向上聚合。
  5. 不负责 reader、embedding、向量库写入、JobManager 调度或 caller-facing IPC。

Data API knowledge handlers

  1. 只暴露数据库可直接满足的读和 base metadata/config 更新。
  2. 不负责 runtime mutation不创建或删除 vector store artifacts。

KnowledgeService

  1. 负责 caller-facing knowledge-runtime:* IPC。
  2. 负责 create/delete/restore base workflow。
  3. 注册 Knowledge JobManager handlers。
  4. 持有 KnowledgeWorkflowServiceKnowledgeLockManager
  5. 对 delete / reindex / chunk 操作做入口 guard。
  6. 不直接执行 reader / chunk / embed / vector write。

KnowledgeWorkflowService

  1. 负责 addItems / deleteItems / reindexItems 的 workflow 分支。
  2. 负责 scheduleItem(baseId, itemId)
  3. directory 分派为 knowledge.prepare-root
  4. file / note / url 分派为 knowledge.index-documents
  5. 负责 add/reindex 调度失败后的状态补偿。

KnowledgeLockManager

  1. 负责同一 base 下的进程内 mutation 串行化。
  2. 保护 vector replace/delete、FileRef cleanup、item status writes 和 destructive cleanup/reset。
  3. 不能替代 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

  1. knowledge.prepare-root
  2. knowledge.index-documents
  3. knowledge.delete-subtree
  4. knowledge.reindex-subtree

每个 base 使用独立队列:

base.${baseId}

JobManager 负责:

  1. job 持久化。
  2. dispatch。
  3. retry / timeout。
  4. cancel。
  5. startup recovery。

Knowledge 不再维护 entries map、controllerrunPromiseinterruptError 或其他 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 后没有可索引 chunksindex-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 表达业务生命周期和粗粒度运行进度:

  1. idle
  2. preparing
  3. processing
  4. reading
  5. embedding
  6. completed
  7. failed
  8. deleting

当前不再保留单独 phase 字段。status 是持久业务状态,不由 JobManager progress 反推。

状态语义:

  1. preparingdirectory 正在 expand / create children。
  2. processingleaf 已接受但尚未进入 reading或 container 仍有 active children。
  3. readingleaf 正在读取 source documents。
  4. embeddingleaf 正在 embedding。
  5. completedleaf indexing 完成,或 container 没有 active children。
  6. failedindex/preparation/scheduling compensation 失败。
  7. 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 的 embeddingModelIddimensions 未变化,也允许创建同配置 clone/rebuild。

9. Search / Chunk 当前边界

search(baseId, query) 当前流程:

  1. 拒绝 failed base。
  2. 拒绝没有 searchable token 的 query。
  3. 使用 base embedding model 生成 query embedding。
  4. 查询 sqlite-vec vector store。
  5. 过滤 missing / other-base / deleting source item 的结果。
  6. 如果配置了 rerank model执行 rerank。
  7. 应用 threshold 并写入 rank。

list-item-chunks / delete-item-chunk 当前规则:

  1. 拒绝 failed base。
  2. 要求目标 item 自身为 completed
  3. 对 completed directory list 请求,如果 subtree 仍含 deleting descendant则拒绝。

10. 当前明确不做的内容

  1. 不使用旧 KnowledgeRuntimeService
  2. 不维护 Knowledge 自己的 in-memory queue。
  3. 不使用 index-leaf job type当前 leaf indexing job 是 knowledge.index-documents
  4. 不保留单独 phase 字段。
  5. 不把 restore same embedding config 视为 no-op 并拒绝。
  6. 不主动 permanent-delete detached FileEntry rows。
  7. Round 1 不接入 FileProcessingknowledge_base.fileProcessorId 当前对 indexing inert。

11. 后续更新本文档时的原则

  1. 如果 canonical 文档已经覆盖事实,优先更新 canonical 文档,再在本文保留短摘要或链接。
  2. 不再新增大段逐实现复制,避免 v2-refactor-temp 与 canonical docs 漂移。
  3. 如果当前实现与 RFC 目标不同,必须明确写“当前实现”还是“目标设计”。