82 lines
3.1 KiB
C#
82 lines
3.1 KiB
C#
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<AgentStepResult> RunAsync(
|
|||
|
|
AIAgent agent,
|
|||
|
|
IReadOnlyDictionary<string, object?> 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<string, object?> { ["filePath"] = filePath },
|
|||
|
|
Outputs = new Dictionary<string, object?>
|
|||
|
|
{
|
|||
|
|
["hasValidCities"] = extraction.HasValidCities,
|
|||
|
|
["cities"] = extraction.Cities,
|
|||
|
|
["reason"] = extraction.Reason,
|
|||
|
|
["raw"] = response.Text,
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static CityExtraction Parse(string text)
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
CityExtraction? result = JsonSerializer.Deserialize<CityExtraction>(
|
|||
|
|
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 };
|
|||
|
|
}
|