Ai Agent 协调者模式 = 一个大脑(Coordinator)+ 四个手脚(Branch Agents)
🎯 一、核心原理
一句话总结
协调者模式 = 一个大脑(Coordinator)+ 四个手脚(Branch Agents)
用户输入 → 协调者分析 → 路由决策 → 分支 Agent 执行 → 返回结果
📐 二、架构图
┌─────────────────────────────────────────────────────────────┐ │ 用户输入层 │ │ (User Input) │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 协调者服务层 │ │ (CoordinatorService) │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ CoordinatorAgentFactory │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ 协调者 Agent (Coordinator) │ │ │ │ │ │ - SystemMessage: 角色定义 + Few-Shot 示例 │ │ │ │ │ │ - FunctionCall: RouteToBranch 函数契约 │ │ │ │ │ │ - JSON Schema: 输出格式约束 │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ↓ ┌───────────────┐ │ 路由决策解析 │ │ - next_agent │ │ - reason │ │ - params │ └───────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 分支 Agent 层 │ │ (Branch Agents) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ FETCH │ │ ANALYZE │ │ RESPOND │ │ TRACK │ │ │ │ 查询投诉 │ │ 分析优先级│ │ 生成回复 │ │ 跟踪完成 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 执行结果层 │ │ (Execution Result) │ └─────────────────────────────────────────────────────────────┘
🔄 三、时序图
用户 CoordinatorService Coordinator BranchAgent │ │ │ │ │──输入请求───→│ │ │ │ │ │ │ │ │──创建协调者─────→│ │ │ │ │ │ │ │──分析意图───────→│ │ │ │ │ │ │ │←─返回决策─────────│ │ │ │ {next_agent, │ │ │ │ reason, params}│ │ │ │ │ │ │ │──解析决策 │ │ │ │ │ │ │ │──创建分支 Agent─────────────────→│ │ │ │ │ │ │──执行任务───────────────────────→│ │ │ │ │ │ │←─返回结果────────────────────────│ │ │ │ │ │←─最终结果────│ │ │ │ │ │ │
核心代码
1、协调者工厂
协调者工厂的核心作用为:根据用户输入的语义,动态创建并选择某一个智能体,在协调者创建的过程中,我们需要明确协调者能够路由的智能体,且告知协调者下一个Agent是什么,以及选择下一个Agnet的原因!
using AutoGen.Core; using AutoGen.OpenAI; using AutoGen.OpenAI.Extension; using CoordinatorS; using OpenAI; using OpenAI.Chat; using System; using System.ClientModel; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp3 { /// <summary> /// 协调者 Agent 工厂(Function Calling + JSON Schema) /// </summary> public class CoordinatorAgentFactory { private readonly ChatClient _chatClient; private readonly string _systemMessage; private readonly ChatResponseFormat _jsonSchemaFormat; private readonly ComplaintTools _complaintTools; // ✅ 字段 public CoordinatorAgentFactory(string apiKey, string endpoint, string modelId) { var client = new OpenAIClient(new ApiKeyCredential(apiKey), new OpenAIClientOptions { Endpoint = new Uri(endpoint) }); _chatClient = client.GetChatClient(modelId); _complaintTools = new ComplaintTools(); // ① 自动生成 SystemMessage _systemMessage = BuildSystemMessage(); // ② 自动生成 JSON Schema var jsonSchema = JsonSchemaGenerator.BuildRouteToBranchSchema(); // ✅ 修正:参数名是 jsonSchemaFormatName,不是 name _jsonSchemaFormat = ChatResponseFormat.CreateJsonSchemaFormat( jsonSchemaFormatName: "coordinator_decision", jsonSchema: BinaryData.FromString(jsonSchema), jsonSchemaFormatDescription: "协调者路由决策输出格式", jsonSchemaIsStrict: true); //Console.WriteLine("✅ CoordinatorAgentFactory 初始化完成"); //Console.WriteLine($"系统消息长度:{_systemMessage.Length} 字符"); //Console.WriteLine($"JSON Schema:\n{jsonSchema}"); } /// <summary> /// 构建 SystemMessage /// </summary> private string BuildSystemMessage() { var sb = new StringBuilder(); sb.AppendLine("你是协调者,负责分析用户意图并路由到合适的分支 Agent。"); sb.AppendLine(); sb.AppendLine(JsonSchemaGenerator.BuildAgentListDescription()); sb.AppendLine(); sb.AppendLine(JsonSchemaGenerator.BuildFewShotPrompt()); sb.AppendLine(); sb.AppendLine("【输出要求】"); sb.AppendLine("1. 必须调用 RouteToBranch 函数"); sb.AppendLine($"2. next_agent: 从 [{string.Join(", ", AgentConfigs.All.Select(a => $@"""{a.Code}"""))}] 中选择一个"); sb.AppendLine(); sb.AppendLine("现在请分析用户输入,调用 RouteToBranch 函数:"); return sb.ToString(); } /// <summary> /// 创建协调者 Agent /// </summary> public IAgent CreateCoordinator() { Console.WriteLine("🔧 创建协调者 Agent..."); // 创建 Agent(传入 JSON Schema 约束输出) var agent = new OpenAIChatAgent( name: "Coordinator", systemMessage: _systemMessage, chatClient: _chatClient, responseFormat: _jsonSchemaFormat) .RegisterMessageConnector() .RegisterPrintMessage(); Console.WriteLine("✅ 协调者 Agent 创建完成"); return agent; } /// <summary> /// 创建分支 Agent /// </summary> public IAgent CreateBranchAgent(string code) { return BranchAgents.Create(code, _chatClient, _complaintTools); } } /// <summary> /// JSON Schema 生成器(用于约束协调者输出) /// </summary> public static class JsonSchemaGenerator { /// <summary> /// 生成 RouteToBranch 函数的 JSON Schema /// </summary> public static string BuildRouteToBranchSchema() { // 从配置中提取所有 Agent Code var agentCodes = AgentConfigs.All.Select(a => $@"""{a.Code}"""); var agentCodesEnum = string.Join(", ", agentCodes); return $$""" { "type": "object", "required": ["next_agent", "reason"], "properties": { "next_agent": { "type": "string", "enum": [{{agentCodesEnum}}], "description": "下一个要调用的 Agent 代码,必须是以下之一:{{string.Join(", ", AgentConfigs.All.Select(a => a.Code))}}" } , "reason": { "type": "string", "maxLength": 100, "description": "路由原因(20 字以内)" } }, "additionalProperties": false } """; } /// <summary> /// 生成 Few-Shot Prompt(从配置的 Examples 自动生成) /// </summary> public static string BuildFewShotPrompt() { var sb = new StringBuilder(); sb.AppendLine("【示例】"); sb.AppendLine("────────────────────────────────────────"); foreach (var config in AgentConfigs.All) { foreach (var example in config.Examples) { sb.AppendLine($"用户:\"{example.UserInput}\""); //这里指定下一个Agent sb.AppendLine($"助手:RouteToBranch(next_agent=\"{example.TargetAgentCode}\", reason=\"{example.Reason}\""); sb.AppendLine("────────────────────────────────────────"); } } return sb.ToString(); } /// <summary> /// 生成 Agent 列表描述 /// </summary> public static string BuildAgentListDescription() { var sb = new StringBuilder(); sb.AppendLine("【可用分支 Agent】"); foreach (var config in AgentConfigs.All) { sb.AppendLine($"- {config.Code} ({config.Name}): {config.Description}"); } return sb.ToString(); } } }
2、分支Agent
2.1、AgentConfig
using AutoGen.Core; using AutoGen.OpenAI; using AutoGen.OpenAI.Extension; using Microsoft.Extensions.AI; using OpenAI; using System; using System.ClientModel; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CoordinatorS { /// <summary> /// Agent Code 枚举(全大写) /// </summary> public enum AgentCodeEnum { /// <summary> /// 查询投诉列表Agent Code /// </summary> 查询投诉, /// <summary> /// 投诉内容分析专家智能体 Code /// </summary> 分析投诉, /// <summary> /// Agent自动回复投诉智能体 Code /// </summary> 回复投诉, /// <summary> /// 完结/跟踪投诉智能体 Code /// </summary> 完结投诉 } /// <summary> /// Agent 配置 /// </summary> public class AgentConfig { /// <summary> /// Agent 代码(必须是大写字母,用于 JSON Schema enum) /// </summary> public string Code { get; set; } = ""; /// <summary> /// Agent 名称(人类可读,可以和 Code 不同) /// </summary> public string Name { get; set; } = ""; /// <summary> /// 职责描述 /// </summary> public string Description { get; set; } = ""; /// <summary> /// Agent 的 SystemMessage /// </summary> public string SystemMessage { get; set; } = ""; /// <summary> /// 调用函数的相关描述 /// </summary> public FunctionCallExample[] Examples { get; set; } = Array.Empty<FunctionCallExample>(); } /// <summary> /// Function Calling 示例 /// </summary> public class FunctionCallExample { /// <summary> /// 用户输入 /// </summary> public string UserInput { get; set; } = ""; /// <summary> /// 期望的路由 Agent 代码 /// </summary> public string TargetAgentCode { get; set; } = ""; public string Reason { get; set; } = ""; } /// <summary> /// 所有 Agent 配置(加新 Agent 在这里改) /// </summary> public static class AgentConfigs { public static readonly List<AgentConfig> All = new() { new AgentConfig { Code = AgentCodeEnum.查询投诉.ToString(), Name = "ComplaintFetcher", Description = "查询投诉列表", SystemMessage = @"你是投诉查询助手,负责查询待处理的投诉列表。 【职责】 1. 调用 GetPendingComplaints 查询指定日期范围内的待处理投诉 2. 只返回 PENDING 状态的投诉单 3. 日期格式:YYYY-MM-DD,查询范围最大 30 天", Examples = new[] { new FunctionCallExample { UserInput = "帮我查一下最近 7 天的投诉", TargetAgentCode = AgentCodeEnum.查询投诉.ToString(),//当用户类似这种描述时,对应的智能体 Reason = "用户需要查询近一周的投诉列表" }, new FunctionCallExample { UserInput = "有待处理的投诉吗", TargetAgentCode = AgentCodeEnum.查询投诉.ToString(),//当用户类似这种描述时,对应的智能体 Reason = "用户需要查询待处理投诉列表" }, new FunctionCallExample { UserInput = "查一下 2026-08-14 到 2026-08-21 的投诉", TargetAgentCode = AgentCodeEnum.查询投诉.ToString(),//当用户类似这种描述时,对应的智能体 Reason = "用户需要查询指定时间段的投诉列表" } } }, new AgentConfig { Code = AgentCodeEnum.分析投诉.ToString(), Name = "ComplaintAnalyzer", Description = "分析投诉优先级", SystemMessage = @"你是投诉分析专家,负责分析投诉内容并判断优先级。 【优先级规则】 - need_immediate_service=true → 高优先级 - user_complaint_times>1 → 高优先级 - problem_type=REFUND → 高优先级 - user_tag_list 包含 HIGH_RISK → 高优先级 【输出格式】 - 投诉单号 - 优先级(高/中/普通) - 建议处理方案", Examples = new[] { new FunctionCallExample { UserInput = "分析这个投诉为什么优先级高", TargetAgentCode = AgentCodeEnum.分析投诉.ToString(), Reason = "用户需要分析投诉优先级" //这里的Reson 会 在协调者中用到 }, new FunctionCallExample { UserInput = "这个投诉紧急吗", TargetAgentCode = AgentCodeEnum.分析投诉.ToString(), Reason = "用户需要分析投诉紧急程度" //这里的Reson 会 在协调者中用到 } } }, new AgentConfig { Code = AgentCodeEnum.回复投诉.ToString(), Name = "ResponseGenerator", Description = "生成回复话术", SystemMessage = @"你是客服回复专家,负责生成专业的投诉回复话术。 【回复原则】 1. 态度诚恳,表达歉意 2. 说明处理方案 3. 给出合理承诺(不要过于具体) 4. 引导用户关闭服务单 5. 字数控制在 20-40 字 【禁止事项】 ❌ 不要承诺具体时间(如""5 分钟内""、""2 小时内"") ❌ 不要承诺具体金额(如""赔偿 100 元"") ❌ 不要承诺具体人员(如""技术总监亲自处理"") 【推荐表达】 ✅ ""尽快"" 而不是 ""5 分钟内"" ✅ ""及时"" 而不是 ""2 小时内"" ✅ ""专人跟进"" 而不是 ""技术总监""", Examples = new[] { new FunctionCallExample { UserInput = "生成一个回复,要态度诚恳", TargetAgentCode = AgentCodeEnum.回复投诉.ToString() , Reason = "用户需要生成诚恳的回复话术", }, new FunctionCallExample { UserInput = "怎么写回复话术", TargetAgentCode = AgentCodeEnum.回复投诉.ToString(), Reason = "用户需要生成诚恳的回复话术", }, new FunctionCallExample { UserInput = "帮我写个回复,说我们会尽快处理", TargetAgentCode = AgentCodeEnum.回复投诉.ToString() , Reason = "用户需要生成诚恳的回复话术", } } }, new AgentConfig { Code = AgentCodeEnum.完结投诉.ToString(), Name = "CompletionTracker", Description = "跟踪完成状态", SystemMessage = @"你是投诉完成跟踪助手,负责检查 PROCESSING 状态的投诉并执行操作。 【检查流程】 1. 调用 GetComplaintDetail 查询投诉详情和状态 2. 查询协商历史,检查用户最新留言 3. 检查最后一次商户回复时间,计算是否已满 24 小时 【执行逻辑】 - 如果用户有留言且不满 → 调用 ResponseComplaint 再次回复 - 如果用户有留言且满意 → 调用 CompleteComplaint 标记完成 - 如果用户无留言且已满 24 小时 → 调用 CompleteComplaint 标记完成 - 如果用户无留言但未满 24 小时 → 返回等待提示", Examples = new[] { new FunctionCallExample { UserInput = "标记这个投诉为完结", TargetAgentCode = AgentCodeEnum.完结投诉.ToString() , Reason = "用户需要标记投诉为完结状态", }, new FunctionCallExample { UserInput = "检查 24 小时等待期", TargetAgentCode =AgentCodeEnum.完结投诉.ToString() , Reason = "用户需要检查 24 小时等待期,大于24小时用户无回复的,可以完结", }, new FunctionCallExample { UserInput = "看看有没有可以完结的投诉", TargetAgentCode = AgentCodeEnum.完结投诉.ToString(), Reason = "用户需要检查可完结的投诉", } } } }; } }
注:AgentConfig的Code为Agent的唯一标识,SystemMessage 为 Agent 的Promot 模版, Examples 为调用函数的相关举例!
Reason 字段为协调者说明选择下一个Agent的原因!
2.2、Agent
using AutoGen.Core; using AutoGen.OpenAI; using AutoGen.OpenAI.Extension; using CoordinatorS; using OpenAI.Chat; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace ConsoleApp3 { /// <summary> /// 分支 Agent 创建器(使用 FunctionHelper 自动注册) /// </summary> public static class BranchAgents { /// <summary> /// 根据 Code 创建对应的 Agent /// </summary> public static IAgent Create(string code, ChatClient chatClient, ComplaintTools complaintTools) { var config = AgentConfigs.All.FirstOrDefault(a => a.Code == code); if (config == null) { throw new ArgumentException($"未知的 Agent 代码:{code}"); } Console.WriteLine($"🔧 创建分支 Agent: {code} ({config.Name})..."); // 创建基础 Agent var agent = new OpenAIChatAgent( name: config.Name, systemMessage: config.SystemMessage, chatClient: chatClient); // ✅ 根据 Code 注册对应的 Function(用 FunctionHelper 自动扫描) if (code == AgentCodeEnum.查询投诉.ToString()) { Console.WriteLine(" 📦 注册 Function: GetPendingComplaints, GetComplaintDetail"); var middleware = FunctionHelper.CreateMiddleware( complaintTools, "GetPendingComplaints", "GetComplaintDetail"); var agentWithConnector = agent.RegisterMessageConnector(); var agentWithMiddleware = agentWithConnector.RegisterMiddleware(middleware); var finalAgent = agentWithMiddleware.RegisterPrintMessage(); return finalAgent; } else if (code == AgentCodeEnum.回复投诉.ToString()) { Console.WriteLine(" 📦 注册 Function: ResponseComplaint"); var middleware = FunctionHelper.CreateMiddleware( complaintTools, "ResponseComplaint"); var agentWithConnector = agent.RegisterMessageConnector(); var agentWithMiddleware = agentWithConnector.RegisterMiddleware(middleware); var finalAgent = agentWithMiddleware.RegisterPrintMessage(); return finalAgent; } else if (code == AgentCodeEnum.完结投诉.ToString()) { Console.WriteLine(" 📦 注册 Function: CompleteComplaint, GetComplaintDetail, ResponseComplaint"); var middleware = FunctionHelper.CreateMiddleware( complaintTools, "CompleteComplaint", "GetComplaintDetail", "ResponseComplaint"); var agentWithConnector = agent.RegisterMessageConnector(); var agentWithMiddleware = agentWithConnector.RegisterMiddleware(middleware); var finalAgent = agentWithMiddleware.RegisterPrintMessage(); return finalAgent; } else { var agentWithConnector = agent.RegisterMessageConnector(); var finalAgent = agentWithConnector.RegisterPrintMessage(); return finalAgent; } } } }
3、函数及函数帮助类
反射/函数帮助类
using AutoGen.Core; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace CoordinatorS { /// <summary> /// Function 辅助工具(自动扫描 + 注册) /// </summary> public static class FunctionHelper { /// <summary> /// 从工具类自动扫描所有带 [Function] 特性的方法,创建 FunctionCallMiddleware /// </summary> /// <param name="toolsInstance">工具类实例(如 ComplaintTools)</param> /// <param name="functionNames">要注册的函数名列表(为空则注册全部)</param> public static FunctionCallMiddleware CreateMiddleware(object toolsInstance, params string[] functionNames) { var contracts = new List<FunctionContract>(); var functionMap = new Dictionary<string, Func<string, Task<string>>>(); var methods = toolsInstance.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(m => m.GetCustomAttribute<FunctionAttribute>() != null); foreach (var method in methods) { var functionAttr = method.GetCustomAttribute<FunctionAttribute>(); var functionName = functionAttr?.FunctionName ?? method.Name; if (functionNames.Any() && !functionNames.Contains(functionName)) continue; var contract = new FunctionContract { Name = functionName, Description = functionAttr?.Description ?? method.GetCustomAttribute<DescriptionAttribute>()?.Description ?? "", Parameters = method.GetParameters() .Select(p => new FunctionParameterContract { Name = p.Name, Description = p.GetCustomAttribute<DescriptionAttribute>()?.Description ?? "", IsRequired = !p.IsOptional, ParameterType = p.ParameterType, DefaultValue = p.DefaultValue }) .ToArray() }; contracts.Add(contract); // ✅ 支持任意返回类型的 functionMap functionMap[functionName] = async (args) => { try { var json = JsonDocument.Parse(args); var parameters = new List<object?>(); foreach (var param in contract.Parameters) { if (json.RootElement.TryGetProperty(param.Name, out var elem)) { var value = elem.Deserialize(param.ParameterType); parameters.Add(value); } else if (param.DefaultValue != null) { parameters.Add(param.DefaultValue); } else { parameters.Add(null); } } // ✅ 调用方法(不强制转 Task<string>) var result = method.Invoke(toolsInstance, parameters.ToArray()) as Task; if (result == null) { return "❌ 方法返回 null"; } await result; // ✅ 获取 Task.Result var resultProperty = result.GetType().GetProperty("Result"); if (resultProperty == null) { return "❌ 找不到 Result 属性"; } var resultValue = resultProperty.GetValue(result); // ✅ 已经是 string 直接返回 if (resultValue is string stringValue) { return stringValue; } // ✅ 否则序列化(支持任意类型) if (resultValue == null) { return "[]"; } return JsonSerializer.Serialize(resultValue, JsonOptions); // ← 用配置好的 options } catch (Exception ex) { return $"❌ 执行失败:{ex.Message}"; } }; } return new FunctionCallMiddleware( functions: contracts, functionMap: functionMap); } /// <summary> /// 从工具类自动扫描所有带 [Function] 特性的方法,返回函数名列表 /// </summary> public static string[] GetAvailableFunctions<T>() { return typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(m => m.GetCustomAttribute<FunctionAttribute>() != null) .Select(m => m.GetCustomAttribute<FunctionAttribute>()?.FunctionName ?? m.Name) .ToArray(); } private static readonly JsonSerializerOptions JsonOptions = new() { Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, WriteIndented = false // 不格式化(节省 Token) }; } }
AI函数
using AutoGen.Core; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp3 { /// <summary> /// 投诉处理工具类(供 Agent 调用) /// </summary> public class ComplaintTools { public ComplaintTools() { } /// <summary> /// 查询待处理投诉列表-最大查询一月时间 /// </summary> [Function(functionName: "GetPendingComplaints", description: "查询指定日期范围内的待处理投诉列表,只返回 PENDING 状态的投诉单")] public async Task<string> GetPendingComplaints( [Description("开始日期(YYYY-MM-DD)")] string beginDate, [Description("结束日期(YYYY-MM-DD)")] string endDate, [Description("分页大小(默认 50)")] int limit = 50) { return "【查询待处理投诉列表】返回值"; } /// <summary> /// 回复用户投诉(支持多次回复) /// </summary> [Function(functionName: "ResponseComplaint", description: "回复用户投诉,提交处理方案。只有 PENDING 或 PROCESSING 状态的投诉单才能回复")] public async Task<string> ResponseComplaint( [Description("投诉单号")] string complaintId, [Description("回复内容")] string responseContent) { return "【回复用户投诉】返回值"; } /// <summary> /// 反馈投诉处理完成(带状态校验) /// 只有状态为 PROCESSING(处理中)的投诉单才能标记完成 /// 标记完成后,状态将从 PROCESSING 变为 PROCESSED /// </summary> [Function(functionName: "CompleteComplaint", description: "反馈投诉处理完成。只有满足以下条件才能标记完成:1. 状态为 PROCESSING 2. 已回复用户 3. 回复后 24 小时内用户未继续投诉")] public async Task<string> CompleteComplaint( [Description("投诉单号")] string complaintId) { return "【反馈投诉处理完成】返回值"; } /// <summary> /// 查询投诉详情 /// </summary> [Function(functionName: "GetComplaintDetail", description: "查询投诉详情,包含状态、投诉内容、用户联系方式等")] public async Task<string> GetComplaintDetail( [Description("投诉单号")] string complaintId) { return "【查询投诉详情】返回值"; } } }
4、main 函数 及项目引用
using Applier; using AutoGen.Core; using CoordinatorS; using OpenAI; using System.ClientModel; using System.Text.Json; namespace ConsoleApp3 { internal class Program { static async Task Main(string[] args) { Console.WriteLine("╔════════════════════════════════════╗"); Console.WriteLine("║ 协调者 Agent 测试 ║"); Console.WriteLine("╚════════════════════════════════════╝"); Console.WriteLine(); try { // ① 初始化 OpenAI 客户端 Console.WriteLine("🔌 正在连接 OpenAI..."); var client = new OpenAIClient( new ApiKeyCredential(ConstParm.apiKey), new OpenAIClientOptions { Endpoint = new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1") }); var chatClient = client.GetChatClient("qwen-plus"); // 通义千问 Console.WriteLine("✅ OpenAI 连接成功"); Console.WriteLine(); Console.WriteLine(); var testInputs = new[] { "帮我查一下最近 7 天的投诉", "分析一下这个投诉为什么优先级高", "生成一个回复,要态度诚恳", "标记这个投诉为完成" }; foreach(var userInput in testInputs) { CoordinatorAgentFactory _factory = new CoordinatorAgentFactory(ConstParm.apiKey, ConstParm.endpoint, ConstParm.modelId); var coordinator = _factory.CreateCoordinator(); var message = new TextMessage(Role.User, userInput, from: "User"); var result = await coordinator.GenerateReplyAsync( messages: new[] { message }); // ✅ 方案:同时支持 TextMessage 和 ToolCallMessage string nextAgent = null; string reason = null; string extractedParams = "{}"; if (result is TextMessage textMsg) { // AI 直接输出 JSON 文本 var content = textMsg.GetContent(); var json = JsonDocument.Parse(content); nextAgent = json.RootElement.GetProperty("next_agent").GetString(); } else if (result is ToolCallMessage toolCall) { // AI 调用函数 var Call = JsonDocument.Parse(toolCall.ToolCalls.First().FunctionArguments); nextAgent = Call.RootElement.GetProperty("next_agent").GetString(); } Console.WriteLine($"🔀用户说:{userInput} ,协调者路由决策:{nextAgent}"); // 创建分支 Agent 并执行 if (!string.IsNullOrEmpty(nextAgent)) { var branchAgent = _factory.CreateBranchAgent(nextAgent); var branchResult = await branchAgent.GenerateReplyAsync( messages: new[] { message }); Console.WriteLine($"✅ 分支结果:{branchResult.GetContent()}"); } } } catch (Exception ex) { Console.WriteLine($"❌ 主程序异常:{ex.Message}"); Console.WriteLine($" 类型:{ex.GetType().Name}"); Console.WriteLine($" 堆栈:{ex.StackTrace}"); } Console.WriteLine(); Console.WriteLine("按任意键退出..."); Console.ReadLine(); } } }
项目
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <Compile Remove="ConversationHistory.cs" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\openClawTest\ConsoleApp1\ConstParm.cs" Link="ConstParm.cs" /> </ItemGroup> <ItemGroup> <PackageReference Include="AutoGen" Version="0.2.3" /> <PackageReference Include="AutoGen.OpenAI" Version="0.2.3" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" /> </ItemGroup> </Project>
5、Ai相关参数
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Applier { internal class ConstParm { /// <summary> /// 大模型 /// </summary> public static string modelId = "qwen-plus"; /// <summary> /// /// </summary> public static string apiKey = "sk-adxxxxxxxxxxxxxxxxxxxxxx101d"; /// <summary> /// 大模型URL /// </summary> public static string endpoint = "https://dashscope.aliyuncs.com/compatible-mode/v1"; /// <summary> /// 高德查询天气预报的 Apikey windows服务类型 /// </summary> public static string amapApiKey = "63xxxxxxxxxxxxxxb78e4xxxxa4b9"; } }

浙公网安备 33010602011771号