后退一步,从更高视角提示模型回答问题
有时候,搜索质量和模型生成可能会受到问题具体细节的影响,用户输入的问题太细,导致向量搜索结果不理想。处理这种情况的一种方法是先生成一个更抽象的“退一步”问题,然后基于原始问题和退一步问题进行查询。
例如,如果我们提出一个形如“为什么我的 LangGraph 代理 astream_events 返回 {LONG_TRACE} 而不是 {DESIRED_OUTPUT}”的问题,如果我们使用更通用的问题“astream_events 如何与 LangGraph 代理一起工作”进行搜索,我们很可能会检索到更相关的文档,而不是使用具体的用户问题进行搜索。
让我们看看在 LangChain YouTube 视频的 Q&A 机器人环境中如何使用退一步
提示优化策略。
设置
安装依赖
# %pip install -qU langchain-core langchain-openai
设置环境变量
在这个例子中,我们将使用 OpenAI:
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
生成退一步问题(更高视角的问题)
生成好的退一步问题取决于编写一个好的提示:
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
system = """您是一个专家,擅长从具体问题中提取一个更通用的问题,以便回答具体问题所需的基本原理。
将会有关于一组用于构建 LLM 应用程序的软件的问题,这些软件包括 LangChain、LangGraph、LangServe 和 LangSmith。
LangChain 是一个 Python 框架,提供了一大批集成,可以轻松组合来构建 LLM 应用程序。
LangGraph 是构建在 LangChain 之上的 Python 包,使得构建有状态的、多角色的 LLM 应用程序变得简单。
LangServe 是构建在 LangChain 之上的 Python 包,使得将 LangChain 应用程序部署为 REST API 变得简单。
LangSmith 是一个平台,使得跟踪和测试 LLM 应用程序变得简单。
针对这些产品的具体用户问题,编写一个需要回答的更通用问题。
如果您对某个词语或首字母缩写不熟悉,就不要试图重新写一遍。
写出简明扼要的问题。"""
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
("human", "{question}"),
]
)
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
step_back = prompt | llm | StrOutputParser()
question = (
"我使用 Gemini Pro 和 vectorstores 等工具构建了一个 LangGraph 代理。如何只获取事件流中的 LLM 调用"
)
result = step_back.invoke({"question": question})
print(result)
LangGraph 提供了哪些特定方法或功能,用于从包括各种交互和数据源的事件流中提取 LLM 调用?
返回退一步问题和原始问题
为了提高我们的召回率,我们很可能希望基于退一步问题和原始问题来检索文档。我们可以轻松地返回这两个问题,如下所示:
from langchain_core.runnables import RunnablePassthrough
step_back_and_original = RunnablePassthrough.assign(step_back=step_back)
step_back_and_original.invoke({"question": question})
{'question': '我使用 Gemini Pro 和 vectorstores 等工具构建了一个 LangGraph 代理。如何只获取事件流中的 LLM 调用',
'step_back': 'LangGraph 提供了哪些特定方法或功能,用于从由使用 Gemini Pro、vectorstores 和 DuckDuckGo search 等外部工具构建的代理生成的事件流中提取 LLM 调用?'}
使用函数调用来获取结构化输出
如果我们将这种技术与其他查询分析技术组合起来,很可能会使用函数调用来获取结构化的查询对象。我们可以使用函数调用来进行步骤回溯提示,就像这样:
from langchain_core.output_parsers.openai_tools import PydanticToolsParser
from langchain_core.pydantic_v1 import BaseModel, Field
class StepBackQuery(BaseModel):
step_back_question: str = Field(
...,
description="给定关于这些产品中一个或多个的具体用户问题,编写一个需要回答以回答具体问题的更通用的问题。",
)
llm_with_tools = llm.bind_tools([StepBackQuery])
hyde_chain = prompt | llm_with_tools | PydanticToolsParser(tools=[StepBackQuery])
hyde_chain.invoke({"question": question})
[StepBackQuery(step_back_question='如何在像LangGraph这样的Python框架中过滤和提取特定类型的事件流中的呼叫步骤是什么?')]