大模型应用系列:Query 变换的示例浅析

【引】NLP中的经典组件在大模型应用中还有效么?大模型对自然语言处理中的典型任务有什么影响么?

RAG应用通过分割文档、嵌入向量化并检索高语义相似性的块来响应用户问题,但面临文档块不相关、用户用词不当及结构化查询需求等问题。若RAG无法找到必要信息,则无法正确回答。对此,可采用Query变换技术,包括Query改写以提高检索准确性、后退提示以获取背景信息及子查询分解以全面检索。这些方法常利用大模型生成新query,关键在于生成提示词的选择。

fe5e22f16f0494efe452c652664a13f6.jpeg

1. Query 变换及其所解决的问题空间

一般地,RAG应用通常将文档分割成块,然后嵌入向量化,并检索与用户问题具有高语义相似性的块。但是,这会带来一些问题: 

(1)文档块可能包含不相关的内容,这会降低检索效率; 
(2)用户提出的问题可能用词不当,不利于检索; 
(3)结构化查询可能需要从用户提出的问题中产生(例如,用元数据过滤或 SQL 数据库查询向量存储)。

也就是说,用户的query可能写得很糟糕,或者表达方式与我们预期的不同。而且,如果我们的 RAG 应用程序不能找到回答这个问题所需的信息,它就不会正确地回答。面对这些问题,一般会采用Query 变换的技术,主要有3种解决方案:

  • Query改写: 使查询更加具体和详细,提高检索最相关信息的可能性

  • 后退提示: 生成更广泛、更一般的查询,以帮助检索相关的背景信息

  • 子查询分解: 将复杂的查询分解为更简单的子查询,以获得更全面的信息检索。

具体而言,如果考虑一个简单的 RAG流水线,通常的流程是将用户提出的问题直接传递给嵌入模型。然后,将这种嵌入与存储在向量存储中的文档进行比较,返回top-k个最相似的文档,而query变换在传递到嵌入模型之前处理用户query的变换。

随着大模型的普及,这些Query变换的方法都乐意使用大模型来生成新的(或多个新的)query,主要区别在于它们使用的生成提示词。

本文会简述各种Query变换的实现方法示例,当然首先是环境搭建,导入必要的库并设置访问权限。

from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplateimport os
from dotenv import load_dotenv# Load environment variables from a .env file
load_dotenv()# Set the OpenAI API key environment variable
os.environ["OPENAI_API_KEY"] = os.getenv('OPENAI_API_KEY')

2. Query改写

简单地说,Query改写意味着我们将用自己的语言改写用户的query,以便于我们的 RAG 应用程序将知道如何最好地回答。我们将采用改写-检索-读取的方法,而不仅仅是检索-读取的模式。

from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain# LLM configuration
def get_rewriting_llm(model_name: str = "gpt-4o", temperature: float = 0, max_tokens: int = 4000) -> ChatOpenAI:return ChatOpenAI(temperature=temperature, model_name=model_name, max_tokens=max_tokens)# Prompt Template for Query Rewriting
def create_query_rewrite_prompt() -> PromptTemplate:template = """You are an AI assistant tasked with reformulating user queries to improve retrieval in a RAG system. Given the original query, rewrite it to be more specific, detailed, and likely to retrieve relevant information.Original query: {original_query}Rewritten query:"""return PromptTemplate(input_variables=["original_query"], template=template)# Build Query Rewriting Chain
def build_query_rewriting_chain(llm: ChatOpenAI) -> LLMChain:prompt_template = create_query_rewrite_prompt()return prompt_template | llm# Function to Rewrite the Query
def rewrite_query(original_query: str, query_rewriter_chain: LLMChain) -> str:response = query_rewriter_chain.invoke(original_query)return response.content.strip()if __name__ == "__main__":  llm = get_rewriting_llm()query_rewriter_chain = build_query_rewriting_chain(llm)original_query = "What are the impacts of climate change on the environment?"rewritten_query = rewrite_query(original_query, query_rewriter_chain)print("Original query:", original_query)print("\nRewritten query:", rewritten_query)

