找回密码
 立即注册
首页 业界区 业界 多Agent协作入门:群聊编排模式

多Agent协作入门:群聊编排模式

侧胥咽 昨天 19:29
大家好,我是Edison。
上一篇我们学习了Semantic Kernel中的顺序编排模式,它非常适合如文档审阅、数据处理管道等工作流类型任务场景。今天,我们学习新的模式:群聊编排。
群聊编排模式简介

在群聊编排模式中,各个Agent就像加入了一个微信群,由群管理员协调进行群聊对话。这种模式非常适合于模拟会议、辩论或协作解决问题的会议类型场景。
下图展示了一个讨论业务建议的用例,由一个Chat Manager负责主持对话,依次让三个参与对话的Agent进行建议发表。这个Chat Manager就像是群管理员,它不仅负责主持对话,也会在必要时引入人工干预。
1.png

实现群聊编排模式

这里我们来实现一个和上一节类似的DEMO,我们定义2个Agent:广告文案写手(CopyWriter) 和 编辑/审稿人(Editor),假设他们是一个小Team,在承接广告文案的创作。假设每个文案都需要审稿人审核,可以有多轮审核,直到审核确认OK才能交付。
为了简单地实现这个功能,我们还是创建一个.NET控制台项目,然后安装以下包:
  1. Microsoft.SemanticKernel.Agents.Core
  2. Microsoft.SemanticKernel.Agents.OpenAI (Preview版本)
  3. Microsoft.SemanticKernel.Agents.Orchestration (Preview版本)
  4. Microsoft.SemanticKernel.Agents.Runtime.InProcess (Preview版本)
复制代码
需要注意的是,由于Semantic Kernel的较多功能目前还处于实验预览阶段,所以建议在该项目的csproj文件中加入以下配置,统一取消警告:
  1. <PropertyGroup>
  2. <NoWarn>$(NoWarn);CA2007;IDE1006;SKEXP0001;SKEXP0110;OPENAI001</NoWarn>
  3. </PropertyGroup>
复制代码
创建一个appsettings.json配置文件,填入以下关于LLM API的配置,其中API_KEY请输入你自己的:
  1. {
  2.   "LLM": {
  3.     "BASE_URL": "https://api.siliconflow.cn",
  4.     "API_KEY": "******************************",
  5.     "MODEL_ID": "Qwen/Qwen2.5-32B-Instruct"
  6.   }
  7. }
复制代码
这里我们使用SiliconCloud提供的 Qwen2.5-32B-Instruct 模型,你可以通过这个URL注册账号:https://cloud.siliconflow.cn/i/DomqCefW 获取大量免费的Token来进行本次实验。
有了LLM API,我们可以创建一个Kernel供后续使用,这也是老面孔了:
  1. Console.WriteLine("Now loading the configuration...");
  2. var config = new ConfigurationBuilder()
  3.     .AddJsonFile($"appsettings.json", optional: false, reloadOnChange: true)
  4.     .Build();
  5. Console.WriteLine("Now loading the chat client...");
  6. var chattingApiConfiguration = new OpenAiConfiguration(
  7.     config.GetSection("LLM:MODEL_ID").Value,
  8.     config.GetSection("LLM:BASE_URL").Value,
  9.     config.GetSection("LLM:API_KEY").Value);
  10. var openAiChattingClient = new HttpClient(new OpenAiHttpHandler(chattingApiConfiguration.EndPoint));
  11. var kernel = Kernel.CreateBuilder()
  12.     .AddOpenAIChatCompletion(chattingApiConfiguration.ModelId, chattingApiConfiguration.ApiKey, httpClient: openAiChattingClient)
  13.     .Build();
复制代码
接下来,我们就一步一步地来看看核心的代码。
定义Agent

这里我们来定义2个Agent:Writer,Editor
(1)Writer 文案写手
  1. var writerAgent = new ChatCompletionAgent()
  2. {
  3.     Name = "CopyWriter",
  4.     Instructions = """
  5.                 You are a copywriter with ten years of experience and are known for brevity and a dry humor.
  6.                 The goal is to refine and decide on the single best copy as an expert in the field.
  7.                 Only provide a single proposal per response.
  8.                 You're laser focused on the goal at hand.
  9.                 Don't waste time with chit chat.
  10.                 Consider suggestions when refining an idea.
  11.                 """,
  12.     Description = "A copy writer.",
  13.     Kernel = kernel
  14. };
