RAG_查询重构与分发
用户的原始问题往往不是最优的检索输入。它可能过于复杂、包含歧义,或者与文档的实际措辞存在偏差。为了解决这些问题,我们需要在检索之前对用户的查询进行“预处理”,这就是本节要探讨的查询重构与分发。
这个阶段主要包含两个关键技术:
- 查询翻译(Query Translation):将用户的原始问题转换成一个或多个更适合检索的形式。
 - 查询路由(Query Routing):根据问题的性质,将其智能地分发到最合适的数据源或检索器。
 
本节将重点介绍几种主流的查询翻译技术,并简要讨论查询路由的概念。
一、查询翻译
查询翻译的目标是弥合用户自然语言提问与文档库中存储信息之间的“语义鸿沟”。通过重写、分解或扩展查询,我们可以显著提升检索的准确率。
1.1 提示工程
这是最直接的查询重构方法。通过精心设计的提示词(Prompt),可以引导 LLM 将用户的原始查询改写得更清晰、更具体,或者转换成一种更利于检索的叙述风格。
在第二节查询构建的代码示例中,我们发现 SelfQueryRetriever 无法正确处理“时间最短的视频”这类需要排序或进行比较的查询。
为了解决这个问题,可以采用一种更高级的提示工程技巧:让 LLM 直接构建出查询指令。
这种方法的思路是,要求 LLM 直接分析用户的意图,并生成一个结构化(例如 JSON 格式)的指令,告诉我们的代码应该如何操作。对于“时间最短的视频”这个问题,我们期望 LLM 能直接告诉我们:“请按‘时长’字段进行升序排序,并返回第一条结果”。
下面,来看看如何修改代码来实现这一思路。我们不再使用 SelfQueryRetriever,而是直接与 LLM 交互,并根据其返回的指令在代码中执行排序逻辑。
关键的修改主要有两部分:
-  
设计一个新的提示词(Prompt),要求 LLM 输出 JSON 格式的排序指令。
# 使用大模型将自然语言转换为排序指令 prompt = f"""你是一个智能助手,请将用户的问题转换成一个用于排序视频的JSON指令。你需要识别用户想要排序的字段和排序方向。 - 排序字段必须是 'view_count' (观看次数) 或 'length' (时长) 之一。 - 排序方向必须是 'asc' (升序) 或 'desc' (降序) 之一。例如: - '时间最短的视频' 或 '哪个视频时间最短' 应转换为 {{"sort_by": "length", "order": "asc"}} - '播放量最高的视频' 或 '哪个视频最火' 应转换为 {{"sort_by": "view_count", "order": "desc"}}请根据以下问题生成JSON指令: 原始问题: "{query}"JSON指令:""" -  
在代码中调用 LLM,解析其返回的 JSON 指令,并执行相应的排序操作。
# ... (前略,初始化LLM客户端)# 请求LLM生成指令,并指定返回JSON格式 response = client.chat.completions.create(model="deepseek-chat",messages=[{"role": "user", "content": prompt}],temperature=0,response_format={"type": "json_object"} )# 解析指令并执行排序 try:import jsoninstruction_str = response.choices[0].message.contentinstruction = json.loads(instruction_str)print(f"--- 生成的排序指令: {instruction} ---")sort_by = instruction.get('sort_by')order = instruction.get('order')if sort_by in ['length', 'view_count'] and order in ['asc', 'desc']:# 在代码中执行排序reverse_order = (order == 'desc')sorted_docs = sorted(all_documents, key=lambda doc: doc.metadata.get(sort_by, 0), reverse=reverse_order)# 获取排序后的第一个结果并打印if sorted_docs:doc = sorted_docs[0]# ... (打印结果的代码)except (json.JSONDecodeError, KeyError) as e:print(f"解析或执行指令失败: {e}") 
通过这种方式,成功地将 LLM 从一个简单的“文本改写员”提升为了一个能够理解复杂意图并生成可执行计划的“智能代理”,从而优雅地解决了“最值”查询的难题。
完整代码
1.2 多查询分解 (Multi-query)
</
