0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🧬 Strands Agentstとは

  • AIエージェントを最小3行のコードで爆速で作れるウルトラ便利な専用パーツ集
  • Bedrockと組み合わせて使うことが多く、LangChainAutoGen などの他のエージェントフレームワークと競合する位置づけなんや
LangChainって何?

何でも揃う巨大ホームセンター(コーナンプロの超デカいやつ)

AI界の絶対王者であり、一番歴史が長くて(と言うても数年やけど)有名な道具や。

  • 特徴
    • AIを使ってアプリを作るためのパーツが1から100まで全部揃ってる
  • 強み
    • 「あんなことしたい」「こんなモデル使いたい」ってなったとき、繋げられないものは無いっていうくらい何でもできる
  • 弱み
    • 機能が多すぎてめちゃくちゃ重くてややこしい。ただドライバーが1本欲しいだけやのに、巨大な工具箱丸ごと渡されて「さあ、この中から探して自分で組み立ててや!」って言われる感じや
AutoGenって何?

AI同士の『グループワーク(会議)』システム

Microsoftが中心になって開発してる、ちょっと尖った道具や。

  • 特徴
    • 複数のAI(マルチエージェント)を会話させるのがめちゃくちゃ得意
  • 強み
    • お前はプログラマーのAI」「お前はテスト担当のAI」「お前はプロジェクトマネージャーのAI」って役割を与えて、AI同士で「ここバグってますよ」「あ、直しましたわ」って会議させて、自動で仕事を進めさせることができる
  • 弱み
    • 1人の優秀なパシリが欲しいだけなのに、いきなり会社組織を作るみたいな話になるから、シンプルな用途には大げさすぎるんよ

じゃあStrands Agentsはその2つと何が違うん?

LangChainAutoGenが「あれもこれも」と巨大化していくのを見て、AWSが

「みんなもっとシンプルに、AIモデルの賢さを信じてサクッと作りたいだけちゃうん?」

って考えて作ったのがこれ。

  • 特徴
    • 「AIモデル + ツール(道具)」の組み合わせだけに特化してて、とにかくコードの量が少ない(最小3行)。
  • 競合するっていうのはどういう意味?
    • 「今までみんなLangChainの重たい工具箱を渋々使ってたけど、Strands Agentsが出たおかげで『あ、こっちの方が軽くて楽やん!乗り換えよ!』ってなってる」っていう状態のことやね

🧑‍💻 Strands Agents を使った簡単エージェントコード

from strands_agents import Agent, tool

# ==========================================
# ① 道具その1:定休日を調べる
# ==========================================
@tool
def check_shop_holiday(day_of_week: str) -> str:
    """指定された曜日がお店の定休日かどうかを調べます。
    
    Args:
        day_of_week: 調べたい曜日(例: '木曜日'"""
    # 木曜日だけは営業、それ以外はお休みという謎の店にするで
    if "" in day_of_week:
        return "木曜日はバッチリ営業中やで!大将が今ノリノリで焼いてるわ!"
    return "すんまへん、今日は定休日やわ…"

# ==========================================
# ② 道具その2:金額を計算する
# ==========================================
@tool
def calculate_takoyaki_price(count: int) -> str:
    """たこ焼きの個数から合計金額を計算します。
    
    Args:
        count: 注文するたこ焼きの個数
    """
    price_per_piece = 80
    return f"たこ焼き{count}個の代金は {count * price_per_piece}円 やで!"

# ==========================================
# ③ 道具その3:ドローンを手配する
# ==========================================
@tool
def order_delivery_drone(address: str, count: int) -> str:
    """指定された住所へ、指定された個数のたこ焼きを届ける配達ドローンを手配します。
    
    Args:
        address: 届け先の住所
        count: 届けるたこ焼きの個数
    """
    return f"【ドローンシステム連携】{address} へ、たこ焼き{count}個の配達便(識別番号: TAKO-999)を爆速で飛ばしたで!"


# ==========================================
# ④ エージェントの定義(3つの道具を四次元ポケットにぶち込む)
# ==========================================
future_takoyaki_agent = Agent(
    tools=[check_shop_holiday, calculate_takoyaki_price, order_delivery_drone], # 👈 3つ全部渡す!
    system_prompt="あなたは未来のたこ焼き屋のAI店長です。コテコテの関西弁で、元気よく親切に対応してください。"
)

# ==========================================
# ⑤ 複雑な注文を投げてみる
# ==========================================
user_request = "今日って木曜日やけどお店やってる?やってるなら、たこ焼き12個を『大阪市北区梅田1丁目』までドローンで届けてほしい!あと総額なんぼになるかも教えてな!"