复制代码
(2)Editor 审核编辑
  1. var editorAgent = new ChatCompletionAgent()
  2. {
  3.     Name = "Reviewer",
  4.     Instructions = """
  5.                 You are an art director who has opinions about copywriting born of a love for David Ogilvy.
  6.                 The goal is to determine if the given copy is acceptable to print.
  7.                 If so, state that it is approved.
  8.                 If not, provide insight on how to refine suggested copy without example.
  9.                 """,
  10.     Description = "An editor.",
  11.     Kernel = kernel
  12. };
复制代码
选择编排模式

这里我们选择的是群聊编排模式:GroupChatOrchestration,将需要编排的2个Agent作为参数传递给它。
需要注意的是:这里我们选择Semantic Kernel预定义好的群管理员类 RoundRobinGroupChatManager,顾名思义,它的策略就是轮流让参与的群成员发言,没有特殊的指定逻辑
  1. // Set up the GroupChat Orchestration
  2. ChatHistory history = [];
  3. ValueTask responseCallback(ChatMessageContent response)
  4. {
  5.     history.Add(response);
  6.     return ValueTask.CompletedTask;
  7. }
  8. // Use RoundRobinGroupChatManager to manage the conversation flow
  9. const string topic = "Create a slogan for a new electric SUV that is affordable and fun to drive.";
  10. var orchestration = new GroupChatOrchestration(
  11.     new RoundRobinGroupChatManager { MaximumInvocationCount = 5 }, // Maximum 5 rounds of conversation
  12.     writerAgent,
  13.     editorAgent)
  14. {
  15.     ResponseCallback = responseCallback
  16. };
复制代码
启动运行时

在Semantic Kernel中,需要运行时(Runtime)才能管理Agent的执行,因此这里我们需要在正式开始前使用InProcessRuntime并启动起来。
  1. // Start the Runtime
  2. var runtime = new InProcessRuntime();
  3. await runtime.StartAsync();
复制代码
调用编排 并 收集结果

准备工作差不多了,现在我们可以开始调用编排了。
这也是老面孔代码了,不过多解释。
  1. // Start the Chat
  2. Console.WriteLine($"# INPUT: {topic}{Environment.NewLine}");
  3. try
  4. {
  5.     // Invoke the Orchestration
  6.     var result = await orchestration.InvokeAsync(topic, runtime);
  7.     // Collect Results from multi Agents
  8.     var output = await result.GetValueAsync(TimeSpan.FromSeconds(10 * 3));
  9.     // Print the Results
  10.     Console.WriteLine($"{Environment.NewLine}# RESULT: {output}");
  11.     Console.WriteLine($"{Environment.NewLine}#ORCHESTRATION HISTORY:{Environment.NewLine}");
  12.     foreach (var message in history)
  13.     {
  14.         Console.WriteLine($"#{message.Role} - {message.AuthorName}:");
  15.         Console.WriteLine($"{message.Content}{Environment.NewLine}");
  16.     }
  17. }
  18. catch (HttpOperationException ex)
  19. {
  20.     Console.WriteLine($"Exception: {ex.Message}");
  21. }
  22. finally
  23. {
  24.     await runtime.RunUntilIdleAsync();
  25.     Console.ResetColor();
  26.     Console.WriteLine();
  27. }
复制代码
上面的代码示例中主动输出了编排过程中每个Agent的生成结果历史记录,便于我们一会儿查看。
效果展示

用户输入问题:"Create a slogan for a new electric SUV that is affordable and fun to drive."
假设客户公司有一个新产品:一辆新的电动SUV汽车,它性价比高,且驾驶乐趣足。
最终经过2个Agent的多轮对话,结果显示如下:
2.png

可以看到:
第一轮对话:Agent1-文案写手根据用户需求写了一个初稿,Agent2-审核员对这个初稿进行了初步审核。
第二轮对话:Agent1-文案写手并没有着急修改而是让审核员确认是否需要进一步完善,Agent2-审核员则在这次对话给出了一些修改建议。
第三轮对话:Agent1-文案写手根据修改建议给出了第二版,这次Agent2-审核员确认OK也没有再给出其他建议,群聊对话也就此为止结束了。
自定义群管理员

