Files
MAF1/MAF1.Core/Agents/FileCity/FileCityAgent.cs
T
admin777 950d09ddb0 docs: 为 CLI、网页编排器和插件协议补充学习向注释
在核心类型、图执行器、stdio 插件和前端入口写清职责与对照路径,不改运行行为。
2026-08-28 11:51:48 +08:00

89 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Text.Json;
using MAF1.Tools;
using MAF1.Utils;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
namespace MAF1.Agents.FileCity;
/// <summary>
/// 「读文件抽城市」Agent。学习路径:Create 注册工具和系统提示 → RunAsync 调模型 → Parse 把模型文本收成结构化结果。
/// CLI、网页系统节点、file-city 插件三处都调用同一套逻辑,避免各写一份 prompt。
/// </summary>
public static class FileCityAgent
{
/// <summary>创建带 ReadTextFile 工具的聊天 Agent。模型必须先读文件,不能凭文件名猜内容。</summary>
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)]);
}
/// <summary>跑一轮:读 filePath 输入,把解析后的 cities / hasValidCities 放进 Outputs。</summary>
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,
},
};
}
/// <summary>从模型原文里抠 JSON。模型偶尔会包 Markdown 代码块,所以先走 JsonText.UnwrapObject。</summary>
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 };
}