Langchain中改进RAG能力的3种常用的扩展查询方法

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 有多种方法可以提高检索增强生成(RAG)的能力,其中一种方法称为查询扩展。我们这里主要介绍在Langchain中常用的3种方法

查询扩展技术涉及对用户的原始查询进行细化,以生成更全面和信息丰富的搜索。使用扩展后的查询将从向量数据库中获取更多相关文档。

1、Step Back Prompting

Take A Step Back: Evoking Reasoning Via Abstraction In Large Language Models

https://arxiv.org/pdf/2310.06117.pdf

这是google deep mind开发的一种方法,它使用LLM来创建用户查询的抽象。该方法将从用户查询中退后一步,以便更好地从问题中获得概述。LLM将根据用户查询生成更通用的问题。

下面是原始查询和后退查询的示例。

 {
     "Original_Query": "Could the members of The Police perform lawful arrests?",
     "Step_Back_Query": "what can the members of The Police do?",
 },
 {
     "Original_Query": "Jan Sindel’s was born in what country?",
     "Step_Back_Query": "what is Jan Sindel’s personal history?",
 }

下面代码演示了如何使用Langchain进行Step Back Prompting

 #---------------------Prepare VectorDB-----------------------------------
 # Build a sample vectorDB
 from langchain.text_splitter import RecursiveCharacterTextSplitter
 from langchain_community.document_loaders import WebBaseLoader
 from langchain_community.vectorstores import Chroma
 from langchain.embeddings import OpenAIEmbeddings
 import os

 os.environ["OPENAI_API_KEY"] = "Your OpenAI KEY"

 # Load blog post
 loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
 data = loader.load()

 # Split
 text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
 splits = text_splitter.split_documents(data)

 # VectorDB
 embedding = OpenAIEmbeddings()
 vectordb = Chroma.from_documents(documents=splits, embedding=embedding)

 #-------------------Prepare Step Back Prompt Pipeline------------------------
 from langchain_core.output_parsers import StrOutputParser
 from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate
 from langchain_core.runnables import RunnableLambda
 from langchain.chat_models import ChatOpenAI

 retriever = vectordb.as_retriever()
 llm = ChatOpenAI()

 # Few Shot Examples
 examples = [
     {
         "input": "Could the members of The Police perform lawful arrests?",
         "output": "what can the members of The Police do?",
     },
     {
         "input": "Jan Sindel’s was born in what country?",
         "output": "what is Jan Sindel’s personal history?",
     },
 ]

 # We now transform these to example messages
 example_prompt = ChatPromptTemplate.from_messages(
     [
         ("human", "{input}"),
         ("ai", "{output}"),
     ]
 )

 few_shot_prompt = FewShotChatMessagePromptTemplate(
     example_prompt=example_prompt,
     examples=examples,
 )

 prompt = ChatPromptTemplate.from_messages(
     [
         (
             "system",
             """You are an expert at world knowledge. Your task is to step back and paraphrase a question to a more generic step-back question, which is easier to answer. Here are a few examples:""",
         ),
         # Few shot examples
         few_shot_prompt,
         # New question
         ("user", "{question}"),
     ]
 )

 question_gen = prompt | llm | StrOutputParser()

 #--------------------------QnA using Back Prompt Technique-----------------
 from langchain import hub

 def format_docs(docs):
     doc_strings = [doc.page_content for doc in docs]
     return "\n\n".join(doc_strings)

 response_prompt = hub.pull("langchain-ai/stepback-answer")

 chain = (
     {
         # Retrieve context using the normal question
         "normal_context": RunnableLambda(lambda x: x["question"]) | retriever | format_docs,
         # Retrieve context using the step-back question
         "step_back_context": question_gen | retriever | format_docs,
         # Pass on the question
         "question": lambda x: x["question"],
     }
     | response_prompt
     | llm
     | StrOutputParser()
 )

 result = chain.invoke({"question": "What Task Decomposition that work in 2022?"})

在那个脚本中,我们的问题是

 Original Query: What Task Decomposition that work in 2022?

Step Back Prompting为

 Step Back Query: What are some examples of task decomposition in the current year?

这两个查询将用于提取相关文档,将这些文档组合在一起作为一个上下文,提供给LLM生成最终的答案。

 {
     # Retrieve context using the normal question
     "normal_context": RunnableLambda(lambda x: x["question"]) | retriever | format_docs,
     # Retrieve context using the step-back question
     "step_back_context": question_gen | retriever | format_docs,
     # Pass on the question
     "question": lambda x: x["question"],
 }

2、 Multi Query

Langchain Multi Query Retriever

https://python.langchain.com/docs/modules/data_connection/retrievers/MultiQueryRetriever

多步查询是一种使用LLM从第一个查询生成更多查询的技术。这种技术试图解决用户提示不是那么具体的情况。这些生成的查询将用于在矢量数据库中查找文档。

多步查询的目标是改进查询,使其与主题更加相关,从而从数据库中检索更多相关的文档。

因为Langchain 有详细的文档,我们就不贴代码了

3、Cross Encoding Re-Ranking

