Skip to content
🔗 分享本题
查看我的学习进度 →

Query Rewrite 利用对话历史消解代词并补全省略,将问题改写为独立检索查询

🧠 记忆锚点:先消歧补全成独立问题,再去检索;重写不改意图。

💡 答案要点

为什么需要上下文重写(Query Rewrite):

用户第1轮: "给我介绍一下张三"
用户第2轮: "他的工作经历是什么?"  ← "他"指的是谁?
用户第3轮: "和李四比呢?"          ← 上下文依赖更深

问题:直接用第2/3轮query去检索,向量数据库不知道"他"是谁!

解决方案:上下文感知重写

展开 Python 代码示例(37 行)
python
async def rewrite_with_context(
    query: str,
    history: list[dict]
) -> str:
    """将多轮对话query重写为独立完整的查询"""

    prompt = f"""
你是一个查询重写助手。根据对话历史,将用户的最新问题重写为
一个完整、独立、不依赖上下文的查询。

对话历史:
{format_history(history)}

用户最新问题:{query}

重写规则:
1. 解析代词(他/她/它/这个/那个)→ 替换为具体指代
2. 补全省略成分("和上面说的比呢" → "XXX和YYY相比有什么区别")
3. 保留原始意图,不要改变问题本质
4. 输出简洁,不要解释

重写后的查询:
    """

    rewritten = await llm.complete(prompt)
    return rewritten

# 示例
history = [
    {"role": "user", "content": "给我介绍一下LangChain"},
    {"role": "assistant", "content": "LangChain是..."}
]
query = "它和LlamaIndex比有什么优势?"

rewritten = await rewrite_with_context(query, history)
# 输出: "LangChain和LlamaIndex相比有什么优势?"
# 现在向量检索就能精准找到相关内容!

完整 RAG 管道中的位置:

用户输入 → [上下文重写] → 向量检索 → Rerank → LLM生成 → 输出

          依赖对话历史

面试话术:

"上下文重写是多轮对话 RAG 的关键环节。问题是用户第N轮的query往往有代词和省略,直接向量检索效果很差。我的方案是:先用 LLM 把当前 query + 历史 context 一起输入,让模型重写成完整独立的查询,再去检索。额外成本是一次小模型调用(约100 token,¥0.0001),但检索准确率提升 30% 以上。"