Swarm (実験的サンプル)
エルゴノミックで軽量なマルチエージェントオーケストレーションフレームワーク
[!WARNING]
Swarmは現在、マルチエージェントシステムのエルゴノミックなインターフェースを探求するための実験的なサンプルフレームワークです。本番環境での使用を意図しておらず、公式サポートもありません。(そのため、PRやIssueのレビューも行いません!)Swarmの主な目的は、Orchestrating Agents: Handoffs & Routinesクックブックで探求されているハンドオフとルーチンのパターンを紹介することです。スタンドアロンのライブラリとしてではなく、主に教育目的で提供されています。
インストール
Python 3.10以上が必要です
pip install git+ssh://git@github.com/openai/swarm.git
または
pip install git+https://github.com/openai/swarm.git
使用方法
from swarm import Swarm, Agent
client = Swarm()
def transfer_to_agent_b():
return agent_b
agent_a = Agent(
name="Agent A",
instructions="あなたは役立つエージェントです。",
functions=[transfer_to_agent_b],
)
agent_b = Agent(
name="Agent B",
instructions="俳句でのみ話してください。",
)
response = client.run(
agent=agent_a,
messages=[{"role": "user", "content": "Agent Bと話したいです。"}],
)
print(response.messages[-1]["content"])
希望の光
新しい道交わる
何をお手伝い
目次
概要
Swarmは、エージェントの調整と実行を軽量で、高度に制御可能、そして簡単にテスト可能にすることに焦点を当てています。
これは、Agent
とハンドオフという2つの基本的な抽象化を通じて実現されています。Agent
はinstructions
とtools
を包含し、いつでも会話を別のAgent
にハンドオフすることができます。
これらのプリミティブは、ツールとエージェントのネットワーク間の豊かな動的関係を表現するのに十分な力を持っており、急峻な学習曲線を避けながら、スケーラブルで実世界のソリューションを構築することができます。
[!NOTE]
SwarmのエージェントはAssistants APIのAssistantsとは関係ありません。便宜上似た名前がついていますが、それ以外は全く無関係です。SwarmはChat Completions APIのみを使用しており、そのため呼び出し間でステートレスです。
なぜSwarmなのか
Swarmは設計上、軽量で、スケーラブル、そして高度にカスタマイズ可能です。単一のプロンプトにエンコードすることが難しい、多数の独立した機能と指示を扱う状況に最適です。
Assistants APIは、完全にホストされたスレッドと組み込みのメモリ管理および検索機能を求める開発者にとって素晴らしいオプションです。一方、Swarmは、コンテキスト、ステップ、ツール呼び出しに対する完全な透明性と細かい制御を求める開発者に最適です。Swarmは(ほぼ)完全にクライアント上で動作し、Chat Completions APIと同様に、呼び出し間で状態を保存しません。
例
インスピレーションを得るために/examples
をチェックしてください!各例の詳細はそのREADMEをご覧ください。
-
basic
: セットアップ、関数呼び出し、ハンドオフ、コンテキスト変数など、基本的な要素の簡単な例 -
triage_agent
: 適切なエージェントにハンドオフするための基本的なトリアージステップを設定する簡単な例 -
weather_agent
: 関数呼び出しの簡単な例 -
airline
: 航空会社のコンテキストで異なる顧客サービスリクエストを処理するマルチエージェントセットアップ -
support_bot
: ユーザーインターフェースエージェントと複数のツールを持つヘルプセンターエージェントを含む顧客サービスボット -
personal_shopper
: 販売や注文の払い戻しを支援できるパーソナルショッピングエージェント
ドキュメント
Swarmの実行
まず、Swarmクライアントをインスタンス化します(内部的には単にOpenAI
クライアントをインスタンス化します)。
from swarm import Swarm
client = Swarm()
client.run()
Swarmのrun()
関数は、Chat Completions APIのchat.completions.create()
関数に類似しています - messages
を受け取り、messages
を返し、呼び出し間で状態を保存しません。ただし、重要な点として、エージェントの関数実行、ハンドオフ、コンテキスト変数の参照を処理し、ユーザーに戻る前に複数のターンを取ることができます。
本質的に、Swarmのclient.run()
は以下のループを実装しています:
- 現在のエージェントから完了を取得
- ツール呼び出しを実行し、結果を追加
- 必要に応じてエージェントを切り替え
- 必要に応じてコンテキスト変数を更新
- 新しい関数呼び出しがなければ、返却
引数
引数 | 型 | 説明 | デフォルト |
---|---|---|---|
agent | Agent |
(初期の)呼び出されるエージェント。 | (必須) |
messages | List |
メッセージオブジェクトのリスト。Chat Completions messages と同一。 |
(必須) |
context_variables | dict |
関数とエージェントの指示で利用可能な追加のコンテキスト変数の辞書。 | {} |
max_turns | int |
許可される会話のターンの最大数。 | float("inf") |
model_override | str |
エージェントが使用するモデルをオーバーライドするためのオプションの文字列。 | None |
execute_tools | bool |
False の場合、エージェントが関数を呼び出そうとしたときに実行を中断し、即座にtool_calls メッセージを返します。 |
True |
stream | bool |
True の場合、ストリーミングレスポンスを有効にします。 |
False |
debug | bool |
True の場合、デバッグログを有効にします。 |
False |
client.run()
が終了すると(潜在的に複数のエージェントとツールの呼び出しの後)、関連するすべての更新された状態を含むResponse
を返します。具体的には、新しいmessages
、最後に呼び出されたAgent
、最新のcontext_variables
が含まれます。これらの値(および新しいユーザーメッセージ)を次のclient.run()
実行に渡すことで、中断したところから対話を継続できます - chat.completions.create()
と同様に。(run_demo_loop
関数は、/swarm/repl/repl.py
で完全な実行ループの例を実装しています。)
Response
フィールド
フィールド | 型 | 説明 |
---|---|---|
messages | List |
会話中に生成されたメッセージオブジェクトのリスト。Chat Completions messages と非常に似ていますが、メッセージの発信元のAgent を示すsender フィールドがあります。 |
agent | Agent |
メッセージを最後に処理したエージェント。 |
context_variables | dict |
入力変数と同じですが、変更がある場合はそれも含みます。 |
エージェント
Agent
は単に一連のinstructions
と一連のfunctions
(および以下の追加設定)をカプセル化し、実行を別のAgent
にハンドオフする能力を持っています。
Agent
を「Xを行う誰か」として擬人化したくなりますが、instructions
とfunctions
によって定義される非常に特定のワークフローまたはステップ(例:一連のステップ、複雑な検索、単一のデータ変換ステップなど)を表すこともできます。これにより、Agent
を「エージェント」、「ワークフロー」、「タスク」のネットワークに構成することができ、すべて同じプリミティブで表現されます。
Agent
フィールド
フィールド | 型 | 説明 | デフォルト |
---|---|---|---|
name | str |
エージェントの名前。 | "Agent" |
model | str |
エージェントが使用するモデル。 | "gpt-4o" |
instructions |
str または func() -> str
|
エージェントの指示。文字列または文字列を返す呼び出し可能オブジェクト。 | "You are a helpful agent." |
functions | List |
エージェントが呼び出せる関数のリスト。 | [] |
tool_choice | str |
エージェントのツール選択(ある場合)。 | None |
指示
Agent
のinstructions
は直接会話のsystem
プロンプトに変換されます(最初のメッセージとして)。アクティブなAgent
のinstructions
のみが常に存在します(例:Agent
のハンドオフがある場合、system
プロンプトは変更されますが、チャット履歴は変更されません)。
agent = Agent(
instructions="あなたは役立つエージェントです。"
)
instructions
は通常のstr
、またはstr
を返す関数のいずれかです。関数はオプションでcontext_variables
パラメータを受け取ることができ、これはclient.run()
に渡されたcontext_variables
によって埋められます。
def instructions(context_variables):
user_name = context_variables["user_name"]
return f"{user_name}さんの要望を何でも手伝ってください。"
agent = Agent(
instructions=instructions
)
response = client.run(
agent=agent,
messages=[{"role":"user", "content": "こんにちは!"}],
context_variables={"user_name":"太郎"}
)
print(response.messages[-1]["content"])
こんにちは、太郎さん!今日はどのようなお手伝いができますか?
関数
- Swarm
Agent
はPython関数を直接呼び出すことができます。 - 関数は通常
str
を返すべきです(値はstr
としてキャストされようとします)。 - 関数が
Agent
を返す場合、実行はそのAgent
に転送されます。 - 関数が
context_variables
パラメータを定義している場合、client.run()
に渡されたcontext_variables
によって埋められます。
def greet(context_variables, language):
user_name = context_variables["user_name"]
greeting = "こんにちは" if language.lower() == "japanese" else "Hello"
print(f"{greeting}, {user_name}さん!")
return "完了"
agent = Agent(
functions=[greet]
)
client.run(
agent=agent,
messages=[{"role": "user", "content": "greet()を日本語で使ってください。"}],
context_variables={"user_name": "太郎"}
)
こんにちは、太郎さん!
-
Agent
の関数呼び出しにエラーがある場合(関数の欠落、引数の誤り、エラー)、エラーレスポンスがチャットに追加され、Agent
が適切に回復できるようにします。 -
Agent
によって複数の関数が呼び出された場合、それらはその順序で実行されます。
ハンドオフとコンテキスト変数の更新
Agent
はfunction
で別のAgent
を返すことで、ハンドオフを行うことができます。
sales_agent = Agent(name="営業担当エージェント")
def transfer_to_sales():
return sales_agent
agent = Agent(functions=[transfer_to_sales])
response = client.run(agent, [{"role":"user", "content":"営業部門に転送してください。"}])
print(response.agent.name)
営業担当エージェント
また、より完全なResult
オブジェクトを返すことで、context_variables
を更新することもできます。これにはvalue
とagent
も含めることができ、単一の関数で値を返し、エージェントを更新し、コンテキスト変数を更新する(またはその3つの任意の組み合わせ)ことができます。
sales_agent = Agent(name="営業担当エージェント")
def talk_to_sales():
print("こんにちは、世界!")
return Result(
value="完了",
agent=sales_agent,
context_variables={"department": "sales"}
)
agent = Agent(functions=[talk_to_sales])
response = client.run(
agent=agent,
messages=[{"role": "user", "content": "営業部門に転送してください"}],
context_variables={"user_name": "太郎"}
)
print(response.agent.name)
print(response.context_variables)
営業担当エージェント
{'department': 'sales', 'user_name': '太郎'}
[!NOTE]
Agent
が複数の関数を呼び出してAgent
にハンドオフする場合、最後のハンドオフ関数のみが使用されます。
関数スキーマ
Swarmは自動的に関数をChat Completions tools
に渡されるJSONスキーマに変換します。
- ドキュメント文字列は関数の
description
になります。 - デフォルト値のないパラメータは
required
に設定されます。 - 型ヒントはパラメータの
type
にマッピングされます(デフォルトはstring
です)。 - パラメータごとの説明は明示的にサポートされていませんが、ドキュメント文字列に追加すれば同様に機能するはずです。(将来的にはドキュメント文字列の引数解析が追加される可能性があります。)
def greet(name, age: int, location: str = "東京"):
"""ユーザーに挨拶します。呼び出す前に必ず名前と年齢を取得してください。
Args:
name: ユーザーの名前。
age: ユーザーの年齢。
location: 最高の場所。
"""
print(f"こんにちは{name}さん、{location}で{age}歳とは素晴らしいですね!")
{
"type": "function",
"function": {
"name": "greet",
"description": "ユーザーに挨拶します。呼び出す前に必ず名前と年齢を取得してください。\n\nArgs:\n name: ユーザーの名前。\n age: ユーザーの年齢。\n location: 最高の場所。",
"parameters": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"location": {"type": "string"}
},
"required": ["name", "age"]
}
}
}
ストリーミング
stream = client.run(agent, messages, stream=True)
for chunk in stream:
print(chunk)
Chat Completions APIのストリーミングと同じイベントを使用します。例として/swarm/repl/repl.py
のprocess_and_print_streaming_response
をご覧ください。
2つの新しいイベントタイプが追加されています:
-
{"delim":"start"}
と{"delim":"start"}
は、Agent
が単一のメッセージ(レスポンスまたは関数呼び出し)を処理するたびに信号を送ります。これはAgent
間の切り替えを識別するのに役立ちます。 -
{"response": Response}
は、便宜上、ストリームの最後に集計された(完全な)レスポンスを含むResponse
オブジェクトを返します。
評価
評価は任意のプロジェクトにとって重要であり、開発者が自身のswarmのパフォーマンスをテストするための独自の評価スイートを持ってくることを推奨します。参考として、airline
、weather_agent
、triage_agent
のクイックスタート例にswarmを評価する方法のいくつかの例があります。詳細はそれぞれのREADMEをご覧ください。
ユーティリティ
run_demo_loop
を使用してswarmをテストしてください!これはコマンドラインでREPLを実行します。ストリーミングをサポートしています。
from swarm.repl import run_demo_loop
...
run_demo_loop(agent, stream=True)
主要な貢献者
- Ilan Bigio - ibigio
- James Hills - jhills20
- Shyamal Anadkat - shyamal-anadkat
- Charu Jaiswal - charuj
- Colin Jarvis - colin-openai
</antArtifact>
Discussion