MAF快速入门(12)主工作流+子工作流
目录简介1 子工作流模式介绍2 主工作流子工作流实验案例2.1 关键依赖包引入2.2 定义数据传输模型2.3 定义产品质量处理子工作流2.4 定义物流问题处理子工作流2.5 构建主工作流2.6 测试工作流3 小结4 示例源码简介大家好我是Edison。上一篇我们学习了MAF中如何进行并行工作流。本篇我们来了解下在MAF中如何开启 主工作流 自工作流 的模式相信这会是大家可能会碰到的场景。1 子工作流模式介绍在实际业务场景中往往需要在主工作流中根据工单类型分发或移交到不同的标准化子流程中进行后续处理。在MAF中我们可以使用 Sub-Worklfow 模式来实现这个目的如下代码片段所示。首先将子工作流转换为一个Executorvar logisticsSubExecutor logisticsSubWorkflow.BindAsExecutor(LogisticsSubWorkflow); var productQualitySubExecutor productQualitySubWorkflow.BindAsExecutor(ProductQualitySubWorkflow);然后构建主工作流并根据条件路由到子工作流Executorvar mainWorkflow new WorkflowBuilder(classifierExecutor) .AddEdgeComplaintProcessingRecord(classifierExecutor, productQualitySubExecutor, condition: record record.Category 产品质量) .AddEdgeComplaintProcessingRecord(classifierExecutor, logisticsSubExecutor, condition: record record.Category 物流问题) .AddEdge(productQualitySubExecutor, complianceExecutor) .AddEdge(logisticsSubExecutor, complianceExecutor) .AddEdge(complianceExecutor, sentimentExecutor) .WithOutputFrom(sentimentExecutor) .Build();这样就实现了主工作流进行分类转发自工作流进行详细处理。2 主工作流子工作流实验案例假设我们是一个企业的客服中心每天都会收到大量的工单需要根据工单类型比如是 产品质量话题 还是 物流话题分发到不同的标准化子流程去做后续处理最后生成一个用户友好 且 满足合规要求 的回复给用户。因此我们的目标是配置 1个主工作流 2个子工作流 来覆盖这个需求。2.1 关键依赖包引入在今天的这个案例中我们仍然创建了一个.NET控制台应用程序安装了以下NuGet包Microsoft.Agents.AI.OpenAIMicrosoft.Agents.AI.WorkflowsMicrosoft.Extensions.AI.OpenAI2.2 定义数据传输模型首先我们定义一下在这个工作流中需要生成传递的数据模型投诉数据模型 及 共享状态namespace SubWorkflow.Models; // 共享状态投诉处理记录各执行器会更新此对象 internal class ComplaintProcessingRecord { public CustomerComplaint Original { get; set; } public string Category { get; set; } 未分类; public string Handler { get; set; } 待分配; public Liststring ProcessingSteps { get; set; } new(); public string AIGeneratedResponse { get; set; } ; public string ComplianceStatus { get; set; } 待审核; public string SentimentScore { get; set; } 未评估; } // 投诉数据模型 internal record CustomerComplaint( string OrderId, string CustomerName, string ComplaintText, DateTime SubmittedAt );2.3 定义产品质量处理子工作流1问题评估封装产品质量评估的逻辑这里仅仅做演示用无实际逻辑internal sealed class ProductEvaluationExecutor() : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(ProductEvaluationExecutor)) { public override ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine( 正在评估产品质量问题...); record.ProcessingSteps.Add([产品评估] 检测到屏幕外观缺陷符合质量问题定义); record.Handler 产品质量团队; return ValueTask.FromResult(record); } }2退/换货判定负责判定是退货 还是 换货 处理。​​​​​​​internal sealed class ReturnPolicyExecutor() : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(ReturnPolicyExecutor)) { public override ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine( 判定退换货政策...); var daysFromOrder (DateTime.Now - record.Original.SubmittedAt).Days; if (daysFromOrder 7) { record.ProcessingSteps.Add([退换货判定] 符合7天无理由退货政策批准全额退款); } else { record.ProcessingSteps.Add([退换货判定] 超过退货期限建议换货或部分补偿); } return ValueTask.FromResult(record); } }3AI回复在投诉内容和判定结果的基础上生成友好的回复返回给用户。​​​​​​​internal sealed class AIResponseGeneratorExecutor(IChatClient chatClient) : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(AIResponseGeneratorExecutor)) { public override async ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine( AI 正在生成客户回复...); var prompt $你是专业的客服主管。根据以下投诉处理信息生成一封正式、有同理心的客户回复邮件150字内 客户{record.Original.CustomerName} 订单号{record.Original.OrderId} 投诉内容{record.Original.ComplaintText} 处理步骤 {string.Join(\n, record.ProcessingSteps)} 要求 1. 表达歉意和理解 2. 说明处理方案 3. 提供后续联系方式 4. 语气真诚、专业; var response await chatClient.GetResponseAsync(prompt, cancellationToken: cancellationToken); record.AIGeneratedResponse response.Text ?? AI 生成失败; record.ProcessingSteps.Add($[AI 回复] 已生成客户回复模板{record.AIGeneratedResponse.Length}字); return record; } }最后构建子工作流并将其转换为一个Executor以便后续集成到主工作流中​​​​​​​var productEvalExecutor new ProductEvaluationExecutor(); var returnPolicyExecutor new ReturnPolicyExecutor(); var aiResponseExecutor new AIResponseGeneratorExecutor(chatClient); var productQualitySubWorkflow new WorkflowBuilder(productEvalExecutor) .AddEdge(productEvalExecutor, returnPolicyExecutor) .AddEdge(returnPolicyExecutor, aiResponseExecutor) .WithOutputFrom(aiResponseExecutor) .Build(); var productQualitySubExecutor productQualitySubWorkflow.BindAsExecutor(ProductQualitySubWorkflow);2.4 定义物流问题处理子工作流1物流追踪封装物流查询逻辑这里仅仅做演示用无实际逻辑​​​​​​​internal sealed class LogisticsTrackingExecutor() : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(LogisticsTrackingExecutor)) { public override ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine( 正在查询物流信息...); record.ProcessingSteps.Add([物流追踪] 包裹在中转站滞留3天当前状态运输中); record.Handler 物流运营团队; return ValueTask.FromResult(record); } }2延迟分析封装延迟分析逻辑这里仅仅做演示用无实际逻辑​​​​​​​internal sealed class DelayAnalysisExecutor() : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(DelayAnalysisExecutor)) { public override ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine( 分析延迟原因...); record.ProcessingSteps.Add([延迟分析] 延迟原因暴雨导致道路封闭预计2天内恢复配送); record.ProcessingSteps.Add([补偿方案] 提供50元优惠券 免运费); return ValueTask.FromResult(record); } }最后构建子工作流并将其转换为一个Executor以便后续集成到主工作流中​​​​​​​var logisticsTrackExecutor new LogisticsTrackingExecutor(); var delayAnalysisExecutor new DelayAnalysisExecutor(); var logisticsAIResponseExecutor new AIResponseGeneratorExecutor(chatClient); var logisticsSubWorkflow new WorkflowBuilder(logisticsTrackExecutor) .AddEdge(logisticsTrackExecutor, delayAnalysisExecutor) .AddEdge(delayAnalysisExecutor, logisticsAIResponseExecutor) .WithOutputFrom(logisticsAIResponseExecutor) .Build(); var logisticsSubExecutor logisticsSubWorkflow.BindAsExecutor(LogisticsSubWorkflow);2.5 构建主工作流现在开始构建主工作流Step1: 获取ChatClient​​​​​​​var chatClient new OpenAIClient( new ApiKeyCredential(openAIProvider.ApiKey), new OpenAIClientOptions { Endpoint new Uri(openAIProvider.Endpoint) }) .GetChatClient(openAIProvider.ModelId) .AsIChatClient();Step2: 创建工单分类Executor,合规审核Executor 以及 情绪评估ExecutorNOTE前面的子工作流均生成了AI回复这里需要对其进行合规审核以防止不合规的回复到用户那里。​​​​​​​// 1. 工单分类执行器 internal sealed class ComplaintClassifierExecutor() : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(ComplaintClassifierExecutor)) { public override ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine(️ 正在分类投诉类型...); // 简单规则分类实际可用 AI 分类 if (record.Original.ComplaintText.Contains(划痕) || record.Original.ComplaintText.Contains(质量) || record.Original.ComplaintText.Contains(退货)) { record.Category 产品质量; } else if (record.Original.ComplaintText.Contains(延迟) || record.Original.ComplaintText.Contains(物流) || record.Original.ComplaintText.Contains(配送)) { record.Category 物流问题; } else { record.Category 其他; } record.ProcessingSteps.Add($[分类器] 投诉类型识别为{record.Category}); return ValueTask.FromResult(record); } } // 2. 合规审核执行器 internal sealed class ComplianceCheckExecutor() : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(ComplianceCheckExecutor)) { public override ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine(️ 合规审核中...); var checks new Liststring(); if (record.AIGeneratedResponse.Contains(歉意)) checks.Add(✅ 包含道歉); if (record.AIGeneratedResponse.Length 300) checks.Add(✅ 字数合规); if (!record.AIGeneratedResponse.Contains(法律) !record.AIGeneratedResponse.Contains(诉讼)) checks.Add(✅ 无敏感法律词汇); record.ComplianceStatus checks.Count 2 ? ✅ 审核通过 : ⚠️ 需人工复审; record.ProcessingSteps.Add($[合规审核] {record.ComplianceStatus} - {string.Join(, , checks)}); return ValueTask.FromResult(record); } } // 3. 情绪评估执行器使用 AI internal sealed class SentimentAnalysisExecutor(IChatClient chatClient) : ExecutorComplaintProcessingRecord, ComplaintProcessingRecord(nameof(SentimentAnalysisExecutor)) { public override async ValueTaskComplaintProcessingRecord HandleAsync(ComplaintProcessingRecord record, IWorkflowContext context, CancellationToken cancellationToken default) { Console.WriteLine( AI 情绪评估中...); var prompt $分析以下客服回复的情绪基调用一个词概括如友好、专业、冷淡、热情 {record.AIGeneratedResponse} 只返回一个词不要解释。; var response await chatClient.GetResponseAsync(prompt, cancellationToken: cancellationToken); record.SentimentScore response.Text?.Trim() ?? 中性; record.ProcessingSteps.Add($[情绪评估] AI 评估语气为{record.SentimentScore}); return record; } }Step3: 创建主工作流​​​​​​​var classifierExecutor new ComplaintClassifierExecutor(); var complianceExecutor new ComplianceCheckExecutor(); var sentimentExecutor new SentimentAnalysisExecutor(chatClient); // 主工作流分类 → 条件路由到子流程 → 合规 → 情绪 var mainWorkflow new WorkflowBuilder(classifierExecutor) .AddEdgeComplaintProcessingRecord(classifierExecutor, productQualitySubExecutor, condition: record record.Category 产品质量) .AddEdgeComplaintProcessingRecord(classifierExecutor, logisticsSubExecutor, condition: record record.Category 物流问题) .AddEdge(productQualitySubExecutor, complianceExecutor) .AddEdge(logisticsSubExecutor, complianceExecutor) .AddEdge(complianceExecutor, sentimentExecutor) .WithOutputFrom(sentimentExecutor) .Build(); Console.OutputEncoding Encoding.UTF8; Console.WriteLine(✅ Main Sub Workflow 构建完成);2.6 测试工作流定义投诉的工单内容如下这是一个产品质量相关的投诉。​​​​​​​var processingRecord new ComplaintProcessingRecord { Original new CustomerComplaint( OrderId: ORD-2025-8821, CustomerName: 张先生, ComplaintText: 收到的手机屏幕有明显划痕要求退货退款, SubmittedAt: DateTime.Now) };通过Streaming流式执行​​​​​​​Console.WriteLine( 开始执行投诉处理流水线...); Console.WriteLine(new string(━, 60)); await using (var streaming await InProcessExecution.StreamAsync(mainWorkflow, processingRecord)) { await foreach (WorkflowEvent evt in streaming.WatchStreamAsync()) { switch (evt) { case ExecutorInvokedEvent started: Console.WriteLine($\n {started.ExecutorId} 开始执行); break; case ExecutorCompletedEvent completed when completed.Data is ComplaintProcessingRecord rec: Console.WriteLine($ 共享状态更新 → 处理步骤数{rec.ProcessingSteps.Count}); break; case WorkflowOutputEvent outputEvt when outputEvt.Data is ComplaintProcessingRecord finalRecord: Console.WriteLine(\n new string(━, 60)); Console.WriteLine( 投诉处理完成最终处理记录:\n); Console.WriteLine(JsonSerializer.Serialize(finalRecord)); Console.WriteLine(\n 处理步骤详情); foreach (var step in finalRecord.ProcessingSteps) { Console.WriteLine($ {step}); } Console.WriteLine(\n AI 生成的客户回复); Console.WriteLine(new string(─, 60)); Console.WriteLine(finalRecord.AIGeneratedResponse); Console.WriteLine(new string(─, 60)); break; } } }测试结果如下图所示首先可以通过监控日志发现准确地进入到了产品质量子流程其次最后由AI生成的回复内容也很友好同时也满足合规审核的要求3 小结本文介绍了MAF中主工作流 子工作流的工作模式最后通过一个企业客服中心处理投诉工单的案例介绍了这种模式的代码实现。需要注意的是建议每个子工作流都是用标准统一的状态模型以便在主工作流中复用 和 传递。建议每个子工作流只保持3~4个步骤单一职责在工作流中同样适用下一篇​​​​​​​我们将继续学习MAF中智能体的几种常见编排模式 - 顺序并发 和 移交。4 示例源码Github: https://github.com/EdisonTalk/MAFDhttps://github.com/mzhongl524/MAFD2026-8月更新示例引入地址