我们使用生成式人工智能模型来改写问题。这个模型是一个大模型,就像我们在最后一步用来回答问题的模型一样。或者,它也可以是一个较小的模型,专门训练来执行这项任务。

3. 后退提示

对基于 RAG 流水线的检索来说,许多问题可能有点过于复杂,以至于无法掌握回答这些问题所需的多层次信息。对于这些情况,生成用于检索的多个附加查询可能很有帮助。这些查询将比原始查询更通用。这将使 RAG 流水线能够在多个级别上检索相关信息。

from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain# LLM Configuration
def get_step_back_llm(model_name: str = "gpt-4o", temperature: float = 0, max_tokens: int = 4000) -> ChatOpenAI:return ChatOpenAI(temperature=temperature, model_name=model_name, max_tokens=max_tokens)# Step-Back Prompt Template
def create_step_back_prompt_template() -> PromptTemplate:template = """You are an AI assistant tasked with generating broader, more general queries to improve context retrieval in a RAG system.Given the original query, generate a step-back query that is more general and can help retrieve relevant background information.Original query: {original_query}Step-back query:"""return PromptTemplate(input_variables=["original_query"], template=template)# Build Step-Back Query Chain
def build_step_back_chain(llm: ChatOpenAI) -> LLMChain:prompt_template = create_step_back_prompt_template()return prompt_template | llm# Function to Generate Step-Back Query
def generate_step_back_query(original_query: str, step_back_chain: LLMChain) -> str:response = step_back_chain.invoke(original_query)return response.content.strip()if __name__ == "__main__":llm = get_step_back_llm()step_back_chain = build_step_back_chain(llm)original_query = "What are the impacts of climate change on the environment?"step_back_query = generate_step_back_query(original_query, step_back_chain)print("Original query:", original_query)print("\nStep-back query:", step_back_query)

4.子查询分解

如果用户Query包含多个问题,这会使上下文检索变得棘手。每个问题可能需要不同的信息,我们不会用所有的问题作为信息检索的基础。为了解决这个问题,我们可以将输入分解为多个子查询,并对每个子查询执行检索。

from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from typing import List# LLM Configuration
def get_subquery_llm(model_name: str = "gpt-4o", temperature: float = 0, max_tokens: int = 4000) -> ChatOpenAI:return ChatOpenAI(temperature=temperature, model_name=model_name, max_tokens=max_tokens)# Sub-query Decomposition Prompt Template
def create_subquery_decomposition_template() -> PromptTemplate:template = """You are an AI assistant tasked with breaking down complex queries into simpler sub-queries for a RAG system.Given the original query, decompose it into 2-4 simpler sub-queries that, when answered together, would provide a comprehensive response to the original query.Original query: {original_query}example: What are the impacts of climate change on the environment?Sub-queries:1. What are the impacts of climate change on biodiversity?2. How does climate change affect the oceans?3. What are the effects of climate change on agriculture?4. What are the impacts of climate change on human health?"""return PromptTemplate(input_variables=["original_query"], template=template)# Build Sub-query Decomposition Chain
def build_subquery_decomposer_chain(llm: ChatOpenAI) -> LLMChain:prompt_template = create_subquery_decomposition_template()return prompt_template | llm# Function to Decompose Query into Sub-queries
def decompose_query(original_query: str, subquery_chain: LLMChain) -> List[str]:response = subquery_chain.invoke(original_query).content# Parse the sub-queries by splitting lines and removing unwanted textsub_queries = [q.strip() for q in response.split('\n') if q.strip() and not q.strip().startswith('Sub-queries:')]return sub_queriesif __name__ == "__main__":llm = get_subquery_llm()subquery_chain = build_subquery_decomposer_chain(llm)original_query = "What are the impacts of climate change on the environment?"sub_queries = decompose_query(original_query, subquery_chain)print("\nSub-queries:")for i, sub_query in enumerate(sub_queries, 1):print(f"{i}. {sub_query}")

