マルチ AI エージェントシステム - CrewAI を使って Yellowfin の営業ピッチを作成

## マルチエージェントシステム（MAS）
最近、マルチエージェントシステム（MAS）という言葉をよく耳にします。MAS とは、自律的に働く複数の AI エージェントを組織し、協業させることで、シングルエージェントでは達成が難しい処理を実行させるものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/5115a9c1-1ebc-4abd-894c-d9d48c9a4a3c.png)

MAS は、スマートグリッド、交通管制、災害時レスキュー支援、製造管理など、幅広い用途への適用が期待されます。多くの機能を統制して運用するこれらの仕組みに対しては、役割の異なるエージェントが自律して動作し、互いに協力し合うモデルが適しています。

## フレームワーク
LangGraph、AutoGen、CrewAI など、マルチエージェントを扱うための Python フレームワークがいくつか存在します。
いずれのフレームワークも、比較的シンプルに実装できるものばかりです。

#### CrewAI
今回は、中でも実装がシンプルに行える [CrewAI](https://docs.crewai.com/introduction) を利用します。[João Moura](https://github.com/joaomdmoura) さんが開発したオープンソースのフレームワークです。

CrewAI では、カギとなる要素が 3 つあります。
|要素|説明|
|---|---|
|Agent|仮想のチームメンバー。自律的に自身に与えられた役割を果たす。|
|Task|Agents に割り当てるタスク。タスクの内容や想定する成果物を明確に定義し、望む結果をもたらすように調整する。|
|Crew|Agent が所属する Crew（チーム）。特定の目的を果たすためにエージェントを集結させ、Crew として稼働させる。|

チームを組織するイメージで、Agent に Task を割り当て、Crew として協業させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/1f7d22a5-b5b9-4b18-b4e4-a15af29d7f4f.png)


## 環境準備

#### 使用環境
使用する環境は以下の通りです。ローカル PC（Windows 11）の Python 実行環境にCrewAI のフレームワークをインストールし、Google Gemini の LLM と連携して処理を実行します。
|役割|環境|
|---|---|
|LLM|Gemini|
|フレームワーク|CrewAI|
|CrewAI 実行環境|Python 3.11.3（Windows 11）|

#### インストール

下記を実行し、Gemini および CrewAI を利用するためのライブラリをインストールします。
```Markdown:pip install
pip install google-generativeai crewai crewai[tools]
```
:::note info
2005 年 6 月 17 日現在、Python の最新バージョンは 3.13.5 です。しかし、3.13.x や 3.12.x では、regex および tiktoken との dependency 関連エラーで、crewai_tools をインストールすることができませんでした。Python のバージョンは、問題なく稼働していた Google CoLab の 3.11.3 に合わせました。
:::

#### Google API Key
Gemini の API にアクセスするためには、API Key が必要です。
API Key の取得方法に関しては、下記が解り易いと思います。

https://www.softmachine.jp/blog/2024/02/%E3%80%90%E6%84%8F%E5%A4%96%E3%81%A8%E7%B0%A1%E5%8D%98%E3%80%91google-maps-api%E3%82%AD%E3%83%BC%E3%81%AE%E5%8F%96%E5%BE%97%E3%83%BB%E5%B0%8E%E5%85%A5%E3%80%90api%E3%82%AD%E3%83%BC%E3%81%AE%E5%8F%96/

取得したAPI Key を OS のシステム環境変数に登録します。
```Markdown:Google_API_Key
setx /M GOOGLE_API_KEY “<your_api_key>”
```

