C# でも動作するマルチエージェント フレームワーク AutoGen ラウンドロビン グループチャット編

2025/01/18
★★★

複数のエージェントを連携させるグループチャット

前回は、マルチエージェント フレームワーク AutoGen for .NET を使用して簡単な壁打ちチャット実装の例を紹介しました。 今回は、より多くのエージェントを使用したグループチャットの実装例を説明したいと思います。

グループチャットを使用することで、複数のエージェントでコンテキストを共有し、エージェントを連携をさせてタスクを解決させることができます。

グループチャットは、IGroupChat の実装として、RoundRobinGroupChatGroupChat が提供されています。

ラウンドロビン グループチャット

RoundRobinGroupChat を使用することで、各エージェントをシーケンシャルに実行できます。チャット履歴が次のエージェントに渡されます。

今回は、この RoundRobinGroupChat を使用した実装例を説明したいと思います。

SemanticKernelAgent

SemanticKernelAgent は、もう一つのエージェント フレームワーク Semantic Kernelラップするエージェントです。AutoGen と Semantic Kernel との位置付けは以下の記事に説明されています。

SemanticKernelAgent を使用することで AutoGen のエージェントとして Semantic Kernel プラグインを利用できるようになります。Semantic Kernel には、Web 検索用のプラグインが含まれています。

今回は、Bing Web Search API を使用する Bing プラグインを利用します。事前に、Azure ポータルから、[Bing Search v7] を配置し、[キーとエンドポイント] から、Bing API のキーを取得しておいてください。

まず、Semantic Kernel の初期化を行います。

string azureOpenAIEndpoint = "<Azure OpenAI Service エンドポイント>";
string azureOpenAIKey = "<Azure OpenAI Service キー>";
string azureOpneAIModelDeployName = "<Azure OpenAI Service 配置モデル名>";
string bingApiKey = "<Bing API キー>";

var kernel = Kernel.CreateBuilder()
	.AddAzureOpenAIChatCompletion(_azureOpenAIModelDeployName, _azureOpenAIEndpoint, _azureOpenAIKey)
	.Build();

次に、Bing プラグインをカーネルに追加します。
事前に、Nuget から、Microsoft.SemanticKernel.Plugins.Web をインストールしてください。 Microsoft.SemanticKernel は、AutoGen の依存関係としてインストールされるためインストールする必要はありません。

#pragma warning disable SKEXP0050

	var bingConnector = new BingConnector(bingApiKey);
	var webSearchPlugin = new WebSearchEnginePlugin(bingConnector);		
	kernel.ImportPluginFromObject(webSearchPlugin, "BingPlugin");

#pragma warning restore SKEXP0054

Bing プラグインは、実験的としてマークされているためビルドが通りません。そのため #pragma warning disable SKEXP0050 でビルドエラーを回避します。

SemanticKernelAgent をインスタンス化します。このとき Semantic Kernel の Kernel インスタンスを設定します。システムメッセージには、検索結果そのままをトリプルクオート内に設置して返すように記述しています。

// Bing Search Agent
var bingSearchAgent = new SemanticKernelAgent(
		kernel: kernel,
		name: "bing-search",
		systemMessage: """
			あなたは Bing で検索を行い、検索結果をそのまま返します。
			検索結果を '''bing と ''' の間に配置します。					

			# 出力の例
			```bing
			Bing 検索結果
			```
			""")		
		.RegisterMessageConnector()
		.RegisterPrintMessage();

要約エージェント

要約エージェントは、SemanticKernelAgent が返す Bing 検索結果を要約します。
前回の記事 で説明したように Azure OpenAI Service のモデルを使用する Assistant Agent としてインスタンス化します。

// チャット クライアント
AzureOpenAIClient azureOpenAIClient = new(new Uri(azureOpenAIEndpoint), new AzureKeyCredential(azureOpenAIKey));
var chatClient = azureOpenAIClient.GetChatClient(azureOpneAIModelDeployName);

// 要約エージェント		
var summarizerAgent = new OpenAIChatAgent(
	chatClient: chatClient,
	name: "summarizer",
	systemMessage: "あなたは Bing からの検索結果を短く簡潔に要約します。")	
	.RegisterMessageConnector()
	.RegisterPrintMessage();

UserProxyAgent

ユーザーから入力として質問を受け取るために UserProxyAgent をインスタンス化します。UserProxyAgent も前回の記事で説明しました。

var userProxyAgent = new UserProxyAgent(
	name: "user",
	humanInputMode: HumanInputMode.ALWAYS)
	.RegisterPrintMessage();

RoundRobinGroupChat

これまでインスタンス化した userProxyAgent, bingSearchAgent, summarizerAgent をラウンドロビン グループチャットに登録します。 登録は、配列で指定します。配列に設定した順でエージェントが起動します。このときエージェントからの返信とチャット履歴が次に起動したエージェントに渡されます。

