Closed14

YAMLでエージェントワークフローを定義できるフレームワーク「FloAI」を試す

kun432kun432

多分Redditで見かけた。

https://github.com/rootflo/flo-ai

Flo AI 🌊

最小限のコードで実稼働可能なAIエージェントとチームを構築

Flo AIは、YAMLを記述するのと同じくらい簡単に、実稼働可能なAIエージェントとチームを構築できるPythonフレームワークです。「AIエージェントのためのKubernetes」と考えてください。独自のAIアーキテクチャを作成する柔軟性を維持しながら、事前構築されたコンポーネントを使用して複雑なAIアーキテクチャを構成できます。

✨ 機能

  • 🔌 本当に構成可能:より小さく再利用可能なコンポーネントを組み合わせることで、複雑なAIシステムを構築
  • 🏗️ 実稼働可能:実稼働環境へのデプロイメントのためのベストプラクティスと最適化が組み込まれています
  • 📝 YAML-First: シンプルなYAMLでエージェントのアーキテクチャ全体を定義
  • 🔧 柔軟性: 事前構築されたコンポーネントを使用するか、独自のコンポーネントを作成
  • 🤝 チーム志向: 連携して動作するAIエージェントのチームを作成および管理
  • 📚 RAGサポート: 検索拡張型生成のための組み込みサポート
  • 🔄 Langchainとの互換性: お気に入りのLangchainツールすべてと連携

🌟Flo AIを選ぶ理由

AIエンジニア向け

  • 開発の高速化:複雑なAIシステムを数日ではなく数分で構築
  • 実用重視:最適化とベストプラクティスを内蔵
  • 柔軟性:当社のコンポーネントを使用するか、独自のコンポーネントを構築

チーム向け

  • 保守性:YAMLを第一に考えるアプローチにより、システムを理解し、修正することが容易
  • 拡張性:単一エージェントから複雑なチーム階層まで
  • テスト可能:各コンポーネントは個別にテスト可能

🎯 使用例

  • 🤖 カスタマーサービスの自動化
  • 📊 データ分析パイプライン
  • 📝 コンテンツ生成
  • 🔍 研究の自動化
  • 🎯 タスク別AIチーム

Quick Startのコードを見る限り、YAMLでコンポーネントを定義して、実行するだけ、みたいなシンプルな感じに思える。あと、考え方としてはCrewAI的な「チーム」を作るような雰囲気に見える。

kun432kun432

開発元のrootfloって何してる会社なのかな?と思って調べてみたけど、

https://www.rootflo.ai/

どうやらオンラインショッピング・オンラインバンキングなどに特化したAIエージェントを作ってるらさいく、それらの業界に特化して、業務効率化・顧客体験のパーソナライズ・顧客エンゲージメントとコンバージョン率の向上あたりをウリにしているみたい。

kun432kun432

公式ドキュメントはこちら

https://flo-ai.rootflo.ai/

🚀FloAIにようこそ

Floは、AIエージェントアーキテクチャの作成を簡素化するコンポーザブルフレームワークです。複雑なAIシステムに必要なパワーと洗練さを維持しながら、エージェントベースのアプリケーションを構築するための柔軟なモジュール式アプローチを提供します。

人工知能の風景は、大規模言語モデル(LLM)によって劇的に変化しました。これらの強力なニューラルネットワークは、人間のようなテキストの理解と生成、複雑な問題の推論、さらにはコードの記述においても、目覚ましい能力を発揮しています。しかし、LLMだけでは、AIアプリケーションで可能なことの始まりに過ぎません。

LLMはテキストの処理と生成に優れていますが、AIエージェントは、重要な要素を追加することで、これらの能力をさらに向上させます。

  • 自律性:独自に意思決定を行い、行動を起こす能力
  • 記憶:文脈を維持し、過去のやり取りから学習する
  • 目標指向の行動:指示に応答するだけでなく、特定の目標に向かって取り組む
  • ツールの使用:外部システムやAPIと統合し、タスクを達成する
  • 状態管理:進捗状況を追跡し、複雑なワークフローを管理する

AIエージェントは、「エージェンシーを備えたLLM」と考えることができます。問い合わせに応答するだけでなく、目標に向かって能動的に作業を行い、長時間のタスクを維持し、複雑な作業を調整することができます。この進歩により、パーソナルアシスタントから複雑な一連のタスクを実行できる自律システムまで、AIアプリケーションにまったく新しい可能性が開かれました。

しかし、高度なAIエージェントを構築するには、独自の課題があります。開発者はしばしば、以下のような問題に直面します。

  • 一般的なアーキテクチャ・パターンの再実装
  • エージェント・コンポーネント全体にわたる状態管理に苦労
  • ゼロから複雑な調整メカニズムを構築
  • 異なるAI機能間の統合に関する課題への対応

そこでFloAIの出番です。

kun432kun432

Quick Start

以下に従って進める。

https://flo-ai.rootflo.ai/getting-started/quickstart

最初はColaboratoryで試してみたんだけど、多分ipythonのバージョンが問題になって、ランタイムがクラッシュしてしまう。今回はローカルのJupyterLabで試そうと思う。

事前準備&インストール

仮想環境+JupyterLabは適宜用意、自分はmiseを使っているのでこんな感じ。

$ mkdir floai-work && cd floai-work
$ mise use python@3.11
$ cat << 'EOS' >> .mise.toml

[env]
_.python.venv = { path = ".venv", create = true }
EOS
$ mise trust

JupyterLabをインストール

$ pip install jupyterlab ipywidgets

flo-aiのパッケージをインストール。.env読み込みのためのpython-dotenvもあわせて。

$ pip install flo-ai python-dotenv
 $ pip freeze | grep -i flo-ai
flo-ai==0.0.3

.envにOPEN_AI_APIキーをセット。あとGetting StartedではTavilyを使った検察をツールとしてエージェントで与えるようなので、こちらもあわせてAPIキーをセットしておく。

.env
OPENAI_API_KEY=XXXXXXXXXXXX
TAVILY_API_KEY=XXXXXXXXXXXX

JupyterLab起動

$ jupyter-lab --ip="0.0.0.0" --NotebookApp.token=""

以降はJupyterLab上で。

エージェントの作成

FloAIでは、YAMLで「エージェント」「ツール」などのコンポーネントおよびそれらの挙動を設定することで、ワークフローを作成・実行することができる。

最初に、インターネット検索をツールとしてもつ、任意のトピックについてのブログ記事を書くAIエージェントを作ってみる。

まず.envを読み込み

from dotenv import load_dotenv

load_dotenv(verbose=True)

LLMを定義。FloAIはま内部でLangChainを使用しているので、LangChainのLLMオブジェクトを作成すればよい。

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model_name='gpt-4o-mini')
ModuleNotFoundError: No module named 'langchain_openai'

お、ここは個別でインストールしないといけないのか・・・ということでインストール。多分Tavilyのツールなども後で必要になりそうなので、まとめて。

!pip install langchain langchain-openai langchain-community tavily-python

再度実行して問題なし