除了预定好的群管理员之外,我们还可以通过继承 GroupChatManager 来创建自定义的群管理员类,如下所示:
  1. using Microsoft.SemanticKernel.Agents.Orchestration.GroupChat;
  2. using Microsoft.SemanticKernel.ChatCompletion;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. public class CustomGroupChatManager : GroupChatManager
  6. {
  7.     public override ValueTask<GroupChatManagerResult<string>> FilterResults(ChatHistory history, CancellationToken cancellationToken = default)
  8.     {
  9.         // Custom logic to filter or summarize chat results
  10.         return ValueTask.FromResult(new GroupChatManagerResult<string>("Summary") { Reason = "Custom summary logic." });
  11.     }
  12.     public override ValueTask<GroupChatManagerResult<string>> SelectNextAgent(ChatHistory history, GroupChatTeam team, CancellationToken cancellationToken = default)
  13.     {
  14.         // Randomly select an agent from the team
  15.         var random = new Random();
  16.         int index = random.Next(team.Members.Count);
  17.         string nextAgent = team.Members[index].Id;
  18.         return ValueTask.FromResult(new GroupChatManagerResult<string>(nextAgent) { Reason = "Custom selection logic." });
  19.     }
  20.     public override ValueTask<GroupChatManagerResult<bool>> ShouldRequestUserInput(ChatHistory history, CancellationToken cancellationToken = default)
  21.     {
  22.         // Custom logic to decide if user input is needed
  23.         return ValueTask.FromResult(new GroupChatManagerResult<bool>(false) { Reason = "No user input required." });
  24.     }
  25.     public override ValueTask<GroupChatManagerResult<bool>> ShouldTerminate(ChatHistory history, CancellationToken cancellationToken = default)
  26.     {
  27.         // Optionally call the base implementation to check for default termination logic
  28.         var baseResult = base.ShouldTerminate(history, cancellationToken).Result;
  29.         if (baseResult.Value)
  30.         {
  31.             // If the base logic says to terminate, respect it
  32.             return ValueTask.FromResult(baseResult);
  33.         }
  34.         // Custom logic to determine if the chat should terminate
  35.         bool shouldEnd = history.Count > 10; // Example: end after 10 messages
  36.         return ValueTask.FromResult(new GroupChatManagerResult<bool>(shouldEnd) { Reason = "Custom termination logic." });
  37.     }
  38. }
复制代码
定义好之后,只需要在使用群聊编排模式的时候使用这个自定义管理器即可,如下所示:
  1. GroupChatOrchestration orchestration
  2.   = new (new CustomGroupChatManager { MaximumInvocationCount = 5 }, ...);
复制代码
AgentChat

对于多Agent群聊来说,Semantic Kernel还提供了AgentChat的具体实现AgentGroupChat,它使用基于策略的方法来管理聊天的动态,具体实现上就是自己定义两个Strategy:SelectionStrategy 和 TerminationStrategy。
  1. // Initialize AgentGroupChat
  2. var groupChat = new AgentGroupChat(reviewerAgent, writerAgent)
  3. {
  4.     ExecutionSettings = new AgentGroupChatSettings()
  5.     {
  6.         SelectionStrategy = new KernelFunctionSelectionStrategy(selectionFunction, kernel)
  7.         {
  8.             InitialAgent = reviewerAgent,
  9.             HistoryReducer = historyReducer,
  10.             HistoryVariableName = KernelFunctionTerminationStrategy.DefaultHistoryVariableName,
  11.             ResultParser = (result) =>
  12.             {
  13.                 var val = result.GetValue<string>() ?? ReviewerAgent.AgentName;
  14.                 return val.ReplaceLineEndings("\n").Trim();
  15.             }
  16.         },
  17.         TerminationStrategy = new KernelFunctionTerminationStrategy(terminationFunction, kernel)
  18.         {
  19.             Agents = [reviewerAgent],
  20.             HistoryReducer = historyReducer,
  21.             HistoryVariableName = KernelFunctionTerminationStrategy.DefaultHistoryVariableName,
  22.             MaximumIterations = 10,
  23.             ResultParser = (result) =>
  24.             {
  25.                 var val = result.GetValue<string>() ?? string.Empty;
  26.                 return val.Contains(TerminationToken, StringComparison.OrdinalIgnoreCase);
  27.             }
  28.         }
  29.     }
  30. };
复制代码
更多详细内容,请阅读《多Agent协作入门:AgentGroupChat》
小结

本文介绍了群聊编排模式的基本概念,然后通过一个案例介绍了如何实现一个群聊编排模式,相信通过这个案例你能够有个感性的认识。
下一篇,我们将学习移交(Handoff)编排模式,它特别适合于动态工作流、专家交接方案等应用场景。
参考资料

Microsoft Learn: https://learn.microsoft.com/zh-cn/semantic-kernel/frameworks/agent/agent-orchestration
推荐学习

圣杰:《.NET+AI | Semantic Kernel入门到精通》
 
3.jpeg

作者:爱迪生
出处:https://edisontalk.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册