76
79

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

2025年 生成AIの新たな波「AI エージェント」の可能性

Last updated at Posted at 2025-02-20

本記事は日本オラクルが運営する下記Meetupで発表予定の内容になります。発表までに今後、内容は予告なく変更される可能性があることをあらかじめご了承ください。

※セミナー実施時に沢山のご質問をいただきありがとうございました。セミナー時間内に回答できなかったご質問や、正確に回答できなかったご質問の補足を最後のコメント欄に纏めましたので併せてご確認ください。

生成AIアプリのコンセプトは「AIエージェント」へ

生成AIを利用したアプリケーションの様々なリファレンス実装がある中、企業用途では世界中のユーザーがRAGと呼ばれるソリューションにフォーカスしたのが2023年、2024年だったと思います。

RAGは「応答品質がよくない」、「LLMはウソをつく」などと言われながらも、極めて有用なソリューションであることは疑いようがなく今後もエンハンスされ続け、定番のソリューションになることは間違いありません

※RAGとは何ですか?という方はこちらの記事をご参照ください。

そして各テック企業が RAGの次にが打ち出しているコンセプトが本記事の主題、「AIエージェント」です

RAGに限らず、これまでの生成AIアプリは「LLMに回答させる」 というかなりシンプルな実装が中心だったのに対して、AIエージェントは「LLMに働かせる」 という、より柔軟で汎用性のある実装だと言えます。

「旅行に行きたい」とAIに話しかけると、「旅行先の提案、スケジュールの確認、フライト、ホテル、タクシーの予約など、会話しながら全てをAIがやってくれるという至れり尽くせりのアレです。

image.png

ビジネスの世界でいうと、「自社の人気商品の売り上げ分析を行いマーケティングや在庫適正化をしたい」とAIに話しかけると、AIが自律的にSNGで人気商品を調査したり、調査結果からデータを分析し、社内のSCMに連携して在庫の過不足をコントロールしてくれるようなイメージです。

俯瞰すると、「AIエージェント」とは、「人間の代わりに複雑なタスクを自律的に実行する」システム と定義でき、現在各テック企業はこのようなSF映画さながらの世界観を実現するベースの技術としてAIエージェントの開発に完全にシフトしている状況です。

AIエージェントの要素技術

実はAIエージェントで使われる要素技術はLLMが流行りだしたかなり初期のころから既にありました。 現在各テック企業が開発しているAIエージェント関連のライブラリやクラウドサービスは主に下記の要素技術がベースになっています。

もちろんこれ以外にも沢山の技術が応用されていますが、上述したような世界観の実現に直接的に影響している仕組みが下記になり、いずれも生成AIアプリ界隈では以前からよくでてくるキーワードですので既にご存じの方々も多いはず。

  • エージェント・システム
  • Function Calling
  • マルチエージェント

エージェント・システム

エージェントは日本語で代理人という意味です。つまりエージェント・システムとは ユーザーの代わりに、様々な処理(検索、調査、分析、プログラムなどなど)を実行してくれる代理人(プログラム) ということになります。

このエージェントと呼んでいるプログラムがユーザーの望む処理を 自律的に行っているように見える仕組みは、LLMによってエージェントに「役割」が与えられることで成り立っています

image.png

例えば上図のような例の場合、「SNSを検索し、ユーザーのプロンプトに応答する」という「役割」がLLMによってエージェントに与えられるというイメージです。この役割によって、ユーザーのプロンプトから①どのような処理が必要なのかを「計画」し、②その処理を「実行」し、③その実行結果から最終的な「応答を生成」 します。

  1. 計画:SNSを検索し人気の商品を探す
  2. 実行:SNSの検索プログラムを実行する
  3. 応答:SNSの検索結果をもとに応答を生成する

このようにユーザーのプロンプトに応じて、自律的に必要な処理を判断し、実行してくれる仕組みのベースとなる技術がエージェントシステムです。

LLMを使ったアプリケーションとして、「ドキュメント検索(RAG)」や「データベース分析」などがありますが、実はこれも上述したようなエージェントシステムの一種です。

ドキュメント検索(RAG)はユーザープロンプトの内容に関係した文書をベクトルデータベースから検索するという役割を持ったエージェントですし、「データベース分析」も同様にユーザープロンプトの内容をSQLに変換しRDBを検索(分析)するという役割を持ったエージェントだということになります。

RAG(文書検索)
https://qiita.com/ksonoda/items/9a40c1017613d3ccf1e0
データベース分析
https://qiita.com/ksonoda/items/60ccc2a4fde15906654a

ユーザープロンプトの内容に応じて、様々な処理を自律的に実行してくれるエージェントですが、この 「様々な処理を実行する」という部分がどのような仕組みで成り立っているのか? というところが非常に重要な要素技術になります。

つまり、上述した例でいうと、「②SNSの検索プログラムを実行する」という部分がどのように自律的に実行されるのか?ということです。そのベースとなる技術がFunction Callingです

Function Calling(Tool Calling、Tool Use、Tools)

ChatGPTやGeminiなど出来上がったサービスのみを利用している方には想像しにくいかもしれませんが、LLM単体では「与えられたテキストに基づいたテキストの生成」しかできず、ウェブ検索を実行したり、SNSを検索したりということはできません

LLMは過去のデータを学習した機械学習の予測モデルのため現在のデータ(リアルタイムのデータ)に関する応答はできません。LLM単体では今何時なのかですら答えることはできないんです。

現在のバージョンのChatGPTやGeminiなどがリアルタイムにウェブ検索を実行してくれるのは、LLM以外にそのようなプログラムが追加で実装されているからです。

image.png

例えば上図のように、今日の天気予報というリアルタイムの情報を含んだテキストを生成したい場合、OpenWeatherなど天気情報を提供しているサービスに都度アクセスし、天気情報を取得する実装が必要になり、この実装をFunction Callingと呼んでいます。(上図の赤枠の部分)

このように、LLMと「LLMの外の世界」を連携させるプログラムを開発できる仕組みがFunction Callingです。LLM単体では実行できない「動的(リアルタイム)な情報取得」や「外部システムとの連携」も可能になり、生成AIアプリの適用範囲を大幅に拡張することができる極めて重要な仕組みとなります

ここd、「LLMの外の世界」とは例えば以下のようなものです。

image.png

  • インターネットに公開されているサービスとの連携
    毎日私達が利用するようなインターネット上で公開されている様々なサービスはAPIでアクセスできるようになっているものが多いのでそれらを利用してFunction Callingを作るパターン

  • 社内システムとの連携
    現状、ユースケースとして挙げられるケースは少ないように思いますが、今後生成AIアプリの適用範囲が広がれば財務、人事、生産、調達、販売システムなどをFunction Callingで連携するパターン

  • 業務アプリ、ユーザー開発アプリとの連携
    社内システムと近しいケースですが、RDB、NoSQL、DWH、データレイク、ETL、BIツールなどと連携するパターン

このように沢山のサービスと連携することで、より便利で汎用的なアプリケーションになることはおわかりになると思います。

また、API CallだけでなくスクレイピングやOSコマンドなど様々なタイプの処理を Function Callingとして定義できますから、 事実上、連携できないものありません

Function Callingや Tool CallingはOpenAI用語です。その他の製品ではTools, Tool, Tool Useなどという呼称がよくでてきますが、基本的に同じことを言っていると思って問題ありません。

※Function Callingの詳細については別記事がありますのでご興味のある方はご参照ください。

このように、AIエージェントのアプリケーションでは様々な処理をFunction Callingとして定義し、エージェントに関連付けることで有用なアプリケーションを開発することができるようになっているのですが、沢山のFunction Callingをエージェントに関連付けるといくつかの問題が発生することがあります

その主だったものが下記になります。

  • プロンプトが複雑だったり抽象的すぎるとエージェントが理解できない
  • 沢山のFunction Callingを定義すると想定したFunction Callingが選択されない
  • 沢山のFunction Callingを定義すると想定した順序でFunction Callingが実行されない

image.png

このようなことが起こる理由は、Function Callingの選択と実行順序が気まぐれなLLMによって決まるからです。(LLMとは機械学習で作られた予測モデルであり、予測モデルが出力する結果はあくまで推論結果、つまり常に100%正しいということにはならないからです。)

便利なアプリケーションには往々にして複雑な処理がつきもので、そのために様々なFunction Callingを定義したいのに、それをすると想定通りの動作にならないという本末転倒な状況が発生してしまいます。

このような状況を可能な限り回避する手法としてマルチ・エージェントがあります。

マルチ・エージェント

マルチ・エージェントとはその名の通り、上述したエージェントを複数構成する手法で、現在、各ベンダーが開発しているAIエージェントの中核的な技術です

image.png

おさえておきたいポイントとしては下記3つです。

  1. 複数のエージェントに役割を分けて、各エージェントにはその役割だけに専念させることでLLMの推論ミスの可能性を減らします。

  2. 同様に、各エージェントにはその役割に関係するFunction Callingのみを関連付けることにより、Function Callingの選択やその実行順序の推論ミスを軽減します。

  3. そしてマルチ・エージェントにおいて、この複数のエージェントをどのように連携させるか? という点が最も重要な設計ポイントになります。例えば、複雑なプロンプトのタスクを分割して「分担」させたり、同じ役割を持たせて一番良い結果を選べるよう「協力」させたり、エージェント同士を「競争や交渉」をさせたり、あるエージェントの提案内容を「批判」させたりといった具合です。

上述3のエージェント同士の連携のロジックを、JavaやPythonなどといった高等言語で、全てのパターンを考慮しながら定義することは極めて難しい(そもそも全てのパターンを洗い出すことができない)ということになりますが、そこを言葉で定義できるところがLLMアプリケーションの最も有用な点であり、生成AIアプリの本質だと個人的には考えています。

このようにして、複雑なプロンプトを実行したり、またその結果の精度を更に向上させることができるようになる仕組みがマルチエージェントです。

AIエージェントの要素技術の主だった考え方は上述したような内容になりますが、これをゼロから自分で開発するのはなかなか骨が折れる作業ということになるので当然、様々なプロバイダーからAIエージェント開発用の製品がリリースされており、既に広範なエコシステムが形成されている状況です。

AIエージェントのエコシステム

現在、AIエージェントを開発するための製品(特にマルチエージェントにフォーカスした製品)は本当に様々なものが開発されており、その全てをリストすることも、それらを綺麗にカテゴライズすることも非常に難しい状況ですが、その中で有名どころをいくつかご紹介します。

Pythonライブラリ

