複数のエージェントを動的に連携させて問題解決を行うグループチャット
前回は、複数のエージェントをシーケンシャルに実行してタスクを実行するラウンドロビン グループチャットについて説明しました。
今回は、タスク解決のために動的にエージェント選択して実行する GroupChat について説明します。
エージェントの種類としては以下を実装していきます。
- coderAgent: タスク解決のためのコードを記述するエージェント。
- runnerAgent: coderAgent が記述したコードを実行するエージェント。
- summarizerAgent: コード実行結果を要約するエージェント。
- userProxyAgent: ユーザーの入力を受け取るエージェント。
- groupAdminAgent: 各エージェントの実行順を制御するエージェント。
これらのエージェントを使用して、与えられた問題をコード記述及び実行によって解決します。
coderAgent
Azure OpenAI を使用して C# コードを記述する coderAgent を実装します。
システム メッセージには、コーディングのルールを宣言します。
string azureOpenAIEndpoint = "<Azure OpenAI Service エンドポイント>";
string azureOpenAIKey = "<Azure OpenAI Service キー>";
string azureOpneAIModelDeployName = "<Azure OpenAI Service 配置モデル名>";
// Azure OpenAI チャット クライアント
AzureOpenAIClient azureOpenAIClient = new(new Uri(azureOpenAIEndpoint), new AzureKeyCredential(azureOpenAIKey));
var azOpenAIChatClient = azureOpenAIClient.GetChatClient(azureOpneAIModelDeployName);
// コーダー エージェント: C# コードの記述
var coderAgent = new OpenAIChatAgent(
name: "coderAgent",
chatClient: azOpenAIChatClient,
systemMessage: """
あなたは C# プログラマーです。あなたは、タスクを解決するために C# コードを記述します。
あなたが記述したコードは、runnerAgent によって実行されます。
C# コードを記述する際のルールは次のとおりです。
- ```csharp と ``` の間にコードを記述してください。
- 明示的な型指定を使用してください。var を使用しないでください。
- 外部ライブラリの使用を避け、代わりに .NET Core ライブラリを使用するようにしてください。
- トップレベルのステートメントを使用してください。Main メソッドを使用してコードを書かないでください。
- コードの実行結果が分かるようにコンソール出力するコードを記述してください。
- .NET Interactive で実行可能なコードを記述してください。
- インターネットへの接続は HttpClient クラスを使用してください。
""")
.RegisterMessageConnector()
.RegisterPrintMessage();
「```csharp と ``` の間にコードを記述してください。」とすることで、runnerAgent でのコード実行時に、コード部分を抽出できるようにしています。
runnerAgent では、.NET Interactive によるコード実行を行うので、「トップレベルのステートメントを使用してください。Main メソッドを使用してコードを書かないでください。」、「.NET Interactive で実行可能なコードを記述してください。」としています。
また、.NET Interactive での実行結果を取得できるように、「コードの実行結果が分かるようにコンソール出力するコードを記述してください。」としています。
その他のルールについては、タスクに対して正しくコードが生成されない場合に、正しくコードが生成されるようなルールを追加していってください。
runnerAgent
.NET Interactive を使用して C# コードを実行する runnerAgent を実装します。
まず、DotnetInteractiveKernelBuilder で .NET Interactive カーネルを初期化します。
// .NET Interactive カーネル
var dotnetInteractiveKernel = DotnetInteractiveKernelBuilder
.CreateDefaultInProcessKernelBuilder()
// .AddPythonKernel("python3") // Python カーネルを追加
.Build();
.AddPythonKernel("python3") とすることで、Python コードを実行させることもできます。
次に、AssistantAgent でコード実行エージェントを実装します。
// コード実行エージェント
var runnerAgent = new AssistantAgent(
name: "runnerAgent",
systemMessage: "あなたは与えられた C# コードを実行します。",
defaultReply: "実行コードが見つかりません。coderAgent さんコードを記述してください。")
.RegisterMiddleware(async (msgs, option, agent, ct) =>
{
var mostRecentCoderMessage = msgs.LastOrDefault(x => x.From == "coderAgent");
if (mostRecentCoderMessage?.ExtractCodeBlock("```csharp", "```") is string code)
{
// コードブロックの実行
var result = await dotnetInteractiveKernel.RunSubmitCodeCommandAsync(code, "csharp");
result = $"""
# コードの実行結果
{result}
""";
return new TextMessage(Role.Assistant, result, from: agent.Name);
}
else
{
// defaultReply を返信
return await agent.GenerateReplyAsync(msgs, option, ct);
}
})
.RegisterPrintMessage();
RegisterMiddleware 拡張メソッドでチャット履歴を取得し、coderAgent が送信したメッセージを取得します。
coderAgent が送信したメッセージから、コード部分を取得して、Microsoft.DotNet.Interactive.Kernel.RunSubmitCodeCommandAsync でコードを実行します。
コード実行時のコンソール出力が戻り値として取得できるので、このエージェントの出力としています。
summarizerAgent
コード実行結果を要約する summarizerAgent を実装します。
// コード実行結果の要約エージェント
var summarizerAgent = new OpenAIChatAgent(
name: "summarizerAgent",
chatClient: azOpenAIChatClient,
systemMessage: """
あなたは runnerAgent が実行したコードの実行結果を要約して説明します。
""")
.RegisterMessageConnector()
.RegisterPrintMessage();
userProxyAgent
ユーザーの入力を受け取る userProxyAgent を実装します。前々回の記事で説明しています。
var userProxyAgent = new UserProxyAgent(
name: "user",
humanInputMode: HumanInputMode.ALWAYS)
.RegisterPrintMessage();
groupAdminAgent
各エージェントの実行順を制御する groupAdminAgent を実装します。
システム メッセージで各エージェントの実行ルールを宣言しています。
// グループ チャット管理者エージェント
var groupAdminAgent = new OpenAIChatAgent(
chatClient: azOpenAIChatClient,
name: "groupAdminAgent",
systemMessage: """
あなたはグループチャットの管理者です。
user から受け取った問題を coderAgent によるコーディング、runnerAgent によるコード実行で解決を行います。
コード実行が成功したら user から受け取った問題とコードの実行結果から summarizerAgent で回答を生成してください。
""")
.RegisterMessageConnector()
.RegisterPrintMessage();
グループチャット
各エージェントをグループチャットに登録します。
// グループチャット
var groupChat = new GroupChat(
admin: groupAdminAgent,
members:
[
coderAgent,
runnerAgent,
summarizerAgent,
userProxyAgent,
]);
GroupChat コンストラクタの admin を指定することで、各エージェントの実行順を制御するエージェントを明示的に登録できます。
members には、グループチャットのメンバーとする各エージェントを設定します。
グループチャットへのメッセージの送信
最後に、グループチャットへの最初のメッセージ送信部分を実装します。
// プロンプトからユーザーのメッセージを取得
Console.Write("input message: ");
string userMessage = Console.ReadLine() ?? string.Empty;
var groupChatManager = new GroupChatManager(groupChat);
// 取得したメッセージで会話を開始
await userProxyAgent.InitiateChatAsync(
message: userMessage,
receiver: groupChatManager,
maxRound: 30);
Console.ReadLine で取得したメッセージでグループチャットを開始します。
マルチエージェントで与えられた問題をコード記述及び実行によって解決
これまで説明したコードをコンソール アプリケーションで実装した例は以下となります。
using AutoGen;
using AutoGen.Core;
using AutoGen.DotnetInteractive;
using AutoGen.DotnetInteractive.Extension;
using AutoGen.OpenAI;
using AutoGen.OpenAI.Extension;
using AutoGen.SemanticKernel.Extension;
using Azure;
using Azure.AI.OpenAI;
namespace AutoGenConsoleAppDemo003;
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";
static async Task Main(string[] args)
{
string azureOpenAIEndpoint = _azureOpenAIEndpoint;
string azureOpenAIKey = _azureOpenAIKey;
string azureOpneAIModelDeployName = _azureOpenAIModelDeployName;
// Azure OpenAI チャット クライアント
AzureOpenAIClient azureOpenAIClient = new(new Uri(azureOpenAIEndpoint), new AzureKeyCredential(azureOpenAIKey));
var azOpenAIChatClient = azureOpenAIClient.GetChatClient(azureOpneAIModelDeployName);
// コーダー エージェント: C# コードの記述
var coderAgent = new OpenAIChatAgent(
name: "coderAgent",
chatClient: azOpenAIChatClient,
systemMessage: """
あなたは C# プログラマーです。あなたは、タスクを解決するために C# コードを記述します。
あなたが記述したコードは、runnerAgent によって実行されます。
C# コードを記述する際のルールは次のとおりです。
- ```csharp と ``` の間にコードを記述してください。
- 明示的な型指定を使用してください。var を使用しないでください。
- 外部ライブラリの使用を避け、代わりに .NET Core ライブラリを使用するようにしてください。
- トップレベルのステートメントを使用してください。Main メソッドを使用してコードを書かないでください。
- コードの実行結果が分かるようにコンソール出力するコードを記述してください。
- .NET Interactive で実行可能なコードを記述してください。
- インターネットへの接続は HttpClient クラスを使用してください。
""")
.RegisterMessageConnector()
.RegisterPrintMessage();
// .NET Interactive カーネル
var dotnetInteractiveKernel = DotnetInteractiveKernelBuilder
.CreateDefaultInProcessKernelBuilder()
// .AddPythonKernel("python3") // Python カーネルを追加
.Build();
// コード実行エージェント
var runnerAgent = new AssistantAgent(
name: "runnerAgent",
systemMessage: "あなたは与えられた C# をコードを実行します。",
defaultReply: "実行コードが見つかりません。coderAgent さんコードを記述してください。")
.RegisterMiddleware(async (msgs, option, agent, ct) =>
{
var mostRecentCoderMessage = msgs.LastOrDefault(x => x.From == "coderAgent");
if (mostRecentCoderMessage?.ExtractCodeBlock("```csharp", "```") is string code)
{
// コードブロックの実行
var result = await dotnetInteractiveKernel.RunSubmitCodeCommandAsync(code, "csharp");
result = $"""
# コードの実行結果
{result}
""";
return new TextMessage(Role.Assistant, result, from: agent.Name);
}
else
{
// defaultReply を返信
return await agent.GenerateReplyAsync(msgs, option, ct);
}
})
.RegisterPrintMessage();
// コード実行結果の要約エージェント
var summarizerAgent = new OpenAIChatAgent(
name: "summarizerAgent",
chatClient: azOpenAIChatClient,
systemMessage: """
あなたは runnerAgent が実行したコードの実行結果を要約して説明します。
""")
.RegisterMessageConnector()
.RegisterPrintMessage();
// ユーザー プロキシ エージェント
var userProxyAgent = new UserProxyAgent(
name: "user",
humanInputMode: HumanInputMode.ALWAYS)
.RegisterPrintMessage();
// グループ チャット管理者エージェント
var groupAdminAgent = new OpenAIChatAgent(
chatClient: azOpenAIChatClient,
name: "groupAdminAgent",
systemMessage: """
あなたはグループチャットの管理者です。
user から受け取った問題を coderAgent によるコーディング、runnerAgent によるコード実行で解決を行います。
コード実行が成功したら user から受け取った問題とコードの実行結果から summarizerAgent で回答を生成してください。
""")
.RegisterMessageConnector()
.RegisterPrintMessage();
// グループチャット
var groupChat = new GroupChat(
admin: groupAdminAgent,
members:
[
coderAgent,
runnerAgent,
summarizerAgent,
userProxyAgent,
]);
// プロンプトからユーザーのメッセージを取得
Console.Write("input message: ");
string userMessage = Console.ReadLine() ?? string.Empty;
var groupChatManager = new GroupChatManager(groupChat);
// プロンプト取得したメッセージで会話を開始
await userProxyAgent.InitiateChatAsync(
message: userMessage,
receiver: groupChatManager,
maxRound: 30);
}
}
このコードの実行後、Console.ReadLineでユーザーの入力を待機します。
フェボナッチ数の問題を質問してみます。
問題を解決するために coderAgent がコードを記述していることが確認できます。
続いて runnerAgent によりコードが実行されています。
最後に、summarizerAgent により結果が要約されています。
前回の記事では、AutoGen for .NET ラウンドロビン グループチャットを使用したシーケンシャルにエージェントを実行するグループチャットの方法について説明しました。 今回は、与えられた問題に対してダイナミックにエージェント実行させてタスクを解決する方法を説明しました。
ラウンドロビン グループチャットを使用した場合ではエージェントの実行順序を明示的に指定できます。今回使用した GroupChat では、admin に指定した groupAdminAgent で実行順を制御できます。 今回の例であるコード記述、コード実行、結果の要約というタスクの実行順は固定的なためラウンドロビン グループチャットでの実装の方が適切かもしれません。
動的なグループチャットを使用するシーンとしては、問題を解決するために複数のタスクの実行が必要で、問題の内容によって実行順序や必要なエージェントが異なる場合ではないかと考えています。
動的なグループチャットでは各エージェントの制御が難しくなるため解決したい問題に応じて各エージェントの制御方法を選択することが重要であると考えます。
コメント (0)
コメントの投稿