🦢

OpenAIの「Swarm」でAIエージェントを開発してみた

2024/10/21に公開

はじめに

はじめまして。データアナリティクスラボ株式会社 データソリューション事業部の力岡と申します。普段はデータサイエンティストとして、データ分析や機械学習モデルの構築、生成AIアプリの開発などを行っています。

近年、AIの発展に伴い、自律的にさまざまなタスクを遂行するAIエージェントが注目を集めています。生成AIに関するシンポジウムやセミナーに参加すると、この「AIエージェント」という言葉を聞く機会が増えており、RAGに続いて次にバズる技術になるのではないかと感じ、今回キャッチアップしてみることにしました。

AIエージェントとは

AIエージェントは技術分野によって定義が多少異なることがありますが、一般的には、環境と対話し、データを収集し、そのデータをもとに自律的にタスクを実行することで、特定の目標を達成するためのソフトウェアを指します。特に、今回焦点とするのは、LLM(大規模言語モデル)をベースにしたAIエージェントとなります。


出典: Azure OpenAI Service Dev Day / LLMでできる!使える!生成AIエージェント

AIエージェントの進化に伴い、複数のエージェントが協力して複雑なタスクを実行するマルチエージェントシステムの開発も加速しています。今回紹介する「Swarm」は、そのようなマルチエージェントシステムの構築を容易にするためのフレームワークです。

Swarmとは

Swarmは、2024年10月12日にOpenAIが公開した、マルチエージェントオーケストレーションのためのフレームワークです。このフレームワークはPythonを使用しており、AIエージェント同士が連携し、自律的に複雑なタスクを進行できるように設計されています。Swarmを使用することで、マルチエージェントシステムを簡単に構築できるようになります。

https://github.com/openai/swarm

他にもAIエージェントを構築するためのライブラリとして、LangGraphがあります。LangGraphは多機能で柔軟性が高い一方、実装が複雑になる傾向があります。これに対して、Swarmは機能が少ないながらも、実装が非常に簡単であることが特徴です。

クラスと関数

SwarmでAIエージェントを作成・実行する際に使う主なクラスと関数について説明します。

Agent

AIエージェントを作成するためのクラスです。エージェントの名前や動作、利用するモデルなどを設定します。

フィールド名 初期値 説明
name str "Agent" エージェントの名前
model str "gpt-4o" 使用するAIモデル
instruction str "You are a helpful agent." エージェントへの指示
functions List [] エージェントが利用できる関数のリスト
tool_choice str None エージェントが使う特定のツールの指定

client.run()

作成したエージェントを実行するための関数です。エージェントに対するメッセージを処理し、会話を進めます。

引数名 初期値 説明
agent Agent 必須 呼び出される初期エージェント
messages List 必須 メッセージオブジェクトのリスト
context_variables dict {} 追加の情報を含むコンテキスト
max_turns int float("inf") 会話の最大ターン数
model_override str None モデルを変更するオプション
stream bool False 応答をストリーミング表示するかどうか
debug bool False デバッグモード

run_demo_loop()

作成したエージェントをコンソール上で繰り返し実行するための関数です。内部でclient.run()を使ってエージェントを動かしています。

引数名 初期値 説明
starting_agent Agent 必須 呼び出される初期エージェント
context_variables dict {} 追加の情報を含むコンテキスト
stream bool False 応答をストリーミング表示するかどうか
debug bool False デバッグモード

サンプルプログラム

公式リポジトリには、いくつかの実装例が公開されており、これらを利用することで理解を深めることができます。

https://github.com/openai/swarm/tree/main/examples

実装サンプル 説明
basic セットアップ、関数の呼び出し、エージェントの引き継ぎ、コンテキスト変数の利用など、基本的な機能をシンプルに紹介する例。
triage_agent 基本的なトリアージ(振り分け)エージェントの設定例。適切なエージェントへの引き継ぎ方法を示します。
weather_agent 関数呼び出しを使ったシンプルな天気予報エージェントの例。
airline 複数のエージェントを使って、航空会社の様々なカスタマーサービスリクエストに対応する例。
support_bot ユーザーインターフェースエージェントと、複数のツールを持つヘルプセンターエージェントを含む、カスタマーサービスボットの例。
personal_shopper 購入のサポートや注文の返金手続きを手助けする、パーソナルショッピングエージェントの例。