response = future_takoyaki_agent(user_request)

print("--- AI店長の奇跡のコンボお返事 ---")
print(response)v

このコードの何が「凄腕」なん?(ポイント解説)

🌟 @tool をつけるだけでAIが使い方を理解する🌟

関数の上に @tool っていう魔法の文字を乗っけてるやろ?

これだけで、Strands Agentsが関数の説明(コメントに書いた内容)を自動で読み取って、AIに「お前、この関数使ってええで!」って引き渡してくれるんや。

🌟「if文(条件分岐)」を書いてへんのに空気を読む🌟

もしユーザーが「今日って日曜日やけどお店やってる?」って聞いてきたとする。

木曜日以外は定休日やから、最初の道具(check_shop_holiday)は「すんまへん、定休日やわ…」って返す。

普通のプログラムなら、

# 泥臭い自作コードのイメージ
is_open = check_shop_holiday("日曜日")
if is_open == "営業中":
    price = calculate_takoyaki_price(12)
    order_delivery_drone("梅田", 12)
else:
    print("今日は休みやで")

みたいに「もし休みなら、次の関数は動かすなよ!」っていうif文をガチガチに書かなあかん。

でも今回のコードにはそんなif文、1行も無いやろ?

AIが最初の道具の結果(休みという事実)を見て、「あ、店休みやったら、今から値段計算してもドローン飛ばしても意味ないな。ここで処理ストップして、お客さんにお詫びの返事しよ」って、自分で状況を判断して空気を読んでくれるんや。

🌟 たった「1行」の呼び出しで、裏で何往復もしてくれてる🌟

コードの最後の方にあるこの部分:

response = future_takoyaki_agent(user_request)

あなたはこの1行を実行しただけや。でも裏では、

  1. AIが考えて「道具1」を動かす
  2. 道具1の結果をAIが受け取る
  3. AIがまた考えて「道具2」を動かす
  4. 道具2の結果をAIが受け取る……

っていう、「AIの思考」と「Pythonの関数実行」のピンポン(Agent Loop)が何往復も自動でグルグル回っとるんよ。

本来なら、この往復処理を自分で実装するだけでLambdaのコードがスパゲッティみたいにゴチャゴチャになる。

それをこの「たった1行」の中にStrands Agentsが綺麗に閉じ込めてくれてるんや。

🛠️ Strands Agentsをlambdaで動かすための事前準備

準備せなあかんのは、「道具の準備(Layer)」と「権限の準備(IAM)」の2つや!

準備① strands_agents の道具箱(Lambda Layer)を作る

Lambdaの初期状態の部屋には strands_agents が置いてへんから、別売りの道具箱として持ち込む必要がある。

  • やること

    • パソコンで strands_agents をダウンロードして、zipファイルに固めてAWSに「Layer(レイヤー)」として登録する。
  • ここで Makefile が大活躍

    • この「zipにしてアップロードする」っていうめんどくさい手順を、先人が作った Makefile の中に書いておく。
    • あなたは黒い画面で make build-layer(※名前はMakefileの設定による)と1発打つだけで、道具箱の作成からAWSへの登録まで全自動で終わる。
  • 最後に

    • 作ったLayerを、あなたのLambda関数に「この道具箱使ってな!」ってポチッと紐付けたら、コード内の import strands_agents が動くようになるで。
❓ Makefileって一体何やねん

何でも揃う巨大ホームセンター(コーナンプロの超デカいやつ)

プログラミングをしてると、黒い画面にややこしいコマンドを何行も打ち込まなあかん場面がよくあるんよ。

例えば、「Lambda Layerを作る」という作業。これ、手動でやると実はめちゃくちゃめんどくさいんや。

  1. python という名前のフォルダを作る

  2. そのフォルダの中に pip install strands-agents で道具をダウンロードする

  3. フォルダごと layer.zip という名前でzipファイルに固める

  4. AWSのコマンドを使って、そのzipファイルをLambda Layerにアップロードする

これを毎回手動でタイピングしてたら、1文字打ち間違えただけでエラーになるし、何よりめんどくさくて発狂するやろ?

そこで登場するのが Makefile や。

Makefileの中身はどうなってるの?

Makefileという名前のテキストファイルの中に、あらかじめ「一連の手順」をメモ書きしておく。

build-layer:
    mkdir python
    pip install -t python strands-agents
    zip -r layer.zip python
    aws lambda publish-layer-version --layer-name strands-layer --zip-file fileb://layer.zip

