CCCMKホールディングス TECH LABの Tech Blog

TECH LABのエンジニアが技術情報を発信しています

ブログタイトル

LLMに行動と思考のプロセスを与える"ReAct: Reasoning and Acting"について調べてみました。

こんにちは、CCCMKホールディングスTECH LABの三浦です。

LLMのフレームワークLangChainの使い方を調べていると、"Agent"というとても面白い機能があることを知りました。これはLLMに状況に応じて適切なTool(例えばインターネットで検索したり、Pythonのプログラムを生成したり)を選択させ、その結果をLLMに解釈させ、さらに次のアクションとして別のツールを選択させる・・・・。これを繰り返すことで複雑なタスクをLLMに解かせることが出来る機能です。

たとえば以下のようなコードで"Agent"を試すことが出来ます。このコードはLangChainのドキュメントに掲載されている、以下のコードを参考に作成しました。

Generic Agent Evaluation — 🦜🔗 LangChain 0.0.151

ReAct — 🦜🔗 LangChain 0.0.151

from langchain import Wikipedia,LLMMathChain
from langchain.llms import AzureOpenAI
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.agents.react.base import DocstoreExplorer
import wikipedia

#数式計算用のLLMChain
math_llm = AzureOpenAI(temperature=0, deployment_name="text-davinci-003")
llm_math_chain = LLMMathChain(llm=math_llm, verbose=True)

docstore=DocstoreExplorer(Wikipedia())
#Agentが使用するToolの設定
tools = [
  Tool(
    name="Search",
      func=docstore.search,
      description="useful for when you need to ask with search"
  ),
  Tool(
      name="Lookup",
      func=docstore.lookup,
      description="useful for when you need to ask with lookup"
  ),
  Tool(
      name="Calculate",
      func=llm_math_chain.run,
      description="useful for doing calculations"
  )
]

llm = AzureOpenAI(temperature=0, deployment_name="text-davinci-003")
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)

"Search"と"Lookup"というToolを使うと、WikipediaのAPIがバックグラウンドで使用されます。agentに質問を入力すると回答してくれるので、たとえば"GPT-3に含まれるパラメータの数の平方根を取るといくつですか?"と質問してみます。 (日本語だと"GPT-3のパラメータの数"が上手く伝わらなかったため、英語で投げかけます・・・)

question = "Find out the number of parameters in GPT-3 and calculate the square root of that number."
agent.run(question)

実行すると以下の様にAgentがどのように考え(Thought)、行動を取り(Action)、どんな結果が得られたのか(Observation)が表示され、それらによって最終的な答えがどう導かれているのかが分かります。

> Entering new AgentExecutor chain...
 I need to find out the number of parameters first, then calculate the square root of that number.
Action: Lookup
Action Input: Number of parameters in GPT-3
Observation: No Results
Thought: I need to search for the number of parameters in GPT-3
Action: Search
Action Input: Number of parameters in GPT-3
Observation: Generative Pre-trained Transformer 3 (GPT-3) is an ...(中略)
Thought: I now know the number of parameters in GPT-3
Action: Calculate
Action Input: Square root of 175 billion

> Entering new LLMMathChain chain...
Square root of 175 billion
text
sqrt(175000000000)

...numexpr.evaluate("sqrt(175000000000)")...

Answer: 418330.01326703775
> Finished chain.

Observation: Answer: 418330.01326703775
Thought: I now know the final answer
Final Answer: The square root of the number of parameters in GPT-3 is 418330.01326703775.

> Finished chain.
Out[14]: 'The square root of the number of parameters in GPT-3 is 418330.01326703775.'

GPT-3に含まれるパラメータ数がおよそ1,750億であること、その平方根の計算も正しいです。こんなことまでLLMで可能なのか・・・と驚きました。

ではなぜこんなことが可能なのでしょうか。気になって調べてみたところ、"ReAct:Reasoning and Acting"というロジックが使われていることが分かりました。そこで今回はこのReActが提案されている論文を読んでこのロジックがどういうものなのかを調べてみましたので、それについてまとめてみたいと思います。

ReAct:Reasoning and Acting

今回読んで、参考にさせて頂いた論文は以下になります。

