Query Rewrite 的核心作用把“人类表达”变成“检索表达”一、为什么 RAG 需要 Query Rewrite很多 RAG 项目上线后最大的问题不是模型不会回答而是检索阶段就没有把正确资料找回来。用户的问题通常很口语、很短、带指代甚至只说“这个怎么弄”。而企业知识库里的文档往往是制度标题、字段名、流程名、产品术语。Query Rewrite 的价值就是在检索之前做一次“翻译”把用户的自然表达改写成更容易命中文档的检索表达。二、在线 RAG 链路里Query Rewrite 放在哪里在在线 RAG 中Query Rewrite 一般放在检索之前。它不是最终答案生成而是让后面的检索、融合、精排、Prompt 组装更稳定。三、方法一直接改写把问题补完整直接改写最常见也最容易落地。它适合处理口语化、省略、指代、多轮上下文缺失等问题。核心要求是只补全不篡改。代码示例Python可复制from pydantic import BaseModel, Field from typing import List class RewriteResult(BaseModel): rewritten_query: str Field(description补全后的检索问题) keywords: List[str] Field(description可用于 BM25 的关键词) keep_original: bool Field(defaultTrue, description是否保留原问题一起检索) risk: str Field(descriptionlow / medium / high表示改写漂移风险) SYSTEM_PROMPT 你是 RAG 查询改写器。 要求 1. 只能补全用户原意不能新增用户没有表达的业务诉求。 2. 结合最近 3 轮对话消解“它、这个、那个、上次”等指代。 3. 输出必须是 JSON不要回答问题本身。 def build_rewrite_prompt(history: list[str], user_query: str) - str: return f 最近对话 {chr(10).join(history[-3:])} 用户当前问题{user_query} 请输出 RewriteResult JSON。 四、方法二HyDE先生成“假文档”再检索HyDE 的思路是原始 Query 太短直接 Embedding 不稳定那就先让模型生成一段“假设性的答案/文档”再用这段更像知识库文本的内容做向量检索。注意HyDE 不是相信假答案而是用它改善召回。代码示例Python可复制from llama_index.core import VectorStoreIndex, SimpleDirectoryReader from llama_index.core.indices.query.query_transform import HyDEQueryTransform from llama_index.core.query_engine import TransformQueryEngine # 1. 构建索引 documents SimpleDirectoryReader(./docs).load_data() index VectorStoreIndex.from_documents(documents) # 2. 普通查询引擎 base_engine index.as_query_engine(similarity_top_k8) # 3. 使用 HyDE 改写生成 hypothetical document 后再检索 hyde HyDEQueryTransform(include_originalTrue) query_engine TransformQueryEngine(base_engine, query_transformhyde) response query_engine.query(新员工怎么申请电脑) print(response)五、方法三Step-back先退一步问上位问题有些知识库不是按具体问题组织而是按制度、原则、流程组织。用户问得越具体越可能检索不到上位规则。Step-back 会先把问题抽象成更高层问题再和原问题一起检索。代码示例Python可复制def build_step_back_queries(user_query: str) - list[str]: 真实生产中这里通常由 LLM 生成。 输出两路查询一路保留具体问题一路抽象成上位规则。 return [ user_query, 与该问题相关的制度依据、处理流程、常见原因和审批规则是什么, ] queries build_step_back_queries(报销发票被退回怎么办) for q in queries: docs retriever.search(q, top_k8) # 后续进入融合排序六、方法四Multi-Query RRF多角度召回再融合Multi-Query 会把一个问题改写成多个等价或互补表达让检索从多个角度去找资料。多个召回列表不能简单拼接一般要用 RRF 或 Rerank 做融合。代码示例Python可复制from collections import defaultdict def reciprocal_rank_fusion(result_lists: list[list[str]], k: int 60) - list[tuple[str, float]]: result_lists: 多路召回结果每一路是按相关性排序的 doc_id 列表。 RRF 思路同一篇文档在多个列表靠前最终分数就更高。 scores defaultdict(float) for results in result_lists: for rank, doc_id in enumerate(results, start1): scores[doc_id] 1.0 / (k rank) return sorted(scores.items(), keylambda x: x[1], reverseTrue) result_lists [ [doc_1, doc_2, doc_5], [doc_2, doc_4, doc_1], [doc_3, doc_2, doc_6], ] print(reciprocal_rank_fusion(result_lists))代码示例Python可复制# LangChain MultiQueryRetriever 示例让 LLM 生成多条检索 Query from langchain.retrievers.multi_query import MultiQueryRetriever retriever vectorstore.as_retriever(search_kwargs{k: 6}) multi_query_retriever MultiQueryRetriever.from_llm( retrieverretriever, llmllm, ) docs multi_query_retriever.invoke(员工出差费用怎么报销)七、方法五Self-Query从自然语言里抽取过滤条件如果你的文档有 metadata例如部门、年份、类型、权限、产品线那么 Self-Query 会非常有用。它把用户问题拆成“语义检索词 结构化过滤条件”。代码示例Python可复制from pydantic import BaseModel, Field from typing import Optional, Literal class StructuredQuery(BaseModel): query: str Field(description用于向量/BM25 检索的文本) doc_type: Optional[Literal[制度, 流程, FAQ, 公告]] None year_gte: Optional[int] None department: Optional[str] None # 用户问题查一下 2025 年以后跟医保报销有关的制度 structured StructuredQuery( query医保报销, doc_type制度, year_gte2025, ) # 注意生产中必须把 filter 映射到白名单字段不能让模型直接拼 SQL。 filter_expr { doc_type: structured.doc_type, year: {$gte: structured.year_gte}, }八、方法六Router Query先判断去哪套知识库查当知识库很多时先路由再检索比全库乱搜更稳定。路由可以按业务域、语言、权限、数据源类型来做。代码示例Python可复制ROUTES { finance: 财务制度库发票、报销、付款、预算, hr: 人事制度库入离职、薪酬、考勤、福利, it: IT 帮助库账号、权限、系统故障、设备申请, } def route_query(user_query: str) - str: prompt f 你是查询路由器只能从 finance/hr/it 中选择一个。 路由说明{ROUTES} 用户问题{user_query} 只输出路由 key。 route llm.invoke(prompt).strip() return route if route in ROUTES else finance route route_query(发票抬头错了怎么处理) docs retrievers[route].search(发票抬头错误处理流程, top_k8)九、到底用哪种改写方式Query Rewrite 没有银弹。直接改写成本最低HyDE 对表达差异大的问题有帮助Multi-Query 更适合复杂问题Self-Query 依赖高质量元数据Router Query 适合多知识库系统。十、工程上怎么评估 Query Rewrite评估时不要只看“改写得是否通顺”。真正要看召回是否更准、排序是否更靠前、答案是否更忠实、延迟是否能接受、有没有改写漂移。代码示例Python可复制def evaluate_rewrite(original_query: str, rewritten_queries: list[str], gold_doc_ids: set[str]) - dict: 一个最小化离线评测示例。 真实项目里可以扩展 RecallK、MRR、nDCG、Faithfulness、Latency 等指标。 origin_docs retriever.search(original_query, top_k10) rewrite_docs [] for q in rewritten_queries: rewrite_docs.extend(retriever.search(q, top_k10)) origin_ids {d.id for d in origin_docs} rewrite_ids {d.id for d in rewrite_docs} return { origin_recall: len(origin_ids gold_doc_ids) / max(len(gold_doc_ids), 1), rewrite_recall: len(rewrite_ids gold_doc_ids) / max(len(gold_doc_ids), 1), new_hits: list((rewrite_ids - origin_ids) gold_doc_ids), }十一、生产级护栏改写可以增强但不能乱改Query Rewrite 最大的风险是“漂移”用户本来问 A改写器为了检索更顺手改成了 B。生产环境里必须保留原 Query、输出结构化 JSON、控制扩展数量、记录日志并对改写前后召回结果做对比。代码示例Python可复制class RewriteGuardrail: def __init__(self, max_queries: int 5, max_drift_score: float 0.35): self.max_queries max_queries self.max_drift_score max_drift_score def validate(self, original: str, rewrites: list[str]) - list[str]: # 1. 控制数量 rewrites rewrites[: self.max_queries] # 2. 保留原问题避免改写失败时完全跑偏 candidates [original] rewrites # 3. 漂移检测实际可以用 embedding 相似度、LLM 判别或规则 safe_queries [] for q in candidates: drift estimate_semantic_drift(original, q) if drift self.max_drift_score: safe_queries.append(q) return safe_queries or [original]十二、可以直接记住的面试回答Query Rewrite 的目的是把用户原始问题改写成更适合检索系统理解和命中的查询表达。它主要解决口语化、上下文缺失、表达不匹配、单一路径召回不足、结构化过滤不足等问题。常见方式包括直接改写、多轮指代消解、HyDE、Step-back、Multi-Query、Self-Query 和 Router Query。工程上不能只追求改写通顺而要通过 RecallK、MRR、nDCG、答案忠实度、延迟、成本和漂移率来评估。生产环境里最稳的做法是保留原 Query 多路改写 混合检索 RRF 融合 Rerank 精排 引用校验 日志回放。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】
RAG 查询改写:如何把用户的随口一问,改写成检索系统能命中问题
发布时间:2026/7/1 2:01:53
Query Rewrite 的核心作用把“人类表达”变成“检索表达”一、为什么 RAG 需要 Query Rewrite很多 RAG 项目上线后最大的问题不是模型不会回答而是检索阶段就没有把正确资料找回来。用户的问题通常很口语、很短、带指代甚至只说“这个怎么弄”。而企业知识库里的文档往往是制度标题、字段名、流程名、产品术语。Query Rewrite 的价值就是在检索之前做一次“翻译”把用户的自然表达改写成更容易命中文档的检索表达。二、在线 RAG 链路里Query Rewrite 放在哪里在在线 RAG 中Query Rewrite 一般放在检索之前。它不是最终答案生成而是让后面的检索、融合、精排、Prompt 组装更稳定。三、方法一直接改写把问题补完整直接改写最常见也最容易落地。它适合处理口语化、省略、指代、多轮上下文缺失等问题。核心要求是只补全不篡改。代码示例Python可复制from pydantic import BaseModel, Field from typing import List class RewriteResult(BaseModel): rewritten_query: str Field(description补全后的检索问题) keywords: List[str] Field(description可用于 BM25 的关键词) keep_original: bool Field(defaultTrue, description是否保留原问题一起检索) risk: str Field(descriptionlow / medium / high表示改写漂移风险) SYSTEM_PROMPT 你是 RAG 查询改写器。 要求 1. 只能补全用户原意不能新增用户没有表达的业务诉求。 2. 结合最近 3 轮对话消解“它、这个、那个、上次”等指代。 3. 输出必须是 JSON不要回答问题本身。 def build_rewrite_prompt(history: list[str], user_query: str) - str: return f 最近对话 {chr(10).join(history[-3:])} 用户当前问题{user_query} 请输出 RewriteResult JSON。 四、方法二HyDE先生成“假文档”再检索HyDE 的思路是原始 Query 太短直接 Embedding 不稳定那就先让模型生成一段“假设性的答案/文档”再用这段更像知识库文本的内容做向量检索。注意HyDE 不是相信假答案而是用它改善召回。代码示例Python可复制from llama_index.core import VectorStoreIndex, SimpleDirectoryReader from llama_index.core.indices.query.query_transform import HyDEQueryTransform from llama_index.core.query_engine import TransformQueryEngine # 1. 构建索引 documents SimpleDirectoryReader(./docs).load_data() index VectorStoreIndex.from_documents(documents) # 2. 普通查询引擎 base_engine index.as_query_engine(similarity_top_k8) # 3. 使用 HyDE 改写生成 hypothetical document 后再检索 hyde HyDEQueryTransform(include_originalTrue) query_engine TransformQueryEngine(base_engine, query_transformhyde) response query_engine.query(新员工怎么申请电脑) print(response)五、方法三Step-back先退一步问上位问题有些知识库不是按具体问题组织而是按制度、原则、流程组织。用户问得越具体越可能检索不到上位规则。Step-back 会先把问题抽象成更高层问题再和原问题一起检索。代码示例Python可复制def build_step_back_queries(user_query: str) - list[str]: 真实生产中这里通常由 LLM 生成。 输出两路查询一路保留具体问题一路抽象成上位规则。 return [ user_query, 与该问题相关的制度依据、处理流程、常见原因和审批规则是什么, ] queries build_step_back_queries(报销发票被退回怎么办) for q in queries: docs retriever.search(q, top_k8) # 后续进入融合排序六、方法四Multi-Query RRF多角度召回再融合Multi-Query 会把一个问题改写成多个等价或互补表达让检索从多个角度去找资料。多个召回列表不能简单拼接一般要用 RRF 或 Rerank 做融合。代码示例Python可复制from collections import defaultdict def reciprocal_rank_fusion(result_lists: list[list[str]], k: int 60) - list[tuple[str, float]]: result_lists: 多路召回结果每一路是按相关性排序的 doc_id 列表。 RRF 思路同一篇文档在多个列表靠前最终分数就更高。 scores defaultdict(float) for results in result_lists: for rank, doc_id in enumerate(results, start1): scores[doc_id] 1.0 / (k rank) return sorted(scores.items(), keylambda x: x[1], reverseTrue) result_lists [ [doc_1, doc_2, doc_5], [doc_2, doc_4, doc_1], [doc_3, doc_2, doc_6], ] print(reciprocal_rank_fusion(result_lists))代码示例Python可复制# LangChain MultiQueryRetriever 示例让 LLM 生成多条检索 Query from langchain.retrievers.multi_query import MultiQueryRetriever retriever vectorstore.as_retriever(search_kwargs{k: 6}) multi_query_retriever MultiQueryRetriever.from_llm( retrieverretriever, llmllm, ) docs multi_query_retriever.invoke(员工出差费用怎么报销)七、方法五Self-Query从自然语言里抽取过滤条件如果你的文档有 metadata例如部门、年份、类型、权限、产品线那么 Self-Query 会非常有用。它把用户问题拆成“语义检索词 结构化过滤条件”。代码示例Python可复制from pydantic import BaseModel, Field from typing import Optional, Literal class StructuredQuery(BaseModel): query: str Field(description用于向量/BM25 检索的文本) doc_type: Optional[Literal[制度, 流程, FAQ, 公告]] None year_gte: Optional[int] None department: Optional[str] None # 用户问题查一下 2025 年以后跟医保报销有关的制度 structured StructuredQuery( query医保报销, doc_type制度, year_gte2025, ) # 注意生产中必须把 filter 映射到白名单字段不能让模型直接拼 SQL。 filter_expr { doc_type: structured.doc_type, year: {$gte: structured.year_gte}, }八、方法六Router Query先判断去哪套知识库查当知识库很多时先路由再检索比全库乱搜更稳定。路由可以按业务域、语言、权限、数据源类型来做。代码示例Python可复制ROUTES { finance: 财务制度库发票、报销、付款、预算, hr: 人事制度库入离职、薪酬、考勤、福利, it: IT 帮助库账号、权限、系统故障、设备申请, } def route_query(user_query: str) - str: prompt f 你是查询路由器只能从 finance/hr/it 中选择一个。 路由说明{ROUTES} 用户问题{user_query} 只输出路由 key。 route llm.invoke(prompt).strip() return route if route in ROUTES else finance route route_query(发票抬头错了怎么处理) docs retrievers[route].search(发票抬头错误处理流程, top_k8)九、到底用哪种改写方式Query Rewrite 没有银弹。直接改写成本最低HyDE 对表达差异大的问题有帮助Multi-Query 更适合复杂问题Self-Query 依赖高质量元数据Router Query 适合多知识库系统。十、工程上怎么评估 Query Rewrite评估时不要只看“改写得是否通顺”。真正要看召回是否更准、排序是否更靠前、答案是否更忠实、延迟是否能接受、有没有改写漂移。代码示例Python可复制def evaluate_rewrite(original_query: str, rewritten_queries: list[str], gold_doc_ids: set[str]) - dict: 一个最小化离线评测示例。 真实项目里可以扩展 RecallK、MRR、nDCG、Faithfulness、Latency 等指标。 origin_docs retriever.search(original_query, top_k10) rewrite_docs [] for q in rewritten_queries: rewrite_docs.extend(retriever.search(q, top_k10)) origin_ids {d.id for d in origin_docs} rewrite_ids {d.id for d in rewrite_docs} return { origin_recall: len(origin_ids gold_doc_ids) / max(len(gold_doc_ids), 1), rewrite_recall: len(rewrite_ids gold_doc_ids) / max(len(gold_doc_ids), 1), new_hits: list((rewrite_ids - origin_ids) gold_doc_ids), }十一、生产级护栏改写可以增强但不能乱改Query Rewrite 最大的风险是“漂移”用户本来问 A改写器为了检索更顺手改成了 B。生产环境里必须保留原 Query、输出结构化 JSON、控制扩展数量、记录日志并对改写前后召回结果做对比。代码示例Python可复制class RewriteGuardrail: def __init__(self, max_queries: int 5, max_drift_score: float 0.35): self.max_queries max_queries self.max_drift_score max_drift_score def validate(self, original: str, rewrites: list[str]) - list[str]: # 1. 控制数量 rewrites rewrites[: self.max_queries] # 2. 保留原问题避免改写失败时完全跑偏 candidates [original] rewrites # 3. 漂移检测实际可以用 embedding 相似度、LLM 判别或规则 safe_queries [] for q in candidates: drift estimate_semantic_drift(original, q) if drift self.max_drift_score: safe_queries.append(q) return safe_queries or [original]十二、可以直接记住的面试回答Query Rewrite 的目的是把用户原始问题改写成更适合检索系统理解和命中的查询表达。它主要解决口语化、上下文缺失、表达不匹配、单一路径召回不足、结构化过滤不足等问题。常见方式包括直接改写、多轮指代消解、HyDE、Step-back、Multi-Query、Self-Query 和 Router Query。工程上不能只追求改写通顺而要通过 RecallK、MRR、nDCG、答案忠实度、延迟、成本和漂移率来评估。生产环境里最稳的做法是保留原 Query 多路改写 混合检索 RRF 融合 Rerank 精排 引用校验 日志回放。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】