5.一句话小结

执行Query变换的方法有很多种,虽然这个概念本身并不新颖,并且在NLP中是一个基本组件,但创新之处在于大模型的应用,方法之间的关键区别往往在于所使用的提示词。

【关联阅读】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/59245.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Oracle】空格单字符通配符查询匹配失败

问题 在进行模糊查询的时候,通过全局任意字符串匹配出含有两个字刘姓的人,但是通过刘_不能匹配出结果。 解决 检查后发现,姓名中包含空格 SELECT * FROM student WHERE TRIM(sname) LIKE 刘_;第一种解决方案就是查询的时候进行去空格处理&a…

讲讲⾼并发的原则?

大家好,我是锋哥。今天分享关于【讲讲⾼并发的原则?】面试题。希望对大家有帮助; 讲讲⾼并发的原则? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 高并发是指系统在同一时间内能够处理大量请求的能力。要有效地管理…

鸿蒙进阶-AlphabetIndexer组件

大家好,这里是鸿蒙开天组,今天我们来学习AlphabetIndexer组件,喜欢就点点关注吧! 通过 AlphabetIndexer 组件可以与容器组件结合,实现导航联动,以及快速定位的效果 核心用法 AlphabetIndexer不是容器组件…

WebGL(Web Graphics Library)

WebGL(Web Graphics Library)是一种基于 JavaScript 的 API,允许在网页上渲染高性能的 2D 和 3D 图形。它利用计算机的 GPU 来实现硬件加速,因此适合创建游戏、数据可视化和交互式应用程序。 WebGL 的基本概念: 上下文…

nvm使用的方法

nvm——Node版本管理工具_node管理工具-CSDN博客

第四部分 可扩展的架构实践

第四部分 可扩展的架构实践 19. 第19章 对架构影响重大的需求20. 第20章 设计架构21. 第21章 评估架构22. 第22章 记录架构23. 第23章 管理架构债

ubuntu交叉编译expat库给arm平台使用

1.下载expat库源码: https://github.com/libexpat/libexpat/release?page=2 wget https://github.com/libexpat/libexpat/release/download/R_2_3_0/expat-2.3.0.tar.bz2 下载成功: 2.解压expat库,并进入解压后的目录: tar xjf expat-2.3.0.tar.bz2 cd expat-2.3.0 <…

Python中的PDF处理工具:PyPDF2和ReportLab使用指南

Python中的PDF处理工具&#xff1a;PyPDF2和ReportLab使用指南 在日常工作和项目中&#xff0c;PDF 文件处理是个常见需求&#xff0c;不论是合并报告、加密文档、填充表单&#xff0c;还是生成发票。Python 中有许多用于操作 PDF 文件的库&#xff0c;其中 PyPDF2 和 ReportL…

【系统面试篇】进程和线程类(1)(笔记)——区别、通讯方式、同步、互斥、锁分类

目录 一、问题综述 1. 进程和线程的区别&#xff1f; 2. 进程的状态有哪些&#xff1f; 3. 进程之间的通信方式? &#xff08;1&#xff09;管道 &#xff08;2&#xff09;消息队列 &#xff08;3&#xff09;共享内存 &#xff08;4&#xff09;信号量 &#xff08…

delphi 编译多语言工程 error RC2104 : undefined keyword or key name:

Delphi 10.3中建立多语言工程&#xff0c;编译时出现错误&#xff1a;error RC2104 : undefined keyword or key name: 出现错误的的文件是.rc文件&#xff0c;出现错误的位置是 System_JSONConsts_SInvalidJavascriptQuote, L"Invalid JavaScript string quote character…

vue 禁用element-ui calendar 取消非本月日期的点击事件

需求描述&#xff1a;原本的日历组件不是本月的日期是灰色的&#xff0c;且点击后会跳转到对应的月份&#xff0c;现在不想它跳转&#xff0c;需要禁用它的点击事件 方法&#xff1a;使用css的pointer-events:none属性即可&#xff0c;把不是当前月份的日历表格的td属性修改 :…

