AI

【AIエージェント】swarmを使ったマルチエージェントの実例

フリーランスエンジニアのまさです。
この記事では、OpenAIが2024年10月12日に公開した実験的なマルチエージェントオーケストレーションのswarmについて、実例を交えながら解説したいと思います。

昨今マルチエージェントシステムとして、langgraph、AutoGPT、difyなど様々なライブラリ・ツールが出てきていますが、それらとの違いも合わせてみていきたいと思います。

それでは順にみていきましょう。

swarmの概要

Swarmは、OpenAIが2024年10月に公開したフレームワークで、複数のAIエージェントを連携させることで、複雑なタスクを効率的に処理するために設計されています。

このフレームワークの目的は、エージェント間のタスク引き継ぎ(ハンドオフ)やタスク管理を簡略化し、シンプルなインターフェースを通じて柔軟かつ拡張可能なシステムを構築することにあります。

Swarmの特徴として、軽量で柔軟性の高い設計ができます。
エージェントの追加やタスクの再構成が非常に容易です。
使ってみた感じ、langgraphよりも簡単にエージェント間をつなぐことができます。

swarmの使い方

swarmの導入については、以下のサイトを順に実行します。

まずは仮想環境にswarmのインストールします。

pip install git+https://github.com/openai/swarm.git

ライブラリのインストールおよびopenAIのAPIキーを設定します。

from swarm import Swarm, Agent

os.environ['OPENAI_API_KEY'] = 'xxxxxxxxx'

では、早速、複数エージェントで連携を取らせる構築を行ってみます。

下の例では、agent_a,agent_bを用意して、agent_aからagent_bを呼び出し、agent_bに回答をさせているような作りになっています。

client = Swarm()


def transfer_to_agent_b():
    return agent_b


agent_a = Agent(
    name="Agent A",
    instructions="あなたはAgent Aです。",
    functions=[transfer_to_agent_b],
)

agent_b = Agent(
    name="Agent B", instructions="あなたはAgent Bです。"
)

response = client.run(
    agent=agent_a,
    messages=[{"role": "user", "content": "Agent Bと話せますか?"}],
)

print(response.messages[-1]["content"])

流れとしては以下のような流れになります。

  1. client.runメソッドを使用して、ユーザーがAgent Aに「Agent Bと話せますか?」と尋ねます。
  2. Agent Aは自身のハンドオフ関数(transfer_to_agent_b)を使用してタスクをAgent Bに引き継ぎます。
  3. Agent Bが応答し、その内容が出力されます。

回答は以下のような結果となりました。

出力結果
はい、Agent Bです。どんなご用件でしょうか?

問題なくAgent Bに連携できていることがわかりました。

swarmを使用したマルチエージェント実例

次に複数エージェントを用意し、ユーザの質問によって回答を行うエージェントを切り替えるような実装を行います。

まずは、各エージェントが使用する関数の定義を行います。
ここでは、3つの関数を用意しています。
search_perplexity:ウェブ検索を行う関数(Perplexity APIを使用しています。)
database_search_employee:社員情報を検索する関数(データはダミー)
database_search_design:設計情報を検索する関数(データはダミー)

## 各エージェントが使用する関数を定義
def search_perplexity(query: str) -> str:
    """2024年の時点の最新の情報をウェブ検索する関数"""
    messages = [
        {
            "role": "system",
            "content": (
                "You are an artificial intelligence assistant and you need to "
                "engage in a helpful, detailed, polite conversation with a user."
            ),
        },
        {
            "role": "user",
            "content": (
                query
            ),
        },
    ]
    client = OpenAI(api_key="xxxxx", base_url="https://api.perplexity.ai")

    response = client.chat.completions.create(
        model="llama-3.1-sonar-large-128k-online",
        messages=messages,
    )
    result = response.choices[0].message.content

    return result

