LLamaIndexの新しいマルチエージェント用フレームワーク「llama-agents」を試す。
llama-agents のアルファ版リリースを発表できることを嬉しく思う。この新しいオープンソースフレームワークは、マルチエージェントAIシステムの構築、反復、デプロイのプロセスを簡素化し、エージェントをプロダクションマイクロサービスにするために設計されている。複雑な質問応答システム、コラボレーションAIアシスタント、分散AIワークフローなど、llama-agentsはあなたのアイデアを実現するために必要なツールと構造を提供する。
llama-agentsの主な特徴
- 分散サービス指向アーキテクチャ: LlamaIndex の各エージェントは、タスクのルーティングと分散を行う、完全にカスタマイズ可能な LLM を搭載したコントロールプレーンによってオーケストレーションされた、独立して動作するマイクロサービスであることができる。
- 標準化されたAPIインターフェイスによるコミュニケーション: 中央のコントロールプレーンオーケストレータを使ってエージェント間のインターフェイスを行う。メッセージキューを使ってエージェント間でメッセージを受け渡す。
- エージェントフローと明示的オーケストレーションフローの定義: 開発者は、エージェント間のインタラクションシーケンスを直接定義することも、タスクに関連するエージェントを決定する "エージェントオーケストレータ "に任せることもできる。
- デプロイの容易さ: 各エージェントとコントロールプレーンを独立して起動、スケール、監視できる。
- スケーラビリティとリソース管理: 組み込みの観測可能性ツールを使用して、システムと個々のエージェントサービスの品質とパフォーマンスを監視する。
新しいレポジトリが出来てる
llama-agents
は、マルチエージェントコミュニケーション、分散ツール実行、ヒューマン・イン・ザ・ループなどを含むマルチエージェントシステムを構築、反復、プロダクションするための非同期ファーストフレームワークである!
llama-agents
では、各エージェントはサービスであり、入ってくるタスクを無限に処理する。各エージェントはメッセージキューからメッセージを取り出し、公開する。
llama-agents
システムの最上位にあるのはコントロールプレーンだ。コントロール・プレーンは、進行中のタスクや、どのサービスがネットワークにあるかを追跡し、オーケストレーターを使って、どのサービスがタスクの次のステップを処理すべきかを決定する。システム全体のレイアウトは下図のようになっている。
refer from https://github.com/run-llama/llama-agents
Getting Started
ブログの記事やGitHubのGetting Startedを参考に進めてみる。まずはColaboratoryで。
事前準備
パッケージインストール。ドキュメントでは、llama-agentsという新しいパッケージと、OpenAI向けのエージェントパッケージである llama-index-agent-openai だけが記載されていたが、OpenAI向けの Embeddingモデルパッケージである llama-index-embeddings-openai も最終的には必要だった。
!pip install llama-agents llama-index-agent-openai llama-index-embeddings-openai
!pip freeze | egrep "llama-"
llama-agents==0.0.3.post1
llama-cloud==0.0.6
llama-index-agent-openai==0.2.7
llama-index-core==0.10.51
llama-index-embeddings-openai==0.1.10
llama-index-llms-openai==0.1.24
OpenAI APIキーをセット。
from google.colab import userdata
import os
os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY')
notebookなのでイベントループのネストを有効化。
import nest_asyncio
nest_asyncio.apply()
エージェントの作成
まずは普通にエージェントを作成する。ここでは2つのエージェントを作成して、片方には関数のツールを与えておく。なお、日本語の場合なのかもしれないけど、gpt-3.5-turboだと後々でうまく行かなかったので、gpt-4oにしている。
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai import OpenAI
def get_the_secret_trivia() -> str:
"""秘密のトリビアを返す"""
return "秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。"
tool = FunctionTool.from_defaults(fn=get_the_secret_trivia)
llm = OpenAI(model="gpt-4o")
agent1 = ReActAgent.from_tools([tool], llm=llm, verbose=True)
agent2 = ReActAgent.from_tools([], llm=llm, verbose=True)
それぞれを単体で動かしてみる。1つ目のエージェント。こちらはツールが渡されている。
response = agent1.chat("秘密のトリビアを1つ教えて。")
print(response)
verbose
の出力
Thought: The current language of the user is: Japanese. I need to use a tool to help me answer the question.
Action: get_the_secret_trivia
Action Input: {}
Observation: 秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
Thought: I can answer without using any more tools. I'll use the user's language to answer.
Answer: 秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
回答
秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
もう1つのエージェント。こちらはツールを持たない。
response = agent2.chat("秘密のトリビアを1つ教えて。")
print(response)
verbose
の出力
Thought: The current language of the user is Japanese. I need to provide an interesting trivia fact.
Answer: では、1つ秘密のトリビアを教えますね。実は、ハチは地球上で唯一、四角形の瞳を持つ生物です。彼らの瞳は六角形のハニカム構造をしており、これが彼らの視覚を非常に鋭くしています。
回答
では、1つ秘密のトリビアを教えますね。実は、ハチは地球上で唯一、四角形の瞳を持つ生物です。彼らの瞳は六角形のハニカム構造をしており、これが彼らの視覚を非常に鋭くしています。
llama-agentsのコンポーネント
ではllama-agentsを使ってエージェントシステムを定義する。llama-agentsでは以下のコンポーネントで全体システムを構成する。
- メッセージキュー
- メッセージキューは、全てのサービスと コントロールプレーンのキューとして動作する。名前付きキューにメソッドを発行するためのメソッドを持ち、 メッセージをコンシューマに委譲する。
- コントロールプレーン
- コントロールプレーンは llama-agents システムの中央ゲートウェイである。現在のタスクや、システムに登録されているサービスを追跡する。また、オーケストレータも保持する。
- オーケストレータ
- このモジュールは入ってくるタスクを処理し、どのサービスに送るか、またサービスからの結果をどう扱うかを決める。オーケストレーターは、エージェント型(LLMが決定を行う)、明示型(クエリパイプラインがフローを定義する)、両方のミックス、または完全にカスタムなものがある。
- サービス
- サービスは実際の作業が行われる場所である。サービスは、入ってくるタスクとコンテキストを受け入れ、それを処理し、結果を公表する。
- ツールサービスは、エージェントツールの実行をオフロードするための特別なサービスである。エージェントは、ツールサービスを呼び出すメタツールを装備することができる。
- 各コンポーネントはメッセージキューを介してやりとりをする。
- コントロールプレーンは、ユーザとのインタフェースであると同時に、タスクやサービス、オーケストレータを内包する。
- コントロールプレーンに内包されたオーケストレータが、タスクの(おそらく)分解や、サービスへのルーティング、を判断する。
- 今回はgpt-4oがそれを行う。
- サービスは実際にタスクを処理する。
- 上で作成したエージェントがこれに該当する。
ではこれらを定義する。
import logging
from llama_agents import (
AgentService,
AgentOrchestrator,
ControlPlaneServer,
SimpleMessageQueue,
)
# ロギングを有効化して、システムが機能していることを確認する。
logging.getLogger("llama_agents").setLevel(logging.INFO)
# メッセージキューの定義
message_queue = SimpleMessageQueue(port=8000)
# コントロールプレーンの定義
control_plane = ControlPlaneServer(
message_queue=message_queue,
# オーレストレータはLLM(gpt-4o)を使う
orchestrator=AgentOrchestrator(llm=OpenAI(model="gpt-4o")),
port=8001,
)
# agent1を使ったエージェントサービスの定義
agent_server_1 = AgentService(
agent=agent1,
message_queue=message_queue,
description="秘密のトリビアを取得するのに便利。",
service_name="secret_trivia_agent",
port=8002,
)
# agent2を使ったエージェントサービスの定義
agent_server_2 = AgentService(
agent=agent2,
message_queue=message_queue,
description="ランダムでバカバカしいトリビアを取得するのに便利",
service_name="dumb_trivia_agent",
port=8003,
)
これらのサービスを起動する。サービスはサーバ・クライアント型でも起動できるが、ここではすべてローカルで簡潔できるLocalLauncher
を使う。
from llama_agents import LocalLauncher
launcher = LocalLauncher(
[agent_server_1, agent_server_2],
control_plane,
message_queue,
)
result = launcher.launch_single("秘密のトリビアを教えて。")
print(f"Result: {result}")
ログやverboseの出力は以下
INFO:llama_agents.message_queues.simple - Consumer AgentService-271ac375-eebc-4c41-87ca-2be4d0ed4b1c: secret_trivia_agent has been registered.
INFO:llama_agents.message_queues.simple - Consumer AgentService-5d61388d-14e2-4a56-8ce3-e997534f4c05: dumb_trivia_agent has been registered.
INFO:llama_agents.message_queues.simple - Consumer b627284e-4523-4fb3-9bae-b01a554f194b: human has been registered.
INFO:llama_agents.message_queues.simple - Consumer ControlPlaneServer-8208b9ef-2241-404e-a956-03b6e2b0064e: control_plane has been registered.
INFO:llama_agents.services.agent - secret_trivia_agent launch_local
INFO:llama_agents.services.agent - dumb_trivia_agent launch_local
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'new_task'
INFO:llama_agents.message_queues.simple - Launching message queue locally
INFO:llama_agents.message_queues.base - Publishing message to 'secret_trivia_agent' with action 'new_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'secret_trivia_agent' to consumer.
Thought: The current language of the user is: Japanese. I need to use a tool to help me answer the question.
Action: get_the_secret_trivia
Action Input: {}
Observation: 秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'completed_task'
Thought: I can answer without using any more tools. I'll use the user's language to answer.
Answer: 秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
INFO:llama_agents.message_queues.base - Publishing message to 'human' with action 'completed_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'human' to consumer.
レスポンス
Result: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
コントロールプレーンと1つ目のエージェントでやりとりが行われて回答が生成されているのがわかる。
もう一つ。別のクエリを投げてみる。
result = launcher.launch_single("バカバカしいトリビアを教えて。")
print(f"Result: {result}")
INFO:llama_agents.message_queues.simple - Consumer AgentService-271ac375-eebc-4c41-87ca-2be4d0ed4b1c: secret_trivia_agent has been registered.
INFO:llama_agents.message_queues.simple - Consumer AgentService-5d61388d-14e2-4a56-8ce3-e997534f4c05: dumb_trivia_agent has been registered.
INFO:llama_agents.message_queues.simple - Consumer 1c2930cb-63d9-47d1-9276-8e720fe3bd13: human has been registered.
INFO:llama_agents.message_queues.simple - Consumer ControlPlaneServer-8208b9ef-2241-404e-a956-03b6e2b0064e: control_plane has been registered.
INFO:llama_agents.services.agent - secret_trivia_agent launch_local
INFO:llama_agents.services.agent - dumb_trivia_agent launch_local
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'new_task'
INFO:llama_agents.message_queues.simple - Launching message queue locally
INFO:llama_agents.message_queues.base - Publishing message to 'dumb_trivia_agent' with action 'new_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'dumb_trivia_agent' to consumer.
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'completed_task'
Thought: (Implicit) I can answer without any more tools!
Answer: 了解しました。では、バカバカしいトリビアを1つご紹介します。
カモノハシは、卵を産む哺乳類であるだけでなく、毒を持つ唯一の哺乳類でもあります。オスのカモノハシは後ろ足に毒針を持っており、これで敵を攻撃することができます。
INFO:llama_agents.message_queues.base - Publishing message to 'dumb_trivia_agent' with action 'new_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'dumb_trivia_agent' to consumer.
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'completed_task'
Thought: (Implicit) I can answer without any more tools!
Answer: 了解しました。では、さらにバカバカしいトリビアを1つご紹介します。
アヒルの鳴き声は「ガーガー」と聞こえますが、実はその鳴き声にはエコーがありません。科学者たちはこの現象を解明しようとしましたが、未だに完全には解明されていません。
INFO:llama_agents.message_queues.base - Publishing message to 'dumb_trivia_agent' with action 'new_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'dumb_trivia_agent' to consumer.
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'completed_task'
Thought: (Implicit) I can answer without any more tools!
Answer: わかりました。では、さらにバカバカしいトリビアをお伝えします。
バナナは実はベリーの一種ですが、イチゴはベリーではありません。植物学的には、バナナは「真のベリー」として分類される一方で、イチゴは「偽果」として分類されます。
INFO:llama_agents.message_queues.base - Publishing message to 'dumb_trivia_agent' with action 'new_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'dumb_trivia_agent' to consumer.
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'completed_task'
Thought: (Implicit) I can answer without any more tools!
Answer: 了解しました。さらにバカバカしいトリビアをお伝えします。
カタツムリには約14,000本の歯があります。これらの歯は非常に小さく、ラドゥラと呼ばれる舌のような器官に並んでいます。カタツムリはこのラドゥラを使って食べ物を削り取ります。
INFO:llama_agents.message_queues.base - Publishing message to 'dumb_trivia_agent' with action 'new_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'dumb_trivia_agent' to consumer.
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'completed_task'
Thought: (Implicit) I can answer without any more tools!
Answer: わかりました。さらにバカバカしいトリビアをお伝えします。
アリクイは、1日に最大35,000匹のアリやシロアリを食べることができますが、歯が全くありません。彼らは長い舌を使ってアリやシロアリを捕まえ、強力な胃酸でそれらを消化します。
INFO:llama_agents.message_queues.base - Publishing message to 'dumb_trivia_agent' with action 'new_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'dumb_trivia_agent' to consumer.
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'completed_task'
Thought: (Implicit) I can answer without any more tools!
Answer: 了解しました。さらにバカバカしいトリビアをお伝えします。
ヒトの鼻は、一生の間に約5,000万リットルの空気を吸い込むと言われています。これは、オリンピックサイズのプール約20杯分に相当します。
INFO:llama_agents.message_queues.base - Publishing message to 'human' with action 'completed_task'
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
INFO:llama_agents.message_queues.simple - Successfully published message 'human' to consumer.
Result: 以下にバカバカしいトリビアをまとめてお伝えします。
1. カモノハシは卵を産む哺乳類であり、オスは後ろ足に毒針を持っています。
2. アヒルの鳴き声にはエコーがありません。
3. バナナはベリーの一種ですが、イチゴはベリーではありません。
4. カタツムリには約14,000本の歯があります。
5. アリクイは歯が全くなく、1日に最大35,000匹のアリやシロアリを食べます。
6. ヒトの鼻は一生の間に約5,000万リットルの空気を吸い込みます。
特に「1つ」と指定しなかったためか、コントロールプレーンと2つ目のエージェントサービスの間で複数回のやりとりがされて、最終回答が生成されているのがわかる。
このように、コントロールプレーン+オーケストレータがタスクの管理を行い、各エージェントはそれぞれが独立したマイクロサービスとして処理を行う、という仕組みを構成してくれるのがllama-agentsということらしい。
上に少し記載しているが、llama-agentsはサーバ・クライアント型での実装も可能。
ここからはローカルのUbuntuサーバ上で構築してみる。作業ディレクトリを作成し、仮想環境を作成しておくこと。
パッケージインストール。OpenAI APIキーは.envで読み込ませるので、python-dotenvもインストールしておく。
$ pip install pip install llama-agents llama-index-agent-openai llama-index-embeddings-openai python-dotenv
.envの作成
OPENAI_API_KEY=XXXXXXXXXXXXXX
サーバ用スクリプトを作成
import logging
from dotenv import load_dotenv
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai import OpenAI
from llama_agents import (
AgentService,
AgentOrchestrator,
ControlPlaneServer,
SimpleMessageQueue,
)
from llama_agents import ServerLauncher, CallableMessageConsumer
logging.getLogger("llama_agents").setLevel(logging.INFO)
load_dotenv(verbose=True)
# エージェントの定義
def get_the_secret_trivia() -> str:
"""秘密のトリビアを返す"""
return "秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。"
tool = FunctionTool.from_defaults(fn=get_the_secret_trivia)
llm = OpenAI(model="gpt-4o")
agent1 = ReActAgent.from_tools([tool], llm=llm, verbose=True)
agent2 = ReActAgent.from_tools([], llm=llm, verbose=True)
message_queue = SimpleMessageQueue(
host="localhost",
port=8000,
)
queue_client = message_queue.client
control_plane = ControlPlaneServer(
message_queue=queue_client,
orchestrator=AgentOrchestrator(llm=OpenAI(model="gpt-4o")),
host="localhost",
port=8001,
)
agent_server_1 = AgentService(
agent=agent1,
message_queue=message_queue,
description="秘密のトリビアを取得するのに便利。",
service_name="secret_trivia_agent",
host="localhost",
port=8002,
)
agent_server_2 = AgentService(
agent=agent2,
message_queue=message_queue,
description="ランダムでバカバカしいトリビアを取得するのに便利",
service_name="dumb_trivia_agent",
host="localhost",
port=8003,
)
#-----
# サーバ向け
#-----
# デフォルトでは、全てのタスク結果は特定の "human "キューにパブリッシュされるため
# この結果を受け取って処理するためのコンシューマーも定義
# (将来的には、この最終キューは設定可能になる予定らしい)
def handle_result(message) -> None:
print(f"Got result:", message.data)
human_consumer = CallableMessageConsumer(
handler=handle_result, message_type="human"
)
# サーバモードでは`ServerLauncher`を使う
launcher = ServerLauncher(
[agent_server_1, agent_server_2],
control_plane,
message_queue,
additional_consumers=[human_consumer],
)
# 起動
launcher.launch_servers()
ではサーバを起動
$ python server.py
メッセージキュー、コントロールプレーン、エージェントサービスx2がそれぞれ別プロセスで起動しているのがわかる。
INFO:llama_agents.message_queues.simple - Launching message queue server at localhost:8000
INFO: Started server process [1163206]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)
INFO:llama_agents.control_plane.server - Launching control plane server at localhost:8001
INFO: Started server process [1163206]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://localhost:8001 (Press CTRL+C to quit)
INFO:llama_agents.message_queues.simple - Consumer ControlPlaneServer-35533c61-bd3a-41ba-af7e-2017d9b6523c: control_plane has been registered.
INFO: 127.0.0.1:55348 - "POST /register_consumer HTTP/1.1" 200 OK
INFO:llama_agents.message_queues.simple - Consumer AgentService-a343b7c2-2bd6-4a0e-b3e4-e83fd92b50d3: secret_trivia_agent has been registered.
INFO:llama_agents.services.agent - Launching secret_trivia_agent server at localhost:8002
INFO: Started server process [1163206]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://localhost:8002 (Press CTRL+C to quit)
INFO: 127.0.0.1:39006 - "POST /services/register HTTP/1.1" 200 OK
INFO:llama_agents.message_queues.simple - Consumer AgentService-fcea80b0-c272-4ee6-a9bd-e17a18f3b942: dumb_trivia_agent has been registered.
INFO:llama_agents.services.agent - Launching dumb_trivia_agent server at localhost:8003
INFO: Started server process [1163206]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://localhost:8003 (Press CTRL+C to quit)
INFO: 127.0.0.1:39018 - "POST /services/register HTTP/1.1" 200 OK
INFO:llama_agents.message_queues.simple - Consumer 043057ab-6a20-43b3-bfec-cd25eb4a6e64: human has been registered.
$ lsof -i:8000,8001,8002,8003
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 1158364 kun432 6u IPv4 1887228 0t0 TCP localhost:8000 (LISTEN)
python 1158364 kun432 7u IPv4 1881049 0t0 TCP localhost:8001 (LISTEN)
python 1158364 kun432 10u IPv6 1881056 0t0 TCP *:8002 (LISTEN)
python 1158364 kun432 11u IPv4 1881057 0t0 TCP *:8002 (LISTEN)
python 1158364 kun432 12u IPv6 1881061 0t0 TCP *:8003 (LISTEN)
python 1158364 kun432 13u IPv4 1881062 0t0 TCP *:8003 (LISTEN)
このサーバに接続するクライアント側のコードは以下。
from llama_agents import LlamaAgentsClient, AsyncLlamaAgentsClient
import time
client = LlamaAgentsClient("http://localhost:8001")
# タスクの作成
task_id = client.create_task("秘密のトリビアを教えて")
time.sleep(10)
# get_task_resultで、タスクが完了していればTaskResult、完了していない場合はNoneを返す、、、、
# とドキュメントにあるが、完了していない場合にget_task_resultを実行すると現時点ではType Errorになる・・・
# メソッド調べてみたけど、タスクの状態を取得するようなものが見つからなかったので一旦sleepで。
response = client.get_task_result(task_id)
print(response.result)
実行してみる。
$ python client.py
秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
コンソールの出力を見ると処理の流れがわかる。
INFO:llama_agents.message_queues.base - Publishing message to 'secret_trivia_agent' with action 'ActionTypes.NEW_TASK'
INFO: 127.0.0.1:47988 - "POST /publish HTTP/1.1" 200 OK
INFO: 127.0.0.1:39550 - "POST /tasks HTTP/1.1" 200 OK
INFO: 127.0.0.1:60366 - "POST /process_message HTTP/1.1" 200 OK
INFO:llama_agents.message_queues.simple - Successfully published message 'secret_trivia_agent' to consumer.
Thought: The current language of the user is: Japanese. I need to use a tool to help me answer the question.
Action: get_the_secret_trivia
Action Input: {}
Observation: 秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
Thought: I can answer without using any more tools. I'll use the user's language to answer.
Answer: 秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。
INFO:llama_agents.message_queues.base - Publishing message to 'control_plane' with action 'ActionTypes.COMPLETED_TASK'
INFO:llama_agents.message_queues.base - Publishing message to 'human' with action 'ActionTypes.COMPLETED_TASK'
INFO: 127.0.0.1:48766 - "POST /publish HTTP/1.1" 200 OK
INFO: 127.0.0.1:43144 - "POST /process_message HTTP/1.1" 200 OK
INFO:llama_agents.message_queues.simple - Successfully published message 'control_plane' to consumer.
Got result: {'task_id': 'c68a41d4-9d48-4f2c-b215-303894ff8532', 'history': [{'role': 'user', 'content': '秘密のトリビアを教えて', 'additional_kwargs': {}}, {'role': 'assistant', 'content': '秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。', 'additional_kwargs': {}}, {'role': 'user', 'content': "Pick the next action to take. Invoke the 'finalize' tool with your full final answer if the answer to the original input is in the chat history. As a reminder, the original input was: 秘密のトリビアを教えて", 'additional_kwargs': {}}], 'result': '秘密のトリビア: 競馬のレースで、公正な発馬が出来なかった場合にスタートをやり直すことを、「カンパイ」と言います。'}
INFO:llama_agents.message_queues.simple - Successfully published message 'human' to consumer.
INFO: 127.0.0.1:43150 - "GET /tasks/c68a41d4-9d48-4f2c-b215-303894ff8532 HTTP/1.1" 200 OK
また、CLIが用意されていて、上記は以下でも確認できる。ポートはコントロールプレーンのポートを指定する。
$ llama-agents monitor --control-plane-url http://localhost:8001
TUIでこんな感じの画面が開く。左上にサービス、左下に実行済(?)のタスクのIDが表示される。
サービスを選択すると、そのサービスの設定や、そのサービスが実行したタスクが表示される。
タスクIDを選択すると、タスクでの会話履歴や結果等が表示される。
この画面からタスクを投げることもできる。一番下に入力する。
新しいタスクIDが表示されるのでそれを選択すると結果が表示される。
もっと低レベルなAPIでアクセスしたい場合は以下
その他、いくつかのサンプルも用意されている。DockerやKubernetesで各コンポーネントごとに分ける例もあるみたい。
まとめ
あくまで個人の所感。
最初は、AutoGenやcrewAIのような、プログラミング的にマルチエージェントコンポーネントを作成するようなフレームワークかなぁと思っていたけど、自分の感覚的には、それにプラスして、マルチエージェントシステムをdocker-composeとかK8Sとかっぽい感じでプログラマブルに構成する、というような、インフラ風味が強いフレームワークという印象を持った。
比較するならば、LangGraphとかAutoGenとかcrewAIとかみたいなフレームワークよりも、発想的にはAgentSeaあたりのほうが近いのかも、という気がする。
出たばっかりのものを少し触っただけなので、もう少しいじってみたら印象がかわるかもしれない。
引き続きLlamaIndexのエージェント実装と、llama-agentsのサンプルを追っかけてみたい(LlamaIndexのエージェント、あんまり触ってないし)
llama-deployというものがリリースされたが、どうやらllama-agentsが改名されたものらしい。
llama-agentsでは、LlamaIndexのエージェントモジュール(ReActAgentとか)で各エージェントサービスを定義していたが、llama-deployではこれをworkflowsで定義するようになっている。
エージェントモジュールのところをworkflowsで書けるになったのが大きいという印象なので、llama-deployの基本的な考え方は、llama-agentsと大きくは変わっていないように思える。