抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

把文档切块、算 embedding、写进向量索引,再接一个生成模型,几天就能搭出知识问答 Demo。这个 Demo 会让人产生一个错觉:只要相似度搜得准,企业知识库就建成了。实际运行一段时间后,问题往往不在向量库,而在知识从哪里来、何时失效、谁能看、答案引用了什么。

我把向量检索当成候选召回器。它回答的是“哪些片段在表示空间里接近这个问题”,不负责证明片段仍然有效,也不负责解决权限、冲突和业务口径。知识库是包含摄取、治理、检索、生成和反馈的一整条链路。

向量召回只是知识问答链路的一段

最近邻解决的是召回效率

DPR 用双编码器分别表示问题和段落,再用向量相似度做开放域问答检索;RAG 把检索到的文档作为生成模型的外部记忆;FAISS 与 HNSW 关注的是大规模相似向量搜索效率和精度。它们分别解决了重要问题,但没有声称一个向量索引自动等于企业知识治理。

企业场景里的失败常常很朴素。用户问“生产任务默认重试几次”,索引召回了三份很像的片段:两年前的制度、测试环境说明、一个故障复盘里的临时参数。相似度最高的那段可能恰好最不适用。

检索对象必须带结构化身份:source_iddocument_versionsection_pathvalid_from/to、environment、owner、ACL 和 ingestion time。向量只负责内容近似,过滤器先按访问身份、环境与有效期收窄范围。没有这些字段,召回分数越高,错误答案反而越自信。

我还会保留原文位置和内容哈希。答案引用某个 chunk 时,可以回到原文的标题、段落与版本;文档更新后,旧 chunk 能被准确撤下,而不是重新导入一份后让新旧内容一起命中。

切块决定了能否回答,不是固定字数参数

固定每 500 字切一块,是最方便实现的方案,也最容易把定义和条件拆开。一段写“默认保留 30 天”,下一段才说明“仅适用于离线任务日志”,模型只拿到前半段就会把结论扩大到所有数据。

我更关注问题的最小证据单元。标题层级、列表、代码块、表格、接口定义和段落之间的指代都应参与切分。一个 chunk 要尽量包含结论、适用条件和必要上下文;过长时按语义子段拆分,同时给每段附上 ancestor headings。

表格尤其不能按纯文本行随意切。列标题丢失后,30 不知道是天数、次数还是容量。代码与配置也要保留文件路径、版本和相邻注释。对数据 Catalog,表、列、指标、关系本来就是结构化对象,先用对象模型检索,再把说明文本用于补充,不必全部压成匿名段落。

切块质量可以用问题反推:准备真实问题,标注最小充分证据,检查它能否完整落在可召回单元中。chunk size 只是实验变量,不是知识库设计原则。

向量召回需要和其他信号协作

语义相近不代表关键词精确。错误码、表名、类名、配置键和版本号往往需要 lexical match;“DataX 速度限制”与“channel speed byte”在表达上相关,但用户给出完整参数名时,关键词命中更可靠。

我通常并行做三路候选:向量召回自然语言语义,BM25/倒排索引处理精确词,结构化查询处理对象关系与过滤。候选合并后再重排,特征至少包括语义分数、关键词命中、文档权威级别、新鲜度、环境匹配和 ACL。

score 不能直接跨索引比较。不同 embedding 模型、索引参数和 query 长度会改变分布。阈值要在标注集上校准,并随 index version 保存。更换模型时做双索引离线回放,再灰度切流;直接重算所有向量并覆盖,出现回退后没有可比较的旧版本。

多路召回仍可能拿不到答案。系统需要识别证据不足:top-k 都低分、片段互相冲突、问题要求的时间晚于知识更新时间,或只有二手说明没有正式来源。此时返回“当前知识中无法确认”并列出检索范围,比用常识填空更有价值。

权限必须在检索前后都检查

把所有文档放进同一个向量库,然后在答案返回前过滤敏感词,不是权限控制。模型已经看到无权内容,即便最终文本没有逐字输出,也可能通过摘要、推断或后续问答泄露。

检索前按用户身份计算允许的 document/object set,向量查询只在这个范围执行。若索引系统的过滤能力不足,至少按安全域分索引,不能先全局 top-k 再删掉无权结果,因为删除后剩下的候选也未必是该用户范围内真正的 top-k。

生成前再做一次 ACL 校验,防止索引元数据与源系统权限不同步。答案返回引用,点击时由源系统重新鉴权。权限快照、用户身份、命中的 source IDs 和 policy version 进入审计日志,才能解释“为什么这个人当时看到了这段内容”。

删除也要闭环。源文档撤销权限或被删除后,事件触发 chunk tombstone;检索层立即过滤 tombstoned IDs,后台再清理向量。依赖异步重建完成才生效,会留下几个小时甚至几天的泄露窗口。

答案需要证据,不只需要流畅

RAG 的生成阶段可能忽略检索片段、混合多份冲突内容,或把文档没有说的推断写成事实。我会要求答案中的关键结论绑定 source span,并在生成后检查引用是否真的支持句子。

引用不是在段末放一个文档链接就结束。它应至少带标题、版本、段落位置和有效时间。多个来源冲突时,不让模型自行投票:优先规则由知识治理定义,例如正式制度高于聊天记录、当前版本高于历史版本;无法判定则把冲突展示出来。

生成上下文也要控制重复。top-k 很可能来自同一文档的相邻 chunk,挤掉其他证据。先按 source/section 去重,再在 token 预算内选择覆盖不同子问题的片段。对一个包含三个条件的问题,不能让相似度最高的单个片段占满全部上下文。

最终答案记录 query、检索过滤、候选列表、重排结果、上下文片段与模型输出。用户指出错误时,我们能判断是知识源错、切块错、召回错、排序错还是生成错,而不是一概归因“模型幻觉”。

评测先拆 Retrieval 与 Answer

知识问答整体准确率下降,至少可能来自两段。retrieval 没拿到充分证据,再强的生成模型也只能猜;retrieval 已拿到证据,答案仍错,才重点看提示、上下文组织与生成。

我会给问题标注 supporting source/chunk,先测 recall@k、MRR 与权限过滤后的有效召回,再在固定上下文上测答案正确性、引用支持度和拒答。这样更换 embedding 模型时不需要同时更换生成模型,能看到改动真正影响哪一段。

线上反馈也不能只有点赞。允许用户选择“来源过期”“没找到关键文档”“引用不支持结论”“无权看到”“答案组织不好”。这些标签进入修复队列,并沉淀成回归用例。知识 owner 负责源内容,平台负责索引与权限,模型团队负责生成,责任边界才不会混在一起。

向量检索值得使用,但它只是把搜索空间缩小。企业知识库的可信度来自来源身份、版本、权限、有效期、混合召回、引用和反馈闭环。先把这些工程环节补齐,再调 top-k 和 embedding 模型,效果才不会只停留在演示环境。

参考论文与资料