ただし、これらの実装例の中にはそのままでは動かないコードや、説明が不足している箇所もあります。以下の記事に、実装例の補足説明や修正コードがまとめてくださっている方がいらっしゃったので、こちらを参考にすると良いかと思います。

https://qiita.com/Maki-HamarukiLab/items/addeffc7ade848a4807a

営業支援ボットの開発

今回は、実際に「Swarm」を利用して、簡易的な営業支援ボットを開発してみました。

コンセプト

データ分析を支援する企業向けの営業支援ボットで、、営業担当者がクライアントからデータ分析に関する相談を受けた際に、効果的な商談ストーリーを組み立てるサポートを行います。
商談では、クライアントの現状や課題を理解し、自社のスタッフがどのようにその課題に対応できるかを効果的に伝えることが重要です。そこで、これらのポイントを押さえた商談ストーリーを自動でまとめられることを目指して、開発を行いました。

全体像

今回作成した営業支援ボットは、4つのエージェントが協力して機能します。トリアージエージェントWeb検索エージェント社員情報検索エージェント、そして商談ストーリー生成エージェントが連携し、商談の支援を行います。

以下に、開発したコードの全体を記載します。

実装コード
from swarm import Swarm, Agent
from swarm.repl import run_demo_loop
from tavily import TavilyClient
from loguru import logger

# 環境変数の読み込み
from dotenv import load_dotenv
load_dotenv()


client = Swarm()
tavily_client = TavilyClient()


def websearch_functions(search_query: str):
    """Web検索を実行する関数"""
    result = tavily_client.qna_search(query=search_query)
    return result

def employee_search_functions(tech_stack: str):
    """社員情報検索を実行する関数"""
    logger.info(f"社員情報検索を実行します: {tech_stack}")
    
    # 本来は検索機能を実装するべきだか、ここではダミーデータを返す
    result = """Aさん
    - 社内向けAIアプリケーションの開発
        - クラウドサービスを活用した安全性の高いシステム設計
        - フレームワークを用いたAIアプリの概念実証(PoC)の推進
        - RAGによる社内データを活用した検索機能や資料生成機能の開発
    
    Bさん
    - 営業支援ツールの概念実証(PoC)の推進
        - 営業担当者向けの次のアクションを支援するツールのPoC
        - RAGによる営業データを活用した検索機能の調査・構築

    Cさん
    - 画像生成AIのビジネス活用に関するPoC
        - 画像生成ツールの環境構築(ローカル、クラウドなど)
        - 拡張機能の技術的な検証
        - 目的に応じた画像生成に向けたプロンプト調整"""
    
    return result

websearch_agent = Agent(
    name="Web検索エージェント",
    instructions="""ユーザーの質問に基づいてWeb検索を行い、その結果を提供してください。
    Web検索が必要ない場合は、トリアージエージェントに会話を転送してください。
    社員情報検索や商談ストーリー生成が必要な場合は、トリアージエージェントに会話を転送してください。""",
    functions=[websearch_functions],
    model="gpt-4o"
)

employee_search_agent = Agent(
    name="社員情報検索エージェント",
    instructions="""該当の技術スタックに精通する社員を検索し、その情報を提供してください。
    社員情報の検索が必要ない場合は、トリアージエージェントに会話を転送してください。
    Web検索や商談ストーリー生成が必要な場合は、トリアージエージェントに会話を転送してください。""",
    functions=[employee_search_functions],
    model="gpt-4o",
)

negotiation_story_agent = Agent(
    name="商談ストーリー生成エージェント",
    instructions="""データ分析を支援する企業に所属する営業社員として、商談ストーリーを生成してください。
    商談ストーリーの生成が必要ない場合は、トリアージエージェントに会話を転送してください。
    Web検索や社員情報検索が必要な場合は、トリアージエージェントに会話を転送してください。""",
    model="gpt-4o",
)