名称 開発元 製品概要
Autogen Microsoft Research マルチエージェントシステムの構築にフォーカスしたOSSライブラリ。グループチャットなどAIエージェント同士の対話やタスク分担を自動化するためのライブラリが特徴的。OpenAI以外の様々なモデルが利用可能かつ、LangChain、Dockerなどその他のライブラリとの連携も可能。
LangGraph LangChain Inc. LLMフレームワークで著名なLangChainの姉妹ライブラリとなり、マルチエージェントシステムの構築にフォーカスしたOSS。LangChainの幅広いエコシステムとの連携が可能で様々なプロバイダのLLMが利用可能。
Llama Stack Meta OSS LLMプロバイダの巨人Metaが手掛けるマルチエージェントシステム構築可能なOSSライブラリ。MetaのLLMのみが利用可能。
OpenAI Assistant API OpenAI OpenAIのマルチエージェントシステム開発用の機能。OpenAIのLLMのみサポート。エージェント同士の会話スレッドがOpenAI側で自動的に管理されたり、Code InterpreterやRetrieval(ファイル検索)のツールが事前定義されていたりと有償サービスらしい特徴あり。

※LangGraphについては過去のセッションで取り扱いましたのでよろしければ下記記事をご参照ください。

総合クラウドベンダー

名称 開発元
Azure AI Agent Service AIエージェントを開発するためのクラウドサービス。Azure SDK for PythonのAgentTeamクラスを使用してマルチエージェントの定義が可能。ローコードでの開発も可能。
Amazon Bedrock Agent AIエージェントを開発するためのクラウドサービス。同サービスのマルチエージェントコラボレーションと呼ばれる機能によりマルチエージェントの構築が可能。ローコードで開発可能。
Google Vertex AI Agent Builder マルチエージェントの構築が可能なローコード開発サービス。
Oracle Generative AI Agents Service ローコードでのエージェント開発サービス。今後マルチエージェントに対応予定。

その他、この市場での様々なプレーヤー(最近は特にDifyさんのようなAIアプリ開発ツールの専業ベンダーが人気のようです)がAIエージェントをキーワードに自社製品やサービスをエンハンスしています。

そのような状況の中、以降のパートでは導入ハードルが低いオープンソースソフトウエアかつ、比較的有名でよく使われているAutoGenを取り上げたいと思います。

AutoGenの概要

Microsoftとペンシルベニア州立大学の共同プロジェクトとして始まり2024年にversion 0.1で初期リリース、その後何度かのエンハンスを経て2025年2月現在はversion 0.46になり初期のころと比べると使い勝手はずいぶんよくなりました。

MicrosoftというとLLMフレームワークのSematic Kernelが有名で、様々なタイプの生成AIアプリ全般をターゲットにリリースされていますが、AutoGenは完全にマルチエージェントにフォーカスされておりポジショニングも明確です。

AutoGen単体だけではなく、LangChainやDockerなどその他様々なツールと連携できるように作られておりマーケットでの期待値も非常に高いライブラリです。

LangChainはマルチエージェント以外の汎用的なエージェントシステム構築のためのフレームワークで古くから人気があるためそのエコシステムは非常に広範です。Autogenではカバーしていないこの広範なエコシステムとそのまま連携できる点は非常に大きなメリットだと思います。

LangChainのエコシステム
https://qiita.com/ksonoda/items/ba6d7b913fc744db3d79#langchain

AutoGenのコンポーネント

Autogenの中のコンポーネント構成は下図のようになっており、主に6つのクラスライブラリ群から構成されています。

image.png

出典 : AutoGen v0.4: Reimagining the foundation of agentic AI for scale, extensibility, and robustness

各コンポーネントの概要説明は以下の通りです。

コンポーネント 概要
Core エージェントシステムを定義するための基本フレームワークとなるライブラリ。エージェントのメッセージ管理、タスク分割、ツール(Function Calling)の定義などフレームワークの中心を開発するためのAPI。
AgentChat Coreで提供している各エージェントの連携パターンのうちグループチャット方式の実装が更に抽象化されたAPI。
Extension AutoGen以外のコンポーネントと連携するためのAPI。様々なプロバイダのLLM、ローカルにホストされたLLM、Dockerとの連携時に利用。
Magentic-One ウェブ検索、ファイル操作、コード生成・実行を専門とするエージェントと、それらを指揮エージェントによって構成されたマルチエージェントシステム。汎用的な用途を目的に複雑なタスクを段階的に解決してゆくAIエージェントのリファレンス実装。
Studio エージェントのローコード開発ツール。開発したAIエージェントのコードを生成することも可能。本番システムではなく研究用途が推奨。※AutoGenの全ての関数が利用できるわけではない点に注意
Bench エージェントのパフォーマンスを測定・評価するためのベンチマークスイート。Docker必須。予め決められたベンチマークシナリオにおいて総コスト、タスク完了時間、会話ターン数などをスコアリング。

基本的な開発の流れとしては

  • CoreかAgentChat(もしくはその両方の混在)とextensionを使ってマルチエージェントのコードを書いてゆきます。
  • 基本はコーディングベースの開発ですが、GUIで開発したい場合はStudioを使います。ただし、現状は本番としての利用は非推奨だとのこと。エージェントの挙動を確認するくらいの利用用途かと思います。
  • マルチエージェントの動作を評価したい場合はBenchを利用。

という感じになります。

今回は分かりやすいAgentChatをメインにサンプルコードを概説します。

AgentChatのプログラミングモデル

AutogenChatでは、その名の通り、私達が普段利用している一般的なグループチャットの挙動をそのままAPIとして実装しています。

image.png

まず、上図に記載されている赤字の名称はそれぞれ下記のものを指します。(名称から想像できると思いますが。)

  • Assistant Agent : エージェント
  • Tool : Function Calling
  • Model : LLM
  • グループチャット(チーム):複数のエージェントから構成されたグループ
  • チャット:エージェント同士の会話
  • メッセージ:エージェントの出力テキスト
  • TERMINATE:会話終了の合図

Model(LLM)とTool(Function Calling)が関連付けられたエージェントをAssistant Agentと呼んでおり、ある役割をもった複数のAssistant Agentをグルーピングし、グループチャットを定義します。

Assistant Agentの出力テキストはメッセージとしてグループ内の他のAssistant Agentに発信され、そのAssistant Agentがその内容に呼応してメッセージをまたグループ内に発信するという、まさに私達が普段使っているチャットツールの仕組みがそのままプログラミングモデルになっています。

最終的に問題のない応答テキストが生成されるとエージェントは会話終了の合図であるTERMINATEをグループに送信し、チャット完了、その内容をユーザーに返します。会話の最大ターン数など、チャットの挙動に関する様々なパラメータを定義することもできるようになっています。

サンプルコードの概説

AutoGenとAgentChatについて理解したところで簡単なサンプルコードを5パターン動かしてみたいと思います。

役割分担型マルチエージェントのサンプルコード
②役割分担型にFunction Callingを追加したパターン
ユーザーがグループチャットに介入するパターン
交渉型マルチエージェントのサンプルコード
OpenAI以外のLLMを使ってみる(OCI Generative AI ServiceのCohere Command R Plus)

①役割分担型マルチエージェントのサンプルコード

まずは一番ベーシックなサンプルコードです。旅行する際に旅程を提案してくれるエージェントの例です。4つのエージェントに役割を分担したパターンになります。

まずは上述たautogenの中の agentchat、 core, extentionなどのライブラリをインポートします。

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
import os
import getpass

OpenAIのAPIキーを入力します。

os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API Key: ")

エージェントを定義します。全体の旅程を立てるエージェント、地元の観光地やアクティビティを提案するエージェント、訪問先での公用語について教えてくれるエージェント、旅程全体をサマリーするエージェントの4つに役割分担する例です。

planner_agent = AssistantAgent(
    "planner_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="旅行の計画を立ててくれる便利なアシスタント",
    system_message="あなたは、ユーザーのリクエストに基づいて旅行プランを提案できる便利なアシスタントです。",
)

local_agent = AssistantAgent(
    "local_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="地元のアクティビティや訪問先を提案できる地元アシスタント",
    system_message="あなたは、本物で興味深い地元のアクティビティや訪問する場所をユーザーに提案し、提供されたコンテキスト情報を利用できる便利なアシスタントです。",
)

language_agent = AssistantAgent(
    "language_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="特定の目的地に関する言語のヒントを提供できる便利なアシスタント",
    system_message="あなたは、旅行計画を検討し、特定の目的地での公用語やコミュニケーションの課題に対処する最善の方法に関する重要なヒントについてフィードバックを提供できる便利なアシスタントです。計画に言語に関するヒントがすでに含まれている場合は、その計画が満足のいくものであることを根拠を添えて言及できます。",
)

travel_summary_agent = AssistantAgent(
    "travel_summary_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="旅行計画をまとめるのに役立つアシスタント",
    system_message="あなたは、他のエージェントからの提案やアドバイスをすべて取り入れ、詳細な最終的な旅行計画を提供できる、役に立つアシスタントです。最終計画が統合され、完全であることを確認する必要があります。最終的な対応は完全な計画でなければなりません。計画が完了し、すべてのパースペクティブが統合されたら、TERMINATE で応答できます。",
)

会話を終えるterminationの条件を定義します。この例ではエージェントの出力に TERMINATE という文字が入っている場合に会話終了です。上述したtravel_summary_agentのsystem_messageに「処理が完了すれば TERMINATE」という旨のシステムメッセージを入れており、これと連動して動作します。

termination = TextMentionTermination("TERMINATE")

次にグループチャットの定義です。今回はRoundRobinGroupChatを使ってみます。この定義では、あるエージェントが出力したメッセージはグループチャット内の他の全てのエージェントに送信されます。(文字通りグループチャットです。)そのメッセージを受け他のエージェントが順番に(Round Robin)応答メッセージを出力します。チャットがエンドレスにならないようにTERMINATEの条件を定義し、チャットの最大ターン数も念のため10に定義しています。

group_chat = RoundRobinGroupChat(
    [planner_agent, local_agent, language_agent, travel_summary_agent],
    termination_condition=termination,
    max_turns=10  # 最大10ターンで終了
)

現在のバージョンではRoundRobinGroupChat以外にSelectorGroupChatがあります。SelectorGroupChat
各メッセージの後に次のエージェントを選択し、順番にメッセージを送信するという制御になります。

Selector Group Chat
https://microsoft.github.io/autogen/stable/user-guide/agentchat-user-guide/selector-group-chat.html

下記のような旅程のリクエストをしてみます。

await Console(group_chat.run_stream(task="ネパールへの3日間の旅行を計画してください。"))

出力はこちら。

---------- user ----------
ネパールへの3日間の旅行を計画してください
---------- planner_agent ----------
ネパールへの3日間の旅行は短いながらも豊富な体験ができる素晴らしいプランです以下はそのサンプルプランです

