C_自定义Exectors1
1 参考文章: https://www.cnblogs.com/edisontalk/p/-/quick-start-on-maf-chatper05
using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; using Microsoft.Extensions.AI; using OpenAI.Chat; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using ChatResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat; namespace ConsoleApp1.WorksFolw { // https://www.cnblogs.com/edisontalk/p/-/quick-start-on-maf-chatper05 public static class Test { public static async Task Run() { AIService chatClient = new AIService(); //AIService chatClient2 = new AIService(); var solganWriter = new SloganWriterExecutor(id: "SloganWriter1111", chatClient.Client); var feebackHandler = new FeedbackExecutor(id: "FeedbackHandler22222", chatClient.Client); //Console.WriteLine(" Executor 实例创建完成"); var workflow = new WorkflowBuilder(solganWriter) .AddEdge(source: solganWriter, target: feebackHandler) // 生成 → 审核 .AddEdge(source: feebackHandler, target: solganWriter) // 审核不通过 → 重新生成 .WithOutputFrom(feebackHandler) // 指定输出来源 .Build(); //Console.WriteLine("工作流构建完成"); // 定义产品任务 //var productTask = "请为马自达一款经济实惠且驾驶乐趣十足的电动SUV创作标语,要求结合马自达电车的特性来创作"; FeedbackResult feedbackResult = new FeedbackResult() { }; //Console.WriteLine($"📋 产品需求: {productTask}\n"); //Console.WriteLine($"📊 审核标准: 评分 >= 8分"); //Console.WriteLine($"🔄 最大尝试: 3次\n"); //Console.WriteLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); //Console.WriteLine("⏱️ 开始执行工作流..."); //Console.WriteLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); // 执行工作流 await using (var run = await InProcessExecution.RunStreamingAsync(workflow, input: feedbackResult)) { await run.TrySendMessageAsync(new TurnToken(emitEvents: true));//如果流式,必须出发这个条件,Agent才会输出 // 监听工作流事件 await foreach (WorkflowEvent evt in run.WatchStreamAsync()) { // 使用模式匹配识别不同类型的事件 switch (evt) { case SloganGeneratedEvent sloganEvent: // 处理标语生成事件 // Console.WriteLine($"✨处理标语生成事件==== {sloganEvent}"); //Console.WriteLine(); break; case FeedbackFinishedEvent feedbackEvent: // 处理审核反馈事件 // Console.WriteLine($"处理审核反馈事件==={feedbackEvent}"); //Console.WriteLine(); break; case WorkflowOutputEvent outputEvent: // 处理最终输出事件 //Console.WriteLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); //Console.WriteLine("🎉 工作流执行完成"); //Console.WriteLine("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); //Console.WriteLine($"{outputEvent.Data}"); break; } } Console.WriteLine("所有流程已完成"); } } } /// <summary> /// 文案生成结果 /// </summary> public class SloganResult { /// <summary> /// 产品任务描述 /// </summary> [JsonPropertyName("task")] public string Task { get; set; } /// <summary> /// 生成的标语 /// </summary> [JsonPropertyName("slogan")] public string Slogan { get; set; } } /// <summary> /// 审核反馈结果 /// </summary> public class FeedbackResult { /// <summary> /// 审核评论 /// </summary> [JsonPropertyName("comments")] public string Comments { get; set; } = string.Empty; /// <summary> /// 质量评分(1-10分) /// </summary> [JsonPropertyName("rating")] public int Rating { get; set; } /// <summary> /// 改进建议 /// </summary> [JsonPropertyName("actions")] public string Actions { get; set; } = string.Empty; } /// <summary> /// 文案已生成事件 /// </summary> public sealed class SloganGeneratedEvent : WorkflowEvent { private readonly SloganResult _sloganResult; public SloganGeneratedEvent(SloganResult sloganResult) : base(sloganResult) { this._sloganResult = sloganResult; } public override string ToString() => $"[文案已生成] {_sloganResult.Slogan}"; } /// <summary> /// 自定义事件:审核反馈完成 /// </summary> public sealed class FeedbackFinishedEvent : WorkflowEvent { private readonly FeedbackResult _feedbackResult; public FeedbackFinishedEvent(FeedbackResult feedbackResult) : base(feedbackResult) { this._feedbackResult = feedbackResult; } public override string ToString() => $""" [审核反馈自定义事件] 评分: {_feedbackResult.Rating}/10 评论: {_feedbackResult.Comments} 建议: {_feedbackResult.Actions} """; } /// <summary> /// 文案生成 Executor - 根据任务或反馈生成标语 /// </summary> public class SloganWriterExecutor : Executor<FeedbackResult, SloganResult> { private AIAgent _agent; private AgentSession mAgeSession; /// <summary> /// 初始化文案生成 Executor /// </summary> /// <param name="id">Executor 唯一标识</param> /// <param name="chatClient">AI 聊天客户端</param> public SloganWriterExecutor(string id, IChatClient chatClient) : base(id) { var instructions = """ 你是一名专业的文案审核专家。 你的任务是评估标语的质量,并生成最终的标语。 【输出格式要求】 你必须且只能返回一个合法的 JSON 对象,不要包含任何 Markdown 标记(如 ```json)、解释性文字或前言后语。 JSON 对象必须严格遵循以下结构,禁止新增、遗漏或修改任何字段名: { "task": "字符串类型,产品任务描述", "slogan": "字符串类型,最终生成的标语" } 【示例】 { "task": "为马自达纯电SUV创作标语", "slogan": "电驭人马一体,触手可及的纯粹驾趣" } """; _agent = chatClient.AsAIAgent(new ChatClientAgentOptions { Name = "文案生成", ChatOptions = new() { Instructions = instructions, ResponseFormat = ChatResponseFormat.ForJsonSchema<SloganResult>() } }); // 创建 Agent 和对话线程 this._agent = _agent; } public async override ValueTask<SloganResult> HandleAsync(FeedbackResult feedback, IWorkflowContext context, CancellationToken cancellationToken = default) { if (mAgeSession == null) { mAgeSession = await _agent.CreateSessionAsync(); } if (string.IsNullOrEmpty(feedback.Comments))//首次生成 { //Console.WriteLine($"✍️【第一次】 [文案生成] 接收到任务:第一次"); var productTask = "请为马自达一款经济实惠且驾驶乐趣十足的电动SUV创作标语,要求结合马自达电车的特性来创作"; // 调用 Agent 生成标语 var result = await this._agent.RunAsync(productTask, mAgeSession, cancellationToken: cancellationToken); // 反序列化结构化输出 var sloganResult = JsonSerializer.Deserialize<SloganResult>(result.Text) ?? throw new InvalidOperationException("❌ 反序列化标语结果失败"); Console.WriteLine($"【第一次】[文案生成] 生成标语: {sloganResult.Slogan},taskid={sloganResult.Task}"); // 发布自定义事件(将在后续定义) await context.AddEventAsync(new SloganGeneratedEvent(sloganResult), cancellationToken); return sloganResult; } else { // 构造反馈消息 var feedbackMessage = $""" 以下是对你之前标语的审核反馈: 评论: {feedback.Comments} 评分: {feedback.Rating} / 10 改进建议: {feedback.Actions} 请根据反馈改进你的标语,使其更加精准有力。 """; Console.WriteLine($"评分: {feedback.Rating}/10"); // 调用 Agent 改进标语(保持对话上下文) var result = await this._agent.RunAsync(feedbackMessage, this.mAgeSession, cancellationToken: cancellationToken); var sloganResult = JsonSerializer.Deserialize<SloganResult>(result.Text) ?? throw new InvalidOperationException("❌ 反序列化标语结果失败"); Console.WriteLine($"重新生成标语: {sloganResult.Slogan}"); // 发布事件 await context.AddEventAsync(new SloganGeneratedEvent(sloganResult), cancellationToken); return sloganResult; } } } /// <summary> /// 审核反馈 Executor - 评估标语质量并提供反馈 /// </summary> public sealed class FeedbackExecutor : Executor<SloganResult, FeedbackResult> { private AIAgent _agent; private AgentSession mAgeSession; private int _attempts = 1; /// <summary> /// 最低评分要求(1-10分) /// </summary> public int MinimumRating { get; init; } = 10; /// <summary> /// 最大尝试次数 /// </summary> public int MaxAttempts { get; init; } = 3; /// <summary> /// 初始化审核反馈 Executor /// </summary> /// <param name="id">Executor 唯一标识</param> /// <param name="chatClient">AI 聊天客户端</param> public FeedbackExecutor(string id, IChatClient chatClient) : base(id) { var instructions = """ 你是一名专业的文案审核专家。你的任务是对给定的标语进行质量评估,并提供改进建议。 【输出格式要求】 你必须且只能返回一个合法的 JSON 对象,不要包含任何 Markdown 标记(如 ```json)、解释性文字或前言后语。 JSON 对象必须严格遵循以下结构,禁止新增、遗漏或修改任何字段名: { "comments": "字符串类型,你对标语质量的审核评论与评价", "rating": "整数类型,标语的质量评分,取值范围严格限制在 1 到 10 之间", "actions": "字符串类型,针对该标语的具体改进建议或下一步行动指南" } """; _agent = chatClient.AsAIAgent(new ChatClientAgentOptions { Name = "文案审核", ChatOptions = new() { Instructions = instructions, ResponseFormat = ChatResponseFormat.ForJsonSchema<FeedbackResult>() } }); // 创建 Agent 和对话线程 this._agent = _agent; } public async override ValueTask<FeedbackResult> HandleAsync(SloganResult slogan, IWorkflowContext context, CancellationToken cancellationToken = default) { if (mAgeSession == null) { mAgeSession = await _agent.CreateSessionAsync(); } // 构造审核消息 var reviewMessage = $""" 请审核以下标语: 任务: {slogan.Task} 标语: {slogan.Slogan} 请提供: 1. 详细的评论(comments) 2. 质量评分(rating,1-10分) 3. 改进建议(actions) """; Console.WriteLine($"[质量审核] 开始审核标语: {slogan.Slogan}"); // 调用 Agent 进行审核 var response = await this._agent.RunAsync(reviewMessage, mAgeSession, cancellationToken: cancellationToken); // 反序列化反馈结果 var feedback = JsonSerializer.Deserialize<FeedbackResult>(response.Text) ?? throw new InvalidOperationException("❌ 反序列化反馈结果失败"); Console.WriteLine($"[质量审核] 本次得到评分: {feedback.Rating}/10"); // 发布自定义事件(将在后续定义) await context.AddEventAsync(new FeedbackFinishedEvent(feedback), cancellationToken); // 业务逻辑:判断是否通过审核 if (feedback.Rating >= this.MinimumRating) { // ✅ 通过审核 await context.YieldOutputAsync( $""" 标语已通过审核! 任务: {slogan.Task} 标语: {slogan.Slogan} 评分: {feedback.Rating}/10 评论: {feedback.Comments} """, cancellationToken ); Console.WriteLine($"[质量审核] 标语通过审核"); return feedback; } // ❌ 未通过审核,检查尝试次数 if (this._attempts >= this.MaxAttempts) { Console.WriteLine($"[质量审核] 达到最大尝试次数{MaxAttempts},终止流程"); // 达到最大尝试次数,输出最终版本 await context.YieldOutputAsync( $""" ⚠️ 标语在 {this.MaxAttempts} 次尝试后未达到最低评分要求。 最终标语: {slogan.Slogan} 最终评分: {feedback.Rating}/10 评论: {feedback.Comments} """, cancellationToken ); return feedback; } // 🔄 继续循环:发送反馈消息回到 SloganWriterExecutor await context.SendMessageAsync(feedback, cancellationToken: cancellationToken); this._attempts++; Console.WriteLine($"[质量审核] 发送反馈,第 {this._attempts} 次尝试"); return feedback; } }
2 效果如图
为了效果,我将设置目标分为10分,永远达不到的效果,就会执行三次的效果

}

浙公网安备 33010602011771号