🙆‍♀️

BeeAI Framework の Quick example を試してみる

に公開

🐝はじめに

前回の記事「BeeAI 入門」では、BeeAIプロジェクトと、その中核を成す BeeAI Framework の概要や目的について紹介しました。

今回は、実際に BeeAI Framework を触ってみた最初の一歩として、公式リポジトリのReadMeにあるQuick example(簡単な動作確認用のサンプル)を動かしてみた体験を紹介します。

コードを読みながら気づいた点や、使ってみて「これは面白い」と感じた部分、逆に「ここはもう少し深掘りしたい」と思ったところなどを、率直にまとめました。

まだ公開されて間もない新しいフレームワークですが、同じように「ちょっと試してみようかな」と思っている方の参考になれば嬉しいです。

🛠 セットアップ

BeeAI Framework のインストールはとてもシンプルで、基本的には pip install だけで始められます。
BeeAI には TypeScript 実装もありますが、今回の記事では Python 実装を使います。
また、BeeAI プロジェクトの中には BeeAI Platform のように事前準備がやや多めのコンポーネントもありますが、BeeAI Framework 自体は軽量で、気軽に試せるのが良いところです。

📌 今回の環境
OS: Windows 11
Python: 3.11
BeeAI Framework: v0.1.17
接続先LLM: サンプルではollama:granite3.1ですが、今回はAzureOpenAI gpt-4oに変更

📦 インストール手順
まずは公式 README に従って、以下のコマンドでインストール:

pip install beeai-framework

ただし、Quick example を動かすには追加で wikipedia オプションも必要でした:

pip install beeai-framework[wikipedia]

README には明記されていなかったのですが、このオプションを入れないと Wikipedia 経由のツールでエラーが出てしまったので、こちらもインストールしておきましょう。

🚀 Quick example を実行してみる

BeeAI Framework の Python 実装には、すぐに試せる Quick example が用意されています。
今回はこれを少しだけカスタマイズして、Azure OpenAI のモデル(gpt-4o)で実行してみました。

✅ 事前準備:.env ファイルの作成
GitHub リポジトリにある .env.example を参考に、.env ファイルを作成します。

.env
AZURE_OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AZURE_OPENAI_API_BASE=https://your-resource-name.openai.azure.com/
AZURE_OPENAI_API_VERSION=2024-10-21
AZURE_OPENAI_CHAT_MODEL=gpt-4o-deploymentname

また、.env ファイルをコード内で読み込むため、スクリプトの先頭に以下を追加します:

from dotenv import load_dotenv  # .envファイルの読み込みに必要
load_dotenv()

🧠 利用モデルの変更
BeeAI Framework では ChatModel.from_name() で LLM を指定できますが、今回は Azure OpenAI 上の gpt-4o を使用したかったので、以下のようにモデル名を変更しました:

async def main() -> None:
    llm = ChatModel.from_name("azure:gpt-4o-deploymentname")  # 利用モデルを変更
    workflow = AgentWorkflow(name="Smart assistant")

このあたりのモデル指定の柔軟さも、BeeAI Framework の良いところですね。

🛠 出力処理のエラー修正
ワークフローの実行結果を表示するコードにおいて、response.result.final_answer にアクセスする際、response.result が None の可能性があるため、コード作成時にエラーとなりました。
そのため、以下のように None チェックを入れておきました:

if response.result is not None:
    print(response.result.final_answer)
else:
    print("エラー: ワークフローの実行結果がありません。")

📝 プロンプトを日本語に変更
デフォルトでは英語の指示文が使われていましたが、日本語でも問題なく動作しました。
今回はプロンプトをすべて日本語に書き換えて、より実運用に近い形で試してみました。

💬 実行結果
このサンプルでは、エージェントがフランスのサントロペを調査するシナリオになっています。
その結果、以下のような回答が返ってきました:

$ python beeai_framework_quick_example_jp.py 

-> ステップ「リサーチャー」が完了しました。結果:

サントロペはフランス南部のヴァール県に位置するリゾート地です。20世紀初頭までは小さな漁村でしたが、1950年代にフランスを代表するアーティストたちが夏を過ごす場所として人気を集め、コート・ダジュールのリゾート地として世界的に知られるようになりました。詳しくは[こちら](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%B3%E3%83%88%E3%83%AD%E3%83%9A)を ご覧ください。

