多Agent协作入门:顺序编排模式
大家好,我是Edison。
上一篇我们学习了Semantic Kernel中的并发编排模式,它非常适合并行分析、独立子任务并集成决策的任务场景。今天,我们学习新的模式:顺序编排。
顺序编排模式简介
在顺序编排模式中,各个Agent被组成一个流程,每个Agent都会处理任务,并将执行结果输出传递给下一个待执行的Agent。可以看出,对于每个基于上一步骤构建的工作流(Workflow)来说,这是比较适合的模式。
目前,像文档审阅、工作流、数据处理管道、多阶段推理等,是比较常见的应用场景。
下图展示了一个文档翻译的用例,文档先通过Agent1生成摘要,然后通过Agent2执行翻译,最后通过Agent3进行审阅和质量保证,最终生成最后的翻译结果。可以看到,每个Agent都在基于上一个步骤的处理结果进行构建,这就是一个典型的顺序编排用例。

实现顺序编排模式
这里我们来实现一个DEMO,我们定义3个Agent:分析师(Analyst)、广告文案写手(CopyWriter) 和 编辑/审稿人(Editor),假设他们是一个小Team,在承接广告文案的创作。
那么我们这个DEMO的目标,就是可以让他们可以来接客,只要客户分配一个广告文案创作的任务,它们就可以配合来生成最终的文案:首先由分析师分析要介绍产品的亮点和宣传思路,再由写手生成一个文案草稿,最后由审稿人进行评估给出最终文案,这就是一个典型的工作流处理。
为了简单地实现这个功能,我们创建一个.NET控制台项目,然后安装以下包:
Microsoft.SemanticKernel.Agents.Core
Microsoft.SemanticKernel.Agents.OpenAI (Preview版本)
Microsoft.SemanticKernel.Agents.Orchestration (Preview版本)
Microsoft.SemanticKernel.Agents.Runtime.InProcess (Preview版本)
需要注意的是,由于Semantic Kernel的较多功能目前还处于实验预览阶段,所以建议在该项目的csproj文件中加入以下配置,统一取消警告:
<PropertyGroup>
<NoWarn>$(NoWarn);CA2007;IDE1006;SKEXP0001;SKEXP0110;OPENAI001</NoWarn>
</PropertyGroup>
创建一个appsettings.json配置文件,填入以下关于LLM API的配置,其中API_KEY请输入你自己的:
{
"LLM": {
"BASE_URL": "https://api.siliconflow.cn",
"API_KEY": "******************************",
"MODEL_ID": "Qwen/Qwen2.5-32B-Instruct"
}
}
这里我们使用SiliconCloud提供的 Qwen2.5-32B-Instruct 模型,你可以通过这个URL注册账号:https://cloud.siliconflow.cn/i/DomqCefW 获取大量免费的Token来进行本次实验。
有了LLM API,我们可以创建一个Kernel供后续使用,这也是老面孔了:
Console.WriteLine("Now loading the configuration...");
var config = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", optional: false, reloadOnChange: true)
.Build();
Console.WriteLine("Now loading the chat client...");
var chattingApiConfiguration = new OpenAiConfiguration(
config.GetSection("LLM:MODEL_ID").Value,
config.GetSection("LLM:BASE_URL").Value,
config.GetSection("LLM:API_KEY").Value);
var openAiChattingClient = new HttpClient(new OpenAiHttpHandler(chattingApiConfiguration.EndPoint));
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(chattingApiConfiguration.ModelId, chattingApiConfiguration.ApiKey, httpClient: openAiChattingClient)
.Build();
接下来,我们就一步一步地来看看核心的代码。
定义3个Agent
这里我们来定义3个Agent:Analyst,Writer,Editor
(1)Analyst 分析师
var analystAgent = new ChatCompletionAgent()
{
Name = "Analyst",
Instructions = """
You are a marketing analyst. Given a product description, identify:
- Key features
- Target audience
- Unique selling points
""",
Description = "A agent that extracts key concepts from a product description.",
Kernel = kernel
};
(2)Writer 文案写手
var writerAgent = new ChatCompletionAgent()
{
Name = "CopyWriter",
Instructions = """
You are a marketing copywriter. Given a block of text describing features, audience, and USPs,
compose a compelling marketing copy (like a newsletter section) that highlights these points.
Output should be short (around 150 words), output just the copy as a single text block.
""",
Description = "An agent that writes a marketing copy based on the extracted concepts.",
Kernel = kernel
};
(3)Editor 编辑/审稿人
var editorAgent = new ChatCompletionAgent()
{
Name = "Editor",
Instructions = """
You are an editor. Given the draft copy, correct grammar, improve clarity, ensure consistent tone,
give format and make it polished. Output the final improved copy as a single text block.
""",
Description = "An agent that formats and proofreads the marketing copy.",
Kernel = kernel
};
选择编排模式
这里我们选择的是顺序编排模式:SequentialOrchestration,将需要编排的3个Agent作为参数传递给它。
需要注意的是:这里为了能够显示每个Agent的执行结果,我们定一个了一个自定义的回调方法 responseCallback,帮助显示每个Agent的输出记录供参考。
// Set up the Sequential Orchestration
ChatHistory history = [];
ValueTask responseCallback(ChatMessageContent response)
{
history.Add(response);
return ValueTask.CompletedTask;
}
var orchestration = new SequentialOrchestration(analystAgent, writerAgent, editorAgent)
{
ResponseCallback = responseCallback
};
启动运行时
在Semantic Kernel中,需要运行时(Runtime)才能管理Agent的执行,因此这里我们需要在正式开始前使用InProcessRuntime并启动起来。
// Start the Runtime
var runtime = new InProcessRuntime();
await runtime.StartAsync();
调用编排 并 收集结果
准备工作差不多了,现在我们可以开始调用编排了。这也是老面孔代码了,不过多解释。
// Start the Chat
Console.WriteLine("----------Agents are Ready. Let's Start Working!----------");
while (true)
{
Console.WriteLine("User> ");
var input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
continue;
input = input.Trim();
if (input.Equals("EXIT", StringComparison.OrdinalIgnoreCase))
{
// Stop the Runtime
await runtime.RunUntilIdleAsync();
break;
}
try
{
// Invoke the Orchestration
var result = await orchestration.InvokeAsync(input, runtime);
// Collect Results from multi Agents
var output = await result.GetValueAsync(TimeSpan.FromSeconds(10 * 2));
// Print the Results
Console.WriteLine($"{Environment.NewLine}# RESULT: {output}");
Console.WriteLine($"{Environment.NewLine}ORCHESTRATION HISTORY");
foreach (var message in history)
{
Console.WriteLine($"#{message.Role} - {message.AuthorName}:");
Console.WriteLine($"{message.Content.Replace("---", string.Empty)}{Environment.NewLine}");
}
}
catch (HttpOperationException ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
finally
{
Console.ResetColor();
Console.WriteLine();
}
}
需要注意的是:上面的代码示例中我主动输出了编排过程中每个Agent的生成结果历史记录,便于我们一会儿查看。
效果展示
用户输入问题:"Please help to introduce our new product: An eco-friendly stainless steel water bottle that keeps drinks cold for 24 hours."
假设客户公司有一个新产品:一个环保的不锈钢水瓶,可以让饮料保持24小时的低温,需要帮忙创作一个广告文案。
最终经过3个Agent的顺序合作,结果显示如下:

可以看到,它们合作写出了一段适合宣传的广告文案。
那么,它们到底是如何合作的呢?刚刚我们主动输出了历史记录,可以看看:

可以看到,Agent1-分析师对产品介绍生成了很多关键卖点和受众群体的分析结果,Agent2-写手便基于分析结果写了一个文案草稿,最终Agent3-编辑对文案进行了审核,最终发布广告文案。
小结
本文介绍了顺序编排模式的基本概念,然后通过一个案例介绍了如何实现一个顺序编排模式,相信通过这个案例你能够有个感性的认识。
下一篇,我们将再次学习群聊编排模式,并通过自定义群组聊天管理器(GroupChatManager)来自定义群聊流程。
参考资料
Microsoft Learn: https://learn.microsoft.com/zh-cn/semantic-kernel/frameworks/agent/agent-orchestration
推荐学习
圣杰:《.NET+AI | Semantic Kernel入门到精通》

多Agent协作入门:顺序编排模式的更多相关文章
- veridata实验举例(6)验证agent启动先后顺序是否对捕获update操作有影响
veridata实验举例(6)验证agent启动先后顺序是否对捕获update操作有影响 续接veridata实验系列 上篇:"veridata实验举例(5)改动主键上的列值.update ...
- 6. oracle学习入门系列之六 模式
oracle学习入门系列之六 模式 上篇咱们学习记录了ORACLE数据库中的数据库结构.内存结构和进程等.篇幅 蛤蟆感觉偏多了.这次要休整下,每次笔记不宜太多,不然与书籍有何差别. 我们要保证的是每次 ...
- IView入门练习~CDN模式全局加载JS
关于 iView iView 是一套基于 Vue.js 的开源 UI 组件库,主要服务于 PC 界面的中后台产品. 特性 高质量.功能丰富 友好的 API ,自由灵活地使用空间 细致.漂亮的 UI 事 ...
- RabbitMQ入门-消息订阅模式
消息派发 上篇<RabbitMQ入门-消息派发那些事儿>发布之后,收了不少反馈,其中问的最多的还是有关消息确认以及超时等场景的处理. 楼主,有遇到消费者后台进程不在,但consumer连接 ...
- 前端之Android入门(3):MVC模式(上)
很多Android的入门书籍,在前面介绍完布局后就会逐个介绍组件,然后开始编写组件使用的例子.每每到此时小伙伴们都可能会有些疑问:是否应该先啃完一本<Java编程思想>学点 Java 知识 ...
- RabbitMQ入门-竞争消费者模式
上一篇讲了个 哈喽World,现在来看看如果存在多个消费者的情况. 生产者: package com.example.demo; import com.rabbitmq.client.Channel; ...
- 微信企业号开发入门(回调模式)java
最近在开发微信企业号,刚接触时云里雾里的,在摸索过程中终于清晰了一点. 刚开始我以为订阅号.服务号.企业号的接口差不多,就一直用订阅号的教程来入门,后来才发现差的挺多的. 首先,微信企业号不像订阅号和 ...
- Mybatis入门案例中设计模式的简单分析
Talk is cheap, show me the code! public class TestMybatis { public static void main(String[] args) t ...
- build模式入门,build模式理解(转载)
问:为何要用? 普通做法: 1.创建pojo public class Person { private String name; private int age; private double he ...
- 使用 Skywalking Agent,这里使用sidecar 模式挂载 agent
文章转载自:https://bbs.huaweicloud.com/blogs/315037 方法汇总 Java 中使用 agent ,提供了以下三种方式供你选择 使用官方提供的基础镜像 将 agen ...
随机推荐
- 题解:P10862 [HBCPC2024] Spicy or Grilled?
题目翻译: 有 nnn 个人,我们为他们买了香辣鸡肉汉堡套餐,每份是 aaa 元,可是里面有 xxx 人不能吃辣,于是还准备了 xxx 份烤鸡汉堡套餐,每份是 bbb 元,求总共要多少元. 解题思路 ...
- Windows查看端口占用、相应进程、杀死进程等[netstat]
Windows 通过cmd或powerShell查看端口占用.相应进程.杀死进程等的命令 由于一般开发环境是在windows上,相应的一些测试必然涉及到一些端口的监听与使用.当开发使用的端口被占用后, ...
- WPF封装一个懒加载下拉列表控件(支持搜索)
因为项目中PC端前端针对基础数据选择时的下拉列表做了懒加载控件,PC端使用现成的组件,为保持两端的选择方式统一,WPF客户端上也需要使用懒加载的下拉选择. WPF这种懒加载的控件未找到现成可用的组件, ...
- spring综合性利用工具-SpringBoot-Scan(一),附下载链接。
日常渗透过程中,经常会碰到Spring Boot搭建的微服务,于是就想做一个针对Spring Boot的开源渗透框架,主要用作扫描Spring Boot的敏感信息泄露端点,并可以直接测试Spring的 ...
- [随记]-我安装 arch linux 的记录
一.下载安装包 archlinux-x86_64.iso 下载传送门:Arch Linux BitTorrent Download 是磁链和种子下载,往下拉,找到 HTTP Direct Downlo ...
- VUE3中的组件通信
工作中使用组件之间传值在此记录 目录VUE3中的组件通信六种方法介绍与基本使用一.父传子(props)二. Emits 传值(子组件向父组件传值)三.v-model 双向绑定四. provide/in ...
- 国产化-消息队列RocketMq(替代kafka)-单节点安装
RocketMQ 是一款由阿里巴巴开源的分布式消息中间件,具有高可靠.高性能.高可扩展性等特点,在众多企业级应用中得到了广泛的应用.以下是对 RocketMQ 的详细介绍: 国内三大IT巨头阿里. ...
- pyqt点击右上角关闭界面但子线程仍在运行
现象: 通过右上角的叉关闭图形界面后,程序运行的子线程却不会被自动关闭,依然留存在系统中 原因: 子线程没有正确关闭 解决方法: 1.将子线程设置成守护线程 self.your_thread = th ...
- 全网最全!1500+ 免费、美观的前端网页模板,建站神器(包括HTML、Vue、Angular、React等)!
前言 经常有小伙伴问我 Vue.React.Bootstrap 或者 Angular 这些有好看且免费的前端模板推荐的吗?今天大姚给大家分享一个宝藏网站,它汇聚了1500+ 免费.美观的前端网页模板, ...
- HashMap get和resize源码解析|Java 17
直奔主题,奉上HashMap中get 函数源码解析: public V get(Object key) { Node<K,V> e; return (e = getNode(hash(ke ...