知识库与文档问答
知识库是 Aivory 的长期文档仓库:把一组文档上传一次,之后任何对话都可以挂载它做检索问答,回答自动带来源引用。本页覆盖知识库的创建、文档入库、对话中的使用方式、检索原理,以及「检索结果为空」的完整排查清单。
与知识库并行的还有两种文档作用域,三者共用同一套解析与检索引擎:
| 作用域 | 存放位置 | 检索范围 | 典型用途 |
|---|---|---|---|
| 对话临时文件 | 上传它的那个对话 | 仅该对话 | 单文件问答,「帮我读一下这份 PDF」 |
| 知识库 | 独立的知识库页面 | 任何挂载了它的对话 | 长期复用的资料集 |
| 项目知识库 | 项目 | 该项目下的全部对话 | 团队/主题资料,见团队工作空间与项目功能 |
前置条件
知识库依赖三类后端能力,缺哪一项会退化成什么行为,先了解清楚:
| 依赖 | 作用 | 未配置时的行为 |
|---|---|---|
嵌入模型(kind='embedding' 的模型条目,或环境变量兜底) | 文档向量化与查询向量化 | 无法完成嵌入,大文档不可检索;小文档仍可全文注入 |
Qdrant(QDRANT_URL) | 稠密向量检索 | 向量检索禁用,RAG 走全文上下文回退 |
| MinerU + 对象存储(S3 / 阿里云 OSS) | 扫描件 PDF、Office 文档、图片的云端解析与 OCR | 非纯文本文档解析失败,知识库文档标记为失败 |
- 生产 Docker Compose 已内置 Qdrant 容器,见Docker Compose 部署。
- 嵌入模型在管理后台「渠道 / 模型」里配置:挂在某个 OpenAI 类型渠道下,填写请求模型名与维度,任何暴露 OpenAI
/v1/embeddings格式的服务(OpenAI、Voyage、自部署 BGE-M3 等)都能接。详见渠道与模型与核心配置。 - MinerU 的 API 地址、token 与对象存储凭据在管理后台「文档」页配置,保存即生效,无需重启。
同一个知识库的所有向量(包括提问时的查询向量)必须来自同一个嵌入模型,不同模型的向量空间互不兼容。因此嵌入模型在建库时选定、建库后不可更换,更换等于全量重新嵌入。
创建知识库
入口:侧栏底部头像菜单里的「知识库」,进入知识库列表页,点「新建知识库」。
创建对话框字段:
| 字段 | 必填 | 说明 |
|---|---|---|
| 名称 | 是 | 同一账号(同一空间)内不可重名 |
| 描述 | 否 | 帮助你和查询路由理解这个库装的是什么 |
| 嵌入模型 | 是 | 从管理员已启用的嵌入模型中选择,下拉里每项显示模型名与维度(如 dim 1536) |
维度自动确定:向量维度由所选嵌入模型的配置决定,不需要也不能手工填写。创建后列表卡片会显示「N 维向量」。同维度的知识库在 Qdrant 中共用一个 collection,靠 payload 隔离租户。
上传第一个文档后嵌入模型即锁定,它决定了整个库的向量空间。选错了只能删库重建。多个知识库如果打算在同一个对话里同时挂载,请使用同一个嵌入模型(原因见下文排查清单第 5 条)。
普通用户可创建的知识库数量受用户组限制(管理员在用户组编辑页的「最大知识库数」设置,0 表示不限),见用户与配额。
上传文档
进入知识库详情页,点「上传文档」。上传对话框有两个标签页:
- 上传文件:点击选择本地文件;
- 粘贴文本:直接粘贴一段文字作为文档入库,适合零散笔记。
支持的文件类型与解析路径
| 类型 | 解析方式 | 速度 |
|---|---|---|
| 纯文本(txt / md / csv / log / json / yaml / xml / html) | 本地直接读取,原样作为 Markdown 进入切块 | 毫秒级 |
| PDF(有文字层) | 本地即时提取文字层,含图也不送 OCR | 秒级 |
| PDF(扫描件 / 无文字层) | MinerU 云端 OCR | 分钟级,取决于页数 |
| DOC / DOCX / PPT / PPTX / XLS / XLSX / 图片 | MinerU 云端解析(含表格与公式识别) | 分钟级 |
扫描件的判定规则:文档含图片且文字密度低于每页 200 字符时视作扫描件,走 MinerU OCR;否则一律本地提取,该花的 OCR 时间只花在真正需要的地方。
实际可上传的扩展名受管理员的上传白名单与大小上限控制(管理后台「文档」页),超限文件在上传时即被拒绝并提示具体上限。
非纯文本文档解析时,原文件先落到你自己配置的 S3 / OSS 桶,MinerU 只拿到一条 1 小时有效期的预签名 URL,你的存储凭据不出域;解析完成后源文件自动从桶里清除。
状态流转
上传后文档进入异步流水线,详情页文档表格实时显示状态徽章:
| 状态 | 显示 | 含义 |
|---|---|---|
| pending | 排队中 | 已入队,等待处理 |
| parsing | 解析中 | 提取文本,扫描件此阶段走 OCR |
| embedding | 嵌入中 | 结构化切块后分批调用嵌入模型(每批最多 128 条) |
| ready | 就绪 | 已可被检索,表格同时显示切片数 |
| failed | 失败 | 流水线自动重试 3 次后仍失败,记录失败原因 |
文档表格列:文件、状态、切片数、添加时间。
失败与重试
- 流水线内部对每个文档自动重试 3 次;重试时已解析的内容会被缓存,只重跑失败的嵌入阶段,不会重复调用计费的 MinerU OCR。
- 3 次仍失败则置为「失败」并记录原因(例如 MinerU 未配置、对象存储不可用、嵌入模型报错)。界面提示「索引失败。请移除该文档后重新上传」:排除根因后,删除该文档并重新上传即可重新走一遍流水线。
- 解析失败的文档不会被向量化入库,不会用占位内容污染检索结果。
- 重复上传同名文档或失败后重入是幂等的,不会在库里叠加陈旧切片。
在对话中使用
挂载知识库
聊天输入框工具栏有一个书本图标的「知识库」选择器:
- 点开后勾选一个或多个知识库,挂载状态绑定到当前对话并持久化,换对话不影响;
- 图标旁显示已挂载的数量;
- 窄屏(手机)上该入口收在输入框的「+」菜单里;
- 还没有知识库时显示「还没有知识库」。
挂载后,每条提问都会按下文的检索流程自动查库,不需要任何特殊指令。回答下方出现「来源」角标,点开可查看命中的文档名、页码、章节路径与原文片段。
在团队工作空间内,只能挂载该空间的知识库;个人空间的知识库与工作空间互相隔离,详见团队工作空间。
单文件问答(对话临时文件)
不建库、直接把文件拖进聊天输入框也能问答:
- 上传后附件芯片显示「索引中…」,解析入库完成后才能发送;有文字层的 PDF 通常几秒完成。
- 小文档(不超过管理员设置的全文注入阈值,默认约 8000 token)直接全文注入本轮提问,不做向量化,即使没有配置 Qdrant 和嵌入模型也能用。
- 大文档走完整的「查询路由 + 检索」流程(见下节)。
- 解析失败时芯片显示「无法读取此文件」并提供「重试」按钮。
- 已完成索引的 PDF 不会再整份内联发给模型,避免模型端重复解析拖慢首字。
对话临时文件只在该对话内可检索。如果对话在项目里,可以把临时文件「加入项目知识库」一键提升为项目共享文档,无需重新嵌入。
消息里的检索状态
每轮回答的顶部会用小卡片标注本轮的文档处理方式,常见几种:
| 提示 | 含义 |
|---|---|
| 已检索来源 | 走了向量 + 关键词混合检索,注入了命中片段 |
| 已注入完整文档 | 文档足够小,整篇进入上下文 |
| 全文档上下文 | 查询路由判定为全局类问题(总结 / 概括),按全文处理 |
| 跳过检索 | 查询路由判定本句与文档无关,零检索开销 |
| 文档解析中 | 文档还没到就绪状态,本轮未使用 |
工具式检索(可选)
除了默认的自动注入,平台还有一个 search_knowledge_base 工具:支持原生 function calling 的模型可以在一段回答里自主发起多次、多跳检索。文档问答的主路径不依赖它,对不支持工具调用的模型同样可用。
检索原理
了解流水线有助于判断「为什么没检索到」。
入库:解析,切块,嵌入
上传 → 解析(本地 / MinerU) → 结构感知切块 → 批量嵌入 → 向量写 Qdrant,文本与元数据写数据库
切块不是按固定字数硬切:
- 递归按标题、段落、句子边界切,目标每块 400 到 800 token,绝不从句子、表格、代码块中间切断;相邻块保留约 10% 到 15% 重叠。
- 每块开头拼上标题面包屑(如「第3章 > 3.2 营收分析」)再嵌入,孤立的数字片段也能带上上下文。
- 父子结构(small-to-big):用小块建向量索引保证定位精准,命中后返回它所在的父级大段给模型,兼顾精度与上下文完整。
提问:查询路由
挂载文档的对话里,每条提问先经过一次廉价的任务模型调用(增加约 300 到 800 毫秒),同时完成两件事:
- 意图分类:
retrieve(问具体点,走检索)、full_doc(总结概括类,按全文处理)、none(与文档无关,跳过); - 查询改写:把口语问题拆成多个精准检索词,并结合最近几轮历史消解「它 / 这个文档」之类的指代。
路由解析失败或超时的兜底是 retrieve,宁可多检索也不漏掉文档上下文。
检索:稠密 + 关键词混合
查询向量化 → Qdrant 向量检索 top-30
∥ 数据库关键词全文检索 top-30(中文分词)
→ RRF 融合排序 → 取 top-K → 回表取完整父级片段 → 注入上下文
- 两路融合显著提升专有名词、编号类查询("案例98"、"条款 4.2")的命中率,这是纯向量检索的弱项。
- Top-K 默认 8,管理员可改;开启动态 Top-K 后不再取固定数量,而是把余弦相似度达到阈值的片段全部注入。
- 相关检索参数(全文注入阈值
rag_full_text_threshold、rag_top_k、rag_dynamic_topk、rag_similarity_threshold)在管理后台「文档」页调整,保存即生效。
引用溯源
注入模型的片段带统一编号与来源元数据:
[1] 《2025年度报告.pdf》第12页 · 第3章 > 3.2 营收分析
营收同比增长23%,主要来自……
模型按编号引用,前端渲染为来源角标,与联网搜索的引用共用同一套 UI。注入内容用明确的边界标记包裹,并在系统提示中声明其为参考资料而非用户指令,降低文档内容里的提示词注入风险。
管理知识库
| 操作 | 位置 | 行为 |
|---|---|---|
| 重命名 | 详情页菜单「重命名」 | 仅改名,不影响文档与向量 |
| 移除单个文档 | 详情页文档行的删除按钮 | 确认后删除该文档及其全部切片与向量 |
| 删除知识库 | 列表行尾部悬停「⋯」菜单,或详情页头部「⋯」菜单 | 见下 |
删除知识库是级联清理:确认弹窗明确提示「将永久删除该库及其全部文档与向量,引用它的对话会自动取消引用,此操作不可恢复」。具体包括:
- 库内全部文档记录与切片;
- Qdrant 中对应的向量;
- 磁盘上的原始文件;
- 挂载过该库的对话自动解除引用,对话本身不受影响。
管理员可以在管理后台用户列表的更多菜单里进入某用户的资料库页,只读查看其知识库与每个文档的状态、切片数、大小,详见用户与配额。
检索为空排查清单
挂载了知识库但回答里没有任何来源、或模型说「找不到相关内容」时,按顺序检查:
- 文档状态是否为「就绪」:知识库详情页查看状态徽章,排队中 / 解析中 / 嵌入中 / 失败的文档都不参与检索。失败的文档点开失败原因。
- Qdrant 是否配置:
QDRANT_URL为空时向量检索被整体禁用,只剩全文注入回退,小文档可用、大文档检索不到。生产 Compose 默认已带 Qdrant;自定义部署检查该环境变量与容器状态,见核心配置。 - 嵌入模型是否可用:知识库绑定的嵌入模型被禁用、所在渠道 key 失效或服务不可达时,新文档会卡在嵌入阶段或标为失败,查询向量化也会失败。到管理后台确认该模型及其渠道状态。
- 维度是否匹配:Qdrant collection 按维度命名(
aivory_c<维度>)。如果更换过输出维度不同的嵌入模型而没有同步维度配置,向量会写进错误的 collection,表现为写入正常但永远检索不到。修正维度后,到管理后台「备份与迁移」的向量维护里重建向量:系统从数据库里保存的切片文本重新嵌入,不需要原始文件,但会消耗嵌入 API 调用。详见备份与迁移。 - 多库嵌入模型是否一致:同一对话挂载多个知识库时,系统会校验它们的嵌入模型一致性,不一致会明确报错而不是静默返回错误结果。把不同模型的库分开在不同对话里用,或统一重建。
- 扫描版 PDF 是否配了 MinerU:没有 MinerU + 对象存储时,扫描件解析不出内容,文档会标为失败。
以上第 2、4、6 条在常见问题里有对应条目("为什么知识库检索结果为空"、"EMBEDDING_DIM 与嵌入模型不匹配怎么办"、"扫描版 PDF 上传后解析不出内容"),包含更完整的配置示例。
最快的验证方法:传一个几 KB 的纯文本小文件到对话里直接提问。小文件走全文注入、不依赖 Qdrant 和嵌入模型,如果连它都答不对,问题在模型侧而不在检索链路;如果小文件正常、大文件不行,按上面清单查向量链路。