### 1日目: カトマンズ探訪
- **午前:**
  - カトマンズに到着後ホテルにチェックイン
  - パシュパティナート寺院を訪問ヒンズー教の重要な寺院で素晴らしい彫刻と巡礼者の姿を楽しめます

- **午後:**
  - バグマティ川沿いにあるスワヤンブナートモンキーテンプルを訪れます360度のパノラマビューが魅力です

- **:**
  - タメル地区で夕食地元のレストランでネパール料理を楽しんでください

### 2日目: パタンとバクタプル訪問
- **午前:**
  - パタンラリトプル市を訪れますパタンダルバール広場の素晴らしい建築物と博物館を見学します

- **午後:**
  - バクタプルに移動中世の雰囲気が残る町を散策しバクタプルダルバール広場やナヤタポラ寺院を訪問します
  - バクタプルで有名なキングカードを味わいます

- **:**
  - カトマンズに戻りホテルでリラックス

### 3日目: ネイチャーとカルチャー体験
- **午前:**
  - ナガルコットへ日の出を見に出発早朝)。ヒマラヤの美しい景色を楽しむことができます

- **午後:**
  - 午後はカトマンズに戻り時間があればボダナートストゥーパを訪れますチベット仏教の象徴であるこの場所で祈りの旗を見ることができます

- **:**
  - 最後の夕食をタメル地区で取りカトマンズの夜を楽しみます現地の民俗音楽を楽しめる場所を探すのも良いでしょう

### 注意事項:
- 天候により景観が変わることがありますので現地の気象情報を確認してください
- 移動はタクシーや現地のツアーガイドを利用すると便利です
- ネパールは高地に位置しているので十分な水分補給と体調管理を心がけてください

このプランを基にあなたの興味に合わせてカスタマイズしてみてください良い旅を
---------- local_agent ----------
ネパールへの3日間の旅行は短期間で素晴らしい文化や自然の魅力を体験する絶好の機会です以下のプランを参考にあなただけの旅を楽しんでください

### 1日目: カトマンズの文化と歴史を探索
- **午前:**
  - カトマンズに到着後ホテルにチェックインし身支度を整えましょう
  - 伝統的で荘厳なパシュパティナート寺院を訪問しましょうここはスピリチュアルな体験と寺院の美しい建築を楽しむことができます

- **午後:**
  - スワヤンブナートモンキーテンプルを訪れ丘の上からカトマンズの全景を楽しみましょうここではヒマラヤ山脈の雄大な景色を眺めることができます

- **:**
  - タメル地区で現地のレストランを訪れて新鮮なネパール料理を堪能しましょう賑やかな通りでのショッピングもお楽しみください

### 2日目: パタンとバクタプルの中世都市訪問
- **午前:**
  - パタン市ラリトプルへ向かいパタンダルバール広場を散策ユネスコの世界遺産に指定されており魅力的な建物や博物館がたくさんあります

- **午後:**
  - バクタプルに移動して中世の雰囲気に浸りましょうバクタプルダルバール広場やナヤタポラ寺院を訪れこの地域の工芸品や特産品を楽しんでください
  - ここで有名なジュジュダウ王のカスタード)」を味わうことをお忘れなく

- **:**
  - カトマンズに戻りリラックスした夜を過ごします

### 3日目: 自然とリラックス
- **早朝:**
  - 日の出前にナガルコットに向かい美しいヒマラヤのお茶を祖とした景色を楽しむ日の出観賞を体験してください

- **午後:**
  - カトマンズに戻りチベット仏教最大のボダナートストゥーパを訪れその平和な雰囲気を楽しんでくださいここはスピリチュアルな体験ができる場所です

- **:**
  - タメル地区での最後の夕食を楽しみ美味しいネパール料理と地元の音楽を楽しんでください

### 旅行のヒント:
- 天候は変わりやすいので旅行前に天気予報を確認しましょう
- 移動にはタクシーや現地のツアーを利用するのが便利です
- 高地のため体調管理と水分補給をしっかり行いましょう

この旅程を基にあなた自身の興味に合うようにカスタマイズしていただけます素晴らしい旅をお楽しみください
---------- language_agent ----------
ネパールへの3日間の旅行プランは文化歴史自然が巧みに組み合わさった素晴らしいものです以下にいくつか特に気を付けるべき言語とコミュニケーションのポイントをお伝えします

### 言語とコミュニケーション:
- **公用語**: ネパールの公用語はネパール語ですが観光地やカトマンズのような都市部では英語も広く通じます
- **ヒンディー語**: インドと近い文化的背景を持つため特に観光関連のエリアではヒンディー語も理解されることがあります
- **基本フレーズ**: 簡単なネパール語のあいさつナマステや感謝の言葉ダンニャバードを覚えておくと地元の人との交流がさらにスムーズになります

### おすすめの対応策:
- **ガイドブックやアプリ**: 英語-ネパール語のガイドブックや翻訳アプリを事前にダウンロードしておくと便利です
- **現地のガイド**: 言語の壁をスムーズに越えるため現地のガイドを利用するのも良い選択ですガイドは観光地の詳細情報を提供してくれます

この旅行プランには公用語とコミュニケーションのタイムリーなアドバイスが含まれており非常に満足のいく内容です旅行の際はこれらのポイントを活かしてネパールネパールの魅力を存分に楽しんでくださいね
---------- travel_summary_agent ----------
ネパールへの3日間の旅行計画が整いました文化歴史自然そしてコミュニケーションのコツを備えた豊かな体験をお楽しみください

---

### 1日目: カトマンズの文化と歴史を探索
- **午前:**
  - カトマンズに到着後ホテルにチェックイン
  - スピリチュアルなパシュパティナート寺院を訪問ヒンズー教の文化を体験し見事な彫刻を楽しみましょう

- **午後:**
  - スワヤンブナートモンキーテンプルへ足を運び丘の上からカトマンズの全景を楽しめますここではヒマラヤ山脈の壮大な景色を見渡せます

- **:**
  - タメル地区で夕食地元のレストランでネパール料理を堪能し賑やかな通りでショッピングも楽しんでみてください

### 2日目: パタンとバクタプルの中世都市を探訪
- **午前:**
  - パタン市ラリトプルを訪問パタンダルバール広場でユネスコの世界遺産に指定された建築物や博物館を散策

- **午後:**
  - バクタプルへ移動バクタプルダルバール広場やナヤタポラ寺院で中世の魅力を堪能特に有名なジュジュダウ王のカスタード)」を試してみましょう

- **:**
  - カトマンズに戻りホテルでリラックス

### 3日目: 自然と静寂を求めて
- **早朝:**
  - 日の出前のナガルコットで美しいヒマラヤの景色を楽しむ日の出観賞をします

- **午後:**
  - カトマンズに戻りボダナートストゥーパを訪問チベット仏教の平和な雰囲気に浸りましょう

- **:**
  - タメル地区での最後の夕食地元の音楽を聴きながら旅行の最後の夜を楽しんでください

---

### 言語とコミュニケーション:
- **基本フレーズ**: 簡単なネパール語のナマステ」(こんにちはダンニャバード」(ありがとうを覚えて地元の人々とより良い交流を
- **ガイドブックやアプリ**: 英語-ネパール語の翻訳アプリを活用しコミュニケーションをスムーズに

---

### 旅行のヒント:
- **天候**: 高地のネパールでは天候が変わりやすいので服装には注意してください
- **移動手段**: タクシーや現地ツアーガイドを利用することで効率よく移動できます

このプランを参考にあなたの旅を個性的で充実したものにしてください素晴らしい旅をお楽しみください

TERMINATE

複数のエージェントによって役割分担され、それらがグループチャットにより会話しながら最終的な旅程を決定している様子がわかると思います。

②Function Callingを追加したパターン

上記の役割分担型のコードにFunction Callingを追加してみたいと思います。旅程提案のAIエージェントが訪問先の通貨の為替レートをヤフーファイナンスで事前にチェックしてくれるというシナリオです。

必要なライブラリをインポートします。ヤフーファイナンスのAPIサービスをCallしますのでそのライブラリyahooqueryのインポートを追加しています。

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
import os
import getpass
from yahooquery import Ticker

OpenAIのAPIキーを入力

os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API Key: ")

ヤフーファイナンスで現在の為替レートをクエリする関数を定義します。

def get_exchange_rate(currency_code: str) -> dict:
    """
    指定した国の通貨と日本円(JPY)の為替レートを取得する。

    Args:
        currency_code (str): 通貨コード(例: "USD", "EUR", "GBP")

    Returns:
        dict: 為替レート情報(通貨ペア、レート、取得時間)
    """
    symbol = f"{currency_code}JPY=X"  # 例: "USDJPY=X"
    ticker = Ticker(symbol)
    data = ticker.price[symbol]

    if "regularMarketPrice" in data:
        return {
            "currency_pair": f"{currency_code}/JPY",
            "exchange_rate": data["regularMarketPrice"],
            "timestamp": data["regularMarketTime"]
        }

    return {"error": "為替レートが取得できませんでした"}

上述の関数を実行して動作確認をします。

rate_info = get_exchange_rate("USD")  # USD/JPY のレート取得
print(rate_info)

出力は以下の通り。

{'currency_pair': 'USD/JPY', 'exchange_rate': 150.542, 'timestamp': '2025-02-20 02:09:08'}

上述の関数をFunction Callingとして定義します。

from autogen_core.tools import FunctionTool

get_exchange_rate_tool = FunctionTool(
    get_exchange_rate, description="現在の為替レートを取得します。"
)

ここからエージェントの定義です。先のコードで作成したエージェント4つに為替レートを調べるexchange_agentを追加しています。AssistantAgentの引数toolsに上述したfunction callingを定義するというシンプルなものです。

planner_agent = AssistantAgent(
    "planner_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="旅行の計画を立ててくれる便利なアシスタント",
    system_message="あなたは、ユーザーのリクエストに基づいて旅行プランを提案できる便利なアシスタントです。",
)

local_agent = AssistantAgent(
    "local_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="地元のアクティビティや訪問先を提案できる地元アシスタント",
    system_message="あなたは、本物で興味深い地元のアクティビティや訪問する場所をユーザーに提案し、提供されたコンテキスト情報を利用できる便利なアシスタントです。",
)

language_agent = AssistantAgent(
    "language_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="特定の目的地に関する言語のヒントを提供できる便利なアシスタント",
    system_message="あなたは、旅行計画の中にある訪問先での公用語に関する情報を提供できる便利なアシスタントです。",
)

# 追加のエージェント。 引数toolsでfunction Callingを定義。
exchange_agent = AssistantAgent(
    name = "exchange_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="訪問先での通貨に関する情報を提供できる便利なアシスタント",
    system_message="あなたは、旅行計画の中にある訪問先での通貨と日本円の為替レートをget_exchange_rate_toolを使って提供できる便利なアシスタントです。",
    tools=[get_exchange_rate_tool]
)

travel_summary_agent = AssistantAgent(
    "travel_summary_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="旅行計画をまとめるのに役立つアシスタント",
    system_message="あなたは、他のエージェントからの提案やアドバイスをすべて取り入れ、詳細な最終的な旅行計画を提供できる、役に立つアシスタントです。最終計画が統合され、完全であることを確認する必要があります。最終的な対応は完全な計画でなければなりません。計画が完了し、すべてのパースペクティブが統合されたら、TERMINATE で応答できます。",
)

terminationの条件とグループチャットの定義。

termination = TextMentionTermination("TERMINATE")
group_chat = RoundRobinGroupChat(
    [planner_agent, local_agent, language_agent, exchange_agent, travel_summary_agent],
    termination_condition=termination
)

下記のようなプロンプトで旅程をリクエスト。

await Console(group_chat.run_stream(task="ヨーロッパの3か国を訪れる3日間の旅行を計画してください。"))

出力がこちら。

---------- user ----------
ヨーロッパの3か国を訪れる3日間の旅行を計画してください
---------- planner_agent ----------
ヨーロッパの3か国を3日間で訪れる旅行は駆け足になりますがいくつかの国が近接しているため可能です以下に効率的に移動できるプランを提案します

**1日目: フランス (パリ)**
- : パリに到着シャルルゴール空港またはオルリー空港に着陸後市内中心部へ移動
- 午前: エッフェル塔を訪れパリの象徴的な景色を楽しみましょう
- : セーヌ川沿いでランチクレープやマカロンはいかがでしょうか
- 午後: ルーヴル美術館を訪れてみることをお勧めします主要な作品を見学する時間は確保できるでしょう
- : モンマルトル地区を散策しサクレクール寺院を訪れるのも良いでしょう

**2日目: ベルギー (ブリュッセル)**
- : 高速列車Thalysでブリュッセルへ移動約1時間30分)。
- 午前: グランプラスを訪れ美しい市庁舎を見学周囲の雰囲気を楽しむことができます
- : ベルギー名物のワッフルやチョコレートを楽しみましょう
- 午後: 小便小僧を見に行った後王立美術館でアート鑑賞をしてみてはいかがでしょうか
- : 欧州議会の周辺を散策し現代的なブリュッセルの一面を体感します

**3日目: オランダ (アムステルダム)**
- : Thalysでアムステルダムへ移動約2時間)。
- 午前: ゴッホ美術館または国立博物館を訪れヨーロッパ芸術の歴史を感じましょう
- : 運河沿いのカフェでランチを取りリラックス
- 午後: アムステルダムの美しい運河をクルーズ船で巡りましょう
- 夕方: ダム広場や旧市街を散策しお土産を購入する時間を設けましょう

