Microsoft guidanceでPlan-and-Solveプロンプトを実装してみた
ChatGPT PluginのLink Readerは信じられないほど便利で、全ての入力情報はLink Readerが理解できるような書式になっているべきだと思えてしまうほどです。
Link Readerを使えば、arXivで公開されている論文の内容をインプットに、簡単な実装をChatGPTに作成してもらうことも容易です。プログラマとしては長々と文章を書かれるよりも、とりあえずコードの形になっていた方が理解が容易なので、簡易的であってもコードの形に落としてくれるのは助かります。
そこで今回はタイトルにあるPlan-and-Solveプロンプト論文を例に簡易コードを生成し、簡易コードを元にMicrosoft guidanceのプロンプトを作成して実行してみたいと思います。
Plan-and-SolveとはCoT(Chain-of-Thought)のように最初からステップバイステップで考えるのではなく、タスクを小さく分割する計画を立ててからタスクを実行し答えを導き出す手法のことで、複数のタスクにおいてCoTよりも常に高い性能を発揮することが確認されています。
論文から簡易コードを生成する
def llm(prompt: str) -> str:
# This function should use a Large Language Model to generate a response based on the given prompt
# For the sake of this example, it's represented as an empty function
pass
def understand_problem_and_devise_plan(problem: str) -> str:
prompt = f"次の問題を理解し、それを解決するための計画を立ててください: {problem}"
plan = llm(prompt)
return plan
def execute_plan_and_solve_problem(plan: str) -> str:
prompt = f"次の計画を実行し、問題をステップバイステップで解決してください: {plan}"
solution = llm(prompt)
return solution
def extract_variables_and_numerals(problem: str) -> str:
prompt = f"次の問題から関連する変数とそれらに対応する数値を抽出してください: {problem}"
variables_and_numerals = llm(prompt)
return variables_and_numerals
def calculate_intermediate_results(problem: str, variables_and_numerals: str) -> str:
prompt = f"次の問題について中間結果を計算してください。計算と常識に注意を払い、次の変数と数値を使用してください: {variables_and_numerals}"
intermediate_results = llm(prompt)
return intermediate_results
def solve_problem_with_ps_prompting(problem: str) -> str:
plan = understand_problem_and_devise_plan(problem)
solution = execute_plan_and_solve_problem(plan)
return solution
def solve_problem_with_ps_plus_prompting(problem: str) -> str:
variables_and_numerals = extract_variables_and_numerals(problem)
intermediate_results = calculate_intermediate_results(problem, variables_and_numerals)
plan = understand_problem_and_devise_plan(problem)
solution = execute_plan_and_solve_problem(plan)
return solution
簡易コードを参考にguidanceのプロンプトを起こす
本来であればここもguidanceのドキュメントをLink Readerに食わせることでgiudanceプロンプトも自動生成したいところですが、現在のREADMEを参照してもらっても「ちゃんとしたAPIドキュメントがないと生成できません」と困り顔をされてしまいます。これからのライブラリドキュメントは常にChatGPTが理解できるような内容であることが求められていきそうです。
というわけで人間の手で生成してみた結果が以下の通りです。
{{#system~}}
Assistant is a large language model trained by OpenAI.
Assistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.
Assistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.
Overall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.
{{~/system}}
{{#user~}}
{{! 次の{問題}から関連する変数とそれらに対応する数値を抽出してください: }}
Extract relevant variables and their corresponding numerals from the following {problem}.
{problem}: """
{{problem}}
"""
{{~/user}}
{{#assistant~}}
{{gen 'variables_and_numerals' temperature=0 max_tokens=800}}
{{~/assistant}}
{{#user~}}
{{! {問題}について中間結果を計算してください。計算と常識に注意を払い、次の{変数と数値}を使用してください: }}
Calculate intermediate results for the following problem, paying attention to calculations and common sense, and using the following {variables and numerals}.
{variables_and_numerals}: """
{{variables_and_numerals}}
"""
{{~/user}}
{{#assistant~}}
{{gen 'intermediate_results' temperature=0 max_tokens=800}}
{{~/assistant}}
{{#user~}}
{{! {問題}を理解し、それを解決するための計画を立ててください: }}
Understand the {problem} and devise a plan to solve it.
{{~/user}}
{{#assistant~}}
{{gen 'plan' temperature=0 max_tokens=800}}
{{~/assistant}}
{{#user~}}
{{! 次の計画を実行し、問題をステップバイステップで解決してください: }}
Execute the following {plan} and solve the {problem} step by step.
{plan}: """
{{plan}}
"""
{{~/user}}
{{#assistant~}}
{{gen 'solution' temperature=0 max_tokens=800}}
{{~/assistant}}
{{#user~}}
最終的な答えについて簡潔に日本語で答えてください。
{{~/user}}
{{#assistant~}}
{{gen 'final_answer' temperature=0 max_tokens=800}}
{{~/assistant}}
このプロンプトをplan_and_solve.handlebarsとして保存し、以下のコードで実行します。
import guidance
with open('plan_and_solve.handlebars', 'r') as f:
prompt = f.read()
gpt3_5 = guidance.llms.OpenAI('gpt-3.5-turbo')
guidance.llm = gpt3_5
plan_and_solve = guidance(prompt)
problem = "ある企業の年間売上は100億円で、そのうち40%が人件費、30%が原材料費、10%が広告費に使われ、残りが利益です。この企業の年間利益はいくらですか?"
out = plan_and_solve(problem=problem)
すると以下の結果が得られます:
(※システムメッセージの表示は省略します)
以上までがguidanceをJupyter Notebookで実行した際に出力される表示ですが、最終的な答えだけを得たい場合は以下のようなコードで取得することができます。
print(out["final_answer"])
ChatGPTでそのまま問題を解いてもらったらどうなる?
以下の結果になりました。
ステップバイステップという指示もないのにステップバイステップで処理しているところを見ると、これまで高評価だった強化学習データにステップバイステップで処理した会話テキストが大量に含まれていたのかなと推測します。インストラクションチューニングが強化されていくと、あんまり凝った指示をしなくても、それなりの回答を返してくれるようになりそうですね。
所感
論文をインプットに簡易コードを生成してもらい、理解を深める手法はとてもオススメです。Show Meなどでチャートを書いてもらった方が良いという声もありますが、個人的には疑似コードでも良いからコードの方が分かりやすいんですよねぇ・・・。
「完全に実行可能なコードを生成してください」とオーダーすると、とりあえず仮でも動く形のコードを生成してくれるので、そこからAPI連携系の関数をモックで定義だけ渡す、みたいなことを繰り返していくと精緻化できます。例えば以下のような形です。
型をつけておくとより精度高く理解してくれるので、型を可能な限りつけていくのが良いですね。
現場からは以上です。
この記事が気に入ったらサポートをしてみませんか?