AutoGen 自由对话 及 标准模式对话(限定次数/轮次)-含中间件/响应时长、日志、Token 估算
🎯 核心功能
1️⃣ 两种对话模式
| 模式 | 方法 | 特点 |
|---|---|---|
| 自由选择模式 | GenerateReplyAsync |
手动管理历史,可导出记录 |
| 标准模式 | InitiateChatAsync |
自动管理历史,多轮对话 |
2️⃣ 三个中间件
| 中间件 | 作用 |
|---|---|
| WithTimestamp | 记录请求/响应时间 |
| WithLogging | 写入日志文件 |
| WithMessageCount | 统计消息数和 Token |
3️⃣ Agent 工厂
统一创建和管理 Agent,封装配置细节。
📚 核心知识点
1️⃣ 中间件机制
// 洋葱模型 agent .WithTimestamp() // 外层 .WithLogging() // 中层 .WithMessageCount(); // 内层 // 执行顺序:LIFO(后进先出) 请求 → MessageCount → Logging → Timestamp → Agent 核心
2️⃣ 委托签名
Func< IEnumerable<IMessage>, // 消息列表 GenerateReplyOptions?, // 选项 IAgent, // 下一个 Agent CancellationToken, // 取消令牌 Task<IMessage> // 返回值 >
3️⃣ 调用链
var response = await nextAgent.GenerateReplyAsync(msgs, options, ct); // ↑ 这行代码调用下一个中间件/核心 Agent
4️⃣ 扩展方法
public static MiddlewareAgent<IAgent> WithTimestamp(this IAgent agent) { return agent.RegisterMiddleware(async (msgs, options, nextAgent, ct) => { // 中间件逻辑 }); }
🎯 学习收获
| 知识点 | 掌握程度 |
|---|---|
| 中间件注册机制 | ⭐⭐⭐⭐⭐ |
| 委托签名理解 | ⭐⭐⭐⭐⭐ |
| 调用链原理 | ⭐⭐⭐⭐⭐ |
| 扩展方法设计 | ⭐⭐⭐⭐ |
| Agent 类型区别 | ⭐⭐⭐⭐ |
| 多轮对话管理 | ⭐⭐⭐⭐ |
项目代码
main
using AutoGen; using AutoGen.Core; namespace ConsoleApp2 { internal class Program { static async Task Main(string[] args) { // 👇 修复控制台编码(必须在第一行!)-- 在控制台输入的内容,传到千问可能乱码 Console.OutputEncoding = System.Text.Encoding.Unicode; Console.InputEncoding = System.Text.Encoding.Unicode; Console.WriteLine("🤖 AutoGen 第 2 课实战"); Console.WriteLine("==============================================\n"); Console.WriteLine("选择模式:"); Console.WriteLine("1 - 自由选择 Agent(学习模式)"); Console.WriteLine("2 - 人机对话(标准模式)"); Console.WriteLine("0 - 退出\n"); var mode = Console.ReadLine(); if (mode == "1") { await RunFreeMode(); } else if (mode == "2") { await RunStandardMode(); } else { Console.WriteLine("👋 再见!"); } } // 自由选择模式 static async Task RunFreeMode() { var factory = new AgentFactory(); var openAIAgent = factory.CreateOpenAIChatAgent() .WithTimestamp() .WithLogging() .WithMessageCount(); // ✅ history 在循环外创建 var history = new List<IMessage>(); Console.WriteLine("\n🤖 AutoGen 第 2 课实战 - 简单对话"); Console.WriteLine("=============================================="); Console.WriteLine("输入 'exit' 或 '退出' 结束对话\n"); while (true) { Console.Write("你:"); var userInput = Console.ReadLine(); if (string.IsNullOrWhiteSpace(userInput)) continue; if (userInput.ToLower() == "exit" || userInput == "退出") { Console.WriteLine("👋 再见!"); break; } var userMessage = new TextMessage(Role.User, userInput, from: "user"); history.Add(userMessage); var response = await openAIAgent.GenerateReplyAsync( messages: history, cancellationToken: CancellationToken.None); history.Add(response); //Console.WriteLine($"\n小助手:{response.GetContent()}\n"); } } // 标准模式(InitiateChatAsync) static async Task RunStandardMode() { var factory = new AgentFactory(); var userProxyAgent = factory.CreateUserProxyAgent(); var openAIAgent = factory.CreateOpenAIChatAgent() .WithTimestamp() .WithLogging() .WithMessageCount(); Console.WriteLine("\n🤖 人机对话模式 - 最多 5 轮"); Console.WriteLine("==============================================\n"); var rs = await userProxyAgent.InitiateChatAsync( receiver: openAIAgent, message: "你好,请介绍一下你自己", //默认的message不算一次 maxRound: 5);//最多问答5次,六爷提问+1,小助手回答+1 // ✅ 带轮次编号 int round = 0; foreach (var item in rs) { var content = item?.GetContent(); if (item.From == "六爷") { round++; Console.WriteLine($"\n📍 第{round}轮 - 六爷问了:{content}"); } if (item.From == "小助手") { Console.WriteLine($"\n📍 第{round}轮 - 小助手回复:{content}"); } } Console.WriteLine("\n✅ 5轮对话结束!"); } } }
中间件
using AutoGen.Core; using Google.Protobuf.WellKnownTypes; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace ConsoleApp2 { /// <summary> /// Agent 中间件扩展方法 /// </summary> public static class AgentMiddlewareExtensions { /// <summary> /// 注册时间戳中间件 /// </summary> public static MiddlewareAgent<IAgent> WithTimestamp(this IAgent agent) { var middlewareAgent = agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { var timestampRequest = DateTime.Now; // 前置处理 //Console.ForegroundColor = ConsoleColor.Gray; //Console.WriteLine($"[{timestampRequest.ToString("HH:mm:ss.fff")}] ⬇️ {nextAgent.Name} 收到 {msgs.Count()} 条消息"); //Console.ResetColor(); // 调用下一个中间件(核心:调用 nextAgent 就是继续执行链) var response = await nextAgent.GenerateReplyAsync(msgs, options, ct); // 后置处理 var timestampResponse = DateTime.Now; Console.ForegroundColor = ConsoleColor.Gray; //Console.WriteLine($"[{timestampResponse.ToString("HH:mm:ss.fff")}] ⬆️ {nextAgent.Name} 发送响应"); Console.WriteLine($"响应时长:{(timestampResponse - timestampRequest).TotalSeconds}秒。"); Console.ResetColor(); return response; }); return middlewareAgent; } /// <summary> /// 注册日志中间件 /// </summary> public static MiddlewareAgent<IAgent> WithLogging(this IAgent agent, string logFile = "agent_logs.txt") { return agent.RegisterMiddleware(async (msgs, options, nextAgent, ct) => { var logEntry = new StringBuilder(); logEntry.AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] Agent: {nextAgent.Name}"); logEntry.AppendLine($" 消息数量:{msgs.Count()}"); var stopwatch = System.Diagnostics.Stopwatch.StartNew(); var response = await nextAgent.GenerateReplyAsync(msgs, options, ct); stopwatch.Stop(); logEntry.AppendLine($" 响应耗时:{stopwatch.ElapsedMilliseconds}ms"); logEntry.AppendLine(new string('-', 50)); // 异步写入日志 _ = Task.Run(async () => { await File.AppendAllTextAsync(logFile, logEntry.ToString()); }); return response; }); } /// <summary> /// 注册消息计数中间件 /// </summary> public static MiddlewareAgent<IAgent> WithMessageCount(this IAgent agent) { // 注意:闭包变量,用于累计统计 int totalMessages = 0; int totalTokens = 0; return agent.RegisterMiddleware(async (msgs, options, nextAgent, ct) => { var inputTokens = msgs.Sum(m => EstimateTokens(m.GetContent())); var response = await nextAgent.GenerateReplyAsync(msgs, options, ct); var outputTokens = EstimateTokens(response.GetContent()); totalMessages++; totalTokens += inputTokens + outputTokens; return response; }); } /// <summary> /// Token 估算(中文按字,英文按词) /// </summary> private static int EstimateTokens(string? content) { if (string.IsNullOrWhiteSpace(content)) return 0; var chineseChars = content.Count(c => c >= 0x4E00 && c <= 0x9FFF); var englishWords = content.Split(new[] { ' ', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries).Length; return chineseChars + englishWords; } } }
Agent工厂
using Applier; using AutoGen; using AutoGen.Core; using AutoGen.OpenAI; using AutoGen.OpenAI.Extension; using OpenAI; using System; using System.ClientModel; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp2 { /// <summary> /// Agent 工厂类 - 统一创建和管理 Agent /// 参考博客:https://www.cnblogs.com/chenwolong/p/22527694 /// </summary> public class AgentFactory { private readonly OpenAIClient _client; public AgentFactory() { // ① 创建 OpenAI 客户端(兼容阿里云百炼) _client = new OpenAIClient( new ApiKeyCredential(ConstParm.apiKey), new OpenAIClientOptions { Endpoint = new Uri(ConstParm.endpoint) }); Console.WriteLine("✅ AgentFactory 初始化完成"); Console.WriteLine($" 使用模型:{ConstParm.modelId}"); } /// <summary> /// 创建 OpenAIChatAgent(调用 LLM) /// 用途:核心对话 Agent,负责调用大模型 /// </summary> public IAgent CreateOpenAIChatAgent( string systemMessage = "你是一个热情友好的 AI 助手,用中文回答用户问题", string agentName = "小助手") { Console.WriteLine($"🔧 创建 OpenAIChatAgent: {agentName}"); var agent = new OpenAIChatAgent( name: agentName, systemMessage: systemMessage, chatClient: _client.GetChatClient(ConstParm.modelId)); // ✅ OpenAIChatAgent 使用专属的 RegisterMessageConnector return agent .RegisterMessageConnector() .RegisterPrintMessage(); } /// <summary> /// 创建 UserProxyAgent(人工介入) /// 用途:人机交互接口,等待用户输入 /// </summary> public IAgent CreateUserProxyAgent( string agentName = "六爷", HumanInputMode humanInputMode = HumanInputMode.ALWAYS) { Console.WriteLine($"🔧 创建 UserProxyAgent: {agentName} (模式:{humanInputMode})"); var agent = new UserProxyAgent( name: agentName, humanInputMode: humanInputMode, defaultReply: ""); // ✅ UserProxyAgent 不需要 RegisterMessageConnector,直接用 RegisterPrintMessage return agent.RegisterPrintMessage(); } } /// <summary> /// Agent 类型枚举 /// 用于工厂方法模式创建不同类型的 Agent /// </summary> public enum AgentType { /// <summary> /// OpenAIChatAgent - 调用 LLM /// </summary> OpenAIChat, /// <summary> /// UserProxyAgent - 人工介入 /// </summary> UserProxy, /// <summary> /// AssistantAgent - 通用助手 /// </summary> Assistant } }
项目引用
<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" /> </ItemGroup> </Project>

浙公网安备 33010602011771号