知识库机制
本页说明文档怎样从上传走到可检索状态,以及 PostgreSQL、MinIO、Milvus、Neo4j、Tasker 和 Agent 工具各自负责什么。第一次操作知识库请看创建并使用知识库,解析器配置见文档处理与 OCR。
能力边界
Yuxi 通过 KnowledgeBaseManager 读取知识库配置、解析权限并选择 executor:
milvus是文档型知识库,支持上传、解析、分块、向量索引、预览和检索,也可以构建知识图谱;dify和notion是只读连接器,只保存外部连接信息并执行 Query,不承载 Yuxi 的上传、解析、索引、文件树和全文预览。
前端按钮只反映 executor 的能力,最终判断由后端完成。只读连接器收到不支持的操作时会明确报错。
两条链路
管理链路改变知识库事实,Agent 链路消费当前用户和当前 Agent 可见的知识库:
flowchart LR
UI["Web / API"] --> Router["路由:认证和输入校验"]
Router --> Tasker["Tasker:后台编排"]
Tasker --> Manager["KnowledgeBaseManager"]
Manager --> MilvusKB["Milvus executor"]
Manager --> Connector["Dify / Notion 只读 executor"]
MilvusKB --> PG[("PostgreSQL")]
MilvusKB --> Object[("MinIO")]
MilvusKB --> Vector[("Milvus")]
MilvusKB --> Graph[("Neo4j,可选")]
Connector --> External["外部检索 API"]
Context["Agent Context.knowledges"] --> Visible["用户权限 ∩ Agent 选择"]
Visible --> Skill["knowledge-base Skill"]
Skill --> Tools["知识库工具"]
Tools --> Manager路由只接收请求并提交任务;Manager 负责配置和 executor 选择;具体 executor 负责解析、索引和检索。知识库配置的最终值在 PostgreSQL,Redis 只缓存最小运行配置,未命中或异常时回源数据库。
文档状态机
上传、解析和索引是三个可以分别观察的动作:
stateDiagram-v2
[*] --> uploaded: 原文件已保存,文件记录已创建
uploaded --> parsing: 条件抢占
error_parsing --> parsing: 重试解析
parsed --> indexing: 条件抢占
error_indexing --> indexing: 重试索引
indexed --> indexing: 重新索引
parsing --> parsed: Markdown 已保存
parsing --> error_parsing: 解析失败或取消
indexing --> indexed: chunk 和向量完成
indexing --> error_indexing: 索引失败或取消
indexing --> uploaded: 缺少 Markdown 产物历史 failed、done 状态只作为兼容输入。parsing 和 indexing 表示当前动作已经抢到执行权;没有抢到允许状态的并发请求会失败,同一文件不会由两个动作同时推进。
uploaded:原文件和文件记录存在,尚未完成解析;parsed:解析后的 Markdown 路径已写入文件记录;indexed:本次分块、向量写入和统计更新已完成;error_parsing、error_indexing:对应阶段失败或取消,并保存错误信息。
任务接口的响应和 Tasker 状态只表示编排结果。验收时重新读取文件状态,并按需核对 Markdown、chunk、向量和图谱数据。
各存储负责什么
| 存储 | 拥有的事实 | 不拥有的事实 |
|---|---|---|
| PostgreSQL | 知识库配置、权限、文件元数据和状态、chunk 正文、图谱处理状态、Tasker 摘要 | 原文件字节、向量索引 |
| MinIO | 上传原件、解析 Markdown、解析图片 | 文件当前状态、用户权限 |
| Milvus | chunk 向量、BM25/混合检索字段、图实体和关系向量 | 权限、文件状态 |
| Neo4j | 可选的实体、关系和 chunk 关联 | 原文件、权限和检索排序 |
| Redis | 知识库最小运行配置缓存 | 配置最终值、文件状态 |
| Tasker 内存队列 | 当前 API 进程内的 coroutine 和顺序 | 跨进程可恢复的执行权 |
Milvus 索引会把 chunk 写入 PostgreSQL 和 Milvus。它不是跨存储事务:任一侧失败时会尝试补偿并把文件置为 error_indexing,排查时需要同时查看两侧。
Tasker 和恢复
上传原文件是同步对象存储操作;批量添加、解析、索引和图谱构建可以交给进程内 Tasker。任务元数据、进度、结果和错误保存到 PostgreSQL,但真正执行的 coroutine 只存在当前 API 进程的 asyncio.Queue。
API 重启时,Tasker 会把非终态任务标记为 failed,不会仅凭持久化 payload 自动重建 coroutine。取消也是协作式的:先保存 cancel_requested,任务在检查点退出。任务失败不等于文件状态已经回滚,外部存储可能已经写入部分结果。
批量“待解析”和“待入库”入口按状态筛选文件,并对活跃任务去重。重试前保留故障现场,检查文件记录、MinIO、chunk、Milvus 和 Neo4j,再选择重新解析、重新索引或图谱修复。
Agent 如何看到知识库
运行时准备阶段先按用户权限读取知识库,再与 Agent 的 Context.knowledges 求交集,结果保存为 _visible_knowledge_bases。工具的 kb_id、file_id 和文件名必须属于这份运行时快照;新的 Run 会重新计算权限,正在运行的 Context 不会因中途撤权而自动刷新。
知识库工具由内置 knowledge-base Skill 提供。模型读取该 Skill 的 SKILL.md 后,才会看到:
list_kbs、query_kb、find_kb_document、open_kb_document、
get_mindmap、search_file、download_kb_file推荐顺序是:列出可见知识库 → 检索候选片段 → 用 file_id 打开或定位原文。download_kb_file 会把有权访问的原始二进制写入当前 Project 的 outputs,供后续工具处理。知识库不会映射为 /home/gem/kbs 沙盒目录。
权限和 LITE
知识库的最终授权由后端依赖、Manager 可见性查询和具体工具目标校验共同完成:
- 读取、检索、打开和下载需要 read 权限;
- 创建、更新、添加文件、解析、索引、删除和图谱写操作需要 manage 权限;
- 原文件上传入口要求管理员,并在传入
kb_id时继续检查该知识库的 manage 权限; - 前端守卫、按钮隐藏、Agent 配置和提示词只控制呈现或缩小范围,不能授予权限。
Agent 的 knowledges 只能缩小用户已有权限。子智能体使用自己的配置,但仍沿用发起用户的身份。私有解析图片通过带知识库权限校验的 API 读取,MinIO 对象 URL 不是授权凭证。
LITE 模式不注册知识库、图谱和评估重运行时,也不注册 knowledge-base Skill。此时知识库资源为空;服务故障也不能用“空检索结果”伪装成 LITE 行为。
失败和重试
- 解析失败或取消:文件进入
error_parsing,查看错误并重新提交解析;批量待解析入口只扫描uploaded。 - 索引失败或取消:文件进入
error_indexing,检查分块、嵌入和存储后重新入库;批量待入库入口扫描parsed和error_indexing。 - 索引缺少 Markdown:文件回到
uploaded,必须重新解析,不会生成空索引。 - Tasker 失败、超时或重启:只能说明后台动作未完成,不能推断外部存储没有部分写入。
- Redis 缓存异常:Manager 回源 PostgreSQL;不支持的知识库类型或 executor 初始化失败会明确阻止操作。
源码定位与验证
- 知识库路由:权限、上传、任务和状态筛选
- KnowledgeBaseManager:配置回源、可见性和 executor 调度
- 知识库基类:文件状态和解析流程
- Milvus executor:分块、双写、检索和重索引
- 只读连接器:Dify/Notion 能力边界
- Tasker:任务持久化和重启结局
- 知识库工具:Agent 目标校验和工具实现
- 知识库 unit tests
- 权限与路由 tests
- 知识库 HTTP integration
- 外部知识库 integration
修改状态、权限、存储或 Agent 工具链路时,至少运行对应 unit 和真实 HTTP integration;涉及外部存储时,从 PostgreSQL、MinIO、Milvus 或 Neo4j 回读最终结果。