```python
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model_name='gpt-4o-mini')

次にエージェントのワークフローをYAMLで定義する。エージェントの名前、役割、ゴール、使用可能なツールなどを定義する。少しK8Sっぽい記述になっているのがわかる。ちなみにnameには日本語を指定できなかった。

agent_yaml = """
apiVersion: flo/alpha-v1
kind: FloAgent
name: blogging-agent
agent:
    name: Blogger
    job: >
      あなたは、与えられたトピックについて、インターネットで調査を行い、ブログ記事を作成することができます。
    tools:
      - name: TavilySearchResults
"""

そして、ツールをセッションに登録して、YAMLからワークフローを作成する。

from flo_ai import Flo, FloSession
from langchain_community.tools.tavily_search.tool import TavilySearchResults

# ツールを登録してセッションを作成
session = FloSession(llm).register_tool(
    name="TavilySearchResults", 
    tool=TavilySearchResults()
)

# YAML定義からFlo(ワークフロー)をビルド
flo: Flo = Flo.build(session, yaml=agent_yaml)

作成されたっぽい。

2024-10-22 14:08:12,998 - SESSION - INFO - New FloSession created with ID: sqwy4edTgtlEmHvD
2024-10-22 14:08:12,999 - SESSION - INFO - Tool 'TavilySearchResults' registered for session sqwy4edTgtlEmHvD
2024-10-22 14:08:13,000 - BUILDER - INFO - Building Flo instance from YAML
2024-10-22 14:08:13,008 - COMMON - INFO - Flo instance created for session sqwy4edTgtlEmHvD

ではワークフローを実行する。

# 入力プロンプト
input_prompt = """
2024年秋の競馬GIレースの展望について、興味深いブログを書いてください。
"""

# ワークフローを実行して、結果を出力
for response in flo.stream(input_prompt):
    if "__end__" not in response:
        print(response)
        print("----")

結果

## 2024年秋の競馬GIレース展望

2024年の秋競馬シーズンがいよいよ始まります。今年の注目は、10月27日に東京競馬場で開催される「天皇賞(秋)」です。このレースは、古馬の中距離王者が集結する重要なGIレースであり、多くの競馬ファンが待ち望んでいます。今回は、天皇賞(秋)に向けた展望をお届けします。

### 注目馬と競争情勢

天皇賞(秋)では、特に注目されるのが「ドウデュース」と「リバティアイランド」です。ドウデュースは過去のレースでも素晴らしい成績を残しており、今回の舞台でも期待が高まります。一方、リバティアイランドはそのスピードとスタミナで観客を魅了しており、彼女のパフォーマンスにも注目です。

過去10年のデータを見ると、リバティアイランドがやや優勢との声もありますが、ドウデュースも負けてはいません。特に、両馬の直近のパフォーマンスを考慮すると、どちらが勝つか予測が難しい状況です。

### レースの舞台

天皇賞(秋)は、東京競馬場の芝2000mで行われます。このコースは、スピードと持久力が求められるため、選手たちの戦略が大きく影響します。特に、スタートからの位置取りや、ペース配分が勝敗を左右する要素となります。

### 競馬ファンへのメッセージ

秋の競馬シーズンは、ただレースを楽しむだけでなく、馬や騎手、調教師たちの物語を感じる絶好の機会です。レース前の緊張感や期待感、そしてレース後の感動は、競馬の醍醐味です。

2024年の天皇賞(秋)は、ドウデュースとリバティアイランドの対決に加え、他の強豪馬たちの挑戦もあるため、目が離せません。ファンの皆さんも、ぜひレースを楽しみにしていてください。

### まとめ

2024年秋の競馬GIレース、特に天皇賞(秋)は、競馬の魅力を存分に味わえるイベントです。馬たちの熱い戦いを見逃さないようにしましょう。最終的に、どの馬が栄冠を手にするのか、今から楽しみです!
kun432kun432

チームの作成

最初の例では1人のエージェントだけになっていた。次に複数のエージェントがチームとして動作するのを試してみる。

from flo_ai import Flo
from flo_ai import FloSession
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search.tool import TavilySearchResults

llm = ChatOpenAI(temperature=0, model_name='gpt-4o-mini')

team_yaml = """
apiVersion: flo/alpha-v1
kind: FloRoutedTeam
name: blogging-flo
team:
    name: BloggingTeam
    router:
        name: TeamLead
        kind: supervisor
    agents:
      - name: Researcher
        role: リサーチャー
        job: インターネットでリサーチを行い、ユーザーが尋ねたトピックに関連する記事を見つけ、常に最新の情報を探すようにしてください。
        tools:
          - name: TavilySearchResults
      - name: Blogger
        role: ブロガー
        kind: llm
        job: リサーチャーが提供した資料を元に、すぐに公開できる300語程度のブログ記事を書いて、それを魅力的なものにブラッシュアップし、元のブログ記事への参照リンクを引用・脚注として追加してください。
"""

session = FloSession(llm).register_tool(
    name="TavilySearchResults", 
    tool=TavilySearchResults()
)

flo: Flo = Flo.build(session, yaml=team_yaml)

flo.invoke("Topic: 2024年秋の競馬GIレースの展望")

ここではBloggingTeamというチームにResearcherBloggerという2人のエージェントを定義、そしてTeamLeadというルーターがこれらのエージェント間の処理フローを制御するというものになっている。

実行結果は以下。

{
  'messages': [
    HumanMessage(
      content='Topic: 2024年秋の競馬GIレースの展望'
    ),
    HumanMessage(
      content='2024年秋の競馬GIレースについての展望を以下にまとめます。\n\n### 主要レース\n1. **天皇賞(秋)**\n   - 日程: 2024年10月27日\n   - コース: 東京芝2000m\n   - 競走馬の中で注目されるのは、過去の成績やコース相性が良い馬です。特に、最近のレースで好成績を収めている馬が期待されています。\n   - 詳細な情報は[こちら](https://m-jockey.co.jp/keiba-navi/jra/tennosho-autumn/)で確認できます。\n\n2. **ジャパンカップ**\n   - 日程: 2024年11月24日\n   - 国際的なレースであり、海外からの強豪馬も参加するため、非常に注目されるレースです。\n   - 過去の成績や馬の調子を考慮した予想が重要です。\n\n3. **有馬記念**\n   - 日程: 2024年12月22日\n   - 年末の大一番として位置づけられ、多くのファンが注目します。出走馬の選定や調教状況がレース結果に大きく影響します。\n\n### 競馬ファンの期待\n- 競馬ファンは、各レースにおいて高い回収率を目指しており、特に天皇賞(秋)やジャパンカップでは、コース相性や馬の調子を重視した予想が求められます。\n- 競馬専門家の分析や過去のデータを基にした予想が、レースの結果に大きく影響することが予想されます。\n\n### 参考情報\n- 詳細なレース情報や出馬表、オッズなどは、[netkeiba](https://race.netkeiba.com/special/index.html?id=0109)や[Yahoo!スポーツ](https://sports.yahoo.co.jp/m/keiba/schedule/yearly?year=2024&type=g1)で確認できます。\n\nこれらの情報を基に、2024年秋の競馬GIレースに向けた準備を進めることができるでしょう。',
      name='Researcher'
    ),
    HumanMessage(
      content='### 2024年秋の競馬GIレース展望\n\n2024年の秋、競馬ファンにとって待望のGIレースが続々と開催されます。特に注目すべきは、天皇賞(秋)、ジャパンカップ、有馬記念の3つのレースです。それぞれのレースには、期待の競走馬が揃い、熱い戦いが繰り広げられることでしょう。\n\n**天皇賞(秋)**は、2024年10月27日に東京芝2000mで行われます。過去の成績やコース相性が良い馬が注目されており、最近のレースで好成績を収めている馬が特に期待されています。詳細な情報は[こちら](https://m-jockey.co.jp/keiba-navi/jra/tennosho-autumn/)で確認できます。\n\n続いて、**ジャパンカップ**は2024年11月24日に開催される国際的なレースです。海外からの強豪馬も参加するため、非常に注目度が高いレースとなります。過去の成績や馬の調子を考慮した予想が重要です。\n\nそして、年末の大一番である**有馬記念**は2024年12月22日に行われます。このレースは多くのファンが注目し、出走馬の選定や調教状況がレース結果に大きく影響します。\n\n競馬ファンは、各レースにおいて高い回収率を目指しており、特に天皇賞(秋)やジャパンカップでは、コース相性や馬の調子を重視した予想が求められます。競馬専門家の分析や過去のデータを基にした予想が、レースの結果に大きく影響することが予想されます。\n\n詳細なレース情報や出馬表、オッズなどは、[netkeiba](https://race.netkeiba.com/special/index.html?id=0109)や[Yahoo!スポーツ](https://sports.yahoo.co.jp/m/keiba/schedule/yearly?year=2024&type=g1)で確認できます。これらの情報を基に、2024年秋の競馬GIレースに向けた準備を進めていきましょう。\n\n---\n\n参考文献: [2024年秋の競馬GIレースの展望](https://m-jockey.co.jp/keiba-navi/jra/tennosho-autumn/)',
      name='Blogger'
    )
  ],
 'next': 'FINISH'
}

ResearcherBloggerそれぞれの出力を取り出すとこんなになっている

Researcher

2024年秋の競馬GIレースについての展望を以下にまとめます。

### 主要レース
1. **天皇賞(秋)**
   - 日程: 2024年10月27日
   - コース: 東京芝2000m
   - 競走馬の中で注目されるのは、過去の成績やコース相性が良い馬です。特に、最近のレースで好成績を収めている馬が期待されています。
   - 詳細な情報は[こちら](https://m-jockey.co.jp/keiba-navi/jra/tennosho-autumn/)で確認できます。

2. **ジャパンカップ**
   - 日程: 2024年11月24日
   - 国際的なレースであり、海外からの強豪馬も参加するため、非常に注目されるレースです。
   - 過去の成績や馬の調子を考慮した予想が重要です。

3. **有馬記念**
   - 日程: 2024年12月22日
   - 年末の大一番として位置づけられ、多くのファンが注目します。出走馬の選定や調教状況がレース結果に大きく影響します。

### 競馬ファンの期待
- 競馬ファンは、各レースにおいて高い回収率を目指しており、特に天皇賞(秋)やジャパンカップでは、コース相性や馬の調子を重視した予想が求められます。
- 競馬専門家の分析や過去のデータを基にした予想が、レースの結果に大きく影響することが予想されます。

### 参考情報
- 詳細なレース情報や出馬表、オッズなどは、[netkeiba](https://race.netkeiba.com/special/index.html?id=0109)[Yahoo!スポーツ](https://sports.yahoo.co.jp/m/keiba/schedule/yearly?year=2024&type=g1)で確認できます。

これらの情報を基に、2024年秋の競馬GIレースに向けた準備を進めることができるでしょう。

Blogger

### 2024年秋の競馬GIレース展望

2024年の秋、競馬ファンにとって待望のGIレースが続々と開催されます。特に注目すべきは、天皇賞(秋)、ジャパンカップ、有馬記念の3つのレースです。それぞれのレースには、期待の競走馬が揃い、熱い戦いが繰り広げられることでしょう。

**天皇賞(秋)**は、2024年10月27日に東京芝2000mで行われます。過去の成績やコース相性が良い馬が注目されており、最近のレースで好成績を収めている馬が特に期待されています。詳細な情報は[こちら](https://m-jockey.co.jp/keiba-navi/jra/tennosho-autumn/)で確認できます。

続いて、**ジャパンカップ**は2024年11月24日に開催される国際的なレースです。海外からの強豪馬も参加するため、非常に注目度が高いレースとなります。過去の成績や馬の調子を考慮した予想が重要です。

そして、年末の大一番である**有馬記念**は2024年12月22日に行われます。このレースは多くのファンが注目し、出走馬の選定や調教状況がレース結果に大きく影響します。

競馬ファンは、各レースにおいて高い回収率を目指しており、特に天皇賞(秋)やジャパンカップでは、コース相性や馬の調子を重視した予想が求められます。競馬専門家の分析や過去のデータを基にした予想が、レースの結果に大きく影響することが予想されます。

詳細なレース情報や出馬表、オッズなどは、[netkeiba](https://race.netkeiba.com/special/index.html?id=0109)[Yahoo!スポーツ](https://sports.yahoo.co.jp/m/keiba/schedule/yearly?year=2024&type=g1)で確認できます。これらの情報を基に、2024年秋の競馬GIレースに向けた準備を進めていきましょう。

---

参考文献: [2024年秋の競馬GIレースの展望](https://m-jockey.co.jp/keiba-navi/jra/tennosho-autumn/)
kun432kun432

コアコンセプト

https://flo-ai.rootflo.ai/getting-started/core-concepts

FloAIには複数のコンポーネントが用意されている。各コンポーネントはそれぞれ異なる役割を持ち、これらを組み合わせる(場合によっては拡張・変更する)ことで、柔軟なエージェントワークフローを作成できるという考え方の様子。

主要なコンポーネントの基本コンセプトは以下。

エージェント

  • 環境・データソース・APIと連携して、自律的にタスクを実行するのがエージェント
  • メール送信やデータベース更新などのツールを持つことができる
  • LLMエージェント、エージェント的エージェント、移譲エージェントなど、複数の種類のエージェントがある

ツール

  • エージェントが外部と連携し、具体的なタスクを実行するための基本要素がツール
  • エージェントの「手」として、情報処理だけでなく具体的な行動を取る
  • 特定の明確なアクションを実行するための関数
    • 構造化された入力を受け、明確な出力を返す
    • 外部システムやAPI、サービスと連携
    • 実世界でのタスクやデータ操作を実行

チーム

  • ルーターで接続された複数のエージェントで構成されるのがチーム
  • 複数のエージェントが協力してタスクを遂行
  • ルーターがチーム内の制御フローを決定
  • スーパーバイザー、リニア、LLMなどの異なる種類のルーターがあある

ルーター

  • ルーターはチーム内やチーム間の実行フローを制御する高レベルコンポーネント
  • ルーターに追加される要素によって、エージェントやチームの実行方法が決定される

構成やコンポーネントの種類によって変わると思うけど、こんな感じかな

kun432kun432

ここからは各コンポーネントごとにどのような種類があるのかを見ていく。

エージェント

https://flo-ai.rootflo.ai/basics/agents

まず基本的なエージェントのYAML定義

name: WeatherAssistant # エージェントの名前
kind: agentic          # エージェントの種類。オプション。デフォルトは"agentic"
job: >                 # エージェントのタスクの定義
  あなたは、与えられた都市名の最新の天気状況を、インターネットで検索して、回答することができます
tools:                 # エージェントが利用できるツールのリスト
  - name: InternetSearchTool

ただしエージェントの種類によっては追加で定義できる項目もある様子。

エージェントの種類

FloAIでは、現時点(v0.0.3)では以下の5つのエージェントが用意されている。

  1. Agentic Agents
  2. LLM Agents
  3. Tool Agents
  4. Reflection Agents
  5. Delegation Agents

1. Agentic Agents

デフォルトのエージェント。ツール利用が前提となり、エージェントがAPIやデータベースなど外部システムとやり取りする場合に使う。

逆に言うと、ツールの定義がない場合は例外が発生してしまう。ツールが不要な場合は後述するLLM Agentsを使う。

Agentic AgentsのYAML定義の例
apiVersion: flo/alpha-v1
kind: FloAgent
name: weather-assistant
agent:
    name: WeatherAssistant
    kind: agentic
    job: >
      あなたは、与えられた都市名の最新の天気状況を、インターネットで検索して、回答することができます
    tools:
      - name: InternetSearchTool

2. LLM Agents

ツールなし、LLMとだけやり取りできるエージェント。外部連携不要で、LLMを使って、例えば、要約させるとか(ワークフローの前ステップの)実行結果を踏まえた意思判断をさせる、といった場合に使う。

LLM AgentsのYAML定義の例
apiVersion: flo/alpha-v1
kind: FloAgent
name: llm-assistant
agent:
    name: Ask llm anything
    kind: llm
    job: >
      あなたは高校の数学教師です。生徒が質問したことには何でも答えてください。

3. Tool Agents

LLM Agentとは逆に、LLMを使わずに、ツール実行だけを行うエージェント。例えばベクトルDBからの検索だけを行う、といったケースで使用する。

以下の例だとおそらく何かしらのツールを実行して出力だけを取得するといった感じっぽい。

Tool AgentsのYAML定義の例
apiVersion: flo/alpha-v1
kind: FloAgent
name: llm-assistant
agent:
    name: tool-to-print-state
    kind: tool
    tools:
        - name: printStateTool

4. Reflection Agents

現在のワークフローの結果を振り返り(reflection)、必要に応じて前のステップを再試行できるエージェント。要は実行→結果を評価→再度実行、みたいな処理を行うことができる。

Reflection AgentsのYAML定義の例
apiVersion: flo/alpha-v1
kind: FloRoutedTeam
name: adding-team
team:
    name: EssayTeam
    agents:
      - name: EssayWriter
        kind: llm
        job: >
          あなたは、300語の優れたエッセイを書くことを任されたエッセイアシスタントです。
          ユーザーのリクエストに対して、可能な限り最高のエッセイを作成してください。
          批評の意見が提供された場合は、修正したバージョンで回答してください。
      - name: ReflectionAgent
        kind: reflection
        retry: 1
        to: 
          - name: EssayWriter
        job: >
          あなたは、提出された論文を採点する教師です。
          ユーザーの提出物に対する批評と推奨事項を作成します。
          長さ、深さ、スタイルなどに関する要望を含め、詳細な推奨事項を提供します。
      - name: FinalEssayProducer
        kind: llm
        job: >
          ユーザーに返すエッセイの最終版を生成します。
    router:
      name: router
      kind: linear

Reflection Agentsの特徴は、2つの追加パラメータがあること。

  • to: 差し戻し先のエージェント、この例ではEssayWriter
  • retry: 振り返りのイテレーション回数、この例では1回。デフォルトは1。

これによりEssayWriter→ReflectionAgent→EssayWriter...というようなフローが定義できる。

なお、v0.0.3時点では、Reflection Agentsを使う場合、ルーターにはlinearしか定義できないという制約がある点に注意。

これちょっと実際の動きも見てみた。今回は2回ループさせてみた。

from flo_ai import Flo
from flo_ai import FloSession
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(temperature=0, model_name='gpt-4o-mini')

team_yaml = """
apiVersion: flo/alpha-v1
kind: FloRoutedTeam
name: adding-team
team:
    name: EssayTeam
    agents:
      - name: EssayWriter
        kind: llm
        job: >
          あなたは、300語の優れたエッセイを書くことを任されたエッセイアシスタントです。
          ユーザーのリクエストに対して、可能な限り最高のエッセイを作成してください。
          批評の意見が提供された場合は、修正したバージョンで回答してください。
      - name: ReflectionAgent
        kind: reflection
        retry: 2
        to: 
          - name: EssayWriter
        job: >
          あなたは、提出された論文を採点する教師です。
          ユーザーの提出物に対する批評と推奨事項を作成します。
          長さ、深さ、スタイルなどに関する要望を含め、詳細な推奨事項を提供します。
      - name: FinalEssayProducer
        kind: llm
        job: >
          ユーザーに返すエッセイの最終版を生成します。
    router:
      name: router
      kind: linear
"""

session = FloSession(llm)

flo: Flo = Flo.build(session, yaml=team_yaml)

response = flo.invoke("競馬に興味がない人に、競馬の魅力を伝えるエッセイを書いてください。")

結果を見てみる。

for r in response["messages"]:
    if r.name is None:
        r.name = "User"
    print(f"########## {r.name} ##########\n\n{r.content}\n")
########## User ##########

競馬に興味がない人に、競馬の魅力を伝えるエッセイを書いてください。

########## EssayWriter ##########

競馬は、単なるギャンブルの一形態ではなく、深い歴史と文化、そして人々の情熱が交錯する魅力的なスポーツです。競馬の魅力は、まずそのドラマティックな瞬間にあります。レースが始まると、観客の心は高鳴り、馬たちが一斉にスタートラインを駆け抜ける瞬間は、まさに息を呑む瞬間です。馬の力強さやスピード、騎手との一体感は、観る者に感動を与えます。

また、競馬は単なるレースだけでなく、馬や騎手、トレーナーの物語でもあります。各馬には独自の背景があり、育成の過程やレースでの挑戦が彼らの成長を物語ります。特に、名馬と呼ばれる存在は、ただの競走馬ではなく、時には国民的な英雄となり、その名は世代を超えて語り継がれます。競馬を通じて、これらの物語に触れることができるのも大きな魅力の一つです。

さらに、競馬は社交の場でもあります。レースを観戦するために集まる人々は、共通の興味を持つ仲間として交流し、喜びや悲しみを分かち合います。競馬場の雰囲気は、緊張感と興奮が入り混じり、まるで一つの大きなコミュニティのようです。

最後に、競馬は戦略的な要素も含まれています。馬の能力や騎手の技術、天候やコースの状態など、さまざまな要因を考慮しながら予想を立てることは、知的な楽しみを提供します。競馬は、単なる運任せのギャンブルではなく、深い洞察力と分析力を必要とするスポーツなのです。

このように、競馬は多面的な魅力を持つスポーツであり、興味がない人でもその奥深さに触れることで、新たな楽しみを見出すことができるでしょう。競馬の世界に一歩足を踏み入れてみることをお勧めします。

########## ReflectionAgent ##########

### 批評と推奨事項

あなたのエッセイは、競馬の魅力を多角的に捉え、興味がない人々にその魅力を伝えるための良い出発点となっています。以下に、いくつかの具体的な批評と推奨事項を示します。

#### 1. 構成と流れ
- **良い点**: エッセイは明確な構成を持ち、競馬の魅力をいくつかの側面から説明しています。各段落が異なるテーマに焦点を当てているため、読みやすいです。
- **推奨事項**: 各段落の間に、よりスムーズなつなぎの文を加えることで、全体の流れをさらに良くすることができます。例えば、各段落の最後に次の段落への導入を加えると、読者が次のポイントに自然に移行できるでしょう。

#### 2. 深さと具体性
- **良い点**: 競馬の歴史や文化、社交的な側面について触れている点は素晴らしいです。
- **推奨事項**: 具体的な例やエピソードを挙げることで、読者の興味を引きつけることができます。例えば、特定の名馬や騎手の成功物語を紹介することで、競馬のドラマをより生き生きと描写できます。

#### 3. スタイルと表現
- **良い点**: 読みやすい言葉遣いとリズムがあり、一般の読者にも親しみやすいスタイルです。
- **推奨事項**: もう少し感情的な表現を加えることで、読者の心に響くエッセイにすることができます。競馬の興奮や緊張感を伝えるために、比喩や描写を使ってみてください。

#### 4. 結論
- **良い点**: 競馬の多面的な魅力を強調し、興味を持つことを促す結論は効果的です。
- **推奨事項**: 結論部分で、競馬を体験するための具体的な方法(例えば、競馬場に行く、レースを観る、競馬関連の書籍を読むなど)を提案すると、読者が実際に行動に移しやすくなります。

### 総評
全体として、あなたのエッセイは競馬の魅力を伝えるための良い基盤を持っています。上記の推奨事項を考慮し、具体的な例や感情的な表現を加えることで、さらに深みのある、魅力的なエッセイに仕上げることができるでしょう。競馬の世界に対する情熱が伝わるよう、ぜひ工夫を凝らしてみてください。

########## EssayWriter ##########

競馬は、単なるギャンブルの一形態ではなく、深い歴史と文化、そして人々の情熱が交錯する魅力的なスポーツです。その魅力は、まずそのドラマティックな瞬間にあります。レースが始まると、観客の心は高鳴り、馬たちが一斉にスタートラインを駆け抜ける瞬間は、まさに息を呑む瞬間です。馬の力強さやスピード、騎手との一体感は、観る者に感動を与えます。

競馬は単なるレースだけでなく、馬や騎手、トレーナーの物語でもあります。例えば、名馬「ディープインパクト」は、数々のレースでの勝利を重ね、国民的な英雄となりました。彼の成長過程やレースでの挑戦は、多くの人々に感動を与え、競馬の魅力を深めています。こうした物語に触れることで、競馬は単なるスポーツ以上の意味を持つのです。

さらに、競馬は社交の場でもあります。レースを観戦するために集まる人々は、共通の興味を持つ仲間として交流し、喜びや悲しみを分かち合います。競馬場の雰囲気は、緊張感と興奮が入り混じり、まるで一つの大きなコミュニティのようです。友人や家族と共にレースを楽しむことで、特別な思い出を作ることができます。

最後に、競馬は戦略的な要素も含まれています。馬の能力や騎手の技術、天候やコースの状態など、さまざまな要因を考慮しながら予想を立てることは、知的な楽しみを提供します。競馬は、単なる運任せのギャンブルではなく、深い洞察力と分析力を必要とするスポーツなのです。

このように、競馬は多面的な魅力を持つスポーツであり、興味がない人でもその奥深さに触れることで、新たな楽しみを見出すことができるでしょう。競馬場に足を運び、実際にレースを観戦することで、その魅力を体感してみることをお勧めします。競馬の世界に一歩足を踏み入れてみることで、あなたの視野が広がるかもしれません。

########## ReflectionAgent ##########

### 批評と推奨事項

あなたのエッセイは、競馬の魅力を具体的な例を交えて伝える良い内容になっています。特に、名馬「ディープインパクト」の例を挙げたことで、読者にとっての理解が深まりました。以下に、さらなる改善点と推奨事項を示します。

#### 1. 構成と流れ
- **良い点**: 各段落が明確なテーマを持ち、全体の流れがスムーズです。
- **推奨事項**: 各段落の冒頭に、次の段落の内容を予告するような文を加えると、より一層の流れが生まれます。例えば、競馬の物語性を語った後に「次に、競馬がどのように社交の場となるのかを見ていきましょう」といった具合です。

#### 2. 深さと具体性
- **良い点**: 具体的な名馬の例を挙げたことで、競馬の魅力がより具体的に伝わります。
- **推奨事項**: 他の名馬や騎手のエピソードも加えることで、さらに多様な視点を提供できます。例えば、異なる時代の名馬や、特に印象的なレースのエピソードを紹介することで、競馬の歴史的な側面も強調できます。

#### 3. スタイルと表現
- **良い点**: 読みやすく、親しみやすい言葉遣いが好印象です。
- **推奨事項**: 感情的な表現をもう少し強調することで、読者の心に響くエッセイにすることができます。例えば、レースの興奮を描写する際に、観客の反応や馬の動きの美しさをより詳細に描写すると良いでしょう。

#### 4. 結論
- **良い点**: 競馬の魅力を体感することを勧める結論は効果的です。
- **推奨事項**: 結論部分で、競馬を体験するための具体的な方法(例えば、競馬場のイベントや特別なレースの日程など)を提案すると、読者が実際に行動に移しやすくなります。また、競馬を観戦する際の楽しみ方や、初心者向けのアドバイスを加えると、より親切な印象を与えられます。

### 総評
全体として、あなたのエッセイは競馬の魅力を効果的に伝えています。上記の推奨事項を考慮し、具体的なエピソードや感情的な表現を加えることで、さらに深みのある、魅力的なエッセイに仕上げることができるでしょう。競馬の世界に対する情熱が伝わるよう、ぜひ工夫を凝らしてみてください。

########## EssayWriter ##########

競馬は、単なるギャンブルの一形態ではなく、深い歴史と文化、そして人々の情熱が交錯する魅力的なスポーツです。その魅力は、まずそのドラマティックな瞬間にあります。レースが始まると、観客の心は高鳴り、馬たちが一斉にスタートラインを駆け抜ける瞬間は、まさに息を呑む瞬間です。馬の力強さやスピード、騎手との一体感は、観る者に感動を与えます。

競馬は単なるレースだけでなく、馬や騎手、トレーナーの物語でもあります。例えば、名馬「ディープインパクト」は、数々のレースでの勝利を重ね、国民的な英雄となりました。彼の成長過程やレースでの挑戦は、多くの人々に感動を与え、競馬の魅力を深めています。さらに、他の名馬たちもそれぞれの物語を持ち、例えば「オルフェーヴル」の壮絶なレースや、「ハーツクライ」の逆転劇など、競馬は常に新たなドラマを生み出しています。

また、競馬は社交の場でもあります。レースを観戦するために集まる人々は、共通の興味を持つ仲間として交流し、喜びや悲しみを分かち合います。競馬場の雰囲気は、緊張感と興奮が入り混じり、まるで一つの大きなコミュニティのようです。友人や家族と共にレースを楽しむことで、特別な思い出を作ることができます。特に、特別なレースの日には、観客が一体となって応援する姿は、競馬の醍醐味の一つです。

最後に、競馬は戦略的な要素も含まれています。馬の能力や騎手の技術、天候やコースの状態など、さまざまな要因を考慮しながら予想を立てることは、知的な楽しみを提供します。競馬は、単なる運任せのギャンブルではなく、深い洞察力と分析力を必要とするスポーツなのです。

このように、競馬は多面的な魅力を持つスポーツであり、興味がない人でもその奥深さに触れることで、新たな楽しみを見出すことができるでしょう。競馬場に足を運び、実際にレースを観戦することで、その魅力を体感してみることをお勧めします。特別なレースの日には、初心者向けのガイドやイベントも用意されているので、気軽に楽しむことができます。競馬の世界に一歩足を踏み入れてみることで、あなたの視野が広がるかもしれません。

########## FinalEssayProducer ##########

競馬は、単なるギャンブルの一形態ではなく、深い歴史と文化、そして人々の情熱が交錯する魅力的なスポーツです。その魅力は、まずそのドラマティックな瞬間にあります。レースが始まると、観客の心は高鳴り、馬たちが一斉にスタートラインを駆け抜ける瞬間は、まさに息を呑む瞬間です。馬の力強さやスピード、騎手との一体感は、観る者に感動を与えます。

競馬は単なるレースだけでなく、馬や騎手、トレーナーの物語でもあります。例えば、名馬「ディープインパクト」は、数々のレースでの勝利を重ね、国民的な英雄となりました。彼の成長過程やレースでの挑戦は、多くの人々に感動を与え、競馬の魅力を深めています。さらに、他の名馬たちもそれぞれの物語を持ち、例えば「オルフェーヴル」の壮絶なレースや、「ハーツクライ」の逆転劇など、競馬は常に新たなドラマを生み出しています。

また、競馬は社交の場でもあります。レースを観戦するために集まる人々は、共通の興味を持つ仲間として交流し、喜びや悲しみを分かち合います。競馬場の雰囲気は、緊張感と興奮が入り混じり、まるで一つの大きなコミュニティのようです。友人や家族と共にレースを楽しむことで、特別な思い出を作ることができます。特に、特別なレースの日には、観客が一体となって応援する姿は、競馬の醍醐味の一つです。

最後に、競馬は戦略的な要素も含まれています。馬の能力や騎手の技術、天候やコースの状態など、さまざまな要因を考慮しながら予想を立てることは、知的な楽しみを提供します。競馬は、単なる運任せのギャンブルではなく、深い洞察力と分析力を必要とするスポーツなのです。

このように、競馬は多面的な魅力を持つスポーツであり、興味がない人でもその奥深さに触れることで、新たな楽しみを見出すことができるでしょう。競馬場に足を運び、実際にレースを観戦することで、その魅力を体感してみることをお勧めします。特別なレースの日には、初心者向けのガイドやイベントも用意されているので、気軽に楽しむことができます。競馬の世界に一歩足を踏み入れてみることで、あなたの視野が広がるかもしれません。

ReflectionAgentにより2回の修正が入っているのがわかる。

5. Delegation Agents

Delegation Agentsもぱっと見はReflection Agentsと似ているのだけど、プロンプトで特定のエージェントにルーティングというか処理を移譲(delegation)させることができる。複数のエージェントがそれぞれ異なるタスクに専門化していて、コンテキストに応じて振り分ける、というようなユースケース向きということらしい。

Reflection Agentsと同様、toretryの設定があり、v0.0.3時点でルーターにはlinearしか定義できないという制約がある。

Delegation AgentsのYAML定義の例
apiVersion: flo/alpha-v1
kind: FloRoutedTeam
name: adding-team
team:
    name: EssayTeam
    agents:
      - name: EssayWriter
        kind: llm
        job: >
          あなたは、100語の優れたエッセイを書くことを任されたエッセイアシスタントです。
          ユーザーのリクエストに対して、可能な限り最高のエッセイを作成してください。
          批評の意見が提供された場合は、修正したバージョンで回答してください。
      - name: DelegatorAgent
        kind: delegator
        retry: 2
        to: 
          - name: EssayWriter
        job: >
          あなたは、提出されたエッセイを採点する教師です。
          エッセイを1〜10の点数で採点してください。10点が最高得点です。
          もし点数が7点以上なら FinalEssayProducer に渡してください。
          もし点数が7点未満なら、訂正すべき点と共に、EssayWriter に返してください。
      - name: FinalEssayProducer
        kind: llm
        job: >
          ユーザーに返すエッセイの最終版を生成します。
    router:
      name: router
      kind: linear

こちらも実際に試してみた。

from flo_ai import Flo
from flo_ai import FloSession
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search.tool import TavilySearchResults

llm = ChatOpenAI(temperature=0, model_name='gpt-4o-mini')

team_yaml = """
apiVersion: flo/alpha-v1
kind: FloRoutedTeam
name: adding-team
team:
    name: EssayTeam
    agents:
      - name: EssayWriter
        kind: llm
        job: >
          あなたは、100語の優れたエッセイを書くことを任されたエッセイアシスタントです。
          ユーザーのリクエストに対して、可能な限り最高のエッセイを作成してください。
          批評の意見が提供された場合は、修正したバージョンで回答してください。
      - name: DelegatorAgent
        kind: delegator
        retry: 2
        to: 
          - name: EssayWriter
        job: >
          あなたは、提出されたエッセイを採点する教師です。
          エッセイを1〜10の点数で採点してください。10点が最高得点です。
          もし点数が7点以上なら FinalEssayProducer に渡してください。
          もし点数が7点未満なら、訂正すべき点と共に、EssayWriter に返してください。
      - name: FinalEssayProducer
        kind: llm
        job: >
          ユーザーに返すエッセイの最終版を生成します。
    router:
      name: router
      kind: linear
"""

session = FloSession(llm)

flo: Flo = Flo.build(session, yaml=team_yaml)
        
response = flo.invoke("競馬に興味がない人に、競馬の魅力を伝えるエッセイを書いてください。")
for r in response["messages"]:
    if r.name is None:
        r.name = "User"
    print(f"########## {r.name} ##########\n\n{r.content}\n")

結果

########## User ##########

競馬に興味がない人に、競馬の魅力を伝えるエッセイを書いてください。

########## EssayWriter ##########

競馬は単なるギャンブルではなく、感動と興奮が詰まったスポーツです。美しい馬たちが力強く走る姿は、見る者の心を奪います。競馬場の雰囲気は、観客の熱気と期待感で満ち溢れ、まるで一つの祭りのようです。また、馬の血統やトレーニング、騎手の技術など、奥深い知識が求められるため、観戦する楽しみも増します。さらに、競馬は歴史的な背景を持ち、文化や伝統が息づいています。競馬を通じて、感動や仲間との絆を深めることができるのです。

########## EssayWriter ##########

競馬は単なるギャンブルではなく、感動と興奮が詰まったスポーツです。美しい馬たちが力強く走る姿は、見る者の心を奪います。競馬場の雰囲気は、観客の熱気と期待感で満ち溢れ、まるで一つの祭りのようです。馬の血統やトレーニング、騎手の技術など、奥深い知識が求められるため、観戦する楽しみも増します。さらに、競馬は歴史的な背景を持ち、文化や伝統が息づいています。競馬を通じて、感動や仲間との絆を深めることができるのです。競馬の魅力は、単なる結果を超えた、心を揺さぶる体験にあります。

########## EssayWriter ##########

競馬は単なるギャンブルではなく、感動と興奮が詰まったスポーツです。美しい馬たちが力強く走る姿は、見る者の心を奪います。競馬場の雰囲気は、観客の熱気と期待感で満ち溢れ、まるで一つの祭りのようです。馬の血統やトレーニング、騎手の技術など、奥深い知識が求められるため、観戦する楽しみも増します。さらに、競馬は歴史的な背景を持ち、文化や伝統が息づいています。競馬を通じて、感動や仲間との絆を深めることができるのです。競馬の魅力は、単なる結果を超えた、心を揺さぶる体験にあります。競馬を知ることで、人生の新たな楽しみを見つけることができるでしょう。

########## FinalEssayProducer ##########

競馬は単なるギャンブルではなく、感動と興奮が詰まったスポーツです。美しい馬たちが力強く走る姿は、見る者の心を奪います。競馬場の雰囲気は、観客の熱気と期待感で満ち溢れ、まるで一つの祭りのようです。観客同士が声を上げ、馬の走りに一喜一憂する様子は、まさに共感と興奮の渦に包まれています。

競馬の魅力は、単にレースの結果を追うことにとどまりません。馬の血統やトレーニング、騎手の技術など、奥深い知識が求められるため、観戦する楽しみも増します。例えば、ある馬がどのような血統を持ち、どのようなトレーニングを受けてきたのかを知ることで、その馬に対する愛着が湧き、レースをより一層楽しむことができます。また、騎手の技術や判断力もレースの結果に大きく影響するため、彼らの動きに注目することで、より深い理解と感動を得ることができるのです。

さらに、競馬は歴史的な背景を持ち、文化や伝統が息づいています。多くの国で長い歴史を持つ競馬は、地域ごとの特色や文化を反映しており、観戦することでその土地の文化を感じることができます。競馬場での体験は、単なるスポーツ観戦を超え、地域の人々との交流や新たな発見をもたらしてくれるのです。

競馬を通じて、感動や仲間との絆を深めることができるのも大きな魅力です。友人や家族と一緒にレースを観戦し、勝利の喜びを分かち合ったり、逆に悔しさを共有したりすることで、絆が深まります。競馬は、単なる結果を超えた、心を揺さぶる体験を提供してくれるのです。

競馬を知ることで、人生の新たな楽しみを見つけることができるでしょう。美しい馬たちの走り、熱気に満ちた競馬場、そして仲間との絆。これらは、競馬が持つ魅力の一部に過ぎません。競馬の世界に足を踏み入れることで、あなたも新たな感動と興奮を体験できるはずです。競馬は、ただのギャンブルではなく、心を豊かにする素晴らしいスポーツなのです。

Delegation Agentsが採点した結果が見えないなぁ、一応DelegationされているからEssayWriterの出力が繰り返されているのだろうとは思うのだけど。日本語がダメなのかなと思ってサンプルそのままで試してみたけど、変わらなかった。

こういう条件分岐みたいなのはちょっとルーターの役割とかぶるような印象があるなぁ・・・

kun432kun432

ツール

https://flo-ai.rootflo.ai/basics/tools

FloAIのツールはLangChainのツールと互換性があるので、そのまま使うことができる。実際、Quickstartの最初のコードではTavilyの検索ツールが使用されていた。

from langchain_openai import ChatOpenAI
from flo_ai import Flo, FloSession
from langchain_community.tools.tavily_search.tool import TavilySearchResults

llm = ChatOpenAI(model_name='gpt-4o-mini')

agent_yaml = """
apiVersion: flo/alpha-v1
kind: FloAgent
name: blogging-agent
agent:
    name: Blogger
    job: >
      あなたは、与えられたトピックについて、インターネットで調査を行い、ブログ記事を作成することができます。
    tools:
      - name: TavilySearchResults
"""

session = FloSession(llm).register_tool(
    name="TavilySearchResults", 
    tool=TavilySearchResults()
)

flo: Flo = Flo.build(session, yaml=agent_yaml)

flo.invoke("Topic: 2024年秋の競馬GIレースの展望")

自分でツールを作成する場合は、LangChainのToolクラスかBaseToolクラスを使う。

Toolクラスを使って、関数をツール化する。

from langchain.tools import Tool

def add_numbers(a: int, b: int) -> int:
    return a + b

add_tool = Tool(
    name="Add Numbers Tool",
    func=add_numbers,
    description="This tool adds two numbers."
)

のだが、これなんか書き方が古い気がする。そのせいか、Flo AIに組み込んでもうまく動かない。自分が書き方がわかってないせいもあるけども。

langchain.coretoolを使うともっとシンプルに書ける。

from langchain_openai import ChatOpenAI
from flo_ai import Flo, FloSession
from langchain_core.tools import tool

@tool
def add(a: int, b: int) -> int:
    """2つの整数を足し算して、結果を整数で返す。"""
    return a + b

@tool
def multiply(a: int, b: int) -> int:
    """2つの整数を掛け算して、結果を整数で返す。"""
    return a * b

llm = ChatOpenAI(model_name='gpt-4o-mini')

agent_yaml = """
apiVersion: flo/alpha-v1
kind: FloAgent
name: blogging-agent
agent:
    name: Blogger
    job: >
      あなたは、与えられた計算式を、ツールを使って計算を行い、結果を返すことができます。
    tools:
      - name: AddNumbersTool
      - name: MultiplyNumbersTool
"""

session = FloSession(llm).register_tool(
    name="AddNumbersTool", 
    tool=add
).register_tool(
    name="MultiplyNumbersTool", 
    tool=multiply
)

flo: Flo = Flo.build(session, yaml=agent_yaml)

flo.invoke("12 + 27 * 5 = ")
> Entering new AgentExecutor chain...

Invoking: `multiply` with `{'a': 27, 'b': 5}`


135
Invoking: `add` with `{'a': 12, 'b': 0}`


12
Invoking: `add` with `{'a': 12, 'b': 135}`


147
12 + 27 * 5 = 147 です。

> Finished chain.
{'messages': [HumanMessage(content='12 + 27 * 5 = ')],
 'output': '12 + 27 * 5 = 147 です。'}

BaseToolクラスからサブクラスを作る場合。

from langchain_openai import ChatOpenAI
from flo_ai import Flo, FloSession
from langchain.tools import BaseTool

class AddNumbersTool(BaseTool):
    name = "AddNumbersTool"
    description = "2つの整数を足し算して、結果を整数で返す。"

    def _run(self, a: int, b: int) -> int:
        return a + b

    async def _arun(self, a: int, b: int) -> int:
        return a + b


class MultiplyNumbersTool(BaseTool):
    name = "MultiplyNumbersTool"
    description = "2つの整数を掛け算して、結果を整数で返す。"

    def _run(self, a: int, b: int) -> int:
        return a * b

    async def _arun(self, a: int, b: int) -> int:
        return a * b

llm = ChatOpenAI(model_name='gpt-4o-mini')

agent_yaml = """
apiVersion: flo/alpha-v1
kind: FloAgent
name: blogging-agent
agent:
    name: Blogger
    job: >
      あなたは、与えられた計算式を、ツールを使って計算を行い、結果を返すことができます。
    tools:
      - name: AddNumbersTool
      - name: MultiplyNumbersTool
"""

session = FloSession(llm).register_tool(
    name="AddNumbersTool", 
    tool=AddNumbersTool()
).register_tool(
    name="MultiplyNumbersTool", 
    tool=MultiplyNumbersTool()
)

flo: Flo = Flo.build(session, yaml=agent_yaml)

flo.invoke("12 + 27 * 5 = ")
> Entering new AgentExecutor chain...

Invoking: `MultiplyNumbersTool` with `{'a': 27, 'b': 5}`


135
Invoking: `AddNumbersTool` with `{'a': 12, 'b': 0}`


12
Invoking: `AddNumbersTool` with `{'a': 12, 'b': 135}`


147
12 + 27 * 5 = 147です。

> Finished chain.
{'messages': [HumanMessage(content='12 + 27 * 5 = ')],
 'output': '12 + 27 * 5 = 147です。'}

ちょっと気になったのはnameが結構冗長になるのと、name内にスペースが入るとダメっぽいというところかな。自分はLlamaIndex派で、LangChainをあまり日常的に使っていないので、詳しいことはわからないけど、このページの書きっぷりは少し古い気がする。

@toolデコレータを使うほうがスッキリ書けていいと思う。

kun432kun432

ルーター

https://flo-ai.rootflo.ai/basics/routers

ルーターはチーム内の複数のエージェント間のフローを定義する。基本的なYAML定義は以下となる。

Team:
    router:
      name: TeamLead
      kind: supervisor

ドキュメントのルーターのページには書いてないのだけど、ここまでのサンプル等でnameというパラメータがあったし、他にもパラメータはあるようだけど、ドキュメントには特に記載がなかった。

kindで指定できるルーターの種類は以下の3つ。

  1. supervisor
  2. linear
  3. llm

1. supervisor

supervisorは、エージェントを階層構造にでつなげて、コンテキストに基づいて各ステップでどのエージェントを呼び出すかを決定する、つまりオーケストレータのような役割となる。

以下のようなイメージ

2. linear

linearは、定義されたエージェントの順にシーケンシャルに処理を行うので、ステップバイステップで進めるようなワークフローに向いている。ただし、Reflection Agentsや Delegation Agentsを使うことで、フロー内での動的な再ルーティングやイテレーションなどの複雑な処理も可能で、Reflection Agentsや Delegation Agentsと現時点v0.0.3ではlinearでしか使えない、

3. llm

llmは、プロンプトに基づいたルーティングを行う。コンテキストの流れが重要、かつ、LLMからの出力によって処理を変えたいようなユースケースでプロンプトを使って制御するというようなユースケースになる。

supervisorも恐らくLLMでルーティングしているのだと思うのだけど、プロンプトを定義できるってのがllmルーターの特徴なんだろうと思う。

具体的な例がドキュメントだとわからなかったのだけど、以下にサンプルのノートブックがあった。

https://github.com/rootflo/flo-ai/tree/develop/examples/llm_router_example.ipynb

from flo_ai import Flo
from flo_ai import FloSession
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(temperature=0, model_name='gpt-4o-mini')

agent_yaml = """
apiVersion: flo/alpha-v1
kind: FloRoutedTeam
name: adding-team
team:
    name: AddingTeam1
    router:
        name: router
        kind: llm
        job: まだ呼び出されていないメンバーを選択して。
    agents:
      - name: Agent1
        kind: llm
        role: 数学専門家
        job: あなたは数学の専門家です。あなたに与えられた数字に1を足してください。そして、その結果を次のエージェントに渡してください。
      - name: Agent2
        kind: llm
        role: 数学専門家
        job: あなたは数学の専門家です。あなたに与えられた数字に1を足してください。そして、その結果を次のエージェントに渡してください。
      - name: Agent3
        kind: llm
        role: 数学専門家
        job: あなたは数学の専門家です。あなたに与えられた数字に1を足してください。そして、その結果を次のエージェントに渡してください。
"""

session = FloSession(llm)

flo: Flo = Flo.build(session, yaml=agent_yaml)

flo.invoke("7からスタート")
{'messages': [HumanMessage(content='7からスタート'),
  HumanMessage(content='7に1を足すと、8になります。次のエージェントに8を渡してください。', name='Agent1'),
  HumanMessage(content='8に1を足すと、9になります。次のエージェントに9を渡してください。', name='Agent2'),
  HumanMessage(content='9に1を足すと、10になります。次のエージェントに10を渡してください。', name='Agent3')],
 'next': 'FINISH'}

ただ、これちょっと難しい。いろいろルーターのプロンプトを変えても制御できない。ちょっとここはサンプルがあまり良くない印象もある。これがハマる実例を知りたい。

kun432kun432

チーム

https://flo-ai.rootflo.ai/basics/teams

チームは複数のエージェント+ルーターをグルーピングするものだけど、複数のエージェントが同じゴールに向かって「協調」する、というところに意味があるのだろうと思う。

すでにチームを定義したサンプルを上の方で試しているので再掲。

apiVersion: flo/alpha-v1
kind: FloRoutedTeam
name: blogging-flo
team:
    name: BloggingTeam
    router:
        name: TeamLead
        kind: supervisor
    agents:
      - name: Researcher
        role: リサーチャー
        job: インターネットでリサーチを行い、ユーザーが尋ねたトピックに関連する記事を見つけ、常に最新の情報を探すようにしてください。
        tools:
          - name: TavilySearchResults
      - name: Blogger
        role: ブロガー
        kind: llm
        job: リサーチャーが提供した資料を元に、すぐに公開できる300語程度のブログ記事を書いて、それを魅力的なものにブラッシュアップし、元のブログ記事への参照リンクを引用・脚注として追加してください。

より複雑な例として、「サブチーム」というのがあり、以下にサンプルもあるのだが、これが動かない。

https://github.com/rootflo/flo-ai/tree/3ae5c5290a4ff5a8097e958693a3cbb1fcbf2f0e/examples/hierarchical_blogging_team.py

YAMLの定義もこれまでのサンプルと比べると違和感がある。もしかするとここはドキュメントがコードの変更に追いついていないかもしれない。

kun432kun432

まとめ

あくまでも個人的な所感

  • 基本的にYAMLでワークフロー定義して実行するだけなのでこの点については楽。
  • コンポーネントの組み方はCrewAIと似たような印象。CrewAIをYAMLで書いているよう感じ。

YAMLでエージェントフロー定義できるってのは意味があると思う。まあK8Sっぽいか?と言われると少し微妙かなと思うけども、この方向性は個人的には好み。まあ細かく制御したい、みたいなニーズをどう構造化するか、ってところはあるだろうけど。

ただいろいろ進めていくにつれて気になるところがチラホラ・・・

  • ドキュメントが足りない、もしくはドキュメントどおりにやっても動かないものがちらほらある。
    • GitHubレポジトリにサンプルコードやnotebookがあるのだけど、全部は見ていないが、こちらも動かないものがいくつかあった
    • 恐らくコードの更新にドキュメントが追いついていないのかなという印象
  • LangChainを使っているようなのだけど、古い書き方をしているところがちらほらある。
    • 例えばツール
    • あとエージェントは現在は非推奨になったAgentExecutorを使っている様子
    • LangGraphも使っているようなのだけど、恐らくルーターのところだけっぽい

最初のリリースから3ヶ月ぐらいなので、まあ致し方ないかなという気もするけどね。

とりあえず今後の改善に期待。どうせならLLMやツールなども含めて全部YAMLで定義できるようになるといいなと思う。

このスクラップは1ヶ月前にクローズされました