-> ステップ「天気予報士」が完了しました。結果:

サントロペ(フランス)の本日の天気をお伝えします。

- **気温**: 現在の気温は13.6°Cで、最高気温は21.3°C、最低気温は11.6°Cです。
- **降水確率**: 本日は降水量が0mmで、雨の心配はありません。
- **湿度**: 現在の湿度は67%です。
- **風**: 風速は10.9km/hで、穏やかな風が吹いています。

快適な天候が予想されますので、屋外での活動に適した一日となりそうです。

-> ステップ「データ統合者」が完了しました。結果:

サントロペはフランス南部のヴァール県に位置する美しいリゾート地で、かつては小さな漁村でした。1950年代にフランスの著名なアーティストたちが訪れるようになり、コート・ダジュールを代表する観光地として世界的に知られるようになりました。

本日のサントロペの天気は快適で、現在の気温は13.6°C、最高気温は21.3°C、最低気温は11.6°Cです。降水量は0mmで雨の心配 はなく、湿度は67%と過ごしやすい環境です。風速は10.9km/hで穏やかな風が吹いており、屋外での活動に適した一日となりそ うです。
==== 最終回答 ====
サントロペはフランス南部のヴァール県に位置する美しいリゾート地で、かつては小さな漁村でした。1950年代にフランスの著名なアーティストたちが訪れるようになり、コート・ダジュールを代表する観光地として世界的に知られるようになりました。

本日のサントロペの天気は快適で、現在の気温は13.6°C、最高気温は21.3°C、最低気温は11.6°Cです。降水量は0mmで雨の心配 はなく、湿度は67%と過ごしやすい環境です。風速は10.9km/hで穏やかな風が吹いており、屋外での活動に適した一日となりそ うです。

Wikipedia からの情報と天気の情報をベースに、Quick example とはいえしっかりとした返答が得られました。

🧩 コードの説明

Quick example のサンプルコードは以下の主要コンポーネントで構成されています:

Workflow:全体の制御ロジック
Agent:特定のタスクを担う実行単位(専門家のようなイメージ)
Tool:Agent が外部データを取得するための道具(APIラッパーなど)

🔄 実際の連携の流れ
ワークフローは以下のように、複数の Agent を順に呼び出して、情報を収集・統合していきます:

  1. Workflow が全体の制御を担当
  2. リサーチャーAgent が WikipediaTool を使って歴史に関する情報を取得
  3. 天気予報士Agent が OpenMeteoTool を使って現在の天気情報を取得
  4. データ統合者Agent はツールを使用せず、前段の Agent の出力を受け取り、それらを統合して最終的な回答(要約)を生成

⚙️ Workflowの実行とイベント処理
Workflow は非同期(asyncio)で実行され、処理完了は "success" イベントとして検知されます。
このイベントをトリガーに、後続の処理(今回のケースでは response.result.final_answer の出力)が実行される、という流れです。

このように、Agent 同士を繋いでいくスタイルは、LLMベースのマルチエージェント構成を手軽に試すにはちょうど良く、コードも読みやすいものとなっています。

なお、この記事内で実際に動作確認したコード(環境設定・プロンプト修正・モデル指定の変更含む)は、記事の最後に全文を添付しています。
「まずは動かしてみたい!」という方は、そちらもぜひご活用ください。

🧠 考察

今回はまだ超シンプルなサンプルを一つ動かしてみただけですが、それでもいくつか印象的だったポイントがあります。良かった点、そして今後もう少し深掘りしたい点を、自分なりの技術的な視点も交えてまとめてみます。

👍 良かった点

  1. シンプルで直感的な設計
  • 基本構成は Workflow、Agent、Tool の3要素のみ
  • APIも素直で、構成を理解しやすい
  1. 柔軟なエージェント定義
  • エージェントごとに「役割」と「使用ツール」を明確に分離
  • 必要に応じてエージェントを足すだけで機能追加できるのが良いと感じました
  1. 非同期&イベントベースの設計
  • asyncio による非同期実行、イベントでの進捗管理など、実装時の制御性も高そうです

