この記事について
マルチAIエージェントを作れるオープンソースのライブラリ、crewaiについて、諸々学んだことをメモ。
ここでは、「これさえ知っておけばとりあえず動くものを作れる」という最低限の部分をコンパクトにメモします。
ToolやLLM、ワークフローの順序制御の詳細など、詳しい話は別途記事を公開します。
メモ
環境
手軽に試したいなら Google Colab が一番便利です。
Colab を開いて crewai をインストールするだけで基本機能が使えます。
!pip install crewai
LLM のモデルに Bedrock を使う時は、Boto3も必要です。
!pip install boto3
基本要素 - Agent, Task, Crew
Agent, Task, Crew の3要素は、crewaiを動かすために必ず必要になります。
インポート
この3要素はコードの先頭で必ずインポートすることになります。
from crewai import Agent, Task, Crew
Agent
タスクを行うためのオブジェクト。
担当者、みたいなイメージです。
以下のように定義します。
# カスタマーサポートエージェント
customer_support_agent = Agent(
role="カスタマーサポート",
goal="あらゆるお客様の質問に正確でタイムリーな回答を返す",
backstory="カスタマーサポートチケットに効率的かつ礼儀正しく対応することに最適化されたAI",
tools=[],
llm='gpt-4',
verbose=True
)
主な属性はこちら。
role
, goal
, backstory
は、LLMが理解できる言語なら何語で書いてもOK。
引数 | 必須 | 型 | 設定内容 |
---|---|---|---|
role | ◯ | String | どんな役割を担当するエージェントなのかを定義する |
goal | ◯ | String | エージェントに達成させたい目的 |
backstory | ◯ | String | roleやgoalを補足する背景情報 |
tools | リスト | Toolオブジェクトを定義した場合で、エージェントにToolを使わせたい場合は、Toolオブジェクトをリスト形式で設定する。デフォルトは空のリスト(Toolなし) | |
llm | 文字列またはLLMオブジェクト | エージェントが利用するLLMのモデル。デフォルトは "gpt-4"
|
|
verbose | boolean | 途中経過を詳細に返す場合は True。テストの時は True にしておくと途中経過がよくわかっておもしろい。 |
Task
エージェントに実際に担当させる仕事の中身。
以下のように定義します。
# タスク
support_task = Task(
description=f"お客様の次の質問に答えてください。{customer_inquiry}",
expected_output="返金ポリシーに関する詳細説明を日本語(敬語)で",
agent=customer_support_agent
)
description の中に、{customer_inquiry}
というのが入っています。
この部分に、ユーザーの入力が入ります。
Task オブジェクトや Agent オブジェクトに渡す文字列では任意の箇所で、上記のような {項目名}
による代入を使うことができます。
Task オブジェクトの主な属性はこちらです。
description
, expected_output
は、LLMが理解できる言語なら何語で書いてもOK。
引数 | 必須 | 型 | 設定内容 |
---|---|---|---|
description | ◯ | String | どんなタスクを実施してほしいかの指示 |
expected_output | ◯ | String | 出力の言語や形式などを指定。後続で自動処理を行う場合は、ここの指定が非常に重要。 |
agent | Agentオブジェクト | タスクを担当させるエージェント |
Crew
エージェントとタスクの結びつきと、処理の順番を定義したもの。
働き手と役割分担、その順番を定義したチームみたいなイメージです。
以下のように定義します。
# Crew
crew = Crew(
agents=[customer_support_agent],
tasks=[support_task]
主な属性はこちら。
引数 | 必須 | 型 | 設定内容 |
---|---|---|---|
agents | ◯ | リスト | Agentオブジェクトのリスト |
tasks | ◯ | リスト | Taskオブジェクトのリスト |
上記のタスクではエージェントもタスクも一つずつしかないが、複数のタスクを数珠つなぎに行う場合は、 登場するエージェントとタスクをすべてリストに列挙する。
LLM の定義
詳細はドキュメントに書かれていますが、よく使うであろう OpenAI と Bedrock についてのメモです。
OpenAIを利用する場合
デフォルトの 'gpt-4' などでは、OpenAIのモデルを参照します。
OpenAIのモデルを利用する場合は、 OPENAI_API_KEY
にOpenAIのキーを設定することでモデルにアクセスが可能になります。
import os
os.environ['OPENAI_API_KEY'] = "OPENAIのAPIキー"
Bedrockを利用する場合
Bedrock を利用する場合は、 Bedrock へのアクセス権を持った IAM ユーザーを作った上で、以下の環境変数を設定します。
import os
os.environ['AWS_ACCESS_KEY_ID'] = "作成したIAMユーザーのアクセスキーID"
os.environ['AWS_SECRET_ACCESS_KEY'] = "作成したIAMユーザーのシークレットアクセスキー"
os.environ['AWS_DEFAULT_REGION'] = "リージョン(ap-northeast-1 など)"
さらに、Bedrock のどのモデルを利用するかを以下のように指定します。model=
以下には、Bedrock のモデルIDを指定します。
# ClaudeをBedrock経由で利用
claude_llm = LLM(
model="anthropic.claude-3-5-sonnet-20240620-v1:0"
)
上記のLLMをエージェントに実際に使わせる場合は、Agentの llm
属性を以下のように指定します。
# カスタマーサポートエージェント
customer_support_agent = Agent(
role="カスタマーサポート",
goal="あらゆるお客様の質問に正確でタイムリーな回答を返す",
backstory="カスタマーサポートチケットに効率的かつ礼儀正しく対応することに最適化されたAI",
tools=[],
llm=claude_llm, # <----ここ!!!
verbose=True
)
実行
以下のように、Crew オブジェクトに対して kickoff
メソッドをかけることでタスクを実行してくれます。
実行例1
customer_inquiry = "届いた商品がくそです。返金してください。"
result = crew.kickoff()
上記の customer_inquiry
という変数名ですが、これは Task オブジェクトの description
の中で指定した {}
内の項目名と一致させる必要があります。
他の箇所で {項目名}
による代入を使った場合も、その項目名と一致する変数を crew.kickoff()
の前に設定しておく必要があります。
実行例2
別の書き方として、crew.kickoff()
の ()
内に辞書形式で必要な項目を渡すこともできます。
result = crew.kickoff({"customer_query": "届いた商品がくそです。返金してください。"})
この場合も、辞書のキーとなる項目は、TaskやAgentなどのオブジェクトを作る際に {項目名}
による代入を指定した箇所の項目名と一致させておく必要があります。
実行結果
上記の実行例1, 2 いずれの場合も、以下のような結果が返ってきます。
(文言は多少変わると思いますが、似たような結果が返ってくるはずです)
上記は返金ポリシーを答えろという指示を Agent に出しつつも、実際にの返金ポリシーなどの知識は与えていないので、LLM のモデルが「返金ポリシーっぽいもの」を適当に作って返している完全なハルシネーションです。
それを防ぐには、Tool を使って実際の返金ポリシーを読ませるなどの工夫が必要になります。
Crewai には他にも順序制御などの便利な機能がありますが、この記事に書いた内容さえわかっていれば、あとは指示の内容などを変更して色々試せるはずです。
Tool や順序制御などの詳細も、随時記事を公開していきたいと思います。
本日の記事は以上です。