def database_search_employee (query: str) -> str:
    """社員情報検索を実行する関数"""
    print(f"社員情報検索を実行します")

    # 本来は検索機能を実装するべきだか、ここではダミーデータを返す
    result = """Aさん
    - 生産管理システムの最適化
        - 生産ラインの稼働状況をリアルタイムで監視するダッシュボードの開発
        - AIを活用した生産計画の自動化と効率化
        - 現場スタッフ向けの使いやすいモバイルアプリの設計・導入
    
    Bさん
    - 製品検査プロセスのデジタル化
        - 画像認識技術を活用した自動検査システムの構築
        - データ解析による不良品の原因分析と予防策の提案
        - 検査結果の可視化ツールを用いた品質管理レポートの作成

    Cさん
    - IoTを活用した工場のスマート化推進
        - センサーデータを活用した設備稼働状況の予測分析
        - クラウドプラットフォームによる生産データの一元管理
        - 設備保全のためのAI予測保全モデルの導入"""
    
    return result

def database_search_design (query: str) -> str:
    """設計情報検索を実行する関数"""

    print(f"設計情報検索を実行します")
    
    # 本来は検索機能を実装するべきだか、ここではダミーデータを返す
    result ="""当社では、3D CADを活用した製品設計を中心に行っています。
    初期段階でのコンセプト設計から、詳細設計、試作品の製造までを一貫してサポート。
    CAE解析を用いて構造強度や熱伝導性のシミュレーションを実施し、製品性能を最適化しています。
    また、設計データはPDMシステムで一元管理し、設計変更やバージョン管理の効率化を図っています。
    これにより、品質向上と設計リードタイムの短縮を実現。顧客のニーズに合わせた高精度な設計を提供します。
    """

    return result

次に各エージェントの定義を行います。
transfer_to_router_agent
他のエージェントからTriage Agentに戻る際に使用する関数です。

transfer_to_web_search_agent
Web Search Agentを生成します。このエージェントはsearch_perplexity関数を使用し、ウェブ検索を実行します。

transfer_to_employee_search_agent
Employee Database Search Agentを生成します。このエージェントはdatabase_search_employeeを使用して社員情報を検索します。

transfer_to_design_search_agent
Design Database Search Agentを生成します。このエージェントはdatabase_search_designを使用して設計情報を提供します。

# 各エージェントの定義
def transfer_to_router_agent():
    return triage_agent

def transfer_to_web_search_agent():
    return Agent(
        name="Web Search Agent",
        instructions="あなたはWeb Search Agentです。最新の情報を検索して回答を生成します。",
        functions=[search_perplexity, transfer_to_router_agent],
    )


def transfer_to_employee_search_agent():
    return Agent(
        name="Employee Database Search Agent",
        instructions="あなたはEmployee Database Search Agentです。該当の技術スタックに精通する社員を検索し、その情報を提供してください。",
        functions=[database_search_employee, transfer_to_router_agent],
    )


def transfer_to_design_search_agent():
    return Agent(
        name="Design Database Search Agent",
        instructions="あなたはDesign Database Search Agentです。技術情報を検索し、その情報を提供してください。",
        functions=[database_search_design, transfer_to_router_agent],
    )

上記エージェントのいずれを使用するかを決めるトリアージエージェントを定義します。
トリアージエージェントは、ユーザーの質問に基づいて、適切なエージェントを選択する役割を担います。

# トリアージエージェントの定義
triage_agent = Agent(
    name="Triage Agent",
    instructions="""あなたはTriage Agentです。ユーザーの質問に対して、適切なエージェントに転送します。

    ウェブ検索を行う場合は、transfer_to_web_search_agentを呼び出してください。
    社員情報に関する情報を聞く場合は、transfer_to_employee_search_agentを呼び出してください。
    設計情報を聞く場合は、transfer_to_design_search_agentを呼び出してください。
    それ以外の場合はあなたが回答してください。必要な情報があればユーザーに質問してください。
    """,
    functions=[
        transfer_to_web_search_agent,
        transfer_to_employee_search_agent,
        transfer_to_design_search_agent,
    ],
)

最後に、ユーザーの入力をTriage Agentに渡すようにします。
client.runでエージェントを実行し、タスクが適切なエージェントに振り分けられます。

def invoke_router_agent(user_input: str):
    messages = [{"role": "user", "content": user_input}]
    response = client.run(
        agent=triage_agent,
        messages=messages,
        debug=True,
    )
    print(response.messages[-1]["content"])

