Skip to content

检索系统概览

检索系统是 Knowledge 服务的核心能力,提供从简单向量检索到复杂混合检索的多种方案,支持重排序优化和上下文补全。

检索架构

检索系统采用 四步流水线 设计:

步骤说明是否可选
基础检索向量检索或混合检索必选
信息补全从数据库补全标题、位置、内容自动执行
重排序qwen3-rerank 精排优化可选
上下文扩展扩展相邻分片可选

基础检索

向量检索 (默认)

基于语义相似度的智能检索,能够理解查询意图:

查询文本 → Embedding 模型 → 查询向量 → 向量相似度计算 → 返回 TopK 相似分片

优势:

  • ✅ 理解语义,支持同义匹配
  • ✅ 不需要精确关键词

劣势:

  • ❌ 可能遗漏专有名词、精确词

混合检索 (可选)

结合关键词检索和向量检索,双路召回:

优势:

  • ✅ 兼顾语义理解与精确匹配
  • ✅ 召回更全面

适用场景: 包含专有名词、技术术语的查询


信息补全 (DocumentEnricher)

基础检索返回的结果可能缺少部分信息 (如标题、完整内容),需要从数据库补全:

java
// 伪代码 - 信息补全流程
public List<RetrievedDocument> enrich(List<RetrievedDocument> docs) {
    // 1. 收集需要补全的文档 ID
    Set<Long> documentIds = collectDocumentIds(docs);
    
    // 2. 批量查询文档信息 (标题、作者、分类等)
    Map<Long, KlDocumentEntity> documents = 
        documentMapper.selectByIds(documentIds);
    
    // 3. 批量查询分片信息 (字符位置、完整内容等)
    Map<Long, KlDocumentChunkEntity> chunks = 
        chunkMapper.selectByVectorIds(vectorIds);
    
    // 4. 填充信息
    for (RetrievedDocument doc : docs) {
        KlDocumentEntity document = documents.get(doc.getDocumentId());
        doc.setTitle(document.getTitle());
        doc.setFileType(document.getFileType());
        doc.setSource(document.getSource());
        
        KlDocumentChunkEntity chunk = chunks.get(doc.getChunkId());
        doc.setCharStartIndex(chunk.getCharStartIndex());
        doc.setCharEndIndex(chunk.getCharEndIndex());
        
        // 如果向量库不支持返回原文,从数据库补全
        if (doc.getContent() == null) {
            doc.setContent(chunk.getContent());
        }
    }
    
    return docs;
}

补全内容:

  • 文档标题
  • 文件类型
  • 来源信息
  • 字符位置 (charStartIndex, charEndIndex)
  • 完整内容 (如果向量库未返回)

重排序 (可选)

对初检结果进行精细化排序,提升结果相关性:

初检结果 (Top 20) → qwen3-rerank 模型 → 精排结果 (Top 5)

原理:

  • 重排序模型深度理解查询与文档的相关性
  • 比向量相似度更精准

成本:

  • 需调用外部 API (阿里云 DashScope)
  • 有额外延迟和费用

适用场景: 对检索精度要求高的场景


上下文扩展 (可选)

通过扩展相邻分片,解决分片截断导致的语义不完整问题:

问题场景

原文:
...分布式锁的实现方式有多种,常见的包括:
1. 基于数据库的实现
2. 基于 Redis 的实现
3. 基于 ZooKeeper 的实现...

分片结果:
Chunk 5: ...分布式锁的实现方式有多种,常见的包括:
Chunk 6: 1. 基于数据库的实现
Chunk 7: 2. 基于 Redis 的实现
Chunk 8: 3. 基于 ZooKeeper 的实现...

检索命中 Chunk 6,但缺少上下文...

解决方案

自动扩展命中分片的前后相邻分片:

命中 Chunk 6 → 扩展 Chunk 5, 6, 7 → 合并为完整语义片段

区间合并:

  • 当多个命中分片在同一文档内且位置相邻时,自动合并区间
  • 允许 100 字符间隙
  • 避免返回重复内容

检索模式对比

模式配置效果成本
基础模式仅向量检索语义匹配
混合模式向量 + 关键词召回更全面
精排模式向量 + 重排序结果更精准中高
完整模式混合 + 重排序 + 上下文最佳效果

元数据过滤

所有检索模式都支持元数据过滤,缩小检索范围:

java
RetrievalOptions options = RetrievalOptions.builder()
        .libraryIds(List.of("lib-1", "lib-2"))  // 按知识库过滤
        .documentId("doc-001")                   // 按文档过滤
        .author("张三")                           // 按作者过滤
        .category("技术文档")                     // 按分类过滤
        .tag("分布式")                            // 按标签过滤
        .enableHybridSearch(true)                // 启用混合检索
        .build();

支持的过滤字段:

字段说明查询类型
library_id知识库 IDEQ / IN
document_id文档 IDEQ
author作者EQ
category分类EQ
tags标签IN (多标签)

核心组件

组件接口/类说明
检索编排KnowledgeRetrievalService四步流水线编排
向量检索VectorSearchServiceSpring AI VectorStore 实现
关键词检索KeywordSearchServiceES / Lucene 实现
混合检索HybridSearchService双路召回 + 融合
重排序RerankServiceqwen3-rerank 调用
信息补全DocumentEnricher数据库补全信息
上下文扩展ContextExpander相邻分片扩展

下一步