相关性检索优化说明.md 6.29 KB

相关性检索优化说明

概述

本次优化将相关性检索从简单的 must 子句中的 multi_match 查询,改为使用 should 子句的多查询策略,参考了成熟的搜索实现,显著提升了检索效果。

主要改进

实现方式

本次优化采用精简实现,直接在 QueryParser 中集成必要的分析功能,不新增独立模块。

1. 查询结构优化

之前的结构(效果差):

{
  "bool": {
    "must": [
      {
        "multi_match": {
          "query": "戏水动物",
          "fields": ["title_zh^3.0", "brief_zh^1.5", ...],
          "minimum_should_match": "67%",
          "tie_breaker": 0.9,
          "boost": 1,
          "_name": "base_query"
        }
      }
    ]
  }
}

优化后的结构(效果更好):

{
  "bool": {
    "should": [
      {
        "multi_match": {
          "_name": "base_query",
          "fields": ["title_zh^3.0", "brief_zh^1.5", ...],
          "minimum_should_match": "75%",
          "operator": "AND",
          "query": "戏水动物",
          "tie_breaker": 0.9
        }
      },
      {
        "multi_match": {
          "_name": "base_query_trans_en",
          "boost": 0.4,
          "fields": ["title_en^3.0", ...],
          "minimum_should_match": "75%",
          "operator": "AND",
          "query": "water sports",
          "tie_breaker": 0.9
        }
      },
      {
        "multi_match": {
          "query": "戏水动物",
          "fields": ["title_zh^3.0", "brief_zh^1.5", ...],
          "type": "phrase",
          "slop": 2,
          "boost": 1.0,
          "_name": "phrase_query"
        }
      },
      {
        "multi_match": {
          "query": "戏水 动物",
          "fields": ["title_zh^3.0", "brief_zh^1.5", ...],
          "operator": "AND",
          "tie_breaker": 0.9,
          "boost": 0.1,
          "_name": "keywords_query"
        }
      }
    ],
    "minimum_should_match": 1
  }
}

2. 集成查询分析功能

QueryParser 中直接集成必要的分析功能:

  • 关键词提取:使用 HanLP 提取查询中的名词(长度>1),用于关键词查询(可选,HanLP 不可用时降级)
  • 查询类型判断:区分短查询和长查询
  • Token 计数:用于判断查询长度

3. 多查询策略

3.1 基础查询(base_query)

  • 使用 operator: "AND" 确保所有词都必须匹配
  • minimum_should_match: "75%" 提高匹配精度
  • 使用 tie_breaker: 0.9 进行分数融合

3.2 翻译查询(base_query_trans_zh/en)

  • 当查询语言不是中文/英文时,添加翻译查询
  • 使用较低的 boost(0.4)避免过度影响
  • 支持跨语言检索

3.3 短语查询(phrase_query)

  • 针对短查询(token_count >= 2 且 is_short_query)
  • 使用 type: "phrase" 进行精确短语匹配
  • 支持 slop(允许词序调整)

3.4 关键词查询(keywords_query)

  • 使用 HanLP 提取的名词进行查询
  • 仅在关键词长度合理时启用(避免关键词占查询比例过高)
  • 使用较低的 boost(0.1)作为补充

3.5 长查询优化(long_query)

  • 当前已禁用(参考实现中也是 False)
  • 未来可根据需要启用

4. 字段映射优化

新增 _get_match_fields() 方法,支持:

  • 根据语言动态获取匹配字段
  • 区分全部字段(all_fields)和核心字段(core_fields)
  • 核心字段用于短语查询和关键词查询,提高精度

实现细节

文件修改清单

  1. 修改文件
    • query/query_parser.py - 添加关键词提取、查询类型判断等功能(HanLP 可选)
    • search/es_query_builder.py - 实现 should 子句的多查询策略
    • search/searcher.py - 传递 parsed_query 给查询构建器

关键参数说明

  • minimum_should_match: 从 "67%" 提升到 "75%",提高匹配精度
  • operator: 从默认改为 "AND",确保所有词都匹配
  • tie_breaker: 保持 0.9,用于分数融合
  • boost 值
    • base_query: 1.0(默认)
    • translation queries: 0.4
    • phrase_query: 1.0
    • keywords_query: 0.1

依赖要求

  • HanLP(可选):如果安装了 hanlp 包,会自动启用关键词提取功能 bash pip install hanlp

如果未安装,系统会自动降级到简单分析(基于空格分词),不影响基本功能。

  • HanLP 模型:首次运行时会自动下载
    • Tokenizer: CTB9_TOK_ELECTRA_BASE_CRF
    • POS Tagger: CTB9_POS_ELECTRA_SMALL

配置说明

  • 忽略关键词:在 _extract_keywords() 方法中配置
    • 默认忽略:['玩具']

使用示例

基本使用

查询会自动使用优化后的策略,无需额外配置:

# 在 searcher.py 中,查询会自动使用优化策略
result = searcher.search(
    query="戏水动物",
    tenant_id="162",
    size=10
)

查看分析结果

可以直接从 parsed_query 查看分析结果:

parsed_query = query_parser.parse("戏水动物")
print(f"关键词: {parsed_query.keywords}")
print(f"Token数: {parsed_query.token_count}")
print(f"短查询: {parsed_query.is_short_query}")
print(f"长查询: {parsed_query.is_long_query}")

性能考虑

  1. HanLP 初始化:采用懒加载,首次使用时才初始化
  2. 错误处理:HanLP 初始化失败或未安装时,系统会降级到简单分析(基于空格分词),不影响服务
  3. 代码精简:所有功能直接集成在 QueryParser 中,无额外模块依赖

后续优化方向

  1. 长查询优化:可以启用长查询的特殊处理
  2. 意图识别:完善意图词典,提供更精准的意图识别
  3. 参数调优:根据实际效果调整 boost 值和 minimum_should_match
  4. A/B 测试:对比优化前后的检索效果

注意事项

  1. HanLP 依赖:HanLP 是可选的,如果未安装或初始化失败,系统会自动降级到简单分析,不会影响基本功能
  2. 性能影响:HanLP 分析会增加一定的处理时间,但采用懒加载机制
  3. 字段匹配:确保 ES 索引中存在对应的中英文字段
  4. 代码精简:所有功能都集成在现有模块中,保持代码结构简洁

参考