218 lines
6.1 KiB
C#
218 lines
6.1 KiB
C#
using System.Diagnostics;
|
||
using Microsoft.Extensions.Logging;
|
||
|
||
namespace Service.AgentFramework;
|
||
|
||
/// <summary>
|
||
/// Agent 基类 - 提供通用的工作流编排能力
|
||
/// </summary>
|
||
public abstract class BaseAgent
|
||
{
|
||
protected readonly IToolRegistry _toolRegistry;
|
||
protected readonly ILogger<BaseAgent> _logger;
|
||
protected readonly List<ExecutionStep> _steps = new();
|
||
protected readonly Dictionary<string, object?> _metadata = new();
|
||
|
||
// 定义 ActivitySource 供 DevUI 捕获
|
||
private static readonly ActivitySource _activitySource = new("Microsoft.Agents.Workflows");
|
||
|
||
protected BaseAgent(
|
||
IToolRegistry toolRegistry,
|
||
ILogger<BaseAgent> logger)
|
||
{
|
||
_toolRegistry = toolRegistry;
|
||
_logger = logger;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 记录执行步骤
|
||
/// </summary>
|
||
protected void RecordStep(
|
||
string name,
|
||
string description,
|
||
object? output = null,
|
||
long durationMs = 0)
|
||
{
|
||
var step = new ExecutionStep
|
||
{
|
||
Name = name,
|
||
Description = description,
|
||
Status = "Completed",
|
||
Output = output,
|
||
DurationMs = durationMs
|
||
};
|
||
|
||
_steps.Add(step);
|
||
|
||
// 使用 Activity 进行埋点,将被 DevUI 自动捕获
|
||
using var activity = _activitySource.StartActivity(name);
|
||
activity?.SetTag("agent.step.description", description);
|
||
if (output != null) activity?.SetTag("agent.step.output", output.ToString());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 记录失败的步骤
|
||
/// </summary>
|
||
protected void RecordFailedStep(
|
||
string name,
|
||
string description,
|
||
string error,
|
||
long durationMs = 0)
|
||
{
|
||
var step = new ExecutionStep
|
||
{
|
||
Name = name,
|
||
Description = description,
|
||
Status = "Failed",
|
||
Error = error,
|
||
DurationMs = durationMs
|
||
};
|
||
|
||
_steps.Add(step);
|
||
|
||
using var activity = _activitySource.StartActivity($"{name} (Failed)");
|
||
activity?.SetTag("agent.step.error", error);
|
||
_logger.LogError("[Agent步骤失败] {StepName}: {Error}", name, error);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置元数据
|
||
/// </summary>
|
||
protected void SetMetadata(string key, object? value)
|
||
{
|
||
_metadata[key] = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取执行日志
|
||
/// </summary>
|
||
protected List<ExecutionStep> GetExecutionLog()
|
||
{
|
||
return _steps.ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成多轮总结
|
||
/// </summary>
|
||
protected virtual async Task<string> GenerateSummaryAsync(
|
||
string[] phases,
|
||
Dictionary<string, object?> phaseResults)
|
||
{
|
||
var summaryParts = new List<string>();
|
||
|
||
// 简单的总结生成逻辑
|
||
// 实际项目中可以集成 AI 生成更复杂的总结
|
||
foreach (var phase in phases)
|
||
{
|
||
if (phaseResults.TryGetValue(phase, out var result))
|
||
{
|
||
summaryParts.Add($"{phase}:已完成");
|
||
}
|
||
}
|
||
|
||
return await Task.FromResult(string.Join(";", summaryParts) + "。");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调用 Tool(简化接口)
|
||
/// </summary>
|
||
protected async Task<TResult> CallToolAsync<TResult>(
|
||
string toolName,
|
||
string stepName,
|
||
string stepDescription)
|
||
{
|
||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||
try
|
||
{
|
||
_logger.LogInformation("开始执行 Tool: {ToolName}", toolName);
|
||
var result = await _toolRegistry.InvokeToolAsync<TResult>(toolName);
|
||
sw.Stop();
|
||
|
||
RecordStep(stepName, stepDescription, result, sw.ElapsedMilliseconds);
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
sw.Stop();
|
||
RecordFailedStep(stepName, stepDescription, ex.Message, sw.ElapsedMilliseconds);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调用带参数的 Tool
|
||
/// </summary>
|
||
protected async Task<TResult> CallToolAsync<TParam, TResult>(
|
||
string toolName,
|
||
TParam param,
|
||
string stepName,
|
||
string stepDescription)
|
||
{
|
||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||
try
|
||
{
|
||
_logger.LogInformation("开始执行 Tool: {ToolName},参数: {Param}", toolName, param);
|
||
var result = await _toolRegistry.InvokeToolAsync<TParam, TResult>(toolName, param);
|
||
sw.Stop();
|
||
|
||
RecordStep(stepName, stepDescription, result, sw.ElapsedMilliseconds);
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
sw.Stop();
|
||
RecordFailedStep(stepName, stepDescription, ex.Message, sw.ElapsedMilliseconds);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调用带多参数的 Tool
|
||
/// </summary>
|
||
protected async Task<TResult> CallToolAsync<TParam1, TParam2, TResult>(
|
||
string toolName,
|
||
TParam1 param1,
|
||
TParam2 param2,
|
||
string stepName,
|
||
string stepDescription)
|
||
{
|
||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||
try
|
||
{
|
||
_logger.LogInformation("开始执行 Tool: {ToolName},参数: {Param1}, {Param2}", toolName, param1, param2);
|
||
var result = await _toolRegistry.InvokeToolAsync<TParam1, TParam2, TResult>(
|
||
toolName, param1, param2);
|
||
sw.Stop();
|
||
|
||
RecordStep(stepName, stepDescription, result, sw.ElapsedMilliseconds);
|
||
return result;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
sw.Stop();
|
||
RecordFailedStep(stepName, stepDescription, ex.Message, sw.ElapsedMilliseconds);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取 Agent 执行结果
|
||
/// </summary>
|
||
protected AgentResult<T> CreateResult<T>(
|
||
T data,
|
||
string summary,
|
||
bool success = true,
|
||
string? error = null)
|
||
{
|
||
return new AgentResult<T>
|
||
{
|
||
Data = data,
|
||
Summary = summary,
|
||
Steps = _steps,
|
||
Metadata = _metadata,
|
||
Success = success,
|
||
Error = error
|
||
};
|
||
}
|
||
}
|