最後に、UserProxyAgent.InitiateChatAsync でチャットを開始します。RoundRobinGroupChat のインスタンスを引数に GroupChatManager をインスタンス化して InitiateChatAsync の receiver に設定します。

// ラウンドロビン グループチャット
var groupChat = new RoundRobinGroupChat(
	agents: [userProxyAgent, bingSearchAgent, summarizerAgent]);
// グループチャット エージェント
var groupChatAgent = new GroupChatManager(groupChat);

// 会話の開始
await userProxyAgent.InitiateChatAsync(
	receiver: groupChatAgent,	
	maxRound: 10);

マルチエージェントで Web 検索結果を要約

これまで説明したコードをコンソール アプリケーションで実装した例は以下となります。

using AutoGen;
using AutoGen.Core;
using AutoGen.OpenAI;
using AutoGen.OpenAI.Extension;
using AutoGen.SemanticKernel;
using AutoGen.SemanticKernel.Extension;
using Azure;
using Azure.AI.OpenAI;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.Web;
using Microsoft.SemanticKernel.Plugins.Web.Bing;

namespace AutoGenConsoleAppDemo002;

internal class Program
{	
	private static readonly string _azureOpenAIEndpoint = "https://<Azure OpenAI Service エンドポイント ドメイン名>.openai.azure.com/";
	private static readonly string _azureOpenAIKey = "<Azure OpenAI Service エンドポイント キー>";
	private static readonly string _azureOpenAIModelDeployName = "gpt-4o-mini";
	private static readonly string _bingApiKey = "<Bing API キー>";

	static async Task Main(string[] args)
	{
		string azureOpenAIEndpoint = _azureOpenAIEndpoint;
		string azureOpenAIKey = _azureOpenAIKey;
		string azureOpneAIModelDeployName = _azureOpenAIModelDeployName;
		string bingApiKey = _bingApiKey;

		var kernel = Kernel.CreateBuilder()
			.AddAzureOpenAIChatCompletion(_azureOpenAIModelDeployName, _azureOpenAIEndpoint, _azureOpenAIKey)
			.Build();

#pragma warning disable SKEXP0050

		var bingConnector = new BingConnector(bingApiKey);
		var webSearchPlugin = new WebSearchEnginePlugin(bingConnector);		
		kernel.ImportPluginFromObject(webSearchPlugin, "BingPlugin");

#pragma warning restore SKEXP0054		

		// Bing Search Agent
		var bingSearchAgent = new SemanticKernelAgent(
				kernel: kernel,
				name: "bing-search",
				systemMessage: """
					あなたは Bing で検索を行い、検索結果をそのまま返します。
					検索結果を '''bing と ''' の間に配置します。					

					# 出力の例
					```bing
					Bing 検索結果
					```
					""")				
				.RegisterMessageConnector()
				.RegisterPrintMessage();

		// チャット クライアント
		AzureOpenAIClient azureOpenAIClient = new(new Uri(azureOpenAIEndpoint), new AzureKeyCredential(azureOpenAIKey));
		var chatClient = azureOpenAIClient.GetChatClient(azureOpneAIModelDeployName);

		// 要約エージェント		
		var summarizerAgent = new OpenAIChatAgent(
			chatClient: chatClient,
			name: "summarizer",
			systemMessage: "あなたは Bing からの検索結果を短く簡潔に要約します。")			
			.RegisterMessageConnector()
			.RegisterPrintMessage();

		var userProxyAgent = new UserProxyAgent(
			name: "user",
			humanInputMode: HumanInputMode.ALWAYS)
			.RegisterPrintMessage();

		// ラウンドロビン グループチャット
		var groupChat = new RoundRobinGroupChat(
			agents: [userProxyAgent, bingSearchAgent, summarizerAgent]);
		// グループチャット エージェント
		var groupChatAgent = new GroupChatManager(groupChat);

		// 会話の開始
		await userProxyAgent.InitiateChatAsync(
			receiver: groupChatAgent,			
			maxRound: 10);
	}
}

このコードの実行後、userProxyAgent がユーザーの入力を待機します。
コード実行後

今回使用した GPT-4o mini 学習データカットオフ日(2023/12)以降の出来事に関する質問をしてみます。
ユーザー質問の入力

bing-search エージェントから Bing 検索結果が返され、続いて summarizer エージェントが要約を行っている様子が分かります。
エージェントの実行

指示語を使いコンテキストにもとづいた追加の質問をしてみます。
追加の質問

指示語が解釈され同様に Bing 検索結果から要約が実行されていることがわかります。 エージェントの実行

前回の記事では、AutoGen for .NET の User Proxy Agent, Assistant Agent を使用した簡単な壁打ちチャットの例を説明しました。続いて今回の記事では、マルチエージェントの例として、ラウンドロビン グループチャットを使用して、各エージェントを順次実行、連携させてタスクを実行する方法を説明しました。今後は、ダイナミックにエージェントを実行するグループチャットの方法について説明できればと考えています。

コメント (0)

コメントの投稿