Title: ReAct: Synergizing Reasoning and Acting in Language Models Authors: Shunyu Yao, Jeffrey Zhao, Dian Yu, Nan Du, Izhak Shafran, Karthik Narasimhan, Yuan Cao Submit: [Submitted on 6 Oct 2022, last revised 10 Mar 2023 URL: https://arxiv.org/abs/2210.03629

ReActの考え方はかなり人間の思考に近いようです。私たちは何か物事に取り組むとき、行動と行動の間に"今これをしたから次はこれをしよう"といったような思考を挟むことが多いと思います。この考え方は以前Prompt Engineeringのテクニックで触れた、"CoT:Chain of Thought"でも採用されている考え方ですが、ReActにはそれに加えて外部環境への行動と、それによって起こった結果の観測、そしてそれに対する考察/思考というプロセスが加わります。

以下はReActをはじめとする様々な手法が、"Question"に対してどのようにアプローチを取るのかを表している論文に掲載されている図です。

ReAct: Synergizing Reasoning and Acting in Language Models, Shunyu Yao, Jeffrey Zhao, Dian Yu, Nan Du, Izhak Shafran, Karthik Narasimhan, Yuan Cao, https://arxiv.org/abs/2210.03629, Figure 1

CoTが抱える問題点として、Hallucination(幻覚)というものがあります。ChatGPTやGPT-3が現実的にあり得ないことを事実の様に返してきた、という話を聞くことがありますが、このことを指しています。CoTによる思考の途中でこのHallucinationが発生してしまうと間違った回答に行きついてしまいます。

ReActは、たとえばWikipedia APIなどを使って自身の外の環境にアクションを起こし、それによって得た情報で自身の情報をアップデートすることが出来ます。それによってHallucinationに陥るのを防ぐことが出来ます。

ReActと他の手法との比較

論文では様々なデータセットを用いてReActと他の手法との比較が行われています。Promptを構成する要素で見ると、それぞれ以下の様になっています。

  • "Question"と"Answer"のみで構成→Original
  • "Question","Action","Observation","Answer"で構成→Act
  • "Question","Thought","Answer"で構成→CoT
  • "Question","Thought","Action","Observation","Answer"で構成→ReAct

ReActはActやOriginalの手法よりは常に精度がよいのですが、CoTに対しては若干精度が下回ることがあるようです。CoTの弱点は先ほど触れたHallucinationですが、ReActは思考ステップにおいて柔軟性に欠けることがあり、その結果同じような思考を繰り返してしまうという現象が発生することがあります。そこでReActで指定のステップ数上手くいかなかったらCoT(+SC:Self-Consistency)のモードに移行し、CoT-SCで上手く行かなかったらReActのモードに移行する"ReAct + CoT-SC"の方法を取ることで両者の弱点を補い、より高い精度が出せるそうです。

ReActのPromptingテクニック

ReActでLLMを動かすためにはLLMに与えるPrompにReActロジックに従ったFew-Shot Exampleをいくつか含めてあげます。扱うタスクにも寄りますが、論文では、6個や3個のExampleを含めていました。

論文のAppendix CにはいくつかのFew-Shot Prompingの例が掲載されています。その中では"Question"に対し、どう"Thought"し、"Action"を起こすのか、それによってこういう"Observation"が得られるからそれに対してこう"Thought"し、こう"Action"し・・・・といったステップと、最終的に"Answer(Action Finish)"にたどり着くまでの道筋が例示されています。この道筋を模範することで、新しい"Question"に対しても同じように回答にたどり着くまでステップをたどること出来るようになります。

まとめ

ということで、今回はLangChainの"Agent"という機能から始まり、それに使われているReActというロジックについて調べてみた話をご紹介しました。LLMはテキストを生成するモデルである、とほんの少し前まで思っていたのですが、調べれば調べるほどそれにとどまらず、LLMを使うことであらゆるシステムが組めるんじゃないか、といった気持ちになってきました。

そして今なおLLMの能力を引き出す研究が進められていることを考えると、LLMがもたらすインパクトは自分が想像していたよりも大きいのかもしれない、そう感じるようになりました。