相关新闻

【信息科学与工程学】【物理/化学和工程技术】第七十九篇 物理化学 系列一 基础知识-1

【信息科学与工程学】【物理/化学和工程技术】第七十九篇 物理化学 系列一 基础知识-1

表格 编号 类型 领域 问题 问题的现象 问题的数学分析 逐step推理思考的数学方程式 参数列表及参数的数值范围及数值分析设计 关联知识 1 推导+计算 化学热力学 理想气体绝热可逆过程的 p-V-T 全关系与功 单原子理想气体 n=2 mol,从 (p₁=10 atm, V₁=5 L, T₁=3…

2026/8/12 20:09:25 阅读更多 →
Python游戏化学习指南:从零到一,在玩中掌握编程核心

Python游戏化学习指南:从零到一,在玩中掌握编程核心

很多Python初学者都经历过这样的阶段:对着枯燥的语法书和练习题,感觉编程既抽象又无趣,学习热情很快就被消磨殆尽。直到有一天,你发现原来Python可以如此“好玩”——通过游戏化的方式,在闯关、解谜、甚至编写小游戏的…

2026/8/12 20:08:24 阅读更多 →
AI Agent上下文压缩:Headroom原理、实战与长对话优化指南

AI Agent上下文压缩:Headroom原理、实战与长对话优化指南

1. 项目概述:为什么我们需要“上下文压缩”?如果你最近在折腾AI Agent或者大语言模型应用,大概率被“上下文长度”这个问题折磨过。无论是OpenAI的GPT-4 Turbo那128K的“豪华”窗口,还是Claude那令人咋舌的200K上下文,…

2026/8/12 20:08:24 阅读更多 →

最新新闻

新手如何避免功能优先的开发误区

新手如何避免功能优先的开发误区

1. 为什么新手容易陷入"先设计功能"的误区 刚入行的产品经理或开发者最容易犯的错误,就是接到需求后立即开始画原型、写代码。我见过太多团队一上来就讨论"这个按钮放左边还是右边"、"要不要加个动画效果",结果开发到一半…

2026/8/12 20:59:51 阅读更多 →
Rust Unsafe 边界:别让检索上下文带着悬垂引用穿层

Rust Unsafe 边界:别让检索上下文带着悬垂引用穿层

Rust Unsafe 边界:别让检索上下文带着悬垂引用穿层 先把问题落到具体对象 在检索和上下文编排链路中,Unsafe 最容易被用来绕过生命周期、共享可变缓存或做零拷贝转换。每个 Unsafe 块都应说明不变量、调用方责任和失效条件。 实施范围如何收敛 不要把临时…

2026/8/12 20:59:51 阅读更多 →
【ORC】ORC 文件如何支持 Schema Evolution(模式演进)?添加/删除列时文件结构如何变化?

【ORC】ORC 文件如何支持 Schema Evolution(模式演进)?添加/删除列时文件结构如何变化?

ORC 文件如何优雅支持 Schema Evolution?添加/删除列的底层机制全解析 在构建流批一体平台和实时数仓的过程中,Schema Evolution(模式演进) 是一项不可或缺的能力。业务需求瞬息万变,数据模型必须随之灵活调整:今天可能需要为用户行为日志增加一个 device_model 字段,明…

2026/8/12 20:59:51 阅读更多 →
Python AI 服务迁到 Rust:先对齐协议,再切执行路径

Python AI 服务迁到 Rust:先对齐协议,再切执行路径

Python AI 服务迁到 Rust:先对齐协议,再切执行路径 先把问题落到具体对象 重写服务最先对齐的不是吞吐,而是请求、响应、错误码、取消和超时语义。Rust 版本只有在这些外部行为稳定后,才适合进入流量切换。 变更如何分阶段 先用脱…

2026/8/12 20:59:51 阅读更多 →
易认证(EAuth)集成Github认证

易认证(EAuth)集成Github认证

介绍 易认证(EAuth)是一款开源的企业级的OIDC认证平台,使用golangreact(ant design pro框架)开发的,提供多种认证方式,包括人脸识别、OpenID Connect(OIDC)、Web身份认证等,支持多因素认证(MFA), 灵活的令牌(Token)生…

2026/8/12 20:59:51 阅读更多 →
Playwright自动化测试与数据抓取:从安装到实战的完整指南

Playwright自动化测试与数据抓取:从安装到实战的完整指南

1. 项目概述:为什么我们需要Playwright?如果你正在为Web自动化测试、数据抓取或者网页操作脚本而头疼,那么Playwright的出现,很可能就是你的“解药”。作为一个由微软开源的现代化浏览器自动化库,它正迅速成为开发者和…

2026/8/12 20:58:51 阅读更多 →

日新闻

Ubuntu 22.04安装与使用tree命令:高效管理Linux目录结构

Ubuntu 22.04安装与使用tree命令:高效管理Linux目录结构

1. 为什么需要一个“目录树”工具?在Linux世界里,尤其是Ubuntu这样的发行版,命令行是很多人的主战场。我们每天都要和文件、目录打交道。ls命令是查看目录内容的首选,它简洁、高效,能列出文件名、权限、大小等关键信息…

2026/8/12 9:33:34 阅读更多 →
博思AI智能体:意图识别、思考链与性能优化的工程实践

博思AI智能体:意图识别、思考链与性能优化的工程实践

在AI应用从“能用”走向“好用”的进程中,系统的响应速度、决策透明度与高并发稳定性是决定用户体验的关键。博思AI智能体近期完成了一次重要的专项优化,聚焦于意图识别、思考链展示与全链路压测三大核心领域,将系统从功能实现推向了工程卓越…

2026/8/12 9:33:34 阅读更多 →
子代理架构:AI智能体任务分解与协同执行的核心原理与实践

子代理架构:AI智能体任务分解与协同执行的核心原理与实践

1. 项目概述:为什么我们需要“子代理”?最近在折腾各种AI应用和自动化流程时,我越来越频繁地遇到一个瓶颈:单个AI智能体(Agent)的能力边界。无论是处理复杂的多步骤任务,还是需要同时调用多个专…

2026/8/12 9:33:34 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/12 1:11:09 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/12 1:11:09 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/12 1:11:08 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/11 17:09:45 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/12 1:11:10 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/11 17:09:45 阅读更多 →