using MAF1.Core.Agents; using MAF1.Tools; using MAF1.Utils; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; namespace MAF1.Agents.Weather; /// /// 「按城市查天气」Agent。真正的 HTTP 查询在 WeatherTools.GetWeather,模型只负责决定调几次工具并写成中文摘要。 /// public static class WeatherAgent { public const string DefaultDescription = "按城市列表查询天气并汇总。"; /// 创建带 GetWeather 工具的 Agent。instructions 要求每个城市都调工具,禁止编造气温。 public static AIAgent Create( AgentFactory factory, WeatherTools weatherTools, string name = "WeatherAgent", string? description = null, string? extraInstructions = null) { string instructions = """ 你负责查询天气。用户给出的每个城市都必须调用一次 GetWeather,不要编造天气。 用中文汇总所有城市的天气。 """; if (!string.IsNullOrWhiteSpace(extraInstructions)) { instructions = instructions + "\n" + extraInstructions; } return factory.CreateAgent( name: name, instructions: instructions, description: string.IsNullOrWhiteSpace(description) ? DefaultDescription : description, tools: [AIFunctionFactory.Create(weatherTools.GetWeather)]); } /// 需要上游把 cities 连到本节点。空列表直接抛错,避免无意义地打 LLM。 public static async Task RunAsync( AIAgent agent, IReadOnlyDictionary inputs, CancellationToken cancellationToken = default) { List cities = AgentInputs.ReadStringList(inputs, "cities"); if (cities.Count == 0) { throw new InvalidOperationException("输入 cities 为空。请把上一节点的 cities 连到本节点的 cities。"); } AgentResponse response = await agent.RunAsync( $"请查询这些城市的天气:{string.Join("、", cities)}", cancellationToken: cancellationToken); return new AgentStepResult { Message = response.Text, Inputs = new Dictionary { ["cities"] = cities }, Outputs = new Dictionary { ["summary"] = response.Text }, }; } }