介绍
在复杂问题的问答任务中,一种名为 Step-Back Prompting(回退提示)的方法能够提高回答的准确性。该技术的核心思想是先提出一个更通用的“回退”问题,再利用它来辅助回答原始问题。这一方法可以与检索增强问答(Retrieval-Augmented Question Answering,RAG)结合,以提升信息检索的质量。
相关论文可查看:Step-Back Prompting 论文
一篇优秀的相关博客文章:Cobus Greyling - Step-Back Prompting
在本教程中,我们将复现 Step-Back Prompting 的实现,并调整提示词使其更适用于聊天模型。
1. 环境准备
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableLambda
2. 创建 Few-Shot 示例
为了帮助模型更好地理解 Step-Back Prompting,我们先提供一些示例:
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?"},
]
example_prompt = ChatPromptTemplate.from_messages([
("human", "{input}"),
("ai", "{output}"),
])
few_shot_prompt = FewShotChatMessagePromptTemplate(
example_prompt=example_prompt,
examples=examples,
)
3. 构造 Step-Back Prompting 生成器
我们创建一个 ChatPromptTemplate
,将 Few-Shot 示例和系统指令结合起来:
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_prompt,
("user", "{question}"),
])
question_gen = prompt | ChatOpenAI(temperature=0) | StrOutputParser()
4. 测试 Step-Back Prompting
question = "was chatgpt around while trump was president?"
print(question_gen.invoke({"question": question}))
5. 检索增强问答 (RAG) 结合 Step-Back Prompting
我们使用 DuckDuckGo 搜索 API 来检索相关信息:
from langchain.utilities import DuckDuckGoSearchAPIWrapper
search = DuckDuckGoSearchAPIWrapper(max_results=4)
def retriever(query):
return search.run(query)
# 使用普通问题进行检索
retriever(question)
# 使用 Step-Back 生成的问题进行检索
retriever(question_gen.invoke({"question": question}))
6. 组合 Step-Back 和问答系统
我们从 LangChain Hub 加载标准的问答模板,并结合 Step-Back 机制进行检索和回答。
from langchain import hub
response_prompt = hub.pull("langchain-ai/stepback-answer")
chain = (
{
"normal_context": RunnableLambda(lambda x: x["question"]) | retriever,
"step_back_context": question_gen | retriever,
"question": lambda x: x["question"],
}
| response_prompt
| ChatOpenAI(temperature=0)
| StrOutputParser()
)
运行 Step-Back 问答系统
chain.invoke({"question": question})
7. 基线实验(不使用 Step-Back Prompting)
我们也可以进行基线测试,仅使用普通检索进行问答。
response_prompt_template = """
You are an expert of world knowledge. I am going to ask you a question. Your response should be comprehensive and not contradicted with the following context if they are relevant. Otherwise, ignore them if they are not relevant.
{normal_context}
Original Question: {question}
Answer:"""
response_prompt = ChatPromptTemplate.from_template(response_prompt_template)
chain_baseline = (
{
"normal_context": RunnableLambda(lambda x: x["question"]) | retriever,
"question": lambda x: x["question"],
}
| response_prompt
| ChatOpenAI(temperature=0)
| StrOutputParser()
)
# 运行基线模型
chain_baseline.invoke({"question": question})
8. 结论
Step-Back Prompting 通过生成更通用的回退问题,可以帮助模型在复杂问答任务中提高回答的准确性。当与检索增强问答(RAG)结合时,它可以有效改善信息检索质量,并提高回答的覆盖率。
你可以在自己的应用中尝试这一技术,并结合不同的模型和数据源,探索其在实际场景中的效果。
参考资料
如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!
欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。
谢谢大家的支持!