Microsoft Agent Framework/C#:了解Workflows的幾種不同模式
前言
最近有空的時候在學習Microsoft Agent Framework,在這個框架中目前Workflows分為了Sequential、Concurrent、Handoffs以及Groupchat四種模式,今天讓我們來了解一下這四種不同的模式。
首先需要以下兩個包:

Sequential 模式
在開始介紹之前,先看下它的效果:

首先需要先構建一個IChatClient:
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("未設置環境變量:OPENAI_API_KEY");
//var model = Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o-mini";
var model = "moonshotai/Kimi-K2-Instruct-0905";
var baseUrl = Environment.GetEnvironmentVariable("OPENAI_BASEURL") ?? throw new InvalidOperationException("未設置環境變量:OPENAI_BASEURL");
ApiKeyCredential apiKeyCredential = new ApiKeyCredential(apiKey);
OpenAIClientOptions openAIClientOptions = new OpenAIClientOptions();
openAIClientOptions.Endpoint = new Uri(baseUrl);
var client = new OpenAIClient(apiKeyCredential, openAIClientOptions).GetChatClient(model).AsIChatClient();
現在通過這個函數方便構建不同的翻譯代理:
/// <summary>為指定目標語言創建翻譯代理。</summary>
private static ChatClientAgent GetTranslationAgent(string targetLanguage, IChatClient chatClient) =>
new(chatClient,
$"你是一個翻譯助手,只使用{targetLanguage}回應。對于任何輸入," +
$"首先輸出輸入語言的名稱,然后將輸入翻譯成{targetLanguage}。");
構建順序工作流:
// 創建順序工作流
var workflow = AgentWorkflowBuilder.BuildSequential(
from lang in (string[])["French", "Spanish", "English"]
select GetTranslationAgent(lang, client)
);

參數就是一組AIAgent,然后工作流會將這些AIAgent按順序組合起來。
運行這個工作流:
List<ChatMessage> messages = [new(ChatRole.User, InputText)];
await RunWorkflowAsync(workflow, messages);
private async Task<List<ChatMessage>> RunWorkflowAsync(Workflow workflow, List<ChatMessage> messages)
{
string? lastExecutorId = null;
await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, messages);
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
if (evt is AgentRunUpdateEvent e)
{
if (e.ExecutorId != lastExecutorId)
{
OutputText += "\n";
lastExecutorId = e.ExecutorId;
OutputText += $"{e.ExecutorId}:\n";
}
OutputText += e.Update.Text;
if (e.Update.Contents.OfType<FunctionCallContent>().FirstOrDefault() is FunctionCallContent call)
{
OutputText += "\n";
OutputText += $"[調用函數 '{call.Name}',參數: {JsonSerializer.Serialize(call.Arguments)}]";
}
}
else if (evt is WorkflowOutputEvent output)
{
OutputText += "\n\n工作流完成!";
return output.As<List<ChatMessage>>()!;
}
}
return [];
}
與直覺不一樣的地方是只有在傳入TurnToken的時候才會開始運行:
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
然后通過WorkflowEvent來進行不同操作。
這個例子看最后的輸入就是這樣的:

Concurrent 模式
還是先來看下效果:

Concurrent就是并發工作流,對同一個輸入,不同的AI Agent同時響應。
看一下怎么構建:
// 創建并發工作流
var workflow = AgentWorkflowBuilder.BuildConcurrent(
from lang in (string[])["French", "Spanish", "English"]
select GetTranslationAgent(lang, client)
);
Handoffs 模式
Handoffs就是交接模式,跟之前的不太一樣,首先我們先創建3個不同的AI Agent:
// 創建專門的代理
ChatClientAgent historyTutor = new(client,
"你提供歷史查詢方面的幫助。清晰地解釋重要事件和背景。只回應歷史相關內容。",
"history_tutor",
"歷史問題的專業代理");
ChatClientAgent mathTutor = new(client,
"你提供數學問題方面的幫助。在每一步解釋你的推理過程并包含示例。只回應數學相關內容。",
"math_tutor",
"數學問題的專業代理");
ChatClientAgent triageAgent = new(client,
"你根據用戶的作業問題確定使用哪個代理。總是將任務交接給另一個代理。",
"triage_agent",
"將消息路由到適當的專業代理");
看下如何構建:
// 創建交接工作流
var workflow = AgentWorkflowBuilder.CreateHandoffBuilderWith(triageAgent)
.WithHandoffs(triageAgent, [mathTutor, historyTutor])
.WithHandoffs([mathTutor, historyTutor], triageAgent)
.Build();
來看下效果:

這次會到這個地方:


內部有一個FunctionCall交接給了對應的代理。
看一下最終的結果:

再問一個數學相關的問題看看效果:

看一下最終的結果:

Groupchat 模式
Groupchat模式就是開啟一個AI群聊,我拿辯論舉個例子。
ChatClientAgent chatClientAgent1 = new(client, "你是辯論正方");
ChatClientAgent chatClientAgent2 = new(client, "你是辯論反方");
// 創建群聊工作流
var workflow = AgentWorkflowBuilder.CreateGroupChatBuilderWith(agents => new RoundRobinGroupChatManager(agents) { MaximumIterationCount = 5 })
.AddParticipants([chatClientAgent1, chatClientAgent2])
.Build();
效果:



浙公網安備 33010602011771號