始めに
ChatGPTなどの言語生成AIサービスは、問い合わせへの回答やプログラムの実行を助けるエージェント機能を持っています。
この機能はChatGPTを使用していると普通に目にするのですが、どのようにLLMの中で実現されているのか、具体的なイメージが湧きにくいです。
本記事では、上記の回答の参考になったtoolformersの論文をもとにエージェント機能の解説を行います。
エージェント機能の実現方法には他にもバリエーションが存在するのですが、今回取り上げる例を通じてその全体像をつかむきっかけになれば幸いです。
言語モデル概要
始めに前提知識として言語モデルの大まかな仕組みを説明します。
言語モデルとは、途中まで記述された文章を入力としてその続きに来る1単語を推測する仕組みです。
言い換えると、途中までの単語列$(z_1,z_2,...,z_n)$が与えられたとき、その次に単語$z_{n+1}$が続く確率を求める関数
p_M(z_{n+1}|z_1,z_2,...,z_n)
モデルMは途中までの文章に続く単語を順次推定しそれを末尾に追加していくプロセスを繰り返すことで、一連の文章を生成しています。
機能説明
では、エージェントがtoolformersで作動する際に言語モデルMがどの様な出力を行うのか説明します。
このモデルでは、文章生成の途中でAPIの呼び出しを行うことでエージェント機能を実現しています。1
API作動時
以下はQ&AのAPIが作動する際に、Mにより出力される文章の一例になります。
The New England Journal of Medicine is a registered trademark of [QA(“Who is the publisher of The New England Journal of Medicine?”) →
- 太字の"$[a(i)\rightarrow$"という形式がモデルMによるAPI呼び出し命令に当たります
- $a$にあたるQAは利用するAPIの名称を指します
- $i$にあたる “Who..." はAPIへ渡される入力変数です
- 末尾の
→
がMにより出力された時点でAPIが呼び出されます
API作動後
API呼び出しが完了すると、文中の→
の後に出力結果$r$と閉じカギ括弧]
が追加されます。
The New England Journal of Medicine is a registered trademark of [QA(“Who is the publisher of The New England Journal of Medicine?”) → Massachusetts Medical Society]
ここでは「The New England Journal of Medicineの発行者は誰?」という質問に対してAPIが「Massachusetts Medical Society」という回答を返しました。
この情報をもとに、モデルMは文章の続きを生成します。
文章生成再開
APIの出力結果を受け取り、Mによる文章生成が再開します。
The New England Journal of Medicine is a registered trademark of [QA(“Who is the publisher of The New England Journal of Medicine?”) → Massachusetts Medical Society] the MMS.
上が出力された最終的な文章です。「The New England Journal of MedicineはMMSの登録商標である。」という正確な情報をもとにした文章が生成されました。
なお、この[...]
内のテキストは指令文のため回答の一部とはみなされません。
そのため、
The New England Journal of Medicine is a registered trademark of the MMS.
が本来の出力文となります。
まとめ
以下のような流れでエージェント機能が実現されています。
- 言語モデルMが固定フォーマット"$[ a(i)\rightarrow$"を出力することで、APIが作動する
- 返された値が文章に追加され、"$[ a(i)\rightarrow r]$"という形式が完成する。
- API出力を基にして、Mは文章生成を継続する
Mが上記の動作を実現するためには、追加学習を行う必要があります。この詳細については次項で説明します。
追加学習
事前学習のみでは、言語モデルMは上記のような特定のフォーマットを出力しません。そのため、Mに対して追加学習が必要になります。
そのためには、API呼び出しを含む文章を学習データとして用意する必要があります。
しかし、手動でデータを作成するには以下のような課題が存在します。
- 学習データを大量に用意するのが手間である
- 手動で挿入したAPI呼び出しが、解答の精度を上げるとは限らない
そのため、論文内ではモデルM自身による学習データ生成を利用しています。
API呼び出し文の記法
あらかじめ、API呼び出し文を表現するための記号を以下のように定義します。
- $a_{c}$: API名
- $i_{c}$: APIに渡される入力値
- $r$: APIの出力値
- $c=(a_{c},i_{c})$: API呼び出しを表すペア
- API呼び出し文の形式:
- 呼び出しのみの場合:
\textbf{e}(c)=[a_{c}(i_{c})]
- 出力値を含む場合
\textbf{e}(c,r)=[a_{c}(i_{c})→r]
①プロンプト設計
元の文$\textbf{x}=x_1,x_2...x_n$にAPI呼び出し$\textbf{e}(c)=[a_{c}(i_{c})]$を適切に挿入させるためのプロンプト$P(\textbf{x})$を用意します。ここで、元の文$x$には事前学習で利用したテキストが利用されます。
以下は$P(\textbf{x})$の一例である、Q&A APIを挿入させるプロンプトです。
各APIについても同様のプロンプトを用意します。
We use the following prompt for the question answering tool:
Your task is to add calls to a Question Answering API to a piece of text. The questions should help you get information required to complete the text. You can call the API by writing ”[QA(question)]” where ”question” is the question you want to ask.
Here are some examples of API calls:
Input: Joe Biden was born in Scranton, Pennsylvania.
Output: Joe Biden was born in [QA(”Where was Joe Biden born?”)] Scranton, [QA(”In which state is Scranton?”)] Pennsylvania.
Input: Coca-Cola, or Coke, is a carbonated soft drink manufactured by the Coca-Cola Company.
Output: Coca-Cola, or [QA(”What other name is Coca-Cola known by?”)] Coke, is a carbonated soft drink manufactured by [QA(”Who manufactures Coca-Cola?”)] the Coca-Cola Company.
Input: x
Output:
②利用可能なAPI呼び出しの生成
$P(\textbf{x})$を利用し、有用と思われるAPI呼び出しの生成を行います。ここでは、網羅的に生成を行うために方法を工夫しています。
まず、プロンプト$P(\textbf{x})$と文の$i-1$番目の単語まで部分文$x_{1:i-1}$を繋げた以下の文章を考えます:
P(\textbf{x}),x_{1:i-1}
この時言語モデルMを利用することで、この文章の次に[
が出現する確率
p_i = p_M([|P(x),x_{1:i-1})
を計算することができます。
ここで、この確率$p_{i}$が閾値$\tau_{s}$を超える位置$i$を確率の高い順に$k$個取得します。
これにより、文章$\textbf{x}$内で、[
が挿入されそうな位置$i$の集合$I $を得ることが出来ます。
次に各$i\in I$に対して、モデルMを用いて$m$個のAPI呼び出し$c_{i}^{1},...,c_{i}^{m}$を生成します。
具体的には、以下のように生成を行います:
- 文"$P(x),x_{1:i-1}[$"を入力として、続きの文章をモデル M に生成させます
- 出力が "]" に到達するまで生成を続けます
この生成プロセスで得られる出力は、 API 呼び出しを表すテキスト$\textbf{e}(c_{i}^{k})$になっていると想定されるため、API呼び出し$c_{i}^{k}$を得ることが出来ます。
③API実行
上で得られた各API呼び出し$c_{i}^{k}$を実際に実行し、出力$r_{i}^{k}$を得ます。
④有効性の評価、学習データ作成
上記で得たAPI呼び出しの中から、正解を導くために有効なもののみを学習データとして採用します。そのために、以下のような方法をとります。
まず、各$j$について以下の2つの文をモデル M の入力とします:
- 元の文 "$x_{1:j-1}$"
- API形式を挿入した文 "$\textbf{e}(c_{i}^{k},r_{i}^{k}),x_{1:j-1}$"2
これにより、次の単語として正解$x_{j}$が生成される確率を両方について計算できます。これらの確率を比較し、以下の基準で評価を行います:
- API 挿入文の方が正解を生成する確率が高い場合、その API 呼び出しは有効と判断される
具体的には、以下の重み付き損失関数を用います。($w_{i}$は重み):
L_{i}(\textbf{z}) = -\sum_{k=i}^n w_{j-i} \cdot \log p_{M}(x_{j}|\textbf{z},x_{1:j-1})
ここで、API 呼び出しが有る場合と無い場合の損失を比較します。つまり、
- API 呼び出しを含む場合:
L_{i}^{+} =L_{i}(\textbf{e}(c_{i}^{k},r_{i}^{k}))
- API 呼び出しを含まない場合 3:
L_{i}^{-} =min(L_{i}(\epsilon),L_{i}(\textbf{e}(c_{i}^{k},\epsilon)))
もしこれらの損失差が閾値$\tau_{f}$を超える場合、すなわち以下
L_{i}^{-}-L_{i}^{+} > \tau_{f}
が成立すると、API 呼び出しは有効なものとみなされます。
この場合、API 呼び出しを含めた文字列
\textbf{x}^{*}=x_{1:i-1},\textbf{e}(c_{i}^{k},r_{i}^{k}),x_{i:n}
は学習データとして追加されることになります。
以上のプロセスを通じて、学習データを効率的かつ妥当に生成することが可能となります。
まとめ
以上でtoolformerのエージェント機能の機構を紹介しました。
冒頭でも述べたように、これはエージェント機能を実現する一例になります。他の例については調査不足のため今回は割愛となってしまいましたが、また調べたいと考えています。
この記事が少しでも参考になりましたら、幸いです。
参考文献
- Toolformer: Language Models Can Teach Themselves to Use Tools.2023-02, https://arxiv.org/abs/2302.04761
- A Survey on Large Language Model based Autonomous Agents. 2024-12, https://arxiv.org/abs/2308.11432