这个方法是多查询和交叉编码器重新排序的结合,当用户使用LLM生成更多的问题时,每个生成的查询都从向量数据库中提取一对文档。

这些提取的文档通过交叉编码器传递,获得与初始查询的相似度分数。然后对相关文档进行排序,并选择前5名作为LLM返回结果。

为什么需要挑选前5个文档?因为需要尽量避免从矢量数据库检索的不相关文档。这种选择确保交叉编码器专注于最相似和最有意义的文档,从而生成更准确和简洁的摘要。

 #------------------------Prepare Vector Database--------------------------
 # Build a sample vectorDB
 from langchain.text_splitter import RecursiveCharacterTextSplitter
 from langchain_community.document_loaders import WebBaseLoader
 from langchain_community.vectorstores import Chroma
 from langchain.embeddings import OpenAIEmbeddings
 from langchain.chat_models import ChatOpenAI
 import os

 os.environ["OPENAI_API_KEY"] = "Your API KEY"

 # Load blog post
 loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
 data = loader.load()

 llm = ChatOpenAI()

 # Split
 text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
 splits = text_splitter.split_documents(data)

 # VectorDB
 embedding = OpenAIEmbeddings()
 vectordb = Chroma.from_documents(documents=splits, embedding=embedding)

 #--------------------Generate More Question----------------------------------
 #This function use to generate queries using LLM
 def create_original_query(original_query):
     query = original_query["question"]
     qa_system_prompt = """
             You are an AI language model assistant. Your task is to generate five 
         different versions of the given user question to retrieve relevant documents from a vector 
         database. By generating multiple perspectives on the user question, your goal is to help
         the user overcome some of the limitations of the distance-based similarity search. 
         Provide these alternative questions separated by newlines."""

     qa_prompt = ChatPromptTemplate.from_messages(
         [
             ("system", qa_system_prompt),
             ("human", "{question}"),
         ]
     )

     rag_chain = (
         qa_prompt
         | llm
         | StrOutputParser()
     )

     question_string = rag_chain.invoke(
         {"question": query}
     )

     lines_list = question_string.splitlines()
     queries = []
     queries = [query] + lines_list

     return queries

 #-------------------Retrieve Document and Cross Encoding--------------------
 from sentence_transformers import CrossEncoder
 from langchain_core.prompts import ChatPromptTemplate
 from langchain_core.runnables import RunnableLambda, RunnablePassthrough
 from langchain_core.output_parsers import StrOutputParser
 import numpy as np

 cross_encoder = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')

 #Cross Encoding happens in here
 def create_documents(queries):
     retrieved_documents = []
     for i in queries:
         results = vectordb.as_retriever().get_relevant_documents(i)
         docString = format_docs(results)
         retrieved_documents.extend(docString)


     unique_a = []
     #If there is duplication documents for each query, make it unique
     for item in retrieved_documents:
         if item not in unique_a:
             unique_a.append(item)

     unique_documents = list(unique_a)

     pairs = []
     for doc in unique_documents:
         pairs.append([queries[0], doc])

     #Cross Encoder Scoring
     scores = cross_encoder.predict(pairs)

     final_queries = []
     for x in range(len(scores)):
         final_queries.append({"score":scores[x],"document":unique_documents[x]})

     #Rerank the documents, return top 5
     sorted_list = sorted(final_queries, key=lambda x: x["score"], reverse=True)
     first_five_elements = sorted_list[:6]
     return first_five_elements

 #-----------------QnA Document-----------------------------------------------
 qa_system_prompt = """
         Assistant is a large language model trained by OpenAI. \
         Use the following pieces of retrieved context to answer the question. \
         If you don't know the answer, just say that you don't know. \

         {context}"""

 qa_prompt = ChatPromptTemplate.from_messages(
     [
         ("system", qa_system_prompt),
         ("human", "{question}"),
     ]
 )

 def format(docs):
     doc_strings = [doc["document"] for doc in docs]
     return "\n\n".join(doc_strings)


 chain = (
     # Prepare the context using below pipeline
     # Generate Queries -> Cross Encoding -> Rerank ->return context
     {"context": RunnableLambda(create_original_query)| RunnableLambda(create_documents) | RunnableLambda(format), "question": RunnablePassthrough()}
     | qa_prompt
     | llm
     | StrOutputParser()
 )

 result = chain.invoke({"question":"What Task Decomposition that work in 2022?"})

从上面代码主要是创建了两个用于生成查询和交叉编码的自定义函数。

create_original_query用于生成查询,它将返回5个生成的问题加上原始查询。

create_documents则根据6个问题(上面的5个生成问题和1个原始查询)检索24个相关文档。这24个相关文档可能重复,所以需要进行去重。

之后我们使用

 scores = cross_encoder.predict(pairs)

给出文档和原始查询之间的交叉编码分数。然后就是对文档重新排序,保留前5个文档。

总结

以上就是最常用的3种改进RAG能力扩展查询方法。当你在使用RAG时,并且没有得到正确或详细的答案,可以使用上述查询扩展方法来解决这些问题。希望所有这些技术可以用于你的下一个项目。