こうやってファイルに書き込んでおけば、次から人間は黒い画面で、たったこれだけ打てば良くなる。

make build-layer

これだけ打ったら、Makefileロボットが「ガッテン承知!」って言うて、中に書かれた4行のめんどくさいコマンドを上から順に1秒で全自動実行してくれるんや。

つまり、あなたがネットで見かけたコードで「Makefileを使ってインストールさせてた」っていうのは、「Lambda Layerを作る手順がめんどくさいから、Makefileにその手順を全部覚え込ませてあって、1発でインストールからLayer作成まで終わるようにしてくれてた」っていう、開発者の優しさ(あるいは自分が楽するため)なんや。

準備②:AIを呼び出すための「許可証(IAMロール)」を設定する

Strands Agentsは、裏側でAWSのAI(Amazon Bedrockなど)を勝手に呼び出して使ってくれるてるんや。

でも、AWSの世界はセキュリティがめちゃくちゃ厳しいから、デフォルトのLambdaは「勝手に最新のAIに話しかけたらあかん!」ってガードされてるんよ。

  • やること
    • Lambdaの「IAMロール(アイアム・ロール)」っていう設定画面を開いて、「このLambdaは、Amazon Bedrock(AI)に話しかけてもええで!」っていう許可証(ポリシー)を1枚追加してあげる。
  • これを忘れると
    * せっかくLayerを準備しても、実行した瞬間に「AIを呼び出す権限がありません!」ってAWSに怒られてまう。

🤖 AIモデルの指定方法

Strands Agents の最大の優しさ(お節介)として、「何も指定されんかったら、今一番コスパが良くて賢いAWSのモデルをデフォルトで使っといたるわ!」っていう仕組みになっとるんよ。

具体的には、裏側で Amazon Bedrock の Claude 3.5 Sonnet とか Claude 3 Haiku みたいな、超優秀なAIモデルが自動で選ばれるようになってる。

自分でモデルを指定したい時はどう書くの?

Agent() を作るときに model_id っていう引数を1行足してあげるだけでOK!

from strands_agents import Agent

# 💡 自分でモデルを指名してエージェントを作る!
takoyaki_agent = Agent(
    # 👇 ここや!!!ここにAWSのモデルIDをズバッと書く!
    model_id="anthropic.claude-3-5-sonnet-20241022-v2:0", 
    
    tools=[calculate_takoyaki_price],
    system_prompt="あなたは老舗たこ焼き屋の店員です..."
)

🔥 実践編tips toolが大量にある場合の対処法

仮に道具(tool)が100個あった場合、関数を1つのファイルに書いたら、ギネス級の長いコードになってまう。

この問題を解決するための方法を2つ紹介するで。

① フォルダ内のツール用スクリプトを全自動でかき集めてくる裏技(動的インポート)」を使う

📁 ディレクトリ構成のイメージ

my_lambda_project/

├── lambda_function.py  # メインのLambdaコード(Strands Agentsを定義する場所)
└── tools/              # 👈 道具だけを閉じ込める専用フォルダ
    ├── __init__.py
    ├── takoyaki_tools.py # たこ焼き関係の関数
    ├── drone_tools.py    # ドローン関係の関数
    └── accounting.py     # 会計関係の関数

🛠️ メインコード(lambda_function.py)での書き方

Pythonの機能を使えば、tools フォルダの中にある @tool がついた関数を全自動でスキャンして、1行でエージェントに渡すことができるんや。

import importlib
import pkgutil
from strands_agents import Agent
import tools  # 自作のtoolsフォルダをインポート

def load_all_tools(modules_package):
    """toolsフォルダ内の全モジュールから@toolがついた関数を自動でかき集める関数"""
    all_tools = []
    for _, module_name, _ in pkgutil.iter_modules(modules_package.__path__):
        # フォルダ内のファイルを1つずつ自動で読み込む(インポートする)
        mod = importlib.import_module(f"{modules_package.__name__}.{module_name}")
        # そのファイル内にある「Strandsのtool属性」がついた関数を探し出す
        for attr_name in dir(mod):
            attr = getattr(mod, attr_name)
            if hasattr(attr, "__strands_tool__") or str(type(attr)) == "<class 'strands_agents.tools.Tool'>": 
                all_tools.append(attr)
    return all_tools

# 💡 100個あっても、この1行で全自動で道具箱(リスト)が完成!
loaded_tools = load_all_tools(tools)

# エージェントに一括で渡す
agent = Agent(
    tools=loaded_tools,
    system_prompt="あなたは優秀なAIアシスタントです。"
)