上記で設定は完了です。
以下実行結果を順に記します。

invoke_router_agent("現在の日本の総理大臣は誰ですか?")

出力結果
現在の日本の総理大臣は、石破茂(Shigeru Ishiba)です。石破総理大臣は2024年から自民党の党首および第102代の総理大臣を務めています。

invoke_router_agent("社員Aの情報について教えてください?")

出力結果
社員Aの情報は以下の通りです:

– **生産管理システムの最適化** – 生産ラインの稼働状況をリアルタイムで監視するダッシュボードの開発 – AIを活用した生産計画の自動化と効率化 – 現場スタッフ向けの使いやすいモバイルアプリの設計・導入 それに関連する業務に精通しています。

他にご質問があればお知らせください。

invoke_router_agent("当社で行っている設計情報について教えてください?")

出力結果
当社では、3D CADを活用した製品設計を行っています。コンセプト設計から詳細設計、試作品の製造まで一貫してサポートしています。CAE解析を使用して、構造強度や熱伝導性のシミュレーションを実施し、製品の性能を最適化することに注力しています。設計データはPDMシステムで一元管理し、設計変更やバージョン管理の効率化を図り、品質向上と設計リードタイムの短縮を実現しています。顧客のニーズに合わせた高精度な設計を提供しています。

質問に対して的確なエージェントを選択して回答を生成していることがわかりました。
今回は3つのエージェントから1つを選択して回答させるというシンプルな構造にしました。

応用例として、エージェント数を増やして、行えるタスクの種類を増やしたり、エージェントから回答された結果をさらに別のエージェントに渡してタスクを行わせるといったことができそうです。

swarm技術を活用する際の課題

今回検証を行ってマルチエージェントシステムの課題としては、どのエージェントが何を担当し、どのようにタスクを進めるかを決定するプロセス定義が非常に難しいと感じました。

ユーザーの質問は自然言語ですが、自然言語には曖昧さや文脈依存の要素が含まれます。
例えば、「この製品の設計情報を教えてください」というリクエストが、具体的にどのような設計情報を求めているのかを正確に把握するのは容易ではありません。
webからの一般情報を求めているのか、社内DBからの情報を求めているのかわかりません。
そのため、ユーザが使用してほしいエージェントが選択されず、欲しい回答が得られないという可能性が発生しそうであると感じました。

swarmと各ライブラリとの違い

最後に、swarmと同じようにマルチエージェントシステムが構築が可能なライブラリ/ツールを比較して一覧にまとめてみました。

項目SwarmLangGraphAutoGPTDify
アーキテクチャ分散エージェント型グラフ構造タスク管理型自律型マルチエージェントGUI中心+API管理
API連携柔軟なカスタマイズ可能豊富な連携オプションプラグインによる連携外部APIの簡易統合機能
設定の簡便性pythonが書ければ比較的簡単設定手順がやや複雑設定手順がやや複雑直感的なGUIで設定可能
ドキュメントの充実度github公式ドキュメントあり活発なコミュニティ支援公式ドキュメントあり
導入難易度実験的なツールのため本番導入には向かない中程度中程度低い

SwarmはOpenAIが実験的に提供しているフレームワークのため、本番などで実装する場合は、LangGraphやDifyを使用するのが良いと思われる。
マルチエージェントシステムをコードベースで構築するのであればLangGraphを、GUIベースでの構築であればDifyを使用していくことになりそうである。

マルチエージェントシステム自体が、今年になってから話題になっている技術のため、今後もまだまだ新しいライブラリやツールが登場しそうです。

まとめ

今回は、OpenAIから2024年10月12日に発表されたSwarmについて検証してみました。

以前langgraphを使用した経験からすると、非常に簡単にマルチエージェントを組めるという感覚です。ただ、その分細かな指示はできなさそうという印象を受けました。
例えば、langgraphでは、エージェントの条件分岐を指定できますが、Swarmではそういったことはできなさそうです。
とはいえ、OpenAIからAIエージェント関連の発表があり今後も同様の発表があると思うと、今から非常に楽しみである。

2025年は、AIエージェントの発表が各社から行われると思うので、今後もこの分野についての技術調査を進めていきます。