はじめに
七尾百合子さん、お誕生日 85日目 おめでとうございます! nikkieです。
GoogleのADKを使っていて「ADKで実装したエージェントを配布できないのかな」という疑問がむくむくと頭をもたげてきました。
そこで実験してみました。
目次
- はじめに
- 目次
- Agent Development Kitはディレクトリで指定したエージェントをロードする
- 結論:adk api_serverに限れば、できる
- ADKで実装したエージェントをインストールし、adk api_server
- adk api_serverで立てたサーバに、site-packages下のエージェントを指定してリクエスト
- 終わりに
Agent Development Kitはディレクトリで指定したエージェントをロードする
ADKの実装を見ると、AgentLoaderにディレクトリを指定して、その中のエージェントの実装をロードします。
先日どんなディレクトリ構造に対応しているか調べました。
当ブログではADKでエージェントを実装する記事をいくつか書いてきました。
ADKが指定するディレクトリ構造でファイルを作る中で思ったのです。「開発者がサンプルコードを手元にコピペしてるけど、配布してこの状況を打開できるんじゃない?」
配布とはpip installでエージェントを(仮想環境のsite-packages下に)インストールして、それを動かすということです。
「このアイデアが成立するのでは」という勝算がありました。
AgentLoaderの実装で、importlib.import_module()を使っているのです。
https://github.com/google/adk-python/blob/v1.2.1/src/google/adk/cli/utils/agent_loader.py#L53
module_candidate = importlib.import_module(agent_name)
Sphinxの拡張はimportlib.import_module()でsite-packages下からロードされます1。
「ADKでも同様なのでは?」と、ADKで実装したエージェントをインストールして実験します。
結論:adk api_serverに限れば、できる
adk v1.2.1時点での話です。
読みなよ... 俺の記事の続きを...
ADKで実装したエージェントをインストールし、adk api_server
コマンドの選択について
adk api_serverとadk webはどちらもFastAPIアプリを起動します。
APIを直接呼べたほうが検証しやすいと考えて、adk api_serverを選びました。
adk runもAgentLoaderを使っているのですが、adk run third_party_agentとsite-packages下のエージェントは指定できません。
Error: Invalid value for 'AGENT': Directory 'third_party_agent' does not exist.
これはclick.Path(exists=True)2で存在するディレクトリに限っている3ためです。
AgentLoaderにsite-packages下のエージェントが渡らないんですね(プルリクチャンスかも)
ADKで実装したエージェントをインストール可能にする
こちらに用意しています。
https://github.com/ftnext/agent-practice/tree/afdcd43e19980df8b4040da5dd72ab33120c01d9/packaging/adk_stop_loop_agent
adk_stop_loop_agent/ ├── src/ │ └── adk_stop_loop_agent/ │ ├── __init__.py │ └── agent.py # root_agent を用意 └── pyproject.toml # インストールするために用意
過去に作ったループを抜けるエージェント4を選択しました。
環境変数の指定不要で動かせるので、まず試しやすいのです。
元の実装との区別のために、ループを抜けるまでのカウントを変えています。
(.venv) % pip install ../packaging/adk_stop_loop_agent
site-packagesの下にadk_stop_loop_agentが入りました。
(pip list | grep adk_stop_loop_agentでも確認できます)
importもできます!
>>> import adk_stop_loop_agent
adk api_serverで立てたサーバに、site-packages下のエージェントを指定してリクエスト
(.venv) % adk api_server
FastAPIなので、ドキュメントが http://127.0.0.1:8000/docs で見られます。
私はヘルスチェック代わりにアプリの一覧を取得します。
これはadk api_serverを起動したディレクトリにあるディレクトリ一覧です。
site-packages下のadk_stop_loop_agentは含まれません。
% curl http://127.0.0.1:8000/list-apps ["refine-loop","stop-loop"]
ここからの手順ですが
- Create Session (
POST /apps/{app_name}/users/{user_id}/sessions) adk_stop_loop_agentをRun (POST /run)
となります。
Create Session
% curl -X POST http://127.0.0.1:8000/apps/adk_stop_loop_agent/users/nikkie/sessions | jq .
{
"id": "085aef5e-908f-4c27-bb68-a1cdf12dbef5",
"appName": "adk_stop_loop_agent",
"userId": "nikkie",
"state": {},
"events": [],
"lastUpdateTime": 1749467551.046664
}
Run
1のレスポンスの.idを使って2のリクエストを組み立てて
{ "appName": "adk_stop_loop_agent", "userId": "nikkie", "sessionId": "085aef5e-908f-4c27-bb68-a1cdf12dbef5", "newMessage": { "parts": [ { "text": "こんにちは" } ], "role": "user" }, "streaming": false }
% curl -H 'Content-Type: application/json' -d@packaging/adk_stop_loop_agent/run_request.json http://127.0.0.1:8000/run | jq .
[
{
"content": {
"parts": [
{
"text": "Counter: 1"
}
],
"role": "model"
},
"invocationId": "e-102b7187-7776-4472-938c-0b82134bac61",
"author": "counter_agent",
"actions": {
"stateDelta": {},
"artifactDelta": {},
"requestedAuthConfigs": {}
},
"id": "NdRCMC7U",
"timestamp": 1749467751.870142
},
{
"content": {
"parts": [
{
"text": "Counter: 2"
}
],
"role": "model"
},
"invocationId": "e-102b7187-7776-4472-938c-0b82134bac61",
"author": "counter_agent",
"actions": {
"stateDelta": {},
"artifactDelta": {},
"requestedAuthConfigs": {}
},
"id": "644EcPgG",
"timestamp": 1749467751.870288
},
{
"content": {
"parts": [
{
"text": "Send STOP signal"
}
],
"role": "model"
},
"invocationId": "e-102b7187-7776-4472-938c-0b82134bac61",
"author": "counter_agent",
"actions": {
"stateDelta": {},
"artifactDelta": {},
"escalate": true,
"requestedAuthConfigs": {}
},
"id": "SovTGW8W",
"timestamp": 1749467751.870328
}
]
Counterが2で止まりました!
site-packages下にインストールしたADK実装のエージェントを、動かせています🙌
終わりに
ADKで実装したエージェントをsite-packages下にインストールし、それをadk api_serverで動かせるか実験しました。
エージェントをロードするAgentLoaderがimportlib.import_module()を使っているため、site-packages下のエージェントもロードできます!
adk api_serverはadk runやadk web(後述)と比べてエージェント指定の検証ロジックが緩いため、site-packages下のエージェントを指定してリクエストを送ることができました。
公式ドキュメントには今のところ記載がないですし、関係するissueやdiscussionは未調査ですが、ひとまず私はadk api_serverで使い倒そうと思っています。
PyPIに置いていくぞ〜
ちなみに、adk webも同様のFastAPIアプリケーションなので同じように動くかと期待しましたが、 http://127.0.0.1:8000/dev-ui/?app=adk_stop_loop_agent というURLをブラウザに直接入力したところ
Agent 'adk_stop_loop_agent' not found
と表示されて進めませんでした。
- 恥ずかしい話が、ここで活きたぞ! ↩
- https://github.com/google/adk-python/blob/v1.2.1/src/google/adk/cli/cli_tools_click.py#L226-L231↩
-
「The
existsargument will verify whether the path exists.」https://click.palletsprojects.com/en/stable/handling-files/#file-path-arguments↩ - ↩