在一些查询分析技术中,有时可能会导致生成任意数量的查询,包括零查询的情况。在这种情况下,我们需要确保在查询分析后做出是否调用检索器的决策。今天,我们就来看看如何实现这一点,以及如何在LangChain中进行查询分析。
技术背景介绍
在构建自然语言处理(NLP)应用时,查询生成是一个常见的问题。在某些场景下,查询分析技术可能无法生成有用的查询,因此需要特别处理这些情况,以优化我们的查询链。
原理深度解析
我们将使用函数调用来结构化输出,并配置大语言模型(LLM),使其不必强制发起查询。然后,我们通过提示(prompt)明确指示何时需要发起查询。
实战代码演示
首先,安装必要的依赖项:
# %pip install -qU langchain langchain-community langchain-openai langchain-chroma
设置环境变量,我们在这里使用OpenAI的API:
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
创建用于模拟的向量存储:
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
texts = ["Harrison worked at Kensho"]
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_texts(texts, embeddings)
retriever = vectorstore.as_retriever()
然后,通过提示模板和运行程序来进行查询分析:
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain_core.pydantic_v1 import BaseModel, Field
class Search(BaseModel):
query: str = Field(..., description="Similarity search query applied to job record.")
system = """You have the ability to issue search queries to get information to help answer user information.
You do not NEED to look things up. If you don't need to, then just respond normally."""
prompt = ChatPromptTemplate.from_messages([("system", system), ("human", "{question}")])
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm = llm.bind_tools([Search])
query_analyzer = {"question": RunnablePassthrough()} | prompt | structured_llm
通过以下代码分析查询结果:
response = query_analyzer.invoke("where did Harrison Work")
# 查看响应中的工具调用
response_with_tool = query_analyzer.invoke("hi!")
优化建议分享
在处理查询分析的过程中,可以考虑使用PydanticToolsParser
进行解析,并通过自定义链条函数来调用检索器:
from langchain_core.output_parsers.openai_tools import PydanticToolsParser
from langchain_core.runnables import chain
output_parser = PydanticToolsParser(tools=[Search])
@chain
def custom_chain(question):
response = query_analyzer.invoke(question)
if "tool_calls" in response.additional_kwargs:
query = output_parser.invoke(response)
docs = retriever.invoke(query[0].query)
return docs
else:
return response
测试我们的自定义链条:
result = custom_chain.invoke("where did Harrison Work")
print(result)
greeting_response = custom_chain.invoke("hi!")
print(greeting_response)
补充说明和总结
通过这种方法,我们能够有效地处理生成零查询的情况,并根据需要灵活调用检索器。整体流程可以说是相当丝滑,确保了我们在实际应用中不浪费计算资源。
今天的技术分享就到这里,希望对大家有帮助。开发过程中遇到问题也可以在评论区交流~
—END—