CrewAIをオープンソースで使う方法:実際に機能するものとしないもの
私は3日間かけて、CrewAIでオープンソースプロジェクトのイシュートリアージを自動化しようとしました。最初の48時間は大惨事でした。ドキュメントには「自律型AIエージェントが協力して作業する」と約束されていましたが、実際には意味不明なエラーと、今日が何日かも一致できないエージェントが返ってきただけでした。何度も失敗を繰り返して実際に機能するパターンを見つけた後、学んだことを以下にまとめます。
オープンソース自動化の本当の問題
オープンソースプロジェクトを管理するということは、イシューのトリアージ、PRのレビュー、ドキュメントの更新、同じ質問への繰り返しの回答といった反復作業に埋もれることを意味します。チームを雇うこともできますが、おそらく私のように資金がないでしょう。CrewAIは、協力するAIエージェントのチームを構築できると約束しています。その約束は魅力的です。しかし現実はもっと複雑です。
CrewAIが実際に得意なこと
5つの異なるオープンソースリポジトリでテストした結果、CrewAIが特に優れているのは以下の3つの分野であることがわかりました。
- 構造化されたワークフロー - 各ステップが前のステップに依存するもの
- ドメイン固有の知識を必要とするタスク(コードレビューなど)
- 複数の視点が必要なシナリオ(トリアージ+テストなど)
リアルタイムのコラボレーションや複雑な状態管理が必要なものでは、見事に失敗します。
最初のCrewのセットアップ
最終的にうまくいったセットアップを説明します。Python 3.11とCrewAI 0.30.0を使用しています。
pip install crewai==0.30.0
重要: バージョンが重要です。0.40.xブランチではセットアップ全体が壊れました。今のところは0.30.0に固執してください。
最小限の実行可能なCrew
実際に機能するスケルトンコードは次のとおりです:
from crewai import Agent, Task, Crew, Process
from crewai.tools import tool
import os
os.environ["OPENAI_API_KEY"] = "your-key-here" # または無料のOllamaを使用
# シンプルなツールを定義
@tool("Read GitHub Issue")
def read_github_issue(issue_url: str) -> str:
"""URLからGitHubイシューの内容を読み取る"""
import requests
response = requests.get(issue_url)
return response.text[:2000] # トークン制限を避けるために切り詰め
# エージェントを作成
triage_agent = Agent(
role="Issue Triage Specialist",
goal="GitHubイシューを分類し優先順位付けする",
backstory="バグ報告と機能リクエストの理解の専門家",
tools=[read_github_issue],
verbose=True,
allow_delegation=False # 重要:無限ループを防止
)
response_agent = Agent(
role="Community Responder",
goal="イシューへの役立つ返信を草案する",
backstory="物事を明確に説明する親しみやすいオープンソースメンテナー",
verbose=True,
allow_delegation=False
)
# タスクを定義
triage_task = Task(
description="{issue_url}のイシューを読み、「bug」「feature」「question」に分類する",
expected_output="1語:bug、feature、またはquestion",
agent=triage_agent
)
response_task = Task(
description="トリアージ結果に基づいて、イシューへの返信を草案する",
expected_output="イシュー作成者への役立つ返信",
agent=response_agent,
context=[triage_task] # これがタスクを連鎖させる方法
)
# Crewを作成
crew = Crew(
agents=[triage_agent, response_agent],
tasks=[triage_task, response_task],
process=Process.sequential, # エージェントは順番に作業
verbose=True
)
# 実行
result = crew.kickoff(inputs={"issue_url": "https://github.com/example/repo/issues/1"})
print(result)
これは3回目の試行で機能しました。最初の2回は以下の理由で失敗しました:
allow_delegation=Trueに設定したため、エージェントが互いに議論し始めたcontextを使用してタスク間で結果を渡さなかった
発見した重要な失敗ポイント
1. エージェントのメモリは嘘
CrewAIの「長期記憶」機能は素晴らしく聞こえますが、メモリを大量に消費します。10件のイシューを処理した後、エージェントは以前の会話を幻覚し始めました。解決策:実行の間にメモリをリセットする:
crew = Crew(
agents=[...],
tasks=[...],
memory=False, # 本当に必要でなければオフにする
cache=True # ただし、速度のためにキャッシュはオンに
)
2. ツールの出力形式が重要
最初のツールは生のJSONを返していました。エージェントはそれを解析できませんでした。ツールの出力はプレーンテキストとしてフォーマットすることを学びました:
@tool("Search Codebase")
def search_codebase(query: str) -> str:
"""リポジトリ内のコードパターンを検索"""
results = grep_code(query) # 実際の検索ロジック
# JSONを返さない。読みやすいテキストを返す。
return f"{len(results)}件の一致が見つかりました:\n" + \
"\n".join([f"- {r['file']}:{r['line']}" for r in results[:5]])
3. トークン予算の罠
各エージェント呼び出しにはトークンがかかります。最初のCrewは50件のイシューを処理し、API呼び出しに$12かかりました。以下が$2に削減した方法です:
Agent(
role="...",
# 各エージェントが見るコンテキストを制限
max_iter=3, # デフォルトは25!多すぎる
max_execution_time=60, # 暴走エージェントを停止
# 単純なタスクには小さなモデルを使用
llm="gpt-3.5-turbo" # 日常的なタスクにはgpt-4ではない
)
実践的なパターン:自動PRレビュー
以下は実際に本番環境で使用しているセットアップです。プルリクエストをレビューし、一般的な問題を検出します:
from crewai import Agent, Task, Crew
from pathlib import Path
@tool("Read PR Diff")
def read_pr_diff(pr_url: str) -> str:
"""プルリクエストの差分を取得"""
# ここにGitHub APIのロジック
return diff_text
@tool("Check Coding Standards")
def check_coding_standards(code: str, language: str) -> str:
"""リンターとスタイルチェッカーを実行"""
# リンターロジック
return violations_text
# 専門エージェント
style_agent = Agent(
role="Style Enforcer",
goal="コードがプロジェクトの規約に従っていることを確認",
backstory="PEP8とプロジェクト固有のルールに厳格",
tools=[read_pr_diff, check_coding_standards],
max_iter=2
)
logic_agent = Agent(
role="Logic Reviewer",
goal="論理エラーとエッジケースを発見",
backstory="他の人が見逃すバグを見つける",
tools=[read_pr_diff],
max_iter=3
)
# 並列タスク
review_style = Task(
description="PRの差分をスタイル違反についてレビュー",
expected_output="見つかったスタイルの問題のリスト",
agent=style_agent
)
review_logic = Task(
description="PRの差分を論理エラーについてレビュー",
expected_output="見つかった潜在的なバグのリスト",
agent=logic_agent
)
# 結果を結合する順次タスク
summarize = Task(
description="スタイルとロジックのレビューを最終的なPRコメントに結合",
expected_output="完全なPRレビューコメント",
agent=Agent(role="Review Summarizer", goal="...", backstory="..."),
context=[review_style, review_logic]
)
crew = Crew(
agents=[style_agent, logic_agent],
tasks=[review_style, review_logic, summarize],
process=Process.hierarchical, # 並列+順次を許可
manager_llm="gpt-4" # 調整にはよりスマートなモデルを使用
)
違うやり方をするなら
やり直すとしたら:
- 最初にOllamaを使用 - GPT-4にお金を使う前に、
ollama run llama3.1:70bでローカルでエージェントをテスト - 最大2エージェントから開始 - エージェントが多いほど障害モードも増える
- 期待される出力をハードコード -
expected_outputをドキュメントだけでなく検証として使用 - 人間参加型のループを追加 - CrewAIには承認ワークフローがない。自分で構築:
def human_approve(response):
print(f"エージェントの提案:{response}")
return input("承認しますか?(y/n):").lower() == 'y'
# 重要なアクションの前にこれを使用
if human_approve(agent_response):
# アクションを実行
pass
正直な結論
CrewAIは強力ですが、壊れやすいです。以下の場合に最適です:
- 既存のイシュー/PRのバッチ処理
- 返信の初稿の生成
- コード品質チェックの自動実行
以下の場合には失敗します:
- リアルタイムコラボレーション - エージェントは共有状態で同時に作業できない
- 複雑な決定木 - 5つ以上の順次タスクで壊れる
- 外部API呼び出しが必要なタスク - ツール統合が脆弱
次のステップ:github.com/yourname/crewai-oss-starterにあるスターターテンプレートをクローンしてください。ツール関数をプロジェクトの実際のAPIに置き換えてください。実際の3つのイシューで実行してください。避けられないエラーを修正してください。そこからスケールアップしてください。
覚えておいてください:CrewAIはオープンソースの作業を補完するためのツールであり、置き換えるものではありません。目標は退屈な作業を処理し、実際のコミュニティ構築に集中できるようにすることです。