🔍 気になった点・今後深掘りしたいところ

  1. メモリ管理と状態共有
  • このサンプルでは明示的な「メモリ」コンポーネントは含まれていませんでした
  • エージェント間でのアウトプット共有やコンテキスト管理の仕組みがどうなっているのかは要調査
  1. エラーハンドリング
  • エージェントやツールの失敗時にどう自律的に回復できるのか
  • アプリ側でどこまで介入・制御できるのかが気になります
  1. ツールの拡張性
  • ビルトインツールのカスタマイズ性
  • 独自ツールを追加する方法と、他エージェントからの使い回しなどの実装方法も試してみたいところです
  1. 複雑なワークフローの構築
  • 条件分岐やループ処理、並列実行など、高度なワークフローが組めるのか
  • 定義方法やビジュアルエディタの有無も今後のポイントになりそうです
  1. GUIツールとの連携性
  • GUIツールとの相性も今後の選択肢として気になるところです(メモ:Chainlit 2.0.5 の場合は aiofiles バージョン競合が発生)

🐝さいごに

BeeAI Framework は、シンプルながら「エージェントで組む面白さ」を手軽に試せるフレームワークでした。
個人的には、「まずは使ってみたい」「自作エージェントを試したい」という人にちょうどいい立ち位置だと思います。
気になる点もいくつか見えてきたので、次はもう少し複雑なケースにもチャレンジしてみたいところです。

実際に動かした修正済みコードは、記事の最後に全文を載せているので、興味のある方はそちらもぜひ参考にしてみてください。

📝修正済みコード

beeai_framework_quick_example_jp.py
import asyncio
from beeai_framework.backend.chat import ChatModel
from beeai_framework.tools.search.wikipedia import WikipediaTool
from beeai_framework.tools.weather.openmeteo import OpenMeteoTool
from beeai_framework.workflows.agent import AgentWorkflow, AgentWorkflowInput

from dotenv import load_dotenv  # .envファイルから環境変数を読み込むために必要
load_dotenv()  # .envファイルから環境変数を読み込むために必要

async def main() -> None:
    llm = ChatModel.from_name("azure:gpt-4o-2024-11-20") # 利用モデルを変更
    workflow = AgentWorkflow(name="Smart assistant")

    workflow.add_agent(
        name="リサーチャー",
        role="勤勉な調査員",
        instructions="特定のトピックについて調べて情報を提供してください。",
        tools=[WikipediaTool()],
        llm=llm,
    )

    workflow.add_agent(
        name="天気予報士",
        role="天気を伝えるレポーター",
        instructions="詳細な天気予報を提供してください。",
        tools=[OpenMeteoTool()],
        llm=llm,
    )

    workflow.add_agent(
        name="データ統合者",
        role="几帳面で創造的なデータ統合者",
        instructions="さまざまな情報をまとめて、最終的な一貫した要約を作成してください。",
        llm=llm,
    )

    location = "サントロペ"

    response = await workflow.run(
        inputs=[
            AgentWorkflowInput(
                prompt=f"{location}の簡単な歴史を教えてください。",
            ),
            AgentWorkflowInput(
                prompt=f"{location}の本日の天気を詳しくまとめてください。",
                expected_output="降水確率、気温、風などの主要な天気情報を、分かる範囲で報告してください。",
            ),
            AgentWorkflowInput(
                prompt=f"{location}の歴史と天気情報をまとめて要約してください。",
                expected_output=f"{location}の歴史を説明した後、現在の天気状況を続けて記述した段落を作成してください。",
            ),
        ]
    ).on(
        "success",
        lambda data, event: print(
            f"\n-> ステップ「{data.step}」が完了しました。結果:\n\n{data.state.final_answer}"
        ),
    )

    print("==== 最終回答 ====")
    # 変更: response.resultはNoneではないことを確認
    if response.result is not None:
        print(response.result.final_answer)
    else:
        print("エラー: ワークフローの実行結果がありません。")

if __name__ == "__main__":
    asyncio.run(main())
DXC Lab

Discussion