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分,永远达不到的效果,就会执行三次的效果

image

 





}

 

posted @ 2026-08-08 17:16  陌念  阅读(0)  评论(0)    收藏  举报