このプランがご参考になれば幸いです時間に余裕を持ちつつ安全で楽しい旅をお過ごしください
---------- local_agent ----------
ヨーロッパの3か国を訪れる3日間の旅行は駆け足になりますがいくつかの国が近接しているため実現可能です以下に効率的に移動できるプランを提案します

**1日目: イタリア (ミラノ)**
- : ミラノマルペンサ空港に到着市内中心部へ移動します
- 午前: ドゥオーモやヴィットーリオエマヌエーレ2世のガレリアを見学
- : 地元のリストランテでイタリアンランチを楽しみましょう
- 午後: ブレラ美術館やレオナルドヴィンチの最後の晩餐を見学
- 夕方: スフォルツェスコ城を訪れミラノの歴史に触れましょう

**2日目: スイス (チューリッヒ)**
- : ミラノから電車でチューリッヒへ移動約3時間)。
- 午前: バンホーフ通りを散策しショッピングやカフェを楽しみましょう
- : スイス名物のチーズフォンデュやロシュティを堪能
- 午後: 歴史のある旧市街を訪れチューリッヒ湖周辺を散策
- : リンデンホーフの丘で美しい夕日を眺めます

**3日目: ドイツ (ミュンヘン)**
- : 電車でミュンヘンへ移動約4時間)。
- 午前: マリエン広場で有名な新市庁舎の鐘を鑑賞
- : ビアホールでプレッツェルとソーセージのランチを
- 午後: 英国庭園を散策しリラックスした時間を
- 夕方: フラウエン教会を訪れドイツのゴシック建築を堪能

この旅程でヨーロッパの異なる文化と歴史を短期間で体験できますぜひ現地の美食と美しい風景を楽しんでください
---------- language_agent ----------
お役に立てて嬉しいです訪れる国々の公用語をまとめておきますので現地でのコミュニケーションの参考にしてください

- **イタリア (ミラノ)**: イタリア語
- **スイス (チューリッヒ)**: ドイツ語フランス語イタリア語が公用語ですがチューリッヒでは主にドイツ語が話されています
- **ドイツ (ミュンヘン)**: ドイツ語

それぞれの言語での基本的な挨拶やフレーズを覚えていくとより楽しい旅になるでしょう素晴らしいヨーロッパ旅行をお楽しみください
---------- exchange_agent ----------
[FunctionCall(id='call_QNxSHsIOwn4ckkht8RviYxdg', arguments='{"currency_code": "EUR"}', name='get_exchange_rate'), FunctionCall(id='call_fe0WHyCKt3vcRg3GMrD3U5hv', arguments='{"currency_code": "CHF"}', name='get_exchange_rate')]
---------- exchange_agent ----------
[FunctionExecutionResult(content="{'currency_pair': 'EUR/JPY', 'exchange_rate': 157.01, 'timestamp': '2025-02-20 02:27:02'}", call_id='call_QNxSHsIOwn4ckkht8RviYxdg'), FunctionExecutionResult(content="{'currency_pair': 'CHF/JPY', 'exchange_rate': 166.702, 'timestamp': '2025-02-20 02:27:01'}", call_id='call_fe0WHyCKt3vcRg3GMrD3U5hv')]
---------- exchange_agent ----------
{'currency_pair': 'EUR/JPY', 'exchange_rate': 157.01, 'timestamp': '2025-02-20 02:27:02'}
{'currency_pair': 'CHF/JPY', 'exchange_rate': 166.702, 'timestamp': '2025-02-20 02:27:01'}
---------- travel_summary_agent ----------
ヨーロッパの3か国を訪れる3日間の旅行プランを最終調整しました以下が詳細な旅程です

**1日目: イタリア (ミラノ)**
- ****: ミラノマルペンサ空港に到着市内中心部へ移動します
- **午前**: ミラノ大聖堂ドゥオーモやヴィットーリオエマヌエーレ2世のガレリアを見学します
- ****: 地元のリストランテでイタリアンランチを楽しみましょう
- **午後**: ブレラ美術館を訪れレオナルドヴィンチの最後の晩餐を鑑賞します
- **夕方**: スフォルツェスコ城を訪れミラノの歴史に触れましょう

**2日目: スイス (チューリッヒ)**
- ****: ミラノから電車でチューリッヒへ移動約3時間)。
- **午前**: バンホーフ通りを散策しショッピングやカフェを楽しみます
- ****: スイス名物のチーズフォンデュやロシュティを堪能
- **午後**: 歴史ある旧市街を訪れチューリッヒ湖周辺を散策します
- ****: リンデンホーフの丘で美しい夕日を観賞します

**3日目: ドイツ (ミュンヘン)**
- ****: 電車でミュンヘンへ移動約4時間)。
- **午前**: マリエン広場で有名な新市庁舎の鐘を鑑賞します
- ****: ビアホールでプレッツェルとソーセージのランチをいただきます
- **午後**: 英国庭園を散策しリラックスした時間を過ごしましょう
- **夕方**: フラウエン教会を訪れドイツのゴシック建築を堪能します

**コミュニケーション**:
- イタリア語ミラノ
- ドイツ語チューリッヒミュンヘン

**為替レート**参考:
- 1ユーロ (EUR) = 157.01 (JPY)
- 1スイスフラン (CHF) = 166.702 (JPY)

このプランがあなたの旅の参考になれば幸いです異なる文化美食そして魅力的な歴史に触れる素晴らしい旅をお楽しみください安全で楽しい旅をお祈りしていますTERMINATE

exchange_rateエージェントによってfunction callingが実行され現在の為替レートが最終の旅程に反映されていることがわかります。

③ユーザーがグループチャットに介入するパターン

グループチャットの最後にユーザー(人間)が介入しエージェントの動きをメッセージで制御するパターンです。

下記のサンプルコートはこれまでと同じ旅程を決めるシナリオになりますが、エージェントの提案にユーザーが追加のリクエストを行い、エージェントがそのリクエストにそって旅程を再提案するといシナリオです。

実ビジネスだと、例えばサプライチェーンシステムなどの発注システムに連携してAIエージェントが発注処理を実行する前に人間が確認・判断を行う必要がある場合など、全ての判断をエージェントに任せられないようなケースでの利用が想定されます。

必要なライブラリをインポートします。

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
import os
import getpass

OpenAIのAPIキーを入力。

os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API Key: ")

エージェントを定義します。これまでのコードとほぼ変わりませんが、travel_summary_agentのシステムメッセージにTERMINATEの条件に関する文言が入りません。これがこれまでのコードと違う点です

planner_agent = AssistantAgent(
    "planner_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="旅行の計画を立ててくれる便利なアシスタント",
    system_message="あなたは、ユーザーのリクエストに基づいて旅行プランを提案できる便利なアシスタントです。",
)

local_agent = AssistantAgent(
    "local_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="地元のアクティビティや訪問先を提案できる地元アシスタント",
    system_message="あなたは、本物で興味深い地元のアクティビティや訪問する場所をユーザーに提案し、提供されたコンテキスト情報を利用できる便利なアシスタントです。",
)

language_agent = AssistantAgent(
    "language_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="特定の目的地に関する言語のヒントを提供できる便利なアシスタント",
    system_message="あなたは、旅行計画を検討し、特定の目的地での言語やコミュニケーションの課題に対処する最善の方法に関する重要なヒントについてフィードバックしてください。",
)

travel_summary_agent = AssistantAgent(
    "travel_summary_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-4o"),
    description="旅行計画をまとめるのに役立つアシスタント",
    system_message="あなたは、他のエージェントからの提案やアドバイスをすべて取り入れ、詳細な最終的な旅行計画を提供できる、役に立つアシスタントです。最終計画が統合され、完全であることを確認する必要があります。最終的な対応は完全な計画でなければなりません。",

)