#### Serper API Key
CrewAI Tools の中には、[Serper](https://serper.dev/) と連動して、インターネット上のデータを、Google ライクに検索する機能がビルトインされています。Agent が Serper と連動して、インターネット上の情報を検索できるようにするためには、Serper API Key を取得する必要があります。下記にアクセスし、アカウントを作成すると、無料で API Key が提供されます。

https://serper.dev/

取得したAPI Key を OS のシステム環境変数に登録します。
```Markdown:Serper_API_Key
setx /M SERPER_API_KEY “<your_api_key>”
```

## コーディング
ここまでの手順で整えた環境を使って、Python でコーディングを行います。

#### Gemini API
API を介して Gemini のモデルと連携するためのコードです。
```python:CrewAI.py
from crewai import Agent, Task, Crew, LLM

llm = LLM(
    model="gemini/gemini-2.0-flash",
    api_key=os.environ["GOOGLE_API_KEY"]
)
```
* `LLM()` CrewAI LLM クラスの中で、OpenAI、Claude、Gemini など、異なるモデルを共通のインターフェースでラップしています。
* `model` Gemini の無料枠の API を利用するために、gemini-2.0-flash モデルを選択しました。
* `api_key` OS のシステム環境変数に登録した GOOGLE_API_KEY を呼び出します。

#### Serper
Serper 経由でインターネット上の情報を検索するためのコードです。
```python:CrewAI.py
from crewai_tools import SerperDevTool

SERPER_API_KEY = os.environ["SERPER_API_KEY"]
search = SerperDevTool()
```
* `SERPER_API_KEY` OS のシステム環境変数に登録した SERPER_API_KEY を呼び出します。
* `search` crewai_tools のビルトイン機能 SerperDevTool をインスタンス化して、Agents が Serper.dev API 経由で、Google ライクな検索を行えるように定義しています。検索機能を呼び出し可能なオブジェクトにラップし、後述のコードの中で `tools=[search]` で Agent に受け渡せるようにします。


#### Agents
`researcher`（市場調査担当）と `writer`（マーケティング担当）の 2 種類の Agent を定義します。researcher が調査・分析した情報を参考に、writer が営業ピッチ向けのコンテンツにまとめる役割を果たします。
```python:CrewAI.py
researcher = Agent(
    role = "市場調査担当",
    goal = "特に競合他社と比較したYellowfinの特徴をレポートとしてまとめる",
    backstory = """Yellowfin Japan株式会社に勤務し、日本のBusiness Intelligence市場を調査・分析し、社内にレポートする役割を担う。
    データベースとBusiness Intelligenceの分野に深い知識を有し、機能面、価格面、製品の将来性など、多角的に製品を分析することに長けている。""",
    verbose = True,
    tools = [search],
    llm = llm)

writer = Agent(
    role = "マーケティング担当",
    goal = "営業担当が顧客の前で、Yellowfinの製品としての特徴を説明し、高い興味を持たせることができる営業ピッチを作成する。",
    backstory = """マーケティング担当として、市場調査担当などがまとめたレポートをもとに、マーケティング活動や営業活動に使う資料を作成する。
    読み手が興味を持つようなコンテンツに仕上げることが重要。""",
    verbose = True,
    tools = [search],
    llm = llm)
```

* `role` 役割（市場担当者、マーケティング担当者）を指定します。
* `goal` 業務の目的を記述します。
* `backstory` Agent のキャラクターや業務的背景などを記述します。
* `verbose` True を指定して、途中経過のやり取りをコンソールに表示します。
* `tools` 先の処理で定義した検索オブジェクト [search] を指定します。
* `llm` 先の処理で定義した llm を指定します。

上記情報は、生成 AI のプロンプトからモデルに受け渡され、モデルの振る舞いを左右します。他にも多くのオプション指定が可能です。詳細は[こちら](https://docs.crewai.com/concepts/agents)をご覧ください。

#### Task
researcher と writer に割り当てる task を定義します。
```python:CrewAI.py
task1 = Task(
    description = """日本のBusiness Intelligence市場の最新情報を収集する。
    収集した情報から、Yellowfinが競合他社に対して優位性を誇ることができる部分を中心に分析する。""",
    expected_output ="分析結果を5つの点に分けて箇条書きでまとめる。",
    agent = researcher)

task2 = Task(
    description = """市場調査担当者が調査しまとめたレポートをもとに、営業活動に使える資料として、Yellowfinの優れた機能を5つの点にまとめる。
    特に競合他社と比較したYellowfinの良さを際立たせるための情報を盛り込み、読み手の興味を掻き立てるコンテンツとして仕上げる。""",
    expected_output = "営業が顧客の前で2分間の営業ピッチとして話ができる内容",
    agent = writer)
```

* `description` Agent の動作を指示します。
* `expected_output` アウトプットの出力形式を指定します。
* `agent` タスクを割り当てる Agent を指定します。

#### Crew
```python:CrewAI.py
crew = Crew(
    agents = [researcher, writer],
    tasks = [task1, task2],
verbose = True)

results = crew.kickoff()
print("\n Final Output:\n", results)
```

* `Crew()` 先の手順で定義した agent と task を指定して、crew を構成します。
* `kickoff()` crew の処理を実行し、`print` 結果をコンソールに表示します。

## 実行
#### 途中経過
プログラムを実行すると、コンソール上で途中経過のやり取りが確認できます。
コンソールに出力された約 270 行のやり取りの一部を抜粋します。

* 市場調査担当が、与えられた role や goal などに基づいて、何を実行するかを考えます。
```cmd:市場調査担当 考え中
# Agent: 市場調査担当
## Thought: 日本のBusiness
Intelligence市場の最新情報を収集し、Yellowfinの競合優位性を分析する必要がある。まず、市場の動向、主要プレイヤー、顧客ニ
ーズに関する情報を収集するためにインターネット検索を行う。次に、収集した情報に基づいて、Yellowfinが競合他社に対して優位
性を持つ可能性のある分野を特定し、5つの点にまとめてレポートを作成する。
  <中略>
```

* 考えた結果、最新情報を入手するために、Serper を使ってインターネットに検索の旅に出て、収集した情報を使って内容をまとめました。

```cmd:市場調査担当 タスク実行中
## Using tool: Search the internet with Serper
  <中略>
  
# Agent: 市場調査担当
## Final Answer:
日本のBusiness Intelligence市場におけるYellowfinの競合優位性：
  <中略>
```

* 市場調査担当に与えられたタスクは無事完了です。
```cmd:市場調査担当 タスク完了
🚀 Crew: crew
└── 📋 Task: 7d6f625b-51a7-4363-84c7-5de515a3ff82
    Assigned to: 市場調査担当
    Status: ✅ Completed
    ├── 🔧 Used Search the internet with Serper (1)
    └── 🔧 Used Search the internet with Serper (2)
```
* 続いて、マーケティング担当が、与えられた role や goal などに基づいて、何を実行するかを考えます。
```cmd:マーケティング担当 考え中
# Agent: マーケティング担当
## Thought:
私は、このレポートを基に、営業担当者が顧客に対してYellowfinの魅力を効果的に伝えられるような、2分間の営業ピッチを作成する
必要があります。特に、競合製品と比較したYellowfinの強みを強調し、顧客の関心を引くように構成します。
```

* 考えた結果、最新情報を入手するために、Serper を使ってインターネットに検索の旅に出て、収集した情報を使って内容をまとめました。
```cmd:マーケティング担当 タスク実行中
## Using tool: Search the internet with Serper
  <中略>
  
# Agent: マーケティング担当
## Final Answer:
**Yellowfin：データ活用の新たな可能性を切り拓くBIソリューション**
  <中略>
```
* Crew としてのタスクが全て完了し、営業ピッチがまとまりました。
```cmd:Crew タスク完了
🚀 Crew: crew
├── 📋 Task: 7d6f625b-51a7-4363-84c7-5de515a3ff82
│   Assigned to: 市場調査担当
│   Status: ✅ Completed
│   ├── 🔧 Used Search the internet with Serper (1)
│   └── 🔧 Used Search the internet with Serper (2)
└── 📋 Task: ede6130f-66ee-458b-86f5-ff5339862810
    Assigned to: マーケティング担当
    Status: ✅ Completed
    └── 🔧 Used Search the internet with Serper (3)
```

#### Final Output
どのような内容にまとまったのか確認してみようと思います。
競合に対する優位性を強調する営業ピッチとしては、なかなか上手くまとまっています。

```cmd:Final Output
Final Output:
 **Yellowfin：データ活用の新たな可能性を切り拓くBIソリューション**

「御社では、データ分析に課題を感じていませんか？ Yellowfinは、その課題を解決し、データドリブンな意思決定を加速させるBIソリューションです。本日は、Yellowfinが競合他社と比べていかに優れているか、5つのポイントに絞ってご紹介いたします。」

1.  **「自動分析で、データから目を離さない」** Yellowfinは、高度な自動分析機能を搭載。異常検知や要因分析により、データ内の重要な変化やトレンドを自動的に特定し、その理由を明確にします。データサイエンティストがいなくても、迅速かつ深いインサイトを得られます。競合製品では、高度な分析には専門知識が必要な場合が多いですが、Yellowfinなら誰でも簡単にデータ分析を始め られます。
2.  **「柔軟な組み込みで、ビジネスを加速する」** Yellowfinは、他のアプリケーションやシステムへの組み込みが非常に容易です。既存のワークフローやプラットフォームにBI機能をスムーズに統合し、企業独自のブランドイメージに合わせたBI環境を構築できます。カスタマイズの自由度が高く、競合製品と比較して、より柔軟なBI戦略を実現できます。
3.  **「直感的な操作性で、誰もがデータ分析のエキスパートに」** Yellowfinは、非技術者でも簡単にデータ分析を行えるように、直感的なインターフェースを備えています。IT部門のサポートを待つことなく、ビジネスユーザー自身がデータから必要な情報を引き出し、分析できます。競合製品には、操作が複雑で習得に時間がかかるものもありますが、Yellowfinなら導入したその日から、デー タ活用を始められます。
4.  **「データストーリーテリングで、情報を魅力的に伝える」** Yellowfinは、データに基づいてストーリーを語るための独自の機能を備えています。分析結果をわかりやすく、説得力のある形で伝えられるため、データに基づいた意思決定を促進し、組織全体のデータリテラシー向上に貢献します。単なるデータの羅列ではなく、ストーリーとして伝えることで、より深い理解と共感を呼び起こします。
5.  **「価格競争力で、ROIを最大化する」** Yellowfinは、競合製品と比較して、価格競争力があります。特に、中小企業や、大規 模なBI投資を行うことが難しい企業にとって、Yellowfinは費用対効果の高い選択肢となります。導入規模や契約条件によって価格は 異なりますが、まずはお気軽にお見積もりをご依頼ください。

「Yellowfinは、御社のデータ活用を強力にサポートし、ビジネスの成長に貢献できると確信しております。ご興味をお持ちいただけ ましたら、ぜひ詳細なデモンストレーションをご体験ください。」
```

#### 最後に
マルチ AI エージェントを自律的に動作させ、チームとして協業させるという発想は、時代の流れに非常によく合っていると感じました。スマートグリッドや交通管制など、多くの機能を統制する必要がある技術分野では、自律的に動作する AI エージェントが機能毎に存在し、それらをお互いに協業させて処理を実施させるというのは、極めて理にかなった考えと言えます。

一方、フレームワークを利用することで、実装はとても楽でした。
また、今回は 2 つのエージェントが、researcher > writer の順に処理を進めるだけでしたが、もっと複雑な連携の形態を取ることも可能です。

これを機に、CrewAI 以外のフレームワークも是非試してみようと思います。

では皆様、良いデータ分析を！

#### 参考情報

https://www.crewai.com/

https://medium.com/@sushmita2310/build-your-first-ai-agent-with-crew-ai-and-gemini-on-google-colab-bce7a289de1c

https://medium.com/accredian/understanding-crewai-a-deep-dive-into-multi-agent-ai-systems-110d04703454