using System.Text.Json; using MAF1.Tools; using MAF1.Utils; using Microsoft.Agents.AI; using Microsoft.Extensions.AI; namespace MAF1.Agents.FileCity; public static class FileCityAgent { public static AIAgent Create(AgentFactory factory) { return factory.CreateAgent( name: "FileCityAgent", instructions: """ 你负责读取用户指定的本地文件,并从中提取有效城市名。 必须先调用 ReadTextFile 读取文件,不要猜测文件内容。 有效城市名:现实世界中真实存在的城市(如 成都、北京、Amsterdam)。 忽略空行、注释、人名、水果、随意单词等不是城市的内容。 只输出一个 JSON 对象,不要 Markdown,不要其它说明: {"hasValidCities": true, "cities": ["成都"], "reason": "说明"} 若没有有效城市:{"hasValidCities": false, "cities": [], "reason": "原因"} cities 去重,保持文件中的出现顺序。 """, tools: [AIFunctionFactory.Create(FileTools.ReadTextFile)]); } public static async Task RunAsync( AIAgent agent, IReadOnlyDictionary inputs, CancellationToken cancellationToken = default) { string filePath = AgentInputs.ReadString(inputs, "filePath") ?? "Data/cities.txt"; AgentResponse response = await agent.RunAsync( $"请读取这个文件并提取有效城市名:{filePath}", cancellationToken: cancellationToken); CityExtraction extraction = Parse(response.Text); return new AgentStepResult { Message = response.Text, Inputs = new Dictionary { ["filePath"] = filePath }, Outputs = new Dictionary { ["hasValidCities"] = extraction.HasValidCities, ["cities"] = extraction.Cities, ["reason"] = extraction.Reason, ["raw"] = response.Text, }, }; } public static CityExtraction Parse(string text) { try { CityExtraction? result = JsonSerializer.Deserialize( JsonText.UnwrapObject(text), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); if (result is null) { return Invalid("无法解析文件 Agent 的输出。"); } result.Cities = result.Cities .Where(city => !string.IsNullOrWhiteSpace(city)) .Select(city => city.Trim()) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); result.HasValidCities = result.HasValidCities && result.Cities.Count > 0; return result; } catch (JsonException ex) { return Invalid($"文件 Agent 没有返回合法 JSON:{ex.Message}"); } } private static CityExtraction Invalid(string reason) => new() { HasValidCities = false, Reason = reason }; }