AutoGen 高并发(限流)、会话隔离、多Agent协助、WorkFlow编排、重试中间件、重试熔断超时中间件
🎯 AutoGen 高并发多 Agent 协作系统 - 架构设计
📐 整体架构图
┌─────────────────────────────────────────────────────────────────────────┐ │ AutoGen 高并发多 Agent 协作系统 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ 用户请求 │ │ ↓ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ L1: RateLimitingService(入口令牌桶限流) │ │ │ │ ├─ ConcurrentDictionary<string, RateLimiter> │ │ │ │ └─ 每用户独立令牌桶(TokenBucket) │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ L2: SemaphoreSlim(系统并发控制) │ │ │ │ └─ 全局信号量(同时最多 5 个请求) │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ L3: GroupChatFactory(Session 隔离)⭐ 核心 │ │ │ │ ├─ ConcurrentDictionary<string, GroupChatManager> │ │ │ │ ├─ 每 Session 独立 Workflow │ │ │ │ └─ 每 Session 独立 Agent 实例 │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ L4: FunctionCallMiddleware(工具限流) │ │ │ │ ├─ 自定义 IMiddleware │ │ │ │ └─ 每工具独立限流(每分钟 N 次) │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ L5: PollyMiddleware(重试 + 熔断 + 超时) │ │ │ │ ├─ 自定义 IMiddleware │ │ │ │ └─ 每工具独立策略(Retry + CircuitBreaker + Timeout) │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ L6: SessionHistoryStore(历史存储隔离) │ │ │ │ ├─ ConcurrentDictionary<string, List<IMessage>> │ │ │ │ └─ 可持久化到 MongoDB/CosmosDB │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ ↓ │ │ GroupChat + Workflow 执行 │ │ UserAgent → WeatherAgent → PlannerAgent → BudgetAgent │ │ │ └─────────────────────────────────────────────────────────────────────────┘
🎯 Workflow 设计(4 Agent 协作)
┌─────────────────────────────────────────────────────────┐ │ 旅行规划 Workflow │ ├─────────────────────────────────────────────────────────┤ │ │ │ UserAgent(用户代理) │ │ ↓ │ │ WeatherAgent(天气查询) │ │ ├─ 调用高德天气 API │ │ └─ 限流:60 次/分钟 │ │ ↓ │ │ PlannerAgent(行程规划) │ │ ├─ 根据天气推荐景点 │ │ └─ 限流:30 次/分钟 │ │ ↓ │ │ BudgetAgent(预算评估) │ │ ├─ 计算交通 + 门票 + 餐饮 │ │ └─ 限流:30 次/分钟 │ │ ↓ │ │ 返回 UserAgent(最终输出) │ │ │ └─────────────────────────────────────────────────────────┘
项目代码
超时/重试/熔断策略--函数/工具级别中间件
using AutoGen.Core; using Microsoft.Extensions.Logging; using Polly; using Polly.CircuitBreaker; using Polly.Timeout; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AutoGenLimit.Middleware { #region 超时/重试/熔断策略--函数/工具级别中间件 /// <summary> /// Polly 策略中间件(重试 + 熔断 + 超时) /// </summary> public static class PollyMiddlewareExtensions { /// <summary> /// 注册 Polly 策略中间件(全局策略) /// </summary> public static MiddlewareAgent<IAgent> WithPolly( this IAgent agent, ILogger? logger = null, int maxRetries = 3, int circuitBreakerThreshold = 5, int timeoutSeconds = 20) { // ✅ 重试:最多 3 次,指数退避 var retryPolicy = Policy .Handle<Exception>() .WaitAndRetryAsync( retryCount: maxRetries, sleepDurationProvider: retry => TimeSpan.FromSeconds(Math.Pow(1.1, retry)), onRetry: (outcome, timeSpan, retryNumber, context) => { logger?.LogWarning( "重试 {Retry}/{Max},等待 {Wait}s,原因:{Error}", retryNumber, maxRetries, timeSpan.TotalSeconds, outcome.GetBaseException()?.Message); }); // ✅ 熔断:连续失败 5 次 → 熔断 30 秒 var circuitBreakerPolicy = Policy .Handle<Exception>() .CircuitBreakerAsync( exceptionsAllowedBeforeBreaking: circuitBreakerThreshold, durationOfBreak: TimeSpan.FromSeconds(30), onBreak: (outcome, timeSpan) => { logger?.LogError("⚠️ 熔断器打开!连续失败 {Count} 次,暂停 {Seconds}s", circuitBreakerThreshold, timeSpan.TotalSeconds); }, onReset: () => { logger?.LogInformation("✅ 熔断器复位,恢复正常"); }); // ✅ 超时:20 秒 var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromSeconds(timeoutSeconds)); // ✅ 组合策略(执行顺序:Timeout → CircuitBreaker → Retry) var policyWrap = Policy.WrapAsync(timeoutPolicy, circuitBreakerPolicy, retryPolicy); return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { try { logger?.LogInformation("🛡️ Polly 执行:{AgentName}", nextAgent.Name); // ✅ 用 Polly 包装执行 return await policyWrap.ExecuteAsync( async () => await nextAgent.GenerateReplyAsync(msgs, options, ct)); } catch (BrokenCircuitException ex) { logger?.LogError("⚡ 熔断触发:{Agent} - {Error}", nextAgent.Name, ex.Message); throw; } catch (TimeoutRejectedException ex) { logger?.LogError("⏱️ 超时触发:{Agent} - {Error}", nextAgent.Name, ex.Message); throw; } catch (Exception ex) { logger?.LogError("❌ Polly 失败:{Agent} - {Error}", nextAgent.Name, ex.Message); throw; } }); } /// <summary> /// 仅注册重试策略(轻量级) /// </summary> public static MiddlewareAgent<IAgent> WithRetry( this IAgent agent, int maxRetries = 3, TimeSpan? delay = null) { delay ??= TimeSpan.FromSeconds(1); var retryPolicy = Policy .Handle<Exception>() .WaitAndRetryAsync( maxRetries, attempt => delay.Value * attempt, onRetry: (exception, timeSpan, retryCount, context) => { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"🔁 重试 {retryCount}/{maxRetries}"); Console.ResetColor(); }); return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { return await retryPolicy.ExecuteAsync( async () => await nextAgent.GenerateReplyAsync(msgs, options, ct)); }); } /// <summary> /// 仅注册超时策略 /// </summary> public static MiddlewareAgent<IAgent> WithTimeout( this IAgent agent, TimeSpan timeout) { var timeoutPolicy = Policy.TimeoutAsync(timeout, TimeoutStrategy.Optimistic); return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { return await timeoutPolicy.ExecuteAsync( async () => await nextAgent.GenerateReplyAsync(msgs, options, ct)); }); } } #endregion }
系统整体流量入口限流服务 - 处理高并发场景 创建和管理限流器 工厂(生产令牌桶)
using AutoGen.Core; using Google.Cloud.Iam.V1; using Microsoft.Extensions.Configuration; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.RateLimiting; using System.Threading.Tasks; namespace AutoGenLimit.Middleware { #region 系统整体流量入口限流服务 - 处理高并发场景 创建和管理限流器 工厂(生产令牌桶) /// <summary> /// 系统整体/流量入口级限流服务【限制的同时允许多少人可以访问系统,令牌的补充机制】 /// </summary> public class RateLimitingService { private readonly ConcurrentDictionary<string, RateLimiter> _limiters = new(); private readonly int _tokenLimit; private readonly int _tokensPerPeriodCount; public RateLimitingService() { _tokenLimit = 5; _tokensPerPeriodCount = 2; } public async Task<bool> TryAcquireAsync(string sessionId) { var limiter = _limiters.GetOrAdd(sessionId, _ => new TokenBucketRateLimiter(new() { TokenLimit = _tokenLimit, // 桶容量 TokensPerPeriod = _tokensPerPeriodCount, // 每次补充数量 ReplenishmentPeriod = TimeSpan.FromSeconds(1), // 补充周期 QueueLimit = 5, // ✅ 队列上限:最多排 5 个请求 QueueProcessingOrder = QueueProcessingOrder.OldestFirst, // 先到先得 AutoReplenishment = true // ✅ 自动补充:定时器自动补 })); using var lease = await limiter.AcquireAsync(1); return lease.IsAcquired; } public RateLimiter GetLimiter(string sessionId) { return _limiters.GetOrAdd(sessionId, _ => new TokenBucketRateLimiter(new() { TokenLimit = _tokenLimit, TokensPerPeriod = _tokensPerPeriodCount, ReplenishmentPeriod = TimeSpan.FromSeconds(1), QueueLimit = 5, QueueProcessingOrder = QueueProcessingOrder.OldestFirst, AutoReplenishment = true })); } public void RemoveLimiter(string sessionId) { if (_limiters.TryRemove(sessionId, out var limiter)) { limiter.Dispose(); Console.WriteLine($"[RateLimitingService] 移除 Session {sessionId} 的限流器"); } } } #endregion #region 函数/工具级限流组件 /// <summary> /// 函数/工具级限流中间件(扩展方法模式) /// </summary> public static class RateLimitMiddlewareExtensions { /// <summary> /// 注册工具调用限流中间件 /// </summary> public static MiddlewareAgent<IAgent> WithRateLimiting( this IAgent agent, RateLimiter rateLimiter, string toolName) { return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { // 检查消息中是否有工具调用 var hasToolCall = msgs.Any(m => m is ToolCallMessage toolCallMsg && toolCallMsg.ToolCalls.Any(tc => tc.FunctionName == toolName)); if (hasToolCall) { // ✅ 修复:使用 AttemptAcquire 立即返回,不等待 using var lease = rateLimiter.AttemptAcquire(1); if (!lease.IsAcquired) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"🚫 触发限流:{toolName}"); Console.ResetColor(); throw new RateLimitExceededException( $"🚫 工具调用频率超限:{toolName}"); } Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine($"🚦 限流通过:{toolName}"); Console.ResetColor(); } return await nextAgent.GenerateReplyAsync(msgs, options, ct); }); } /// <summary> /// 注册全局限流中间件(不限工具类型) /// </summary> public static MiddlewareAgent<IAgent> WithGlobalRateLimiting( this IAgent agent, RateLimiter rateLimiter) { return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { using var lease = rateLimiter.AttemptAcquire(1); if (!lease.IsAcquired) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"🚫 触发全局限流"); Console.ResetColor(); throw new RateLimitExceededException("🚫 全局请求频率超限,请稍后重试"); } return await nextAgent.GenerateReplyAsync(msgs, options, ct); }); } } /// <summary> /// 限流异常 /// </summary> public class RateLimitExceededException : Exception { public RateLimitExceededException(string message) : base(message) { } } #endregion }
注册时间戳中间件(记录响应时长)
using AutoGen.Core; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AutoGenLimit.Middleware { public static class TimestampLoggingMiddlewareExtensions { /// <summary> /// 注册时间戳中间件(记录响应时长) /// </summary> public static MiddlewareAgent<IAgent> WithTimestamp(this IAgent agent) { return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { var timestampRequest = DateTime.Now; Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine($"[{timestampRequest:HH:mm:ss.fff}] ⬇️ {nextAgent.Name} 收到 {msgs.Count()} 条消息"); Console.ResetColor(); var response = await nextAgent.GenerateReplyAsync(msgs, options, ct); var timestampResponse = DateTime.Now; Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine($"[{timestampResponse:HH:mm:ss.fff}] ⬆️ {nextAgent.Name} 发送响应"); Console.WriteLine($" 响应时长:{(timestampResponse - timestampRequest).TotalMilliseconds}ms"); Console.ResetColor(); return response; }); } /// <summary> /// 注册日志中间件(写入日志文件) /// </summary> public static MiddlewareAgent<IAgent> WithLogging( this IAgent agent, string logFile = "agent_logs.txt") { return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { var logEntry = new StringBuilder(); logEntry.AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Agent: {nextAgent.Name}"); logEntry.AppendLine($" 消息数量:{msgs.Count()}"); var stopwatch = 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> /// 注册消息计数中间件(统计 Token) /// </summary> public static MiddlewareAgent<IAgent> WithMessageCount(this IAgent agent) { // ✅ 闭包变量在 lambda 外部初始化(累计统计) int totalMessages = 0; int totalTokens = 0; return agent.RegisterMiddleware<IAgent>(async (msgs, options, nextAgent, ct) => { // ✅ 先拼接所有消息内容,再估算 Token var allContent = string.Join(" ", msgs.Select(m => m.GetContent())); var inputTokens = EstimateTokens(allContent); var response = await nextAgent.GenerateReplyAsync(msgs, options, ct); var outputTokens = EstimateTokens(response.GetContent()); totalMessages++; totalTokens += inputTokens + outputTokens; Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($"📊 累计消息:{totalMessages} | 估算 Token: {totalTokens}"); Console.ResetColor(); return response; }); } 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; } } }
用户会话、会话隔离核心工厂
using Applier; using AutoGen; using AutoGen.Core; using AutoGen.OpenAI; using AutoGen.OpenAI.Extension; using AutoGenLimit.Middleware; using Microsoft.Extensions.Configuration; using OpenAI; using System; using System.ClientModel; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace AutoGenLimit { #region 用户会话、会话隔离核心工厂 /// <summary> /// GroupChat 工厂类 - 实现 Session 隔离 /// 每 Session 独立的 GroupChatManager + Workflow + Agent 实例 /// </summary> public class GroupChatFactory { private readonly ConcurrentDictionary<string, GroupChatManager> _managers = new(); private readonly string _apiKey; private readonly string _endpoint; private readonly string _modelId; private readonly RateLimitingService _rateLimitingService; private readonly HttpClient _httpClient; private readonly string _amapApiKey; public GroupChatFactory( RateLimitingService rateLimitingService) { _apiKey = ConstParm.apiKey; _endpoint = ConstParm.endpoint; _modelId = ConstParm.modelId ?? "qwen-plus"; _rateLimitingService = rateLimitingService; _httpClient = new HttpClient(); _amapApiKey = ConstParm.amapApiKey!; Console.WriteLine("✅ GroupChatFactory 初始化完成"); Console.WriteLine($" 使用模型:{_modelId}"); } /// <summary> /// 获取或创建 GroupChatManager(自动创建 Workflow) /// </summary> public GroupChatManager GetOrCreateGroupChat(string sessionKey) { return _managers.GetOrAdd(sessionKey, key => { Console.WriteLine($"[GroupChatFactory] Creating GroupChat for Session: {key}"); // ① 创建每 Session 独立的 Agent var userAgent = CreateUserAgent(key); var weatherAgent = CreateWeatherAgent(key); var plannerAgent = CreatePlannerAgent(key); var budgetAgent = CreateBudgetAgent(key); // ② 定义 Workflow(固定业务流程) var workflow = new Graph(); workflow.AddTransition(Transition.Create(userAgent, weatherAgent)); workflow.AddTransition(Transition.Create(weatherAgent, plannerAgent)); workflow.AddTransition(Transition.Create(plannerAgent, budgetAgent)); workflow.AddTransition(Transition.Create(budgetAgent, userAgent)); // ③ 创建 GroupChat var groupChat = new GroupChat( members: new[] { userAgent, weatherAgent, plannerAgent, budgetAgent }, workflow: workflow); return new GroupChatManager(groupChat); }); } /// <summary> /// 移除 Session 的 GroupChat(清理资源) /// </summary> public void RemoveGroupChat(string sessionKey) { if (_managers.TryRemove(sessionKey, out _)) { Console.WriteLine($"[GroupChatFactory] Removed GroupChat for Session: {sessionKey}"); } } #region Agent 创建方法 /// <summary> /// 创建用户代理(Human-in-the-loop) /// </summary> private IAgent CreateUserAgent(string sessionKey) { var userProxy = new UserProxyAgent( name: $"User-{sessionKey}", humanInputMode: HumanInputMode.NEVER); return userProxy .RegisterPrintMessage(); // ✅ 返回 MiddlewareAgent<IAgent>,隐式转换为 IAgent } /// <summary> /// 创建天气查询 Agent(带限流 + Polly) /// </summary> private IAgent CreateWeatherAgent(string sessionKey) { // 获取该 Session 的限流器(每 Session 独立) var limiter = _rateLimitingService.GetLimiter(sessionKey); var client = new OpenAIClient( new ApiKeyCredential(_apiKey), new OpenAIClientOptions { Endpoint = new Uri(_endpoint) }); var weatherTool = new WeatherTool(_httpClient, _amapApiKey); var functionContract = new FunctionContract { Name = "GetWeatherAsync", Description = "获取指定城市的实时天气信息", Parameters = new List<FunctionParameterContract> { new FunctionParameterContract { Name = "city", Description = "城市名称,如:北京、上海", IsRequired = true, ParameterType = typeof(string) } } }; var functionMap = new Dictionary<string, Func<string, Task<string>>> { { functionContract.Name, async (args) => { var city = JsonDocument.Parse(args) .RootElement.GetProperty("city").GetString(); return await weatherTool.GetWeatherAsync(city!); } } }; var functionCallMiddleware = new FunctionCallMiddleware( functions: new[] { functionContract }, functionMap: functionMap); var agent = new OpenAIChatAgent( name: $"WeatherAgent-{sessionKey}", systemMessage: "你是专业天气预报分析师。当用户询问天气时,必须调用 GetWeatherAsync 函数获取真实数据。", chatClient: client.GetChatClient(_modelId)); // ✅ 链式注册中间件(限流 + Polly) return agent .RegisterMessageConnector() .RegisterMiddleware(functionCallMiddleware) .WithRateLimiting(limiter, "GetWeatherAsync") // ⭐ L3 工具限流 .WithPolly(maxRetries: 3, timeoutSeconds: 30) // ⭐ L5 Polly 策略 .RegisterPrintMessage(); } /// <summary> /// 创建行程规划 Agent /// </summary> private IAgent CreatePlannerAgent(string sessionKey) { var limiter = _rateLimitingService.GetLimiter(sessionKey); var client = new OpenAIClient( new ApiKeyCredential(_apiKey), new OpenAIClientOptions { Endpoint = new Uri(_endpoint) }); var plannerTool = new TravelPlannerTool(); var functionContract = new FunctionContract { Name = "PlanTravel", Description = "根据天气情况推荐旅游行程", Parameters = new List<FunctionParameterContract> { new FunctionParameterContract { Name = "city", Description = "城市名称", IsRequired = true, ParameterType = typeof(string) }, new FunctionParameterContract { Name = "weather", Description = "天气状况", IsRequired = true, ParameterType = typeof(string) }, new FunctionParameterContract { Name = "temperature", Description = "温度(摄氏度)", IsRequired = true, ParameterType = typeof(int) } } }; var functionMap = new Dictionary<string, Func<string, Task<string>>> { { functionContract.Name, async (args) => { var json = JsonDocument.Parse(args); var city = json.RootElement.GetProperty("city").GetString(); var weather = json.RootElement.GetProperty("weather").GetString(); var temperature = json.RootElement.GetProperty("temperature").GetInt32(); return plannerTool.PlanTravel(city!, weather!, temperature); } } }; var functionCallMiddleware = new FunctionCallMiddleware( functions: new[] { functionContract }, functionMap: functionMap); var agent = new OpenAIChatAgent( name: $"PlannerAgent-{sessionKey}", systemMessage: "你是专业旅游规划师。根据天气情况推荐合适的行程。", chatClient: client.GetChatClient(_modelId)); return agent .RegisterMessageConnector() .RegisterMiddleware(functionCallMiddleware) .WithRateLimiting(limiter, "PlanTravel") .WithPolly(maxRetries: 3, timeoutSeconds: 30) .RegisterPrintMessage(); } /// <summary> /// 创建预算评估 Agent /// </summary> private IAgent CreateBudgetAgent(string sessionKey) { var limiter = _rateLimitingService.GetLimiter(sessionKey); var client = new OpenAIClient( new ApiKeyCredential(_apiKey), new OpenAIClientOptions { Endpoint = new Uri(_endpoint) }); var budgetTool = new BudgetCalculatorTool(); var functionContract = new FunctionContract { Name = "CalculateBudget", Description = "计算旅行预算(交通 + 门票 + 餐饮)", Parameters = new List<FunctionParameterContract> { new FunctionParameterContract { Name = "city", Description = "城市名称", IsRequired = true, ParameterType = typeof(string) }, new FunctionParameterContract { Name = "days", Description = "游玩天数", IsRequired = true, ParameterType = typeof(int) }, new FunctionParameterContract { Name = "people", Description = "人数", IsRequired = true, ParameterType = typeof(int) } } }; var functionMap = new Dictionary<string, Func<string, Task<string>>> { { functionContract.Name, async (args) => { var json = JsonDocument.Parse(args); var city = json.RootElement.GetProperty("city").GetString(); var days = json.RootElement.GetProperty("days").GetInt32(); var people = json.RootElement.GetProperty("people").GetInt32(); return budgetTool.CalculateBudget(city!, days, people); } } }; var functionCallMiddleware = new FunctionCallMiddleware( functions: new[] { functionContract }, functionMap: functionMap); var agent = new OpenAIChatAgent( name: $"BudgetAgent-{sessionKey}", systemMessage: "你是专业预算评估师。计算旅行的交通、门票、餐饮费用。", chatClient: client.GetChatClient(_modelId)); return agent .RegisterMessageConnector() .RegisterMiddleware(functionCallMiddleware) .WithRateLimiting(limiter, "CalculateBudget") .WithPolly(maxRetries: 3, timeoutSeconds: 30) .RegisterPrintMessage(); } #endregion } #endregion }
并发控制器(L2 系统并发控制)
全局信号量,限制同时执行的请求数
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AutoGenLimit { /// <summary> /// 并发控制器(L2 系统并发控制) /// 全局信号量,限制同时执行的请求数 /// </summary> public static class ConcurrencyController { private static readonly SemaphoreSlim _semaphore = new(5, 5); private static int _currentCount = 0; /// <summary> /// 执行带并发限制的操作(无返回值) /// </summary> public static async Task ExecuteWithLimitAsync(Func<Task> action) // ✅ 无返回值版本 { await _semaphore.WaitAsync(); var newCount = Interlocked.Increment(ref _currentCount); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($"[并发控制] 进入请求,当前并发:{newCount}/5"); Console.ResetColor(); try { await action(); } finally { var remainingCount = Interlocked.Decrement(ref _currentCount); _semaphore.Release(); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($"[并发控制] 释放请求,当前并发:{remainingCount}/5"); Console.ResetColor(); } } /// <summary> /// 执行带并发限制的操作(有返回值) /// </summary> public static async Task<T> ExecuteWithLimitAsync<T>(Func<Task<T>> action) { await _semaphore.WaitAsync(); var newCount = Interlocked.Increment(ref _currentCount); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($"[并发控制] 进入请求,当前并发:{newCount}/5"); Console.ResetColor(); try { return await action(); } finally { var remainingCount = Interlocked.Decrement(ref _currentCount); _semaphore.Release(); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($"[并发控制] 释放请求,当前并发:{remainingCount}/5"); Console.ResetColor(); } } public static int GetCurrentConcurrency() => _currentCount; public static int GetAvailableSlots() => 5 - _currentCount; } }
工具 functionCall
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace AutoGenLimit { /// <summary> /// 天气查询助手 /// </summary> public class WeatherTool { private readonly HttpClient _httpClient; private readonly string _apiKey; public WeatherTool(HttpClient httpClient, string apiKey) { _httpClient = httpClient; _apiKey = apiKey; } public async Task<string> GetWeatherAsync(string city) { try { // ① 查城市 ADCode var adcodeUrl = $"https://restapi.amap.com/v3/config/district?keywords={city}&subdistrict=0&key={_apiKey}"; var adcodeData = await _httpClient.GetStringAsync(adcodeUrl); var adcodeJson = JsonDocument.Parse(adcodeData); if (adcodeJson.RootElement.GetProperty("status").GetString() != "1") { return $"❌ 未找到城市:{city}"; } var adcode = adcodeJson.RootElement.GetProperty("districts")[0] .GetProperty("adcode").GetString(); // ② 查实时天气 var weatherUrl = $"https://restapi.amap.com/v3/weather/weatherInfo?city={adcode}&key={_apiKey}"; var weatherData = await _httpClient.GetStringAsync(weatherUrl); var weatherJson = JsonDocument.Parse(weatherData); if (weatherJson.RootElement.GetProperty("status").GetString() != "1") { return $"❌ 天气查询失败:{city}"; } var info = weatherJson.RootElement.GetProperty("lives")[0]; var result = new { city = info.GetProperty("city").GetString(), weather = info.GetProperty("weather").GetString(), temperature = info.GetProperty("temperature").GetString(), humidity = info.GetProperty("humidity").GetString(), windDirection = info.GetProperty("winddirection").GetString(), windPower = info.GetProperty("windpower").GetString(), reportTime = info.GetProperty("reporttime").GetString() }; return JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true }); } catch (Exception ex) { return $"❌ 错误:{ex.Message}"; } } } /// <summary> /// 行程规划助手 /// </summary> public class TravelPlannerTool { public string PlanTravel(string city, string weather, int temperature, int days = 1) { var recommendations = new List<string>(); // 根据天气推荐 if (weather.Contains("晴") || weather.Contains("多云")) { recommendations.Add("✅ 适合户外活动"); recommendations.Add($"- 推荐景点:{city}园林、古镇、湖边散步"); recommendations.Add("- 建议穿薄外套,带防晒霜"); } else if (weather.Contains("雨")) { recommendations.Add("☔ 建议室内活动"); recommendations.Add($"- 推荐景点:{city}博物馆、美术馆、购物中心"); recommendations.Add("- 记得带伞,穿防水鞋"); } else { recommendations.Add("⚠️ 天气一般,灵活安排"); recommendations.Add("- 准备室内外两套方案"); } // 根据温度推荐 if (temperature < 10) { recommendations.Add("🥶 天气较冷,注意保暖"); } else if (temperature > 30) { recommendations.Add("☀️ 天气炎热,注意防暑"); } return string.Join("\n", recommendations); } } public class BudgetCalculatorTool { // ✅ 提取为静态常量 private static readonly string[] FirstTierCities = { "北京", "上海", "广州", "深圳" }; private static readonly int BaseMinBudget = 300; // 基础最低预算/人/天 private static readonly int BaseMaxBudget = 1000; // 基础最高预算/人/天 private static readonly int FirstTierMinBudget = 500; // 一线城市最低预算 private static readonly int FirstTierMaxBudget = 1500; // 一线城市最高预算 public string CalculateBudget(string city, int days, int people) { // ✅ 使用 LINQ 判断 var isFirstTier = FirstTierCities.Any(city.Contains); var minBudget = isFirstTier ? FirstTierMinBudget : BaseMinBudget; var maxBudget = isFirstTier ? FirstTierMaxBudget : BaseMaxBudget; var minMoney = people * days * minBudget; var maxMoney = people * days * maxBudget; return $"大约花费{minMoney}~{maxMoney}元"; } } }
Main.cs
using AutoGen; using AutoGen.Core; using AutoGenLimit.Middleware; using Microsoft.Extensions.Configuration; namespace AutoGenLimit { class Program { static async Task Main(string[] args) { Console.OutputEncoding = System.Text.Encoding.Unicode; Console.InputEncoding = System.Text.Encoding.Unicode; Console.WriteLine("🤖 AutoGen Workflow 多 Agent 协作系统 - 高并发限流版"); Console.WriteLine("=====================================================\n"); // ② 初始化 L1 入口限流服务(令牌桶) var rateLimitingService = new RateLimitingService(); Console.WriteLine($"✅ RateLimitingService 初始化完成"); // ③ 初始化 L3 Session 隔离工厂 var groupChatFactory = new GroupChatFactory(rateLimitingService); Console.WriteLine("========================================"); Console.WriteLine("🌍 旅行咨询智能体已就绪!"); Console.WriteLine("💬 输入旅行计划,如:"); Console.WriteLine(" - 我想明天去北京玩 3 天,有什么建议?"); Console.WriteLine(" - 上海天气怎么样?帮我规划一下行程"); Console.WriteLine("输入 'quit' 退出\n"); Console.WriteLine("========================================\n"); // ④ 主循环(处理用户输入) while (true) { Console.Write("👤 你:"); var input = Console.ReadLine(); if (string.IsNullOrWhiteSpace(input) || input.ToLower() == "quit") { Console.WriteLine("\n👋 再见!"); break; } // ⑤ 生成 Session ID(每用户独立) var sessionId = Guid.NewGuid().ToString("N")[..8]; // 8 位短 ID Console.WriteLine($"[Session] {sessionId}\n"); try { // ⑥ L1 入口限流检查 if (!await rateLimitingService.TryAcquireAsync(sessionId)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("🚫 限流:请求太多,请稍后重试"); Console.ResetColor(); continue; } // ⑦ L2 并发控制执行 // L2 并发控制执行 await ConcurrencyController.ExecuteWithLimitAsync(async () => { var groupChatManager = groupChatFactory.GetOrCreateGroupChat(sessionId); Console.WriteLine("\n🔄 智能体正在协作处理...\n"); var userProxy = new UserProxyAgent( name: $"User-{sessionId}", humanInputMode: HumanInputMode.NEVER); var chatHistory = new List<IMessage> { new TextMessage(Role.User, input, from: $"User-{sessionId}") }; var response = await userProxy.InitiateChatAsync( receiver: groupChatManager, message: input, maxRound: 4); Console.WriteLine("\n========================================"); Console.WriteLine("💬 对话记录:"); Console.WriteLine("========================================\n"); foreach (var message in response) { Console.WriteLine($"【{message.From}】: {message.GetContent()}\n"); } Console.WriteLine("\n✅ 处理完成\n"); }); } catch (RateLimitExceededException ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"🚫 限流异常:{ex.Message}\n"); Console.ResetColor(); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"❌ 异常:{ex.Message}\n"); Console.ResetColor(); } } } } }
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <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="Polly" Version="8.4.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> <PackageReference Include="System.Threading.RateLimiting" 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>

浙公网安备 33010602011771号