nginx(四):如何在 Nginx 中配置以保留真实 IP 地址

如何在 Nginx 中配置以保留真实 IP 地址 1、概述2、nginx配置示例2.1、配置说明2.2、客户端获取真实IP2.2.1、代码说明 3、插曲4、总结 大家好&#xff0c;我是欧阳方超&#xff0c;可以我的公众号“欧阳方超”&#xff0c;后续内容将在公众号首发。 1、概述 当使用nginx作为…

传统的自然语言处理评估指标

目录 传统的自然语言处理评估指标 EM(Exact Match) BLEU(Bilingual Evaluation Understudy) 传统的自然语言处理评估指标 传统评估指标 EM(Exact Match) 计算方式:如果生成的答案与参考答案完全相同(字符级完全匹配),则 EM 得分为 1,否则为 0。这是一种比较严格的…

DiskGenius工具扩容Mac OS X Apple APFS分区

DiskGenius是一款功能强大的磁盘分区工具&#xff0c;它支持Windows和Mac OS X系统&#xff0c;可以用于管理硬盘分区&#xff0c;包括扩容Mac OS X的Apple APFS分区。然而&#xff0c;直接使用DiskGenius来扩容Mac OS X的APFS分区可能存在一定的风险&#xff0c;因为不是专门为…

C++《list的模拟实现》

在上一篇C《list》专题当中我们了解了STL当中list类当中的各个成员函数该如何使用&#xff0c;接下来在本篇当中我们将试着模拟实现list&#xff0c;在本篇当中我们将通过模拟实现list过程中深入理解list迭代器和之前学习的vector和string迭代器的不同&#xff0c;接下来就开始…

【Python基础】第02节课:数字与盒子的奇妙冒险

数字与盒子的奇妙冒险 1. 引言2. 算术运算符探险3. 运算顺序小挑战4. 计算小能手5 生活中的数学:帮妈妈买鸡蛋6. 变量小盒子6.1 变量的小故事:小猴子的果园探险1. 引言 想象一下,你手里有一个神秘的盒子,里面藏着数学和编程的秘密!你知道吗?在我们的日常生活中,尤其是玩…

本篇万字,博客最细,oled多级菜单代码解析,与实现教程,指针实现(含源码)!!!

目录 教程前言 多级菜单基本知识 驱动文件创建 ​编辑 ​编辑 ​编辑 定义菜单数据类型代码解析 按键代码解析 菜单数据赋值代码解析 菜单按键切换显示代码解析 项目工程移植地址 教程前言 前言&#xff1a;编写不易&#xf…

华为HarmonyOS打造开放、合规的广告生态 - 贴片广告

场景介绍 贴片广告是一种在视频播放前、视频播放中或视频播放结束后插入的视频或图片广告。 接口说明 接口名 描述 loadAd(adParam: AdRequestParams, adOptions: AdOptions, listener: AdLoadListener): void 请求单广告位广告&#xff0c;通过AdRequestParams、AdOptions…

Leetcode137只出现一次的数字|| 及其拓展

简述&#xff1a; 虽然标题是这么描述的&#xff0c;但是我们不是一上来就解这道题&#xff0c;先看一下他的子题和扩展 子题&#xff1a;136. 只出现一次的数字 - 力扣&#xff08;LeetCode&#xff09; 扩展题&#xff1a; 所以我们由易到难&#xff0c;先来看第一道&#x…

【解决办法】无法使用右键“通过VSCode打开文件夹”

个人博客&#xff1a;苏三有春的博客 前言 作者的编程环境为VScode&#xff0c;工作时常使用VScode打开整个工程文件夹。如果先打开VScode再从VScode中选择文件夹打开效率太慢&#xff0c;作者一般使用的方式是右键文件夹&#xff0c;直接选择"通过code打开文件夹"…