Files
admin777 b0e89b6092 feat: 新增方案 C 的 Handoff 路由宿主,并让抽城市支持自然语言。
把图 JSON 编译成 CreateHandoffBuilderWith + WithHandoff;Agent 固定 Id 以免交接工具名错位;DeepSeek 关闭 thinking,避免多轮丢掉 reasoning_content 导致 400。
2026-09-01 17:56:41 +08:00

64 lines
2.4 KiB
C#

using MAF1.Core.Agents;
using MAF1.Tools;
using MAF1.Utils;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
namespace MAF1.Agents.Weather;
/// <summary>
/// 「按城市查天气」Agent。真正的 HTTP 查询在 WeatherTools.GetWeather,模型只负责决定调几次工具并写成中文摘要。
/// </summary>
public static class WeatherAgent
{
public const string DefaultDescription = "按城市列表查询天气并汇总。";
/// <summary>创建带 GetWeather 工具的 Agent。instructions 要求每个城市都调工具,禁止编造气温。</summary>
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)]);
}
/// <summary>需要上游把 cities 连到本节点。空列表直接抛错,避免无意义地打 LLM。</summary>
public static async Task<AgentStepResult> RunAsync(
AIAgent agent,
IReadOnlyDictionary<string, object?> inputs,
CancellationToken cancellationToken = default)
{
List<string> 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<string, object?> { ["cities"] = cities },
Outputs = new Dictionary<string, object?> { ["summary"] = response.Text },
};
}
}