対話型ロールプレイングAIエージェント"CAMEL"の論文紹介と実装

# はじめに

この記事は「[LLM・LLM活用 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/large-language-model)」5日目の記事になります。

生成AIについての話題を聞かない日はないくらい、生成AIが盛り上がりを見せていますね。そんな生成AIの中でも、私はAIエージェントに注目しています。  
AIエージェントは特定のタスクを**自律的に**実行し、環境と相互作用する能力を持つようなAIシステムのことで、2025年はAIエージェントが話題の中心になるとも言われています。AIエージェントにもさまざまな種類がありますが、大きく「シングル型」と「マルチ型」に分けることが出来ます。  
[昨日の記事](https://qiita.com/t_serizawa/items/0810a2b05c099c08105e)ではシングル型AIエージェントの"ReAct"についてご紹介しましたが、本記事ではマルチAIエージェントの中でも非常に有名な"CAMEL"というAIエージェントの論文と実装方法を紹介します。

# Camelとは

## 概要

"CAMEL"は2023年のNeurIPSで発表された「[CAMEL: Communicative Agents for "Mind" Exploration of Large Language Model Society](https://proceedings.neurips.cc/paper_files/paper/2023/hash/a3621ee907def47c1b952ade25c67698-Abstract-Conference.html)」で提案されたAIエージェントです。  
従来のLLMは、人間による細かな指示や介入が必要不可欠という課題がありました。  
そこで、人間がざっくりとしたタスクを渡すだけで、自律的にタスクを進めることが出来るコミュニケーティブエージェントとして、CAMELを提案しています。

## 特徴

このモデルでは、AIエージェント同士のロールプレイング形式でタスクを進行していきます。  
AIエージェントは3つ用意され、それぞれ「タスク指定エージェント」、「ユーザエージェント」、「アシスタントエージェント」として役割を与えられます。  
ロールプレイングは以下の流れで進行していきます。

1. 人間が大まかなアイディアやタスクを入力します (人間が介入するのはここのみ)
2. タスク指定エージェントが、人間から渡されたアイディアを具体的なタスクに変換します
3. 具体的なタスクに対し、ユーザエージェントが指示を出してアシスタントエージェントが回答する形で対話を行い、タスク解決を目指します

各エージェントには、試行錯誤の上でプロンプト設計がされたようで、表のようなインセプションプロンプトが与えられています。  
具体的には、以下のような工夫がなされています。
- アシスタントエージェントがユーザエージェントに対して指示しないよう明確に指示
- 指示と応答が一貫性を保つようにフォーマットを固定化
- 無限ループや役割の混乱を防止するための制約を盛り込む

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542065/ff7710b7-3e48-463c-a53a-a62378bffbc5.png)
CAMEL: Communicative Agents for "Mind" Exploration of Large Language Model Society, Figure 2

# 実装方法

CAMELの実装は、[CamelのGithubページ](https://github.com/camel-ai/camel)に方法が載っています。  
Google Colabに用意されているNotebookを使う方法と、自分のローカル環境で試す方法があり、とりあえず試してみたい場合には、Colabを使うのが簡単かと思います。

:::note warn
CAMELはAIエージェント同士が会話を行うため、1回の実行あたりのAPI利用量が大きくなります。スクリプト内chat_turn_limitで会話回数制限をするなどしてAPI使用量を抑えることをおススメします。
:::

## Google Colabを使用する場合

Notebookは以下のリンクから利用することが出来ます。

https://colab.research.google.com/drive/1AzP33O8rnMW__7ocWJhVBXjKziJXPtim?usp=sharing

実行するには、以下2点を修正することで実行できます。
- 事前にOpenAI API KEYを取得しておき、API KEYを入力
```python
os.environ["OPENAI_API_KEY"] = "{取得したAPI KEYを入力}"
```

- task_promptに解決したいアイディア・タスクを入力
```python
from colorama import Fore

from camel.societies import RolePlaying
from camel.utils import print_text_animated

task_prompt = "{解決したいアイディア・タスクを入力}"
…
```

## 自分のローカル環境で試す場合

CAMELはpipでインストールすることが出来ます。

```shell
$ pip install camel-ai
```

OpenAI APIを利用するため、API KEYを.envファイルに記述します。  
または、実行ファイルに直接書いても良いですが、Gitなどにあげてしまわないよう注意しましょう。

実行ファイルは以下の通り記述します。  
修正箇所は、OpenAI API KEYとtask promptの2ヶ所だけで実行できます。

```python
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
# Licensed under the Apache License, Version 2.0 (the “License”);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an “AS IS” BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
from colorama import Fore

from camel.societies import RolePlaying
from camel.utils import print_text_animated
import os

os.environ["OPENAI_API_KEY"] = "{取得したAPI KEYを入力}"

def main(model=None, chat_turn_limit=50) -> None:
    task_prompt = "{解決したいアイディア・タスクを入力}"
    role_play_session = RolePlaying(
        assistant_role_name="Python Programmer",
        assistant_agent_kwargs=dict(model=model),
        user_role_name="Stock Trader",
        user_agent_kwargs=dict(model=model),
        task_prompt=task_prompt,
        with_task_specify=True,
        task_specify_agent_kwargs=dict(model=model),
    )

    print(
        Fore.GREEN
        + f"AI Assistant sys message:\n{role_play_session.assistant_sys_msg}\n"
    )
    print(
        Fore.BLUE + f"AI User sys message:\n{role_play_session.user_sys_msg}\n"
    )

    print(Fore.YELLOW + f"Original task prompt:\n{task_prompt}\n")
    print(
        Fore.CYAN
        + "Specified task prompt:"
        + f"\n{role_play_session.specified_task_prompt}\n"
    )
    print(Fore.RED + f"Final task prompt:\n{role_play_session.task_prompt}\n")

    n = 0
    input_msg = role_play_session.init_chat()
    while n < chat_turn_limit:
        n += 1
        assistant_response, user_response = role_play_session.step(input_msg)

        if assistant_response.terminated:
            print(
                Fore.GREEN
                + (
                    "AI Assistant terminated. Reason: "
                    f"{assistant_response.info['termination_reasons']}."
                )
            )
            break
        if user_response.terminated:
            print(
                Fore.GREEN
                + (
                    "AI User terminated. "
                    f"Reason: {user_response.info['termination_reasons']}."
                )
            )
            break

        print_text_animated(
            Fore.BLUE + f"AI User:\n\n{user_response.msg.content}\n"
        )
        print_text_animated(
            Fore.GREEN + "AI Assistant:\n\n"
            f"{assistant_response.msg.content}\n"
        )

        if "CAMEL_TASK_DONE" in user_response.msg.content:
            break

        input_msg = assistant_response.msg


if __name__ == "__main__":
    main()
```

# 実行例

上記スクリプトを実行するとどのような結果が得られるのか、紹介します。

## 論文にあった株式市場向けの取引ボットの開発

論文では、株式市場向けの取引ボットの開発が実行例として示されています。

![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542065/55f17433-f42e-e8f6-af50-4d9e17f79c5d.png)
CAMEL: Communicative Agents for "Mind" Exploration of Large Language Model Society, Figure 1

`task prompt`として、"Develop a trading bot for the stock market"が入力されています。  
これを実行すると、以下の画像のように会話が続いていきます。

![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542065/9778ad54-0fcb-4051-15af-4af7e6012679.png)
実行中の様子

黄色のtask promptに対し、水色のタスク指定エージェント (Specified task prompt) がアイディアをタスク化しています。  
赤文字の最終タスクを定義づけた上で、ユーザエージェントとアシスタントエージェントの対話が始まっていきます。  
今回のスクリプトでは`chat_turn_limit=50`としているので、50回のやり取りで終わるようにしています。

## 自分のアイディアを試す

ここでは、音声認識アプリを作ってみる例を紹介したいと思います。

`task prompt`に"create a voice recognition app"と入力すると、以下のような出力が得られました。

![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542065/bcfffe3f-9bea-82e2-d127-084b355b6b0b.png)
音声認識アプリの構築例

単純に「音声認識アプリを作る」と指示したものに対し、タスク指定エージェントが  
「株式トレーダー向けの音声認識アプリを開発します。このアプリでは、音声コマンドを使用して、取引の実行、株価の取得、アラートの設定を行うことができます。自然言語処理を統合して取引の専門用語を理解し、リアルタイムの市場更新情報を提供することで、ユーザーが外出中やマルチタスクを行っている間もシームレスなやり取りを実現します。」  
とタスクを具体化してくれました。  
そして、そのタスクを実行する手順をユーザエージェントとアシスタントエージェントが対話形式で示してくれています。

# まとめ

今回はマルチAIエージェントのCAMELについてご紹介しました。  
この論文は執筆時点で460回以上引用されており、非常にメジャーな手法の一つといえます。  
AIエージェントについてのキャッチアップの一助になれば幸いです。