triage_agent = Agent(
    name="トリアージエージェント",
    instructions="""ユーザーの要求を最適に処理できるエージェントを判断し、その会話をそのエージェントに転送します。
    リクエストをエージェントにトリアージするためにもっと情報が必要な場合は、理由を説明せずに直接質問してください。""",
)

def transfer_to_websearch():
    logger.info("Web検索エージェントに転送します")
    return websearch_agent

def transfer_to_employee_search():
    logger.info("社員情報検索エージェントに転送します")
    return employee_search_agent

def transfer_to_negotiation_story():
    logger.info("商談ストーリー生成エージェントに転送します")
    return negotiation_story_agent

def transfer_back_to_triage():
    """現在のエージェントが処理できないトピックについてユーザーが質問している場合、この関数を呼び出します。"""
    logger.info("トリアージエージェントに転送します")
    return triage_agent

triage_agent.functions = [transfer_to_websearch, transfer_to_employee_search, transfer_to_negotiation_story]
websearch_agent.functions.append(transfer_back_to_triage)
employee_search_agent.functions.append(transfer_back_to_triage)
negotiation_story_agent.functions.append(transfer_back_to_triage)

# 実行
run_demo_loop(triage_agent, debug=False)

ライブラリのインストール

まずは必要なライブラリをインストールします。

pip install git+https://github.com/openai/swarm.git
pip install openai python-dotenv tavily-python loguru

環境設定ファイルの作成

次に環境設定ファイルを作成します。今回は、OpenAIとTavilyのサービスを利用するので、これらのAPIキーを.envファイルを作成して環境変数に記述します。

.envs
OPENAI_APY_KEY=your_openai_api_key
TAVILY_API_KEY=your_tavily_api_key

エージェントの実装

各エージェントの実装を行います。

トリアージエージェント

このエージェントは、ユーザーのリクエストを適切なエージェントに振り分ける機能を持っています。ユーザーのリクエストがWeb検索なのか、社員情報検索なのか、商談ストーリーの生成なのかを判断し、必要なエージェントに転送します。

triage_agent = Agent(
    name="トリアージエージェント",
    instructions="""ユーザーの要求を最適に処理できるエージェントを判断し、その会話をそのエージェントに転送します。
    リクエストをエージェントにトリアージするためにもっと情報が必要な場合は、理由を説明せずに直接質問してください。""",
)

Web検索エージェント

このエージェントは、Web検索を実施するためのエージェントです。Web検索機能は、Tavilyというサービスを利用して、APIを通じてWeb検索結果を取得します。

def websearch_functions(search_query: str):
    """Web検索を実行する関数"""
    result = tavily_client.qna_search(query=search_query)
    return result
websearch_agent = Agent(
    name="Web検索エージェント",
    instructions="""ユーザーの質問に基づいてWeb検索を行い、その結果を提供してください。
    Web検索が必要ない場合は、トリアージエージェントに会話を転送してください。
    社員情報検索や商談ストーリー生成が必要な場合は、トリアージエージェントに会話を転送してください。""",
    functions=[websearch_functions],
    model="gpt-4o"
)

Tavilyは、AIエージェント専用に構築された検索エンジンで、Search APIを利用してリアルタイムにWeb情報を検索できます。無料プランでは毎月1,000回のAPIコールが可能です。

https://tavily.com/

以下は、Tavily APIの実装サンプルです。最新の情報を正確に取得できていることが分かるかと思います。

from tavily import TavilyClient

tavily_client = TavilyClient(api_key=your_tavily_api_key)
answer = tavily_client.qna_search(query="現在の日本の総理大臣は誰ですか?")
print(answer)

現在の日本の総理大臣は石破茂総裁です。彼は第102代の総理大臣に選出され、石破内閣を発足させています。

社員情報検索エージェント

このエージェントは、技術スタックやスキルに基づいて、特定の社員情報を検索するためのエージェントです。このエージェントを活用することで、特定のプロジェクトや顧客のニーズに合った社員を見つけることが可能になります。
今回は時間の都合上、ダミーデータを使用していますが、実際の運用では社内のデータベースや人材管理システムと連携し、リアルタイムで社員情報を取得することが理想となります。