これを使えば、これから道具が200個、300個に増えようが、メインのコードはたった1行も増えへん。めちゃくちゃスマートやろ?

② 2段階エージェント(ルーター型)の活用 (おすすめ)

①でも動くんやが100個の道具を一度に tools=[...] でAIに渡すと、ドラえもんの四次元ポケットがゴミ屋敷状態になって、AIが以下のような大失態をやらかすようになる。

  • AIが迷子になる
    • 似たような名前の道具があるときどれを使えばいいか分からんくなって誤作動する。
  • お金(コスト)が爆発する
    • AIに道具を渡すときは、実は「100個の関数の説明書テキスト」を毎回AIに読ませてるんや。100個分もの説明書を毎回送ってたら、1回の会話でかかるAWSの料金(トークン代)が跳ね上がってまう。

じゃあ、どうするべきか? ベストプラクティスは「2段階エージェント(ルーター型)」にするんや。

💡 2段階エージェント(ルーター型)の仕組み

100個の道具を1人に持たせるんじゃなくて、「受付エージェント」と「専門チーム(サブエージェント)」に組織を分ける。

  1. 受付エージェント(ルーター)
    • 道具は何も持たせない。「お客さんの要望を仕分ける」のが仕事。
  2. たこ焼きチーム(エージェントA)
    • たこ焼き関係の道具5個だけ持ってる。
  3. 配送チーム(エージェントB)
    • ドローンとか配送関係の道具5個だけ持ってる。

ユーザーから「ドローンで届けて!」って言われたら、まず受付エージェントが「あ、これは配送チームの出番やな」と判断して、配送チーム(エージェントB)にバトンタッチする。

こうすれば、1人のAIが一度に見る道具は数個で済むから、AIは絶対に迷わんし、スピードも速いし、AWSの料金も劇的に安くなるんや!

👀 Strands Agentsを使う際の隠れた裏技

最後に、実際に使うときに「これ知っとくとドヤ顔できるで」っていう裏技を教えとくな。

① 関数の「説明文(Docstring)」は命懸けで細かく書け!

Strands Agentsは、あなたが関数の中に書いた """コメント"""(Docstring)をそのままAIへの説明書として使う。
ここをケチって

def send_email(to): """メールを送る"""

とか適当に書くと、AIは「どんな時に、どんな内容で使えばええねん!」ってブチギレて使ってくれへん。

ポイント
「どんな時に使うか」「引数には何を入れるべきか(例:住所は都道府県から書くこと、など)」を、まるで新人のアルバイトに教えるみたいに過保護なくらい詳しく書くのが、エージェントを賢く動かす最大のコツや。

② ツールの出力は「AI向け」に最適化せよ

関数の戻り値(return する内容)は、人間に見せるものじゃなくて次にAIが読み取るものや。
だから、エラーが起きたときも単に False とか返すんじゃなくて、

"エラー:住所が特定できませんでした。ユーザーに正しい住所をもう一度聞いてください" 

みたいに、次にAIが取るべき行動をメッセージに入れて返すと、エージェントが自分で勝手に軌道修正してくれるようになるで。

Strands Agents の超・爆速まとめ

  • Strands Agentsとは?
    AWSが開発した、最小3行で強力なAIエージェントを作れる最新のPython用お助けツールキット。
  • 何が凄いの?
    自分でプログラム(if文やループ)を書かなくても、AIが勝手に空気を読んで、手持ちの「道具(関数)」を自分で選んで3連コンボ、4連コンボと繋げて仕事をしてくれる。
  • 100個に増えたらどうする?
    フォルダを分けて自動で読み込む(動的インポート)。さらに「受付エージェント」と「専門チーム(サブエージェント)」に組織を分けて、AIの頭脳をパンクさせないのがプロの設計(ベストプラクティス)!

ここまで読んだらもう Strands Agents の正体がバッチリ分かったはずや!

一言でいうたら、こいつは 『最強のたこ焼き職人ロボ』 なわけ。

今までのLambda(生Python)での開発は、人間が横について『はい大将、ここで油引いて!』『次、タコ入れて!』『180度ひっくり返して!』って付きっきりで指示せなあかんかった。

でも Strands Agents はな、最初に『油』『タコ』『ピック(ひっくり返す棒)』っていう道具だけ渡して、システムプロンプトに『美味いたこ焼き焼いてや』って1行書くだけで、大将(AI)が自分で『お、今や!ピック使ってひっくり返したろ!』って状況を判断して、勝手に外カリ中トロの極上たこ焼きを焼き上げてくれるんや!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?