Query Expansion(查询扩展)是在真正检索前,给原始短查询补充同义词、相关概念或多视角表述,从而扩大召回范围的技术。它直接缓解”词汇鸿沟”——用户用词和文档用词不一致导致漏检。在 AI 热点监控(工具)里,它把运营手写的一两个种子词,自动展开成多组检索式,覆盖更多说法,减少热点漏抓。
一、为什么需要查询扩展
用户 query 往往很短,承载的语义不完整。两个典型问题:
- 词汇鸿沟:用户搜”LLM 速度”,文档里写”大型语言模型 推理延迟”,关键词匹配直接失败。扩展后加入”推理延迟””响应时间”等说法,才能命中。
- 语义不完整:用户只丢一句口语化短句,向量表示稀疏,召回质量低。补充相关术语后,语义向量更饱满。
扩展不追求”改写得漂亮”,只追求”把该命中的文档捞上来”,核心指标是召回率(Recall)。
二、三类主流方法对比
| 方法 | 原理 | 优点 | 风险 |
|---|---|---|---|
| 同义词/词典扩展 | 用 WordNet、领域词典补同义词 | 可解释、零模型依赖 | 词表覆盖有限 |
| 多视角生成(Multi-Query) | 用 LLM 生成多个语义视角 query | 覆盖广、语义相关 | 易主题漂移 |
| 假设文档嵌入(HyDE) | 先让 LLM 写假设答案,再嵌入检索 | 语义更密、适配稠密检索 | 生成质量影响结果 |
传统伪相关反馈(PRF)从初检结果里挑高频词做扩展,成本低但只看词频、忽略语义。LLM 驱动的方法弥补了这点,却引入了”主题漂移”——生成的变体跑偏,反而拉低精度。控制漂移的办法是给扩展词加语义约束,并限定数量。
三、在热点监控项目里的实现
把种子词变成可检索的多组表达式,按四步执行:
- 接收运营配置的种子词(如”AI 芯片””算力”);
- 调用大模型生成同义词、上位词、关联概念,并给出多视角 query;
- 把多组 query 拼成平台检索式(Twitter 用
OR连接,B站用标签组合); - 对各路结果做融合与去重,再送内容分析模块。
下面给出一段扩展函数的精简实现:
import openai
def expand_query(seed: str) -> list[str]:
prompt = f"""你是检索增强助手。基于关键词"{seed}"生成 5 个检索变体,
要求:覆盖同义词、相关概念、不同表述;不要解释,每行一个。"""
resp = openai.OpenAI().chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
)
variants = [line.strip("- ").strip()
for line in resp.choices[0].message.content.splitlines()
if line.strip()]
return [seed] + variants[:5] # 保留原词,限制数量防漂移
def build_twitter_query(seeds: list[str]) -> str:
expanded = []
for s in seeds:
expanded += expand_query(s)
# 去重后用 OR 拼接,控制长度避免超查询上限
uniq = list(dict.fromkeys(expanded))
return " OR ".join(f'"{w}"' for w in uniq[:10])
这里把原词保留进结果,保证不丢失本意;用 dict.fromkeys 去重,并把数量压到平台查询上限内,避免拼接出的检索式过长被拒。
四、避坑:主题漂移与成本控制
扩展词越多,召回越高,但噪声也随之上升。实测经验是单组种子控制在 3–6 个变体,过多反而稀释相关结果。对扩展结果做一层”相关度过滤”——只保留与种子词语义相似度高于阈值的变体——能有效压住漂移。
成本上,每轮扩展都要调一次大模型。热点词相对固定,可把扩展结果缓存到 Redis,仅在词表变更时重建,避免每次轮询都重复生成。
稠密检索(向量检索)配合扩展效果更稳:原 query 与扩展 query 分别向量化后融合,既保关键词命中,又补语义召回。BM25 这类稀疏检索则更依赖同义词词典,对生成式扩展的增益有限。
常见问题(FAQ)
Q1:查询扩展和查询改写是一回事吗?
不是。改写是换一种清楚说法,扩展是追加同义/相关词以扩大召回。
Q2:扩展词太多会怎样?
会引入主题漂移,召回变广但精度下降,建议每组限 3–6 个。
Q3:HyDE 一定要用大模型吗?
是的,它先生成假设文档再嵌入,依赖模型写作质量,也可用真文档替代。