https://avoid.overfit.cn/post/39c514dafe0a4cabaa747c83ec1d4e3f

作者:Wayan Wardana

相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
目录
相关文章
|
1月前
|
存储 人工智能 搜索推荐
解锁AI新境界:LangChain+RAG实战秘籍,让你的企业决策更智能,引领商业未来新潮流!
【10月更文挑战第4天】本文通过详细的实战演练,指导读者如何在LangChain框架中集成检索增强生成(RAG)技术,以提升大型语言模型的准确性与可靠性。RAG通过整合外部知识源,已在生成式AI领域展现出巨大潜力。文中提供了从数据加载到创建检索器的完整步骤,并探讨了RAG在企业问答系统、决策支持及客户服务中的应用。通过构建知识库、选择合适的嵌入模型及持续优化系统,企业可以充分利用现有数据,实现高效的商业落地。
85 6
|
1月前
|
SQL 数据库
LangChain-09 Query SQL DB With RUN GPT 查询数据库 并 执行SQL 返回结果
LangChain-09 Query SQL DB With RUN GPT 查询数据库 并 执行SQL 返回结果
33 2
|
3月前
|
机器学习/深度学习 SQL 数据挖掘
ADB优化器背后的秘密:如何用成本估算和规则引擎编织高效的查询网络?
【8月更文挑战第27天】AnalyticDB (ADB) 是一款专为大规模数据集设计的高性能分析型数据库。本文深入探讨ADB的优化器如何通过成本估算、规则引擎及机器学习等策略生成高效执行计划。成本估算是选择最优路径的关键;规则引擎通过谓词下推等手段优化查询;机器学习则使优化器能基于历史数据预测执行效率。结合示例代码与执行计划分析,展现了ADB在提升查询性能方面的强大功能。未来,ADB将继续进化以满足日益增长的大数据分析需求。
39 0
|
1月前
|
机器学习/深度学习 人工智能 开发框架
解锁AI新纪元:LangChain保姆级RAG实战,助你抢占大模型发展趋势红利,共赴智能未来之旅!
【10月更文挑战第4天】本文详细介绍检索增强生成(RAG)技术的发展趋势及其在大型语言模型(LLM)中的应用优势,如知识丰富性、上下文理解和可解释性。通过LangChain框架进行实战演练,演示从知识库加载、文档分割、向量化到构建检索器的全过程,并提供示例代码。掌握RAG技术有助于企业在问答系统、文本生成等领域把握大模型的红利期,应对检索效率和模型融合等挑战。
159 14
|
1月前
|
存储 人工智能 搜索推荐
揭秘LangChain+RAG如何重塑行业未来?保姆级实战演练,解锁大模型在各领域应用场景的神秘面纱!
【10月更文挑战第4天】随着AI技术的发展,大型语言模型在各行各业的应用愈发广泛,检索增强生成(RAG)技术成为推动企业智能化转型的关键。本文通过实战演练,展示了如何在LangChain框架内实施RAG技术,涵盖金融(智能风控与投资决策)、医疗(辅助诊断与病历分析)及教育(个性化学习推荐与智能答疑)三大领域。通过具体示例和部署方案,如整合金融数据、医疗信息以及学生学习资料,并利用RAG技术生成精准报告、诊断建议及个性化学习计划,为企业提供了切实可行的智能化解决方案。
63 5
|
1月前
|
存储 搜索推荐 数据库
运用LangChain赋能企业规章制度制定:深入解析Retrieval-Augmented Generation(RAG)技术如何革新内部管理文件起草流程,实现高效合规与个性化定制的完美结合——实战指南与代码示例全面呈现
【10月更文挑战第3天】构建公司规章制度时,需融合业务实际与管理理论,制定合规且促发展的规则体系。尤其在数字化转型背景下,利用LangChain框架中的RAG技术,可提升规章制定效率与质量。通过Chroma向量数据库存储规章制度文本,并使用OpenAI Embeddings处理文本向量化,将现有文档转换后插入数据库。基于此,构建RAG生成器,根据输入问题检索信息并生成规章制度草案,加快更新速度并确保内容准确,灵活应对法律与业务变化,提高管理效率。此方法结合了先进的人工智能技术,展现了未来规章制度制定的新方向。
34 3
|
1月前
|
JSON 计算机视觉 数据格式
LangChain-17 FunctionCalling 利用大模型对函数进行回调 扩展大模型的额外的能力 比如实现加减乘除等功能
LangChain-17 FunctionCalling 利用大模型对函数进行回调 扩展大模型的额外的能力 比如实现加减乘除等功能
39 4
|
1月前
|
SQL 数据库
LangChain-08 Query SQL DB 通过GPT自动查询SQL
LangChain-08 Query SQL DB 通过GPT自动查询SQL
17 3
|
1月前
LangChain-06 RAG With Source Doc 通过文档进行检索增强
LangChain-06 RAG With Source Doc 通过文档进行检索增强
35 3
|
1月前
|
存储 自然语言处理
LangChain-04 RAG Retrieval-Augmented Generation 检索增强生成
LangChain-04 RAG Retrieval-Augmented Generation 检索增强生成
26 3