def employee_search_functions(tech_stack: str):
    """社員情報検索を実行する関数"""
    logger.info(f"社員情報検索を実行します: {tech_stack}")
    
    # 本来は検索機能を実装するべきだか、ここではダミーデータを返す
    result = """Aさん
    - 社内向けAIアプリケーションの開発
        - クラウドサービスを活用した安全性の高いシステム設計
        - フレームワークを用いたAIアプリの概念実証(PoC)の推進
        - RAGによる社内データを活用した検索機能や資料生成機能の開発
    
    Bさん
    - 営業支援ツールの概念実証(PoC)の推進
        - 営業担当者向けの次のアクションを支援するツールのPoC
        - RAGによる営業データを活用した検索機能の調査・構築

    Cさん
    - 画像生成AIのビジネス活用に関するPoC
        - 画像生成ツールの環境構築(ローカル、クラウドなど)
        - 拡張機能の技術的な検証
        - 目的に応じた画像生成に向けたプロンプト調整"""
    
    return result
employee_search_agent = Agent(
    name="社員情報検索エージェント",
    instructions="""該当の技術スタックに精通する社員を検索し、その情報を提供してください。
    社員情報の検索が必要ない場合は、トリアージエージェントに会話を転送してください。
    Web検索や商談ストーリー生成が必要な場合は、トリアージエージェントに会話を転送してください。""",
    functions=[employee_search_functions],
    model="gpt-4o",
)

商談ストーリー生成エージェント

このエージェントは、商談のシナリオやストーリーを生成するためのエージェントです。営業担当者がクライアントに対して効果的な提案を行うためのストーリーを自動生成します。

negotiation_story_agent = Agent(
    name="商談ストーリー生成エージェント",
    instructions="""データ分析を支援する企業に所属する営業社員として、商談ストーリーを生成してください。
    商談ストーリーの生成が必要ない場合は、トリアージエージェントに会話を転送してください。
    Web検索や社員情報検索が必要な場合は、トリアージエージェントに会話を転送してください。""",
    model="gpt-4o",
)

エージェント転送機能

最後にエージェントの転送機能を実装します。この関数がないと、エージェント間の移動ができないので、忘れずに実装してください。

def transfer_to_websearch():
    logger.info("Web検索エージェントに転送します")
    return websearch_agent

def transfer_to_employee_search():
    logger.info("社員情報検索エージェントに転送します")
    return employee_search_agent

def transfer_to_negotiation_story():
    logger.info("商談ストーリー生成エージェントに転送します")
    return negotiation_story_agent

def transfer_back_to_triage():
    """現在のエージェントが処理できないトピックについてユーザーが質問している場合、この関数を呼び出します。"""
    logger.info("トリアージエージェントに転送します")
    return triage_agent

triage_agent.functions = [transfer_to_websearch, transfer_to_employee_search, transfer_to_negotiation_story]
websearch_agent.functions.append(transfer_back_to_triage)
employee_search_agent.functions.append(transfer_back_to_triage)
negotiation_story_agent.functions.append(transfer_back_to_triage)

実行例

以下が本プログラムの実行例です。データアナリティクスラボ社からRAGの導入に関する相談を受けたというシナリオを想定しています。会社概要の検索、RAGに詳しい社員の検索、商談ストーリーの作成という一連の流れがスムーズに実行されていることが確認できます。

User: Web検索をしたいです。データアナリティクスラボ株式会社の事業概要について教えて下さい。

Web検索エージェント: データアナリティクスラボ株式会社(DAL)は、データ分析受託事業を行う企業で、2019年4月に設立されました。データサイエンスに特化し、大手企業や上場企業をクライアントに持つなど成長を遂げています。本社は東京都港区にあり、他にも大阪支社(梅田)と名古屋支社を展開しています。創業者の谷川昭雄氏は起業家として、複数の会社を経営しています。

User: 社員情報検索をしたいです。データアナリティクスラボ株式会社にRAGの導入支援を依頼されています。弊社に対応できる社員や事例などはありますか。

社員情報検索エージェント: データアナリティクスラボ株式会社からのRAG導入支援の依頼に対応できそうな社員は次の通りです:

1. **Aさん**
   - 社内向けAIアプリケーションの開発経験があります。
   - クラウドサービスを活用した安全性の高いシステム設計を行っています。
   - RAGを利用して社内データを活用した検索機能や資料生成機能の開発に携わっています。

2. **Bさん**
   - 営業支援ツールの概念実証(PoC)の推進を担当しています。
   - RAGを活用した営業データを利用した検索機能の調査・構築経験があります。

これらの情報をもとに、支援可能な社員を選定することができます。
User:  商談ストーリーを作成したいです。データアナリティクスラボ会社にRAG導入の支援を提案するために、これまでの情報を元に商談ストーリーを作成してください。

商談ストーリー生成エージェント: 商談ストーリーの提案例を以下に示します。これは、データアナリティクスラボ株式会社にRAG(Retrieval-Augmented Generation)技術の導入支援を提案するためのものです。

---

**タイトル:データアナリティクスラボ株式会社へのRAG導入支援提案商談**

**会場:データアナリティクスラボ株式会社 本社(東京都港区)  
参加者:DALのプロジェクトマネージャー、AIシステム担当エンジニア、貴社営業担当(Aさん、Bさん)**

---

**1. オープニング**

- 挨拶と自己紹介
  - 「本日はお時間をいただきありがとうございます。私は[あなたの名前]で、データアナリティクスラボ様の業務効率化に向けたAIソリューションを担当しております。」

- 商談の目的説明
  - 「本日は、RAG技術を活用することで、貴社のデータ活用能力をさらに強化するご提案をさせていただければと思います。」

**2. データアナリティクスラボ様のニーズ確認**

- 現在の業務プロセスやデータ活用の課題
  - 「貴社が持つ豊富なデータは、さらにどういった形で活用したいか具体的なビジョンをお聞かせいただけますか?」

- 既存システムの導入状況と満足度
  - 「RAG導入前に現在お使いのシステムやツールに対する率直なご意見を伺いたいと思います。」

**3. ソリューション提案**

- RAG技術の概要説明
  - 「RAGはリアルタイムにデータを引き出しつつ、それを基に新しい価値を生成する技術です。特に検索機能の効率化やクリエイティブな資料作成に役立ちます。」

- 実績や事例の紹介
  - 「弊社のAさん、Bさんは貴社のニーズに最適な形でRAGを導入する豊富な経験があります。具体的には、社内データを活用した高度な検索機能を実現してきました。」

**4. 具体的な導入プラン**

- 導入ステップの提案
  - 「まず、貴社の現状システムとの親和性確認からPoCを開始し、次に段階的に本格導入を進めていくプランです。」

- 見積もりとROIの提示
  - 「導入にかかるコストと、それにより得られる効果について具体的な数値を提示させていただきます。」

**5. 質疑応答**

- 貴社からのご質問を受け、誠実に回答。

**6. 次のアクション**

- 提案内容のフィードバック収集
  - 「ぜひ、この提案についてご意見をお聞かせいただき、次に進めるべき方向性を検討していただければと思います。」

- 次回のミーティング日程調整
  - 「次回は、実際にプランの細部を詰めていく段階に進みたいと思いますが、ご都合はいかがでしょうか?」

**クローズ**

- 商談を終了し、関係構築の継続を希望します。

---

このような流れで商談を進めると、データアナリティクスラボ株式会社に対するRAG導入支援の提案が明確になり、実現に向けた具体的な一歩となるでしょう。

おわりに

Swarmを活用して営業支援ボットを開発してみました。実際に使ってみた印象としては、プロンプトの冒頭でどのエージェントに接続するかを明示しないと、意図したエージェントにうまくつながらないことが多く、活用には少し工夫が必要だと感じました。ただし、プロンプト設計を工夫すれば、ここらへんもうまく行うことができるのかもしれません。

今後、さらなる機能を持ったエージェントや、RAGを実行する際に参照リソースを選択するエージェントなど、様々な分野でエージェント技術が活用されていくことが期待されます。AIエージェントに関する最新動向は引き続きキャッチアップしていこうと思います。

DAL Tech Blog

Discussion