ユーザーがグループチャットに介入するためのエージェントを新たに追加します。これまではAssistantAgentという関数でエージェントを定義しましたが、ユーザーに処理を渡す(ユーザーの入力を求める)必要があるため、別の関数UserProxyAgentでエージェントを定義します

UserProxyAgentタイプのエージェントがグループチャットに存在すると、グループチャットの最後に必ずこのUserProxyAgentに処理が渡されユーザーの入力を求めるというシーケンスになります。

from autogen_agentchat.agents import UserProxyAgent

user_proxy = UserProxyAgent("user_proxy", input_func=input)

TERMINATIONの条件を定義します。以下はユーザーが入力するメッセージに『APPROVE』の文字があった場合にチャット終了という条件でグループチャットを定義しています。

termination = TextMentionTermination("APPROVE")

group_chat = RoundRobinGroupChat(
    [user_proxy, planner_agent, language_agent, travel_summary_agent],
    termination_condition=termination,
    max_turns=10  # 最大10ターンで終了
)

定義したグループチャットを実行します。

stream = group_chat.run_stream()
await Console(stream)

UserProxyAgentが存在するグループチャットなので、初めにユーザーが入力を求められます。

Enter your response:

これまで同様「ヨーロッパの3か国を訪れる3日間の旅行を計画してください。」と入力してみます。

Enter your response: ヨーロッパの3か国を訪れる3日間の旅行を計画してください

このメッセージに反応し、他のエージェントがチャットを始めます。

Enter your response:  ヨーロッパの3か国を訪れる3日間の旅行を計画してください
---------- user_proxy ----------
ヨーロッパの3か国を訪れる3日間の旅行を計画してください
---------- planner_agent ----------
ヨーロッパで3日間の旅行はとても短期間ですが効率よく計画すれば3つの異なる国を訪れることができます以下はアクセスしやすい都市を選んだモデルプランです

### 1日目: フランス(パリ)
**午前:**
- シャルルゴール空港に到着
- ホテルにチェックイン
- 朝食後エッフェル塔を訪問観光バスを利用すると時間を節約できます

**午後:**
- ルーブル美術館を訪問名作を堪能しつつガイドツアーで効率的に観覧
- 昼食はルーブル周辺のカフェでフランス料理を満喫

**:**
- セーヌ川クルーズで夜景を楽しみながらパリの美しさを堪能
- オルセー美術館の近くでディナー

### 2日目: ベルギー(ブリュッセル)
**午前:**
- 午前中の早い時間にタリス高速列車でブリュッセルへ移動約1時間半)。
- グランプラスを見学し周辺の観光スポットを散策

**午後:**
- 昼食はベルギーワッフルを試しつつ地元のビールを楽しむ
- アトミウムへ訪れアートと建築の融合を体験

**:**
- サントカトリーヌ広場周辺のレストランで夕食
- ブリュッセル北駅近くのホテルに宿泊

### 3日目: オランダ(アムステルダム)
**午前:**
- 朝早く出発してインターシティエクスプレスでアムステルダムへ移動約2時間)。
- 市内の中心ダム広場を訪問し王宮を観光

**午後:**
- ライクスミュージアムかアムステルダム国立美術館を訪問しオランダの芸術を堪能
- 市内運河沿いのカフェでランチ

**:**
- ヴォルヘルスト公園を訪れ自然を楽しむ
- ユニークなハーリングやストロープワッフルを試しつつ軽食を楽しみながらアムステルダム中央駅へ
- 帰国のためのフライトに備えてスキポール空港へ移動

このプランではなるべく公共交通機関を利用して時間を節約し各都市の主要スポットを楽しむようにしています滞在時間は短いですがそれぞれの文化と観光地を最大限に堪能できることでしょう旅行に必要なビザやチケット宿泊先は事前に予約しておくのをお忘れなく
---------- language_agent ----------
旅行計画に関してヨーロッパでの言語とコミュニケーションの課題に対処するためのいくつかのヒントを提供します

1. **基本フレーズを学ぶ**: 各国の基本的なフレーズ挨拶感謝尋ねる言葉などをあらかじめ学んでおくと便利です小さなジェスチャーが地元の人々との距離を縮める助けになります

2. **翻訳アプリを活用**: Google翻訳やDeepLのような翻訳アプリをスマートフォンにダウンロードしておけばリアルタイムでテキストや音声を翻訳することができ緊急時やサポートが必要なときに役立ちます

3. **地図アプリのオフライン利用**: オフラインで使える地図アプリをダウンロードしておくと通信が不安定な場所でも道に迷わずに済みます事前に主要地点をマークしておくと便利です

4. **非言語コミュニケーション**: 必要な情報を伝える際ジェスチャーや手ぶりを使って意思疎通を図ることも可能です特に指差しや数量を示すジェスチャーは言語を超えて理解できます

5. **現地の言語サポートブックを持参**: 簡単なガイドブックやポケット辞書を持っていると現地で必要な言語をすぐに確認できます

6. **宿泊先のスタッフに聞く**: 宿泊先のスタッフに現地の情報やおすすめのスポットを尋ねると地元の観光情報を得たりコミュニケーションの仲介をしてもらったりできます

これらのヒントを活用すれば旅行中のコミュニケーションの課題をよりスムーズに乗り越えることができるでしょう楽しい旅をお過ごしください
---------- travel_summary_agent ----------
素晴らしい旅行計画を最大限に活用するために言語のヒントも取り入れた最終的なヨーロッパ旅行計画をご案内します

### 1日目: フランス(パリ)
**午前:**
- シャルルゴール空港に到着後タクシーやシャトルでホテルにチェックイン
- エッフェル塔を訪問事前にチケット予約をしておくと待ち時間を短縮できます観光バスツアーを利用すると効率的です

**午後:**
- ルーブル美術館を訪問名作を効率的に観覧するためにガイドツアーを利用館内の看板は多言語対応ですが翻訳アプリが役立つときもあります
- 昼食はルーブル周辺のカフェでフランス料理を満喫

**:**
- Google翻訳を活用しつつセーヌ川クルーズで夜景を楽しむ音声ガイドが多言語で利用できる場合もあり)。
- オルセー美術館の近くでディナー基本的なフランス語挨拶を試してみてください

### 2日目: ベルギー(ブリュッセル)
**午前:**
- 午前中のタリス高速列車でブリュッセルへ移動約1時間半)。列車には多言語案内があり翻訳アプリも補助になります
- グランプラスを訪れ周辺を散策基本的なオランダ語やフランス語のフレーズを使ってみましょう

**午後:**
- ベルギーワッフルとビールを楽しんでランチ
- アトミウムを訪問翻訳アプリで案内を理解しつつ展示を楽しむ

**:**
- サントカトリーヌ広場周辺で夕食地図アプリを活用しながらレストランを探してみましょう
- ブリュッセル北駅近くのホテルにチェックイン

### 3日目: オランダ(アムステルダム)
**午前:**
- 早朝にインターシティエクスプレスでアムステルダムへ約2時間)。駅での案内は多言語対応です
- ダム広場を観光し王宮内を散策英語での案内も多くコミュニケーションは容易です

**午後:**
- ライクスミュージアムを訪問名作を鑑賞し翻訳機能を使用しながら説明を理解
- 運河沿いのカフェでランチ地図アプリで現地情報を確認しつつ移動

**:**
- ヴォルヘルスト公園で自然を楽しむ
- ハーリングやストロープワッフルを試しながらアムステルダム中央駅へ帰国のフライト準備としてスキポール空港に向かいます

3日間とはいえ事前準備とテクノロジーの活用を駆使することで3つの国の魅力をしっかり探索できます各国の基本フレーズをおさえつつアプリを使いこなして素晴らしい旅をお楽しみください

Enter your response:

一通りのエージェントがチャットを終え、処理がUserProxyAgentに戻り、再度入力を求められます。ここで内容に問題がなければ『APPROVE』と入力すればチャット完了です。

今回は、訪問先の一部を別の国に変更するようなプロンプトを入力してみます。

Enter your response: ベルギーを別の国に変更してください

上述のプロンプトを受け、以降、グループチャットのやり直しという状況になります。

---------- user_proxy ----------
ベルギーを別の国に変更してください
---------- planner_agent ----------
かしこまりましたではベルギーの代わりにドイツを旅程に組み込みます以下はドイツを含む3日間の旅行プランです

### 1日目: フランス(パリ)
**午前:**
- シャルルゴール空港に到着
- ホテルにチェックイン
- 朝食後エッフェル塔を訪問観光バスを利用すると時間を節約できます

**午後:**
- ルーブル美術館を訪問名作を堪能しつつガイドツアーで効率的に観覧
- 昼食はルーブル周辺のカフェでフランス料理を満喫

**:**
- セーヌ川クルーズで夜景を楽しみながらパリの美しさを堪能
- オルセー美術館の近くでディナー

### 2日目: ドイツ(ケルン)
**午前:**
- 午前中にタリス高速列車またはICEでパリからケルンへ移動約3時間)。
- ケルン大聖堂を訪問ケルンの象徴的な建築物でガイドツアーがあるので利用するのもおすすめです

**午後:**
- ライン川沿いを散策しながらリラックス地元のレストランでランチ
- ケルン市立美術館や応用工芸美術館を訪問地方の文化や歴史を堪能

**:**
- ケルンの旧市街で夕食伝統的なドイツ料理を楽しんでみましょう
- ケルンのホテルに宿泊

### 3日目: オランダ(アムステルダム)
**午前:**
- 朝早く出発してインターシティエクスプレスでアムステルダムへ移動約3時間)。
- 市内の中心ダム広場を訪問し王宮を観光

**午後:**
- ライクスミュージアムやアムステルダム国立美術館を訪れオランダの芸術を堪能
- 市内運河沿いのカフェでランチ

**:**
- ヴォルヘルスト公園を訪れ自然を楽しむ
- ユニークなハーリングやストロープワッフルを試しつつ軽食を楽しんでアムステルダム中央駅へ

このプランでは各都市の主要スポットを効率的に楽しむことを重視していますドイツ特にケルンの歴史的建造物や美術館も短い滞在でも印象に残る観光地です旅行の準備には各都市での宿泊や交通機関の予約を忘れずに行ってください楽しい旅をお過ごしください
---------- language_agent ----------
言語のヒントを活用しながらの旅行計画を以下にご案内します

### 1日目: フランス(パリ)
**午前:**
- シャルルゴール空港に到着後ホテルにチェックイン到着時にフランス語の基本フレーズを使うと好印象
- エッフェル塔を訪問事前にオンラインでチケット予約がおすすめです

**午後:**
- ルーブル美術館へガイドツアーは多言語対応フランス語の案内を翻訳アプリで補完できます
- 昼食にはフランス料理を堪能しメニューを翻訳アプリで確認

**:**
- セーヌ川のクルーズで夜景を楽しむ際音声ガイドが多言語対応か確認
- パリのカフェでディナー時に簡単な挨拶を練習して

### 2日目: ドイツ(ケルン)
**午前:**
- ドイツに向かう国際列車内ではドイツ語の基本フレーズを勉強車内案内は多言語が基本
- ケルン大聖堂を訪問観光情報は英語でも広く提供されているので便利です

**午後:**
- ライン川沿いへ景観と歴史を楽しみながら昼食翻訳アプリでメニューを確認
- ケルン市内美術館を訪れる前に展示情報をオンラインで確認

**:**
- ドイツのビアホールで夕食を地元料理を楽しみつつ店員にドイツ語での注文を試みます
- ケルンの中心地に宿泊

### 3日目: オランダ(アムステルダム)
**午前:**
- アムステルダムに向かう列車ではオランダ語の基本的な挨拶をマスター到着時に役立ちます
- ダム広場に到着歴史的な地点を観光し王宮内部を見学

**午後:**
- ライクスミュージアムやゴッホ美術館を巡りオランダの芸術を楽しんでください展示案内は多言語対応が多いです
- カフェでランチ翻訳アプリで通常のメニューも確認可能

**:**
- ヴォルヘルスト公園で夕方をリラックスマーケットで地元のお菓子を試食
- アムステルダム中央駅からスキポール空港へ行き帰国準備

翻訳アプリと基本的な言語スキルを駆使することで国境を越える短期間の旅行でもしっかりとした文化体験を得られるはずです安全で楽しい旅をお楽しみください
---------- travel_summary_agent ----------
最終プランとして言語のヒントを盛り込んだ3日間のヨーロッパ旅行をご案内します

### 1日目: フランス(パリ)
**午前:**
- シャルルゴール空港に到着後タクシーやシャトルでホテルにチェックインフランス語の基本フレーズ(「Bonjourで挨拶、「Merciで感謝を試してみてください
- エッフェル塔を訪問事前にオンラインでチケット予約をし観光バスツアーを利用すると効率的です

**午後:**
- ルーブル美術館を訪問ガイドツアーが多言語に対応しており翻訳アプリで補足情報を確認できます
- 昼食はルーブル周辺のカフェでフランス料理を楽しみましょう翻訳アプリでメニューを確認するとスムーズです

**:**
- セーヌ川クルーズで美しい夜景を楽しむ音声ガイドは多言語対応
- オルセー美術館近くのカフェでディナー店員にフランス語の簡単な挨拶とフレーズを試してみてください

### 2日目: ドイツ(ケルン)
**午前:**
- ドイツのケルンへの移動はタリス高速列車またはICEで車内アナウンスは多言語対応簡単なドイツ語のフレーズ(「Halloで挨拶、「Dankeで感謝も活用してみましょう
- ケルン大聖堂を訪問観光情報や案内板は英語にも対応しています

**午後:**
- ライン川散策と地元レストランでのランチドイツ料理を堪能翻訳アプリでメニュー確認が便利
- ケルン市立美術館を訪問展示情報をHPで確認し見学を効率よく

**:**
- 旧市街での夕食ビアホールでの注文で簡単なドイツ語を試みてみましょう
- ケルン市内のホテルに宿泊

### 3日目: オランダ(アムステルダム)
**午前:**
- アムステルダムへはインターシティエクスプレスで移動車内でオランダ語の基本フレーズ(「Hoiで挨拶、「Dank jeで感謝を学んでみましょう
- ダム広場訪問王宮を見学案内は英語でもあります

**午後:**
- ライクスミュージアムを訪問オランダの芸術を楽しみ翻訳アプリで展示説明を確認
- 市内運河沿いのカフェでランチメニューを翻訳アプリでチェック

**:**
- ヴォルヘルスト公園でリラックス地元のマーケットでストロープワッフルなどのお菓子を試食
- アムステルダム中央駅からスキポール空港へ移動し帰国準備

この旅行プランは各国の主要な観光スポットを訪れつつそれぞれの国での基本的な言語スキルを実践する機会を提供しますテクノロジーを利用してコミュニケーションをサポートしながら充実した文化体験を満喫してください良い旅をお過ごしください

Enter your response: 

一通りエージェントのチャットが処理されたので、再度User Proxy Agentに処理が渡り、入力を求められます。『Approve』を入力するとチャット終了です。

Enter your response: APPROVE
---------- user_proxy ----------
APPROVE

エージェントの会話にユーザーが介入する様子がおわかりいただけたのではないでしょうか。

④交渉型マルチエージェントのサンプルコード

不動産の売り手エージェントと不動産の買い手エージェントが交渉を行い、交渉仲介エージェントがそれを纏めるという交渉型マルチエージェントのシナリオです。

不動産の買い手エージェントにのみ、不動産の市場価格情報を検索できるFunction Callingを定義してみました。

必要なライブラリのインポート

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_core.tools import FunctionTool
from typing import List
import os
import getpass

OpenAIのAPIキーの入力

os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API Key: ")

不動産価格情報として架空の市場データ定義します。本来であればこの部分は不動産情報ライブラリ(国土交通省)などのサービスにAPI Callするfunction callingを作成すべきですが今回は簡易的に下記のデータを検索するfunction callingを定義します。

real_estate_data = {
    "新宿駅": [
        {"価格(万円)": 8500, "広さ(㎡)": 60, "駅徒歩(分)": 5},
        {"価格(万円)": 10500, "広さ(㎡)": 80, "駅徒歩(分)": 10},
        {"価格(万円)": 15000, "広さ(㎡)": 100, "駅徒歩(分)": 10},
    ],
    "渋谷駅": [
        {"価格(万円)": 9200, "広さ(㎡)": 55, "駅徒歩(分)": 15},
        {"価格(万円)": 15500, "広さ(㎡)": 75, "駅徒歩(分)": 10},
        {"価格(万円)": 9200, "広さ(㎡)": 55, "駅徒歩(分)": 4},
    ],
    "品川駅": [
        {"価格(万円)": 9700, "広さ(㎡)": 60, "駅徒歩(分)": 5},
        {"価格(万円)": 14000, "広さ(㎡)": 90, "駅徒歩(分)": 10},
        {"価格(万円)": 13000, "広さ(㎡)": 80, "駅徒歩(分)": 15},
    ],
}

不動産価格情報のデータを検索する関数を定義。(これを後のステップでFunction Callingにします。

def search_real_estate_info(station_name: str) -> List:
    """
    指定された駅の不動産情報(価格・広さ・駅徒歩)をすべてリスト型で返す。

    Args:
        station_name (str): 検索する駅名。

    Returns:
        List[Dict[str, Any]]: 指定駅の不動産情報リスト。
            - 例: [{"価格(万円)": 8500, "広さ(㎡)": 60, "駅徒歩(分)": 5}, {...}]
            - データがない場合: [{"エラー": "データなし"}]
    """
    return real_estate_data.get(station_name, [{"エラー": "データなし"}])

定義した関数の動作確認。品川駅で検索してみる。

search_real_estate_info("品川駅")

下記が出力結果。品川駅の3件が検索できている。

[{'価格(万円)': 9700, '広さ(㎡)': 60, '駅徒歩(分)': 5},
 {'価格(万円)': 14000, '広さ(㎡)': 90, '駅徒歩(分)': 10},
 {'価格(万円)': 13000, '広さ(㎡)': 80, '駅徒歩(分)': 15}]

定義した関数を Function Callingとして定義。

search_real_estate_tool = FunctionTool(
    search_real_estate_info, description="指定された駅の不動産価格情報を調査します。"
)

エージェントを定義。
不動産の売り手エージェント、買い手エージェント、両者をとりもつ交渉エージェントを定義。

# 売り手エージェント(できるだけ高い価格を提示)
seller_agent = AssistantAgent(
    "seller_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-3.5-turbo"),
    description="できるだけ高い価格で売りたい不動産の売り手エージェント",
    system_message=(
        "あなたはユーザーの依頼を受け、不動産を売却する売り手エージェントです。最初に高めの価格を提示し、できるだけ高い価格で売ることを目指してください。 "
        "ただし、あまりにも強気すぎると買い手が離れる可能性がありますので注意してください。"
    )
)

# 買い手エージェント(できるだけ低い価格を提示)
buyer_agent = AssistantAgent(
    "buyer_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-3.5-turbo"),
    description="できるだけ低い価格で買いたい不動産の買い手エージェント",
    system_message=(
        "あなたは不動産の買い手エージェントです。"
        "購入を希望する駅の不動産情報をツール 'search_real_estate_info' で検索し、価格・広さ・駅徒歩を考慮して交渉してください。"
    ),
    tools=[search_real_estate_tool]
)

# 交渉エージェント(合意可能な価格を決定)
negotiation_agent = AssistantAgent(
    "negotiation_agent",
    model_client=OpenAIChatCompletionClient(model="gpt-3.5-turbo"),
    description="売り手と買い手の意見を調整し、交渉をまとめるエージェント",
    system_message=(
        "あなたは交渉の進行役です。両者の提示価格、広さ、駅徒歩を考慮し、公平な合意価格を提案してください。\n"
        "交渉が決まったら『交渉成立: 最終価格は○○万円です 』と出力してください。\n"
        "交渉が決裂する場合は『交渉決裂』と出力してください。"
    )
)

会話終了の条件とグループチャットの定義。

# 終了条件:「交渉成立」または「交渉決裂」
termination = TextMentionTermination("交渉成立 | 交渉決裂")

group_chat = RoundRobinGroupChat(
    [seller_agent, buyer_agent, negotiation_agent],
    termination_condition=termination,
    max_turns=10  # 最大10ターンで終了
)

下記のプロンプトで交渉スタート。

await Console(group_chat.run_stream(task="東京都内でありながら緑豊かな眺望、近隣には多くのレストランやショッピング施設、公園などがあり、品川駅から徒歩10分、広さ70㎡のマンションを売却したいです。"))

出力結果は下記の通り。

---------- user ----------
東京都内でありながら緑豊かな眺望近隣には多くのレストランやショッピング施設公園などがあり品川駅から徒歩10分広さ70のマンションを売却したいです
---------- seller_agent ----------
それは素晴らしい物件ですね同様の物件は市場で高い需要がありますこのような魅力的な条件を考慮して価格設定できるだけ高めに設定することが重要ですまずは周辺の類似物件の価格や売り出し価格を調査し相場を把握することが大切ですそしてその上で70のマンションとして特に魅力的な点を強調し高めの価格で提示することをお勧めします買い手も利点を理解し魅力に引かれることでより高い価格で取引が成立する可能性が高まります
---------- buyer_agent ----------
[FunctionCall(id='call_AIO4RmaVL2lZPSAwrpZxQdO5', arguments='{"station_name":"品川駅"}', name='search_real_estate_info')]
---------- buyer_agent ----------
[FunctionExecutionResult(content="[{'価格(万円)': 9700, '広さ(㎡)': 60, '駅徒歩(分)': 5}, {'価格(万円)': 14000, '広さ(㎡)': 90, '駅徒歩(分)': 10}, {'価格(万円)': 13000, '広さ(㎡)': 80, '駅徒歩(分)': 15}]", call_id='call_AIO4RmaVL2lZPSAwrpZxQdO5')]
---------- buyer_agent ----------
[{'価格(万円)': 9700, '広さ(㎡)': 60, '駅徒歩(分)': 5}, {'価格(万円)': 14000, '広さ(㎡)': 90, '駅徒歩(分)': 10}, {'価格(万円)': 13000, '広さ(㎡)': 80, '駅徒歩(分)': 15}]
---------- negotiation_agent ----------
上記の類似物件価格を参考にしつつあなたのマンションの特長を踏まえて価格を設定することが重要です素晴らしい眺望周辺施設の魅力品川駅からのアクセスの良さなどを強調し信頼性のある査定価格サイトなどで比較検討を行うことをお勧めしますそれに基づき価格面で購入希望者と合意に達することが肝要です価格交渉を進めるときには相手の提示価格や条件を十分に把握し柔軟な交渉を心掛けましょう

提示価格: 11000万円
広さ: 70
駅徒歩: 10

これらの条件を踏まえ11000万円での売却をご検討いただけますでしょうかご担当者さまのご提案をお待ちしております
---------- seller_agent ----------
提示価格は中間的であり競合物件の価格に依拠する同時に高めの価格を提示しています柔軟な価格設定をし交渉を進めることで買い手との合意が得られる可能性を高めています買い手エージェントからの反応に注目しましょう
---------- buyer_agent ----------
価格交渉の進展を願っています必要に応じて査定サイトや不動産エージェントのアドバイスなども活用して円滑な取引が進むことを期待しています
---------- negotiation_agent ----------
交渉成立: 最終価格は11000万円です
---------- seller_agent ----------
交渉成立おめでとうございます11000万円での売却が成立し円滑な取引が行われました買い手エージェントの提案に合意できる条件が整い上手く合意に達したようですね今後の手続きや引き渡しに向けて買い手エージェントと共にスムーズな進行を図ることが大切です何かご不明点やお手続きの支援が必要な場合はいつでもお知らせください
---------- buyer_agent ----------
円滑な取引成立おめでとうございます引き続き買い手エージェントおよび関係者との協力を通じて手続きを円滑に進めていくことが重要です何かお手伝いできることがあればお知らせください
---------- negotiation_agent ----------
ありがとうございます円滑に取引が成立して大変喜ばしいです引き続きの手続きや問題解決において必要に応じてサポートさせていただきますよろしくお願いいたします
---------- seller_agent ----------
円滑な取引成立おめでとうございます今後の手続きもスムーズに進むことを願っております引き続きご協力させていただきますので何かお困りのことやご相談がございましたらいつでもお知らせくださいありがとうございました

上記は交渉成立のパターンですが、何度も実行していると交渉決裂のパターンも現れます。

⑤OpenAI以外のLLMを使ってみる(OCI Generative AI ServiceのCohere Command R Plus)

AutoGenはOpenAI以外のモデルも動かせるようになっています。その際はLLMをAutoGenのカスタムLLMとして定義する必要があります。AutoGenが直接サポートしているLLMもあれば、OllamaやLangChainで定義されているモデルをカスタムLLMとして利用することもできます。

以下のコードはOracle Cloudで提供されているGenerative AI ServiceのLLMをLangChain経由でAutoGenにカスタムLLMとして認識させるパターンです。エージェントの構成としては旅程提案のシナリオになります。

まずはGenerative AI ServiceのLLMをLangChainのカスタムLLMとして定義します。この際、Oracle CloudのAccelerated Data Scienceというデータサイエンティスト向けのライブラリを利用すると下記のように定義がシンプルになります。

import ads
from ads.llm.chat_template import ChatTemplates
from ads.llm.autogen.client_v02 import LangChainModelClient, register_custom_client

# カスタムLLMの定義
register_custom_client(LangChainModelClient)

# OCI Generative AIのLLMの設定をAutogenのconfig_list形式に変換
config_list_custom = [
    {
        "model_client_cls": "LangChainModelClient",
        "langchain_cls": "langchain_community.chat_models.oci_generative_ai.ChatOCIGenAI",
        "client_params": {
            "model_id": "cohere.command-r-plus-08-2024",
            "compartment_id": "<コンパートメントのOCID>",
            "model_kwargs": {
                "temperature": 0,
                "max_tokens": 4000
            },
            "service_endpoint": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com",
            "auth_type": "API_KEY",                      
            "auth_profile": "DEFAULT",
        },
    }
]

# LLMのパラメータ
llm_config={
        "seed": 0,
        "config_list": config_list_custom,
        "temperature": 0,
}

ユーザー介入型のUserProxyAgentを定義しますが、今回はhuman_input_mode="NEVER"とし、ユーザーの入力は求めず、全てエージェントだけでやり切ってもらいます。

また、注意すべき点としては、今回のLLMのケースでは AgentChatがサポートしていないのでAutogen Coreのほうのライブラリを利用します。従って、agentchatではなく、autogen直下のUserProxyAgentクラスを使ってエージェントを定義します。

from autogen import UserProxyAgent

user_proxy = UserProxyAgent(
    name="User_proxy",
    system_message="A human admin.",
    code_execution_config=False,

    human_input_mode="NEVER",
    max_consecutive_auto_reply=0,
    is_termination_msg=lambda msg: "TERMINATE" in msg["content"],
)

AssistantAgentも同様にautogen直下のクラスを利用して定義します。そこに、llm_configという引数で事前に定義したOCI Generative AIのLLMをカスタムLLMとして指定することでLLMの定義は完了です。

from autogen import AssistantAgent

planner_agent = AssistantAgent(
    name = "planner_agent",
    llm_config=llm_config,
    description="旅行の計画を立ててくれる便利なアシスタント",
    system_message="あなたは、ユーザーのリクエストに基づいて旅行計画を提案できるアシスタントです。",
)

local_agent = AssistantAgent(
    name = "local_agent",
    llm_config=llm_config,
    description="訪問先での観光名所を提案できる便利なアシスタント",
    system_message="あなたは、旅行計画の中にある訪問先の有名な観光名所とその見どころをユーザーに提案できるアシスタントです。",
)

language_agent = AssistantAgent(
    name = "language_agent",
    llm_config=llm_config,
    description="訪問先での公用語に関する情報を提供できる便利なアシスタント",
    system_message="あなたは、旅行計画の中にある訪問先での公用語に関する情報を提供できる便利なアシスタントです。",
)

travel_summary_agent = AssistantAgent(
    name = "travel_summary_agent",
    llm_config=llm_config,
    description="旅行計画をまとめるのに役立つアシスタント",
    system_message="あなたは、他のエージェントからの提案やアドバイスをすべて取り入れ、詳細な最終的な旅行計画を提供できる、便利なアシスタントです。最終計画を取り纏め、それが完全であることを確認する必要があります。最終的な対応は完全な計画でなければなりません。計画が完了すると TERMINATE で応答できます。",
)

次にエージェントの実行順序を定義します。今回のタイプのLLMではagentchatのRoundRobinGroupChatクラスは利用できないため下記のようにautogenのグラフのクラスを使って有効巡回グラフの形式で定義します。

from autogen.graph_utils import visualize_speaker_transitions_dict 

agents = [user_proxy, planner_agent, local_agent, language_agent, travel_summary_agent]

# エージェントを順番に遷移できるように定義
agent_graph = {
    user_proxy: [planner_agent],
    planner_agent: [local_agent],
    local_agent: [language_agent],
    language_agent: [travel_summary_agent],
    travel_summary_agent: [user_proxy],
}

# エージェントの順序を可視化
visualize_speaker_transitions_dict(agent_graph, agents)

image.png

次にグループチャットを定義しますが、上述した通り、今回のLLMではAgentChatのRoundRobinGroupChatはサポートされていませんので、coreのGroupChat関数を利用します。その場合、定義したGroupChatをGroupChatManagerに渡すことで、グループチャットが制御されるような仕組みになっています。

from autogen import GroupChat

group_chat = GroupChat(
    agents=agents,
    messages=[],
    max_round=20,
    allowed_or_disallowed_speaker_transitions=agent_graph,
    speaker_transitions_type="allowed"
)

from autogen import GroupChatManager

# Create the manager
chat_manager = GroupChatManager(
    groupchat=group_chat, llm_config=llm_config, code_execution_config=False
)

下記プロンプトでチャットを開始してみます。

user_proxy.initiate_chat(
    chat_manager, message="ヨーロッパの3か国の旅行を計画してください。"
)

出力はこちら。

User_proxy (to chat_manager):

ヨーロッパの3か国の旅行を計画してください

--------------------------------------------------------------------------------

Next speaker: planner_agent

planner_agent (to chat_manager):

ヨーロッパの3か国への旅行プランをご提案しますこの旅では文化歴史そして美しい景色を満喫できるでしょう

**1. フランス (パリ)**
- エッフェル塔を訪れるパリの象徴的なランドマークであるエッフェル塔は必見です塔に登り街の素晴らしい景色を眺めましょう
- ルーヴル美術館世界的に有名なルーヴル美術館ではモナリザやヴィーナスミロなどの芸術作品を鑑賞できます
- ノートルダム大聖堂ゴシック様式の傑作である大聖堂を探索しその建築の美しさに感動しましょう
- セーヌ川クルーズロマンチックなセーヌ川クルーズでパリの景色を異なる視点から楽しみましょう

**2. イタリア (ローマ)**
- コロッセオ古代ローマの円形闘技場であるコロッセオは歴史的価値のある見どころですその壮大な構造と歴史に浸りましょう
- ローマ教皇庁バチカン市国を訪れシスティーナ礼拝堂とサンピエトロ大聖堂の素晴らしい芸術と建築を体験しましょう
- トレヴィの泉伝説のトレヴィの泉でコインを投げ再びローマを訪れることを願いましょう
- ローマのフォロロマーノ古代ローマの遺跡を散策しその歴史的な重要性を実感しましょう

**3. スペイン (バルセロナ)**
- サグラダファミリアアントニガウディの未完の傑作であるサグラダファミリアはその独特な建築様式で有名です
- グエル公園ガウディが設計したもう一つの素晴らしい作品で色彩豊かでユニークな公園です
- ランブラス通り活気溢れるランブラス通りを散策しストリートパフォーマーや市場を楽しみましょう
- バルセロネータビーチ地中海の美しいビーチでリラックスしビーチ沿いのレストランで食事を楽しみましょう

旅程はパリで3日間ローマで2日間バルセロナで3日間滞在することをお勧めします各都市間の移動は飛行機または高速鉄道を利用できますヨーロッパの都市間を移動する際には事前に列車のチケットを予約するか格安航空券をチェックすることをお勧めします

宿泊施設に関しては各都市の中心部にあるホテルやアパートメントを検討してください事前に予約することで好みの宿泊施設を確保しやすくなります

食事に関してはフランス料理イタリア料理スペイン料理を存分に味わえるでしょう各都市で地元のレストランやカフェを訪れ伝統的な料理やワインを楽しんでください

この旅行プランはヨーロッパの文化と歴史の豊かさを体験するのに最適です芸術建築そして素晴らしい食事を満喫できるでしょう旅の詳細については各都市の観光局や旅行ガイドをご覧になることをお勧めします

--------------------------------------------------------------------------------

Next speaker: local_agent

local_agent (to chat_manager):

素晴らしいですねこの旅行プランでヨーロッパの魅力に触れる旅ができそうですね

## フランス (パリ)
パリは芸術ファッション美食の都として世界的に有名です

- **凱旋門**パリの有名な凱旋門はナポレオン時代の栄光を記念して建てられました頂上からの眺めは見逃せません
- **オルセー美術館**印象派やポスト印象派の作品が豊富な美術館ですモネルノワールゴッホなどの名作を鑑賞できます
- **シャンゼリゼ通り**パリで最も有名な通りの一つで高級ブティックやカフェが並びます散策しながらショッピングを楽しめます
- **モンマルトル**芸術家の街として知られるモンマルトルはサクレクール寺院やテルトル広場で有名なエリアです

## イタリア (ローマ)
ローマは古代の歴史と現代の魅力が融合した都市です

- **パンテオン**古代ローマの建築の傑作であるパンテオンはその巨大なドームが特徴的です内部にはラファエロの墓もあります
- **スペイン広場**美しい階段と噴水で知られる広場です映画ローマの休日で有名になりました
- **ボルゲーゼ公園**緑豊かな公園で散歩やピクニックに最適です公園内にはボルゲーゼ美術館もあり芸術作品を鑑賞できます
- **トラステヴェレ地区**ローマの伝統的な雰囲気が残るエリアで地元料理やワインバーが人気です

## スペイン (バルセロナ)
バルセロナはガウディの作品と地中海の魅力が溢れる都市です

- **カサバトリョ**ガウディが設計したユニークな建物で波打つような外観が印象的です
- **バルセロナ大聖堂**ゴシック様式の大聖堂でその荘厳な内装は必見です
- **ボケリア市場**活気溢れる市場で新鮮な食材や地元の食べ物を楽しめます
- **モンセラット**バルセロナ郊外にある山で独特な形の岩山とモンセラット修道院が有名です

パリローマバルセロナはいずれも見どころ満載の都市ですので旅程に余裕があれば各都市でさらに滞在期間を延長しても充実した旅になるでしょう移動手段や宿泊施設はご予算やご希望に応じて選択できます

ヨーロッパの食文化を体験するのも旅の醍醐味です各都市で地元のレストランやカフェを訪れフランス料理イタリア料理スペイン料理の味覚の旅もお楽しみください

より詳細な情報やおすすめのレストランなどについては各都市の観光ガイドや旅行ブログをご参照ください素晴らしい旅になりますように

--------------------------------------------------------------------------------

Next speaker: language_agent

language_agent (to chat_manager):

素晴らしい旅程をさらに充実させるために各都市での体験をいくつか追加しました

## フランス (パリ)

- **セーヌ川ディナークルーズ**ロマンチックなセーヌ川でのディナークルーズはパリの夜景を楽しむのに最適です美味しい食事とワインを楽しみながらエッフェル塔やノートルダム大聖堂のライトアップされた姿に感動しましょう
- **ルーヴル美術館ガイドツアー**膨大なコレクションを持つルーヴル美術館を効率的に回るにはガイドツアーがお勧めです専門のガイドがモナリザやその他の有名な作品について解説し美術館の歴史や裏話も教えてくれます
- **ベルサイユ宮殿**パリ郊外にあるベルサイユ宮殿はフランス王ルイ14世の栄華を物語っています豪華な宮殿と美しい庭園は必見です

## イタリア (ローマ)

- **バチカン美術館とシスティーナ礼拝堂**バチカン市国にあるバチカン美術館は膨大な芸術作品を収蔵していますミケランジェロの天井画で有名なシスティーナ礼拝堂はその美しさに圧倒されるでしょう
- **コロッセオ地下と上層階ツアー**コロッセオの一般公開されていないエリアを探索するツアーに参加しましょう地下や上層階から古代ローマの闘技場の裏側を覗き見ることができます
- **ローマの伝統料理教室**地元のシェフからローマの伝統料理を学ぶ料理教室はいかがでしょう フレッシュパスタやティラミスなどの料理を作りイタリアの食文化を体験できます

## スペイン (バルセロナ)

- **ガウディ建築ツアー**バルセロナにはガウディの作品が数多くありますサグラダファミリアカサバトリョカサミラなどガウディの建築ツアーに参加してその独特な世界観を深く理解しましょう
- **タパスバー巡り**バルセロナのタパスバーやワインバーを巡る食べ歩きツアーは地元のグルメを体験するのに最適です様々なタパスやワインを楽しみながらバルセロナの食文化に触れましょう
- **モンセラット半日ツアー**バルセロナから日帰りでモンセラットを訪れるツアーは人気です独特な景観のモンセラット山を楽しみモンセラット修道院では黒人聖母像を見学しましょう

これらの追加アクティビティは各都市の文化や歴史をより深く体験するのに役立ちます食事芸術歴史そしてユニークな体験を組み合わせることで忘れられないヨーロッパの旅になるでしょう

旅の計画を立てる際は各都市の観光局や旅行ブログで詳細な情報を入手しご自身の好みに合わせて旅程をカスタマイズすることをお勧めします

--------------------------------------------------------------------------------

Next speaker: travel_summary_agent

travel_summary_agent (to chat_manager):

## 最終的な旅行計画

### フランス (パリ)
**滞在期間4日間**
- エッフェル塔
- ルーヴル美術館ガイドツアー
- セーヌ川ディナークルーズ
- 凱旋門
- オルセー美術館
- シャンゼリゼ通りでのショッピング
- モンマルトル散策
- ベルサイユ宮殿見学

### イタリア (ローマ)
**滞在期間3日間**
- コロッセオとコロッセオ地下ツアー
- ローマ教皇庁とシスティーナ礼拝堂
- パンテオン
- スペイン広場
- ボルゲーゼ公園と美術館
- トラステヴェレ地区で地元料理を堪能
- ローマの伝統料理教室

### スペイン (バルセロナ)
**滞在期間4日間**
- サグラダファミリア
- グエル公園
- カサバトリョ
- バルセロナ大聖堂
- ランブラス通り
- ボケリア市場
- バルセロネータビーチでのリラックス
- ガウディ建築ツアー
- タパスバー巡り
- モンセラット半日ツアー

**旅程概要**
1. パリに4日間滞在しエッフェル塔ルーヴル美術館セーヌ川クルーズなどの名所を満喫します
2. 高速鉄道や飛行機でローマに移動し3日間滞在コロッセオバチカン市国スペイン広場などを訪れます
3. 再び高速鉄道や飛行機でバルセロナへ4日間滞在しサグラダファミリアグエル公園ランブラス通りモンセラットなどガウディの作品と地中海の魅力を満喫します

**移動手段**
パリとローマローマとバルセロナの間は高速鉄道や格安航空券を利用して移動します事前に列車のチケットを予約するか航空券をチェックしておくとスムーズです

**宿泊施設**
各都市の中心部にあるホテルやアパートメントを予約します事前に予約することで好みの宿泊施設を確保しやすくなります

**食事**
フランス料理イタリア料理スペイン料理を存分に味わいましょう各都市で地元のレストランやカフェを訪れ伝統的な料理やワインを楽しみましょう特にパリのセーヌ川ディナークルーズローマの伝統料理教室バルセロナのタパスバー巡りはおすすめです

**追加情報**
- ベルサイユ宮殿はパリ郊外にありますが見学には半日程度必要です
- ローマの料理教室では事前に予約が必要な場合があります
- バルセロナのモンセラット半日ツアーは人気があるため事前に予約することをお勧めします

この旅行計画ではヨーロッパの3都市で芸術歴史食文化を満喫できます各都市の見どころを効率的に回りながら充実した時間を過ごせるでしょう

TERMINATE

--------------------------------------------------------------------------------

カスタムLLMを使う場合はAgentChatと多少コードが異なりますが、エージェントを定義してグループチャットという流れは変わらないということがおわかりいただけたのではないでしょうか。

マルチエージェントデザインパターンはAutoGenのマニュアルにもいつくか掲載されていますので是非ご参考に。

https://microsoft.github.io/autogen/stable/user-guide/core-user-guide/design-patterns/intro.html

本記事に掲載した内容やサンプルコードはAutoGenのごく一部になります。これら以外にも様々な実装ができますが、まとめとして特徴的な点を挙げるとすると

  • グループチャットという私達が普段慣れ親しんだ仕組みをそのままプログラミングモデルとしてAPIに落とし込んでいるので理解しやすい
  • ライブラリの抽象度が非常に高く、複雑な処理をシンプルにコーディングできる
  • チュートリアルやリファレンス実装が沢山あり、マニュアルもわかりやすい
  • 著名なライブラリのためインターネットに情報が多い
  • LangChainとの連携が可能(LangChainのAgentやToolと連携可能)

というところでしょうか。動作が怪しい点はまだありますが非常に利用しやすく、マルチエージェント入門としては現状、最適なライブラリではないかという印象です。

おわりに

大規模言語モデルは今のところ人類が作り出した最も頭の良い人工知能だと言えます。そのような知能を持った複数のエージェントがお互いの知能をぶつけ合って生成したデータが人間の予想を超えてしまうことは想像に易く、これはまさにマルチエージェントの技術がAIシンギュラリティの門をくぐろうとしている歴史的な瞬間なのかもしれません。

76
79
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
76
79

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?