分块元数据增强与多向量检索方案
项目地址:https://github.com/WiSiW/AI-RAG
摘要
在完全保留原始 chunk 正文、章节和 chunk_id 的前提下,为每个 chunk 生成 5–10 个 BM25 友好关键词、约 50 字摘要及 1–2 个假设问题。使用独立轻量模型,失败时回退规则生成。Milvus 改为“表示行”模式,每个原始块、摘要及问题分别存储向量并共享 chunk_id,检索时与 BM25 组成四路召回并做加权 RRF。
关键实现
1. 增强数据与生成
- 在
document_chunks增加summary、keywords、hypothetical_questions、enrichment_status、enrichment_meta;状态为pending/ready/degraded。 - 新增
ModelKind.ENRICHMENT和知识库enrichment_profile_id。新知识库必须配置增强模型;存量知识库在回填前完成配置。 - 每批最多 8 个 chunk,一次请求返回严格 JSON:关键词、摘要、问题。失败重试一次,单个 chunk 解析失败时仅对该 chunk 使用规则回退。
- 关键词采用与 Whoosh 相同的 jieba 分词规则,过滤停用词、标点和泛化词,保留实体、术语、缩写及高频核心词,限制 5–10 个。
- 摘要目标 45–60 个中文字符,硬上限 80 字,超出时优先截断在完整句末。
- 问题最多生成 2 个、每个不超过 100 字;规则回退使用关键词模板生成。
- 在
enrichment_meta记录生成方式、模型、提示词版本、表示向量数量及降级原因。提示词版本变化时允许重新生成。 - 原始 chunk 内容、章节路径和分块方式均不修改,摘要和问题仅作为派生数据。
2. Milvus 与 BM25 索引
- 新建版本化 Milvus 集合,采用每表示一行:公共字段包括
chunk_id/doc_id/source/section,表示字段包括representation_type、question_index、indexed_text和embedding。 representation_type取original/summary/question;每个问题单独一行,但共享同一 chunk_id。- 原始向量、摘要向量和问题向量均使用知识库现有 Embedding 模型生成,保证同一向量空间和维度。
- 更换或重试文档时先按
doc_id删除全部表示,再批量插入,保证幂等且不产生重复向量。 - Whoosh schema 增加关键词字段,搜索正文、章节和关键词;关键词字段权重 1.5,其余字段保持原有权重。
- PostgreSQL 始终是正文和增强字段的唯一事实源;Milvus 命中后统一按 chunk_id 回表,输出原始 chunk 内容。
3. 检索与融合
- 每次查询按 Embedding 模型只生成一次查询向量,多知识库共享同模型查询向量。
- 每个知识库产生四路召回:BM25、原始块向量、摘要向量、问题向量。
- 问题向量检索允许同一 chunk 的多个问题命中;按 chunk_id 去重并保留最佳排名,检索时按问题数量适当扩大候选集。
- 路由权重保存在知识库
settings.retrieval_weights,默认:bm25=1.0, original=1.0, summary=1.0, questions=1.0。 - 跨路由 RRF 以 chunk_id 合并,保留各路由分数、排名和命中表示;完成后仍使用原 chunk 正文进行 Rerank 和最终生成,不把摘要或问题替代原文送入 LLM。
- 兼容现有
fusion_weight:最终路由权重为其与类型权重的乘积。 - 摘要或问题向量失败时省略对应路由并标记 chunk 为
degraded;已生成的原向量继续生效,不阻断文档入库。
4. 全量回填与切换
- 新增 Milvus 和 Whoosh 的 v2 索引命名空间,知识库记录当前活动索引版本。
- 回填直接读取 PostgreSQL 中现有 chunk,不重新解析、不重新分块、不改变 chunk_id;重新生成增强字段和全部表示向量。
- 回填期间搜索继续读取 v1;新入库文档同时写入 v1/v2。
- 某知识库所有 ready 文档处理完成后,同时切换 Milvus 和 BM25 的读取版本;失败文档可断点重试。
- v1 索引在切换后保留一个稳定发布周期,用于回滚及对比;验收后再由管理员清理。
接口与类型变更
ChunkRead增加summary、keywords、hypothetical_questions、enrichment_status、enrichment_meta。ModelKindValue和前端模型类型增加"enrichment";模型页面支持新增、测试和展示增强模型。- 知识库创建、更新和读取接口增加
enrichment_profile_id;知识库页面增加模型选择。 SearchResult增加matched_representations、representation_scores和representation_ranks;现有vector_score/vector_rank兼容为最佳向量路由结果。SearchQualitySummary增加各路由命中数;检索质检页面展示表示命中标签及路由分数。- 文档预览页展示摘要、关键词标签、假设问题和降级状态;本地 chunk 搜索同时覆盖增强字段。
IngestionJob.result增加增强成功数、降级数、表示向量数和使用的增强模型。
测试与验收
- 单元测试增强结果的 JSON 解析、长度约束、关键词去重、1–2 个问题生成及规则回退。
- 使用伪造模型验证入库后 chunk 正文逐字未变,且原始、摘要、问题表示均关联同一 chunk_id。
- 测试 LLM、问题 Embedding 失败时文档仍成功入库,状态为 degraded,原向量仍可召回。
- 测试仅关键词命中、仅摘要命中、仅问题命中的查询都能返回对应原始 chunk。
- 测试多表示 RRF 去重、可配置权重、命中路由信息和多知识库检索。
- 测试回填任务幂等、保留 chunk_id、可断点重试,并在全部完成后切换 v2。
- 使用现有 30–50 条评测集比较增强前后的 Recall@5、MRR、引用准确率、入库耗时和 p95 延迟;默认等权,再依据评测调整知识库权重。
假设与默认值
- 增强模型是 OpenAI-compatible 的轻量聊天模型;Embedding 继续使用知识库现有模型。
- LLM 不可用或输出非法时始终使用确定性规则补齐,不阻断入库。
- 原始 Embedding 调用失败仍按现有严格策略重试并失败,不将文档错误标记为可用。
- 摘要和问题只服务于召回,最终回答上下文只包含原始 chunk 或原有父块内容。
- v2 切换完成后保留旧索引一个稳定发布周期,不自动删除。
最后更新: 2026年11月03日 15:01