LangChain の Step-back Prompting を試す
「LangChain」の「Step-back Prompting」を試したので、まとめました。
1. Step-back Prompting
「Step-back Prompting」は、論文「Take a Step Back」で紹介されている、LLMの質問応答の性能を向上させる手法です。
アルゴリズムは次のとおりです。
2. Colabでの実行
Colabでの実行手順は、次のとおりです。
(1) パッケージのインストール。
Web検索も行うので「duckduckgo-search」をインストールします。
# パッケージのインストール
!pip install langchain
!pip install openai
!pip install duckduckgo-search
!pip install langchainhub
(2) 環境変数の準備。
以下のコードの <OpenAI_APIのトークン> にはOpenAI APIのトークンを指定します。(有料)
# 環境変数の準備
import os
os.environ["OPENAI_API_KEY"] = "<OpenAI_APIのトークン>"
(3) ステップバック質問を生成するプロンプトテンプレートの準備。
日本語対応のため、Few-ShotのExampleを日本語にしています。
from langchain.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate
# Few-ShotのExampleの準備
examples = [
{
"input": "警察のメンバーは合法的に逮捕できるでしょうか?",
"output": "警察のメンバーは何ができるでしょうか?"
},
{
"input": "ヤン・シンデルはどこの国で生まれましたか?",
"output": "ヤン・シンデルの経歴は何ですか?"
},
]
# ステップバック質問を生成するプロンプトテンプレートの準備
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_prompt,
("user", "{question}"),
])
(4) ステップバック質問を生成するチェーンの準備。
from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
# ステップバック質問を生成するチェーンの準備
question_gen = prompt | ChatOpenAI(temperature=0) | StrOutputParser()
(5) ステップバック質問を生成。
# プロンプトの準備
question = "トランプが大統領だった時にChatGPTは存在していましたか?"
# ステップバック質問を生成
question_gen.invoke({"question": question})
ChatGPTはいつ開発されたのですか?
(6) Web検索から情報収集するRetrieverの準備。
from langchain.utilities import DuckDuckGoSearchAPIWrapper
# Web検索から情報収集するRetrieverの準備
search = DuckDuckGoSearchAPIWrapper(max_results=6)
def retriever(query):
return search.run(query)
(7) 元の質問を使って情報収集するRetrieverを実行。
ノーマルコンテキストが出力されます。
# 元の質問を使って情報収集するRetrieverを実行
retriever(question)
(7) ステップバック質問を使って情報収集するRetrieverを実行。
ステップバックコンテキストが出力されます。
# ステップバック質問を使って情報収集するRetrieverを実行
retriever(question_gen.invoke({"question": question}))
(8) LangChain Hubから「stepback-answer」プロンプトテンプレートを取得。
from langchain import hub
response_prompt = hub.pull("langchain-ai/stepback-answer")
このプロンプトテンプレートの中身は、次のとおりです。
# 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}
# {step_back_context}
# Original Question: {question}
# Answer:"""
# response_prompt = ChatPromptTemplate.from_template(response_prompt_template)
(9) 「stepback-answer」プロンプトテンプレートを使用するチェーンの準備。
パラメータとして、ノーマルコンテキスト、ステップバックコンテキスト、質問を渡します。
from langchain.schema.runnable import RunnableLambda
# 「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()
(10) 「stepback-answer」プロンプトテンプレートを使用するチェーンの準備。
# 「stepback-answer」プロンプトテンプレートを使用するチェーンの実行
chain.invoke({"question": question})
3. ステップバックしない場合
ステップバックしない場合の質問応答の結果を確認してみます。
(1) プロンプトテンプレートの準備。
# プロンプトテンプレートの準備
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)
(2) チェーンの準備。
# チェーンの準備
chain = {
"normal_context": RunnableLambda(lambda x: x['question']) | retriever,
"question": lambda x: x["question"]
} | response_prompt | ChatOpenAI(temperature=0) | StrOutputParser()
(3) チェーンの実行。
# チェーンの実行
chain.invoke({"question": question})
関連
この記事が気に入ったらサポートをしてみませんか?