分块元数据增强与多向量检索方案

项目地址: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