はじめに
前回、Amazon Bedrock AgentCore の全体像と ① Rutime 編について書きました。
今回は、② Code Interpreter ③ Browser 編について動かしながら記載していきたいと思います。
② Code Interpreter
Code Interpreter は、AI エージェントがコードを安全に実行するためのサンドボックス環境をフルマネージドで提供するよというサービスです。
そもそも、Code Interpreter とは?
エージェントがタスク遂行のために必要なプログラム処理を、エージェント自ら考えてコードを作成して、実行するものです。
Amazon Bedrock のエージェントにも、Code Interpreter 機能がありますのでそちらを触れてみていただくのも良いかもしれません。
https://dev.classmethod.jp/articles/agents-for-amazon-bedrock-code-interpreter-preview/
AWS ドキュメントのサンプルを参考に進めていきます。
特徴
- Python、JavaScript、TypeScript などの複数のプログラミング言語をサポート
- デフォルトで 15 分の実行時間をサポートし、最大 8 時間まで延長可能
- インラインアップロードでは最大 100 MB のファイルをサポートし、ターミナルコマンド経由で Amazon S3にアップロードする場合は 5 GB まで対応可能
bedrock-agentcore と strands-agentsのインストール
AgentCore SDK を利用するため、pip でインストールしておきます。
pip install bedrock-agentcore
後で、strands-agents も利用するため、pip でインストールしておきます。
pip install strands-agents
サンプルコードの準備
my_bedrock_agentcore_code_interpreter.py
# Code Interpreter をインポート
from bedrock_agentcore.tools.code_interpreter_client import CodeInterpreter
import json
# Code Interpreter のインスタンスを作成とセッションの開始
code_client = CodeInterpreter('us-west-2')
code_client.start()
# Hello World の実行
response = code_client.invoke("executeCode", {
"language": "python",
"code": 'print("Hello World!!!")'
})
# レスポンスの処理と出力
for event in response["stream"]:
print(json.dumps(event["result"], indent=2))
# Code Interpreter の停止
code_client.stop()
サンプルコードの実行と確認
作成したコードを実行します。
python3 my_bedrock_agentcore_code_interpreter.py
AWS マネージメントコンソール上から確認してみると呼び出された Code Interpreter セッションが以下に表示されていたことが確認できました。
エージェントからコードを実行してみる
my_bedrock_agentcore_code_interpreter.py
from strands import Agent, tool
# Code Interpreter クライアントをインポート
from bedrock_agentcore.tools.code_interpreter_client import code_session
import asyncio
import json
SYSTEM_PROMPT = """あなたはコード実行によってすべての回答を検証する有益なAIアシスタントです。
検証原則:
1. コード、アルゴリズム、または計算について主張する際は、それらを検証するコードを書く
2. execute_pythonを使用して数学的計算、アルゴリズム、ロジックをテストする
3. 答えを提供する前に理解を検証するテストスクリプトを作成する
4. 実際のコード実行で常に作業内容を示す
5. 不確実な場合は、明示的に制限を述べ、可能な範囲で検証する
アプローチ:
- プログラミング概念について質問された場合、実装してデモンストレーションする
- 計算について質問された場合、プログラムで計算しコードも表示する
- アルゴリズムを実装する場合、正確性を証明するテストケースを含める
- 透明性のために検証プロセスを文書化する
- 実行間で状態が維持されるため、以前の結果を参照できる
利用可能なツール:
- execute_python: Pythonコードを実行して出力を確認
応答形式: execute_pythonツールは以下を含むJSON応答を返します:
- sessionId: コードインタープリターセッションID
- id: リクエストID
- isError: エラーがあったかどうかを示すブール値
- content: typeとtext/dataを持つコンテンツオブジェクトの配列
- structuredContent: コード実行の場合、stdout、stderr、exitCode、executionTimeを含む
成功したコード実行の場合、出力はcontent[0].textおよびstructuredContent.stdoutにあります。
エラーがあったかどうかはisErrorフィールドを確認してください。
可能な限り徹底的で正確な検証を行ってください。"""
# Code Interpreter を使用して Python コードを実行するツール
@tool
def execute_python(code: str, description: str = "") -> str:
"""
Code Interpreter を使用して Python コードを実行
Args:
code (str): 実行する Python コード
description (str): コードの説明(オプション)
Returns:
str: 実行結果のJSON文字列
"""
if description:
code = f"# {description}\n{code}"
print(f"\n Code: {code}")
# Code Interpreter のセッションの開始
with code_session("us-west-2") as code_client:
# コードを実行
response = code_client.invoke("executeCode", {
"code": code,
"language": "python",
"clearContext": False
})
for event in response["stream"]:
return json.dumps(event["result"])
# ツールを含む strands エージェントを設定
agent = Agent(
tools=[execute_python],
system_prompt=SYSTEM_PROMPT,
callback_handler=None
)
query = "太陽系の全ての惑星は地球と月の間に収まりますか?"
# エージェントを非同期で呼び出し、レスポンスをストリームで受信
async def main():
response_text = ""
async for event in agent.stream_async(query):
if "data" in event:
chunk = event["data"]
response_text += chunk
print(chunk, end="")
asyncio.run(main())
このプログラムは、「太陽系の全ての惑星は地球と月の間に収まりますか?」という不思議な質問ですがこれに対して、実際に Python コードを実行して科学的に検証し、答えを提供する AI アシスタントです。
エージェントの実行と確認
作成したコードを実行します。
python3 my_bedrock_agentcore_code_interpreter.py
実行結果は以下の通りですが、エージェントが動いたことだけを確認できれば良いので内容は読み飛ばしても良いです。
エージェントの実行結果
興味深い質問ですね!これを検証するために、太陽系の惑星の直径と地球と月の間の距離を比較してみましょう。
Code: # 太陽系の惑星の直径合計と地球月間距離を比較
# 太陽系の惑星の直径(km)
planets = {
'水星': 4879,
'金星': 12104,
'地球': 12756,
'火星': 6792,
'木星': 142984,
'土星': 120536,
'天王星': 51118,
'海王星': 49528
}
# 地球と月の間の距離
earth_moon_distance = 384400 # km
print("太陽系の惑星の直径:")
total_diameter = 0
for planet, diameter in planets.items():
print(f"{planet}: {diameter:,} km")
total_diameter += diameter
print(f"\n全惑星の直径の合計: {total_diameter:,} km")
print(f"地球と月の間の距離: {earth_moon_distance:,} km")
print(f"\n比較結果:")
print(f"全惑星の直径の合計 ÷ 地球月間距離 = {total_diameter / earth_moon_distance:.2f}")
if total_diameter < earth_moon_distance:
print("✅ はい、太陽系の全ての惑星は地球と月の間に収まります!")
余裕 = earth_moon_distance - total_diameter
print(f"余裕: {余裕:,} km")
else:
print("❌ いいえ、太陽系の全ての惑星は地球と月の間に収まりません。")
不足 = total_diameter - earth_moon_distance
print(f"不足: {不足:,} km")
結果をもう少し詳しく分析してみましょう:
Code: # 詳細な分析と視覚化
import matplotlib.pyplot as plt
import numpy as np
# より詳細な分析
print("詳細分析:")
print(f"地球と月の間の距離: {earth_moon_distance:,} km")
print(f"全惑星の直径合計: {total_diameter:,} km")
print(f"差異: {total_diameter - earth_moon_distance:+,} km")
print(f"パーセンテージ: {(total_diameter / earth_moon_distance - 1) * 100:.1f}% 超過")
print("\n各惑星の直径が全体に占める割合:")
for planet, diameter in planets.items():
percentage = (diameter / total_diameter) * 100
print(f"{planet}: {percentage:.1f}%")
# 木星と土星だけでどうなるか
jupiter_saturn = planets['木星'] + planets['土星']
print(f"\n木星と土星だけの場合:")
print(f"木星 + 土星の直径: {jupiter_saturn:,} km")
print(f"地球月間距離との比較: {jupiter_saturn / earth_moon_distance:.2f}")
if jupiter_saturn < earth_moon_distance:
print("✅ 木星と土星だけなら収まります")
else:
print("❌ 木星と土星だけでも収まりません")
# 視覚的な比較
fig, ax = plt.subplots(figsize=(12, 6))
# 棒グラフで比較
categories = ['地球月間距離', '全惑星直径合計']
values = [earth_moon_distance, total_diameter]
colors = ['blue', 'red']
bars = ax.bar(categories, values, color=colors, alpha=0.7)
ax.set_ylabel('距離 (km)')
ax.set_title('地球月間距離 vs 太陽系全惑星の直径合計')
# 値をバーの上に表示
for bar, value in zip(bars, values):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5000,
f'{value:,} km', ha='center', va='bottom')
plt.tight_layout()
plt.show()
# 惑星の直径の比較
fig, ax = plt.subplots(figsize=(12, 8))
planet_names = list(planets.keys())
planet_diameters = list(planets.values())
bars = ax.bar(planet_names, planet_diameters, color='skyblue', alpha=0.7)
ax.axhline(y=earth_moon_distance, color='red', linestyle='--',
label=f'地球月間距離 ({earth_moon_distance:,} km)')
ax.set_ylabel('直径 (km)')
ax.set_title('太陽系の惑星の直径比較')
ax.legend()
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
変数を再定義して詳細分析を実行します:
Code: # 詳細分析(変数再定義込み)
# 変数を再定義
planets = {
'水星': 4879,
'金星': 12104,
'地球': 12756,
'火星': 6792,
'木星': 142984,
'土星': 120536,
'天王星': 51118,
'海王星': 49528
}
earth_moon_distance = 384400 # km
total_diameter = sum(planets.values())
print("詳細分析:")
print(f"地球と月の間の距離: {earth_moon_distance:,} km")
print(f"全惑星の直径合計: {total_diameter:,} km")
print(f"差異: {total_diameter - earth_moon_distance:+,} km")
print(f"パーセンテージ: {(total_diameter / earth_moon_distance - 1) * 100:.1f}% 超過")
print("\n各惑星の直径が全体に占める割合:")
for planet, diameter in planets.items():
percentage = (diameter / total_diameter) * 100
print(f"{planet}: {diameter:,} km ({percentage:.1f}%)")
# 木星と土星だけでどうなるか
jupiter_saturn = planets['木星'] + planets['土星']
print(f"\n木星と土星だけの場合:")
print(f"木星 + 土星の直径: {jupiter_saturn:,} km")
print(f"地球月間距離との比較: {jupiter_saturn / earth_moon_distance:.2f}")
if jupiter_saturn < earth_moon_distance:
print("✅ 木星と土星だけなら収まります")
余裕 = earth_moon_distance - jupiter_saturn
print(f"余裕: {余裕:,} km")
else:
print("❌ 木星と土星だけでも収まりません")
不足 = jupiter_saturn - earth_moon_distance
print(f"不足: {不足:,} km")
# 地球型惑星(内側の4惑星)だけの場合
terrestrial_planets = planets['水星'] + planets['金星'] + planets['地球'] + planets['火星']
print(f"\n地球型惑星(水星、金星、地球、火星)だけの場合:")
print(f"地球型惑星の直径合計: {terrestrial_planets:,} km")
print(f"地球月間距離との比較: {terrestrial_planets / earth_moon_distance:.2f}")
print("✅ 地球型惑星だけなら余裕で収まります")
グラフで視覚化してみましょう:
Code: # 視覚化グラフの作成
import matplotlib.pyplot as plt
import numpy as np
# 日本語フォントの設定
plt.rcParams['font.family'] = 'DejaVu Sans'
# 比較グラフ
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
# 1つ目のグラフ: 地球月間距離 vs 全惑星直径合計
categories = ['地球月間距離', '全惑星直径合計']
values = [earth_moon_distance, total_diameter]
colors = ['blue', 'red']
bars1 = ax1.bar(categories, values, color=colors, alpha=0.7)
ax1.set_ylabel('距離 (km)')
ax1.set_title('地球月間距離 vs 太陽系全惑星の直径合計')
# 値をバーの上に表示
for bar, value in zip(bars1, values):
ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5000,
f'{value:,} km', ha='center', va='bottom')
# 2つ目のグラフ: 各惑星の直径
planet_names = list(planets.keys())
planet_diameters = list(planets.values())
bars2 = ax2.bar(planet_names, planet_diameters, color='skyblue', alpha=0.7)
ax2.axhline(y=earth_moon_distance, color='red', linestyle='--',
label=f'地球月間距離 ({earth_moon_distance:,} km)')
ax2.set_ylabel('直径 (km)')
ax2.set_title('太陽系の惑星の直径比較')
ax2.legend()
ax2.tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()
# パイチャートで惑星サイズの割合を表示
fig, ax = plt.subplots(figsize=(10, 8))
# 小さい惑星をまとめる
large_planets = ['木星', '土星', '天王星', '海王星']
small_planets = ['水星', '金星', '地球', '火星']
large_diameters = [planets[p] for p in large_planets]
small_total = sum(planets[p] for p in small_planets)
sizes = large_diameters + [small_total]
labels = large_planets + ['地球型惑星合計']
colors = ['gold', 'lightcoral', 'lightblue', 'lightgreen', 'orange']
wedges, texts, autotexts = ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
ax.set_title('太陽系惑星の直径構成比')
plt.show()
print("\n結論:")
print("🔍 検証結果:")
print(f" ❌ 太陽系の全惑星は地球と月の間に収まりません")
print(f" 📊 全惑星直径合計: {total_diameter:,} km")
print(f" 📏 地球月間距離: {earth_moon_distance:,} km")
print(f" ⚠️ 不足: {total_diameter - earth_moon_distance:,} km (4.2%超過)")
print(f"\n🎯 ただし部分的には:")
print(f" ✅ 地球型惑星4個だけなら: {terrestrial_planets:,} km (余裕あり)")
print(f" ✅ 木星と土星だけなら: {jupiter_saturn:,} km (収まる)")
print(f" ❌ 全8惑星だと: わずか16,297 km不足")
変数を含めて最終的な結論を出しましょう:
Code: # 最終結論と要約
# データを再定義して最終結論
planets = {
'水星': 4879,
'金星': 12104,
'地球': 12756,
'火星': 6792,
'木星': 142984,
'土星': 120536,
'天王星': 51118,
'海王星': 49528
}
earth_moon_distance = 384400 # km
total_diameter = sum(planets.values())
terrestrial_planets = planets['水星'] + planets['金星'] + planets['地球'] + planets['火星']
jupiter_saturn = planets['木星'] + planets['土星']
print("=" * 60)
print("🌍 太陽系の全惑星は地球と月の間に収まるか?")
print("=" * 60)
print()
print("📊 データ:")
print(f" 🌙 地球と月の間の距離: {earth_moon_distance:,} km")
print(f" 🪐 太陽系全8惑星の直径合計: {total_diameter:,} km")
print(f" 📏 差異: {total_diameter - earth_moon_distance:+,} km")
print()
print("🔍 検証結果:")
if total_diameter <= earth_moon_distance:
print(" ✅ はい、収まります!")
else:
excess_km = total_diameter - earth_moon_distance
excess_percent = (excess_km / earth_moon_distance) * 100
print(" ❌ いいえ、収まりません")
print(f" ⚠️ {excess_km:,} km 不足 ({excess_percent:.1f}% 超過)")
print()
print("🎯 興味深い事実:")
print(f" • 木星と土星だけなら: {jupiter_saturn:,} km → ✅ 収まる (余裕 {earth_moon_distance - jupiter_saturn:,} km)")
print(f" • 地球型4惑星だけなら: {terrestrial_planets:,} km → ✅ 余裕で収まる")
print(f" • 木星だけで全体の {(planets['木星']/total_diameter*100):.1f}% を占める")
print(f" • 木星+土星で全体の {((planets['木星']+planets['土星'])/total_diameter*100):.1f}% を占める")
print()
print("📝 まとめ:")
print(" 太陽系の全8惑星を一列に並べると、地球と月の間の距離を")
print(f" わずかに超えてしまいます({excess_km:,} km 不足)。")
print(" しかし、非常に僅差であることが興味深いですね!")
## 答え:**いいえ、収まりません(ただし僅差です!)**
検証の結果、**太陽系の全8惑星を一列に並べても地球と月の間には収まりません**。
### 詳細な計算結果:
- **地球と月の間の距離:** 384,400 km
- **全惑星の直径合計:** 400,697 km
- **不足分:** 16,297 km(4.2%超過)
### 興味深いポイント:
1. **非常に僅差** - わずか16,297 kmの差で収まらない
2. **木星と土星だけなら収まる** - 263,520 km(余裕120,880 km)
3. **地球型4惑星は余裕** - 36,531 km(地球月間距離の10%以下)
4. **木星が最大** - 全体の35.7%を占める
この結果は宇宙のスケールの絶妙なバランスを示しており、太陽系の惑星サイズと地球月間距離が驚くほど近い値になっているという興味深い偶然を物語っています!
AWS マネージメントコンソール上から確認してみると何度か呼び出された Code Interpreter セッションが以下に表示されていたことが確認できました。
ポイントはコード内の "clearContext": False
により、論理的なセッション状態が保持されているようです。
③ Browser
Browser は、AI エージェントがウェブサイトと対話できるようにする安全なクラウドベースのブラウザを提供するよというサービスです。
AWS ブログを参考に進めてみます。
特徴
- Web 操作: AI が Web サイトを人間のように自動操作できる
- クラウド管理: サーバー不要で使った分だけ課金される
- AI 理解: 画面を見てコンテンツを理解できる
- セキュリティ: 各セッションが完全に分離され安全
- 人間連携: 必要時に人間が介入・監視できる
BrowserViewerServer
ローカルマシンでブラウザーを視覚化するには、次に clone するリポジトリ内の01-tutorials/05-AgentCore-tools/02-Agent-Core-browser-tool/interactive_tools
にある BrowserViewerServer
コンポーネントが必要です。
git clone https://github.com/awslabs/amazon-bedrock-agentcore-samples.git
cd amazon-bedrock-agentcore-samples/01-tutorials/05-AgentCore-tools/02-Agent-Core-browser-tool/interactive_tools
bedrock-agentcore と playwright のインストール
AgentCore SDK を利用するため、pip でインストールしておきます。
pip install bedrock-agentcore
playwright も利用するためこちらも、pip でインストールしておきます。
pip install playwright
その他パッケージもインストールしておきます。
pip install -r requirements.txt
ブラウザエージェントの構築
my_bedrock_agentcore_browser.py
from playwright.sync_api import sync_playwright, Playwright, BrowserType
# browser_session と BrowserViewerServer のインポート
from bedrock_agentcore.tools.browser_client import browser_session
from browser_viewer import BrowserViewerServer
import time
from rich.console import Console
console = Console()
def run(playwright: Playwright):
# browser_session を開始
with browser_session('us-west-2') as client:
ws_url, headers = client.generate_ws_headers()
# BrowserViewerServer を開始
viewer = BrowserViewerServer(client, port=8005)
viewer_url = viewer.start(open_browser=True)
# Chromium ブラウザに接続
chromium: BrowserType = playwright.chromium
browser = chromium.connect_over_cdp(
ws_url,
headers=headers
)
context = browser.contexts[0]
page = context.pages[0]
try:
page.goto("https://amazon.com/")
console.print(page.title())
# 60秒間保持
while True:
time.sleep(60)
except KeyboardInterrupt:
console.print("\n\n[yellow]Shutting down...[/yellow]")
if 'client' in locals():
client.stop()
console.print("✅ Browser session terminated")
except Exception as e:
console.print(f"\n[red]Error: {e}[/red]")
import traceback
traceback.print_exc()
with sync_playwright() as playwright:
run(playwright)
エージェントの実行と確認
python3 my_bedrock_agentcore_browser.py
http://localhost:8005
にアクセスされ実行されたことが確認できました。
また、AWS マネージメントコンソール上から確認してみると実行された Browser セッションが以下に表示されていたことが確認できました。