当前位置: 首页 > news >正文

RAG--Query改写

一、 为什么要进行Query改写?
想象一下,你去图书馆查资料,但问管理员的问题很模糊、有错别字、或者缺少背景信息,管理员就很难找到你真正需要的书。

Query改写就是帮用户“把问题问得更好”。
主要解决以下问题:

1. 表述模糊:用户查询简短、不完整

2. 词汇不匹配:用户用词和文档用词不同

3. 缺少上下文:多轮对话中,当前查询脱离了历史背景

4. 意图不明确:需要推测用户的深层需求

二、 Query改写的主要策略

将策略分为四个层次:

Level 1: 基础改写(适合快速上手)
1. 查询扩展(Query Expansion)
思路:为原始查询添加同义词、相关词

# 使用同义词库扩展
import nltk
from nltk.corpus import wordnetdef expand_query_with_synonyms(query):expanded_terms = []for word in query.split():synonyms = set()for syn in wordnet.synsets(word):for lemma in syn.lemmas():synonyms.add(lemma.name())if synonyms:expanded_terms.append(f"({' OR '.join(list(synonyms)[:3])})")else:expanded_terms.append(word)return ' '.join(expanded_terms)# 示例:将"car"扩展为"(car OR auto OR automobile OR motorcar)"

2.拼写纠正

# 使用TextBlob(需安装:pip install textblob)
from textblob import TextBlobdef correct_spelling(query):blob = TextBlob(query)return str(blob.correct())

Level 2: 上下文感知改写(处理多轮对话)

1. 对话历史整合

def rewrite_with_conversation_history(current_query, history, max_turns=3):"""history格式: [{"user": "...", "assistant": "..."}, ...]"""if not history:return current_query# 提取最近的几轮对话recent_history = history[-max_turns:]# 构建带历史的提示词context = "\n".join([f"User: {h['user']}\nAssistant: {h['assistant']}" for h in recent_history])prompt = f"""基于以下对话历史和当前问题,重写当前问题使其更完整、独立。对话历史:
{context}当前问题:{current_query}重写后的问题:"""# 调用LLM进行改写(以智谱AI为例)from zai import ZhipuAiClientclient = ZhipuAiClient(api_key="")response = client.chat.completions.create(model="",messages=[{"role": "user", "content": prompt}],temperature=0.3)return response.choices[0].message.content

Level 3: 高级意图理解(使用LLM进行智能改写)

1. 多角度改写(HyDE - Hypothetical Document Embeddings)

def generate_hypothetical_documents(query, n=3):"""让LLM生成假设的答案文档,然后用这些文档的向量进行检索"""prompt = f"""根据以下问题,生成{n}个可能的答案段落。
问题:{query}生成的答案应专业、详细,包含相关术语。
每个答案用'---'分隔:"""# 调用LLM生成假设答案# ... (类似上面的LLM调用)# 返回生成的假设答案列表return hypothetical_docs# 检索时,用生成的假设文档的向量来查询

2. 分步思考改写(Step-by-Step)

def stepwise_query_rewrite(query):prompt = f"""请按照以下步骤分析并重写查询:
1. 识别查询的深层意图:用户真正想知道什么?
2. 识别缺失的关键信息:哪些信息对检索是必要的但缺失了?
3. 识别专业术语:哪些词可以替换为更专业的术语?
4. 生成3个不同角度的改写版本。查询:{query}分析步骤1(深层意图):
分析步骤2(缺失信息):
分析步骤3(专业术语):
改写版本1(详细版):
改写版本2(关键词版):
改写版本3(疑问解答版):"""# 调用LLM并解析结果# ...return rewritten_queries  # 返回多个版本

Level 4: 专业领域优化

1. 领域术语标准化

def domain_specific_rewrite(query, domain_glossary):"""domain_glossary: 领域术语词典,如{"ML": "机器学习", "NLP": "自然语言处理"}"""# 1. 术语替换for term, standard_term in domain_glossary.items():if term.lower() in query.lower():query = query.replace(term, standard_term)# 2. 添加领域限定词prompt = f"""作为{domain}领域的专家,请重写以下查询,使其更专业:原始查询:{query}重写时请考虑:
- 使用领域标准术语
- 明确问题边界
- 添加必要的技术上下文重写后的查询:"""# ...

三、 完整的实现架构

class QueryRewriter:def __init__(self, llm_client, strategy="auto"):self.llm = llm_clientself.strategy = strategy# 预定义的改写提示词模板self.templates = {"general": """请重写以下查询,使其更适合文档检索:
{query}要求:
1. 保持原意不变
2. 更详细、更具体
3. 使用更正式的表述
4. 包含可能的同义词重写后:""","hyde": """请为以下问题生成一个假设性的详细答案段落:
问题:{query}生成的段落应:
1. 直接回答问题
2. 包含相关细节和术语
3. 类似百科全书中的解释
4. 长度在100-200字假设答案:""","conversational": """基于对话历史重写当前查询:对话历史:
{history}当前查询:{query}重写要求:
1. 使查询独立完整
2. 融入必要的上下文
3. 明确指代关系
4. 保持自然流畅重写后:"""}def rewrite(self, query, history=None, domain=None):# 1. 基础预处理query = self._preprocess(query)# 2. 根据策略选择改写方式if self.strategy == "hyde":return self._hyde_rewrite(query)elif self.strategy == "multi" and history:return self._multi_turn_rewrite(query, history)else:return self._general_rewrite(query, domain)def _preprocess(self, query):"""基础清洗和纠正"""# 去除多余空格query = ' '.join(query.split())# 可选:拼写纠正# query = correct_spelling(query)return querydef _general_rewrite(self, query, domain=None):"""通用LLM改写"""template = self.templates["general"]if domain:prompt = template.format(query=query) + f"\n领域:{domain}"else:prompt = template.format(query=query)response = self.llm.generate(prompt)return response.strip()def _hyde_rewrite(self, query):"""生成假设文档"""prompt = self.templates["hyde"].format(query=query)hypothetical_doc = self.llm.generate(prompt)# 这里可以返回假设文档用于检索# 或者用假设文档再次生成查询hyde_query_prompt = f"""基于以下问题和生成的假设答案,提炼出最佳的检索查询:原始问题:{query}
假设答案:{hypothetical_doc}最适合向量检索的查询(关键词形式):"""return self.llm.generate(hyde_query_prompt)def generate_multiple_versions(self, query, n=3):"""生成多个改写版本,用于多向量检索"""prompt = f"""请为以下查询生成{n}个不同的改写版本,每个版本侧重不同角度:原始查询:{query}要求:
1. 版本1:详细扩展版(添加细节和上下文)
2. 版本2:简洁关键词版(提取核心关键词)
3. 版本3:疑问解答版(以问题形式表达)输出格式:
版本1:...
版本2:...
版本3:..."""response = self.llm.generate(prompt)# 解析response,提取各个版本versions = []for line in response.split('\n'):if line.startswith('版本'):versions.append(line.split('', 1)[1])return versions if versions else [query]

四、 评估改写效果

def evaluate_rewrite(original_query, rewritten_query, retrieved_docs):"""简单的评估函数retrieved_docs: 检索到的文档列表"""# 1. 检索相关度评估(需要人工标注或使用LLM评估)# 2. 多样性评估:改写是否带来了新的有效关键词# 3. 忠实度评估:改写是否改变了原意
    evaluation_prompt = f"""请评估查询改写的质量:原始查询:{original_query}
改写后查询:{rewritten_query}
检索到的文档数:{len(retrieved_docs)}请从以下维度评分(1-5分):
1. 忠实度(保持原意):
2. 明确性(更具体):
3. 检索友好度(适合检索):
4. 自然度(表达自然):简要说明:"""# 用LLM评估或人工评估return scores

 五、 最小简单示例

# 最简化的起点代码
from zai import ZhipuAiClient
import requestsclass SimpleRewriter:def __init__(self, api_key):self.client = ZhipuAiClient(api_key=api_key)def rewrite(self, query):response = self.client.chat.completions.create(model="",messages=[{"role": "system", "content": "你是一个查询改写专家。"},{"role": "user", "content": f"请改进以下查询以便更好地检索相关信息:{query}"}],temperature=0.3,max_tokens=100)return response.choices[0].message.content# 使用
rewriter = SimpleRewriter("api-key")
improved_query = rewriter.rewrite("如何学习Python?")
print(f"原始查询:如何学习Python?")
print(f"改写后:{improved_query}")
# 输出可能是:"Python编程语言的学习路径、入门教程和最佳实践"

没有完美的Query改写策略,只有最适合数据和场景的策略。

http://www.jsqmd.com/news/173348/

相关文章:

  • Java毕设项目:基于SpringBoot的吉他谱分享平台的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 贪心(一)——从动态规划到贪心 算法设计与分析 国科大
  • A.每日一题——1351. 统计有序矩阵中的负数
  • 传统管理问题多,智能插座为高校宿舍违规电器治理开新路
  • 如何借助AI写论文?12款写论文的AI工具推荐,AI写作效率与低查重兼得! - 掌桥科研-AI论文写作
  • 【计算机毕业设计案例】基于SpringBoot的相机拍立得购买平台的设计与实现构建用户交流社区,分享拍摄技巧(程序+文档+讲解+定制)
  • 第七届护理与保健国际研讨会 (ICNH 2026)
  • 2026年食品科学与先进技术国际研讨会(FSAT 2026)
  • 数据资产变现:大数据领域的商业价值挖掘指南
  • 【计算机毕业设计案例】基于java的吉他谱分享平台的设计与实现基于SpringBoot的吉他谱分享平台的设计与实现(程序+文档+讲解+定制)
  • 物品复活系统开发总结 - CelestialZ
  • 软件测试实验室授权签字人任职条件及考核范围
  • 【深度实测】Google Gemini 3 Pro 全场景性能测评及订阅环境配置踩坑指南
  • 【毕业设计】基于SpringBoot的相机拍立得购买平台的设计与实现(源码+文档+远程调试,全bao定制等)
  • Java计算机毕设之基于SpringBoot的吉他谱分享平台的设计与实现基于SpringBoot+Vue的吉他谱分享平台管理系统设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • 英语_阅读_electric cars on the road_待读
  • Lux 上手指南:让 AI 直接操作你的电脑
  • 阿虎医考师承重构中医学习路径,打通从师承到执业的“最后1公里” - 资讯焦点
  • Markdown 编辑器技术调研:把“写”这件事拆给你看
  • 云雀播放器 6.34.12 | 高颜值音乐播放器,超一亿用户,动画非常流畅
  • 数据与算法架构提升之路
  • UDP与TCP
  • UGUI中Canvas的嵌套使用 - 冷夜
  • 化工防爆气象站:为化工生产提供关键的气象数据支持,有效预防安全事故的发生
  • 2025年山东省创新产品应用推荐目录的通知解析,中承信安助力企业信创产品认证
  • ML、DL与LLM实战讲解与分析
  • 计算机Java毕设实战-基于SpringBoot的相机拍立得购买平台的设计与实现相机销售、配件关联、订单管理的一体化【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • “道德黑客”的理解
  • 客户反馈,年底总结
  • Java毕设项目:基于springboot和vue的阅读交流分享平台(源码+文档,讲解、调试运行,定制等)