十四、成本与性能优化:把 Token 和延迟降下来
十四、成本与性能优化:把 Token 和延迟降下来
Agent Framework 工程实战系列
本篇定位
这一篇解决的问题是:在效果可接受前提下压缩成本和延迟。
我按真实项目的推进顺序来写,尽量把“为什么这么做”和“怎么落地”都讲清楚。
学习目标
- 把 CostPerformance 这块的职责边界说清楚。
- 给出能直接照着改的 C# 示例。
- 把上线前最容易漏掉的点提前补上。
- 补齐可复用的测试样例,方便放进 CI 做回归。
场景约束
- 团队技术栈:
.NET 8 + ASP.NET Core + xUnit。 - 运行环境:容器化部署,日志走标准输出。
- 交付目标:先稳定,再追求花哨能力。
- 质量底线:错误可定位、行为可解释、风险可回滚。
架构设计
先把边界划清楚,再谈实现细节。这里用四层结构来组织:
Application:业务编排与用例入口。Domain:规则和核心模型。Infrastructure:外部依赖、存储、网络访问。Observability:日志、指标、追踪和告警。
实际执行时,建议按“先校验输入,再执行业务,最后统一返回和兜底”来走,排查问题会轻松很多。
目录建议
src/
CostPerformance/
Api/
Application/
Domain/
Infrastructure/
Observability/
Program.cs
tests/
CostPerformance.Tests/
核心实现(C#)
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace CostPerformance;
public sealed record AgentRequest(
string SessionId,
string UserId,
string Query,
Dictionary<string, string>? Metadata = null);
public sealed record AgentResponse(
bool Success,
string Message,
string? ErrorCode = null,
Dictionary<string, object>? Data = null,
string? TraceId = null);
public interface IRequestValidator
{
void EnsureAllowed(AgentRequest request);
}
public interface IExecutor
{
Task<Dictionary<string, object>> ExecuteAsync(AgentRequest request, CancellationToken ct = default);
}
public interface IResponseMapper
{
AgentResponse Compose(AgentRequest request, Dictionary<string, object> result, string traceId);
}
public sealed class RequestValidator : IRequestValidator
{
public void EnsureAllowed(AgentRequest request)
{
if (string.IsNullOrWhiteSpace(request.SessionId))
throw new ArgumentException("sessionId 不能为空");
if (string.IsNullOrWhiteSpace(request.UserId))
throw new ArgumentException("userId 不能为空");
if (string.IsNullOrWhiteSpace(request.Query))
throw new ArgumentException("query 不能为空");
if (request.Query.Length > 2000)
throw new ArgumentException("query 长度超出限制");
}
}
public sealed class CostPerformanceExecutor : IExecutor
{
private readonly ILogger<CostPerformanceExecutor> _logger;
public CostPerformanceExecutor(ILogger<CostPerformanceExecutor> logger)
{
_logger = logger;
}
public async Task<Dictionary<string, object>> ExecuteAsync(AgentRequest request, CancellationToken ct = default)
{
var sw = Stopwatch.StartNew();
// 示例里先用 Task.Delay 模拟一次 I/O,接入真实系统时换成 API/仓储调用。
await Task.Delay(25, ct);
var output = new Dictionary<string, object>
{
["topic"] = "CostPerformance",
["query"] = request.Query,
["status"] = "ok",
["handler"] = "CostPerformanceExecutor",
["timestamp"] = DateTimeOffset.UtcNow,
["hints"] = new[]
{
"先给可执行结论",
"把关键前置条件写清楚",
"失败时给下一步处理建议"
}
};
sw.Stop();
_logger.LogInformation("execute finished topic={Topic} costMs={CostMs}", "CostPerformance", sw.ElapsedMilliseconds);
output["costMs"] = sw.ElapsedMilliseconds;
return output;
}
}
public sealed class ResponseMapper : IResponseMapper
{
public AgentResponse Compose(AgentRequest request, Dictionary<string, object> result, string traceId)
{
var summary = $"这次请求已经处理完成(主题:CostPerformance),原始问题:{request.Query}";
return new AgentResponse(
Success: true,
Message: summary,
Data: result,
TraceId: traceId
);
}
}
public sealed class AgentOrchestrator
{
private readonly IRequestValidator _validator;
private readonly IExecutor _executor;
private readonly IResponseMapper _mapper;
private readonly ILogger<AgentOrchestrator> _logger;
public AgentOrchestrator(
IRequestValidator validator,
IExecutor executor,
IResponseMapper mapper,
ILogger<AgentOrchestrator> logger)
{
_validator = validator;
_executor = executor;
_mapper = mapper;
_logger = logger;
}
public async Task<AgentResponse> HandleAsync(AgentRequest request, CancellationToken ct = default)
{
var traceId = Activity.Current?.TraceId.ToString() ?? Guid.NewGuid().ToString("N");
try
{
_validator.EnsureAllowed(request);
var result = await _executor.ExecuteAsync(request, ct);
return _mapper.Compose(request, result, traceId);
}
catch (ArgumentException ex)
{
_logger.LogWarning(ex, "validation failed");
return new AgentResponse(false, "请求参数不合法", "BAD_REQUEST", null, traceId);
}
catch (OperationCanceledException)
{
_logger.LogWarning("request canceled");
return new AgentResponse(false, "请求已取消", "CANCELED", null, traceId);
}
catch (Exception ex)
{
_logger.LogError(ex, "unexpected error");
return new AgentResponse(false, "服务暂时不可用", "INTERNAL_ERROR", null, traceId);
}
}
}
public static class Bootstrap
{
public static WebApplication BuildApp(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLogging();
builder.Services.AddSingleton<IRequestValidator, RequestValidator>();
builder.Services.AddSingleton<IExecutor, CostPerformanceExecutor>();
builder.Services.AddSingleton<IResponseMapper, ResponseMapper>();
builder.Services.AddSingleton<AgentOrchestrator>();
var app = builder.Build();
app.MapPost("/agent/run", async (AgentRequest req, AgentOrchestrator orchestrator, CancellationToken ct) =>
{
var res = await orchestrator.HandleAsync(req, ct);
return Results.Json(res);
});
app.MapGet("/health", () => Results.Ok(new { status = "ok", topic = "CostPerformance" }));
return app;
}
}
配置示例(appsettings.json)
{
"App": {
"Name": "CostPerformanceAgent",
"Environment": "Development",
"MaxQueryLength": 2000,
"DefaultTimeoutMs": 10000
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
}
}
启动入口(Program.cs)
using CostPerformance;
var app = Bootstrap.BuildApp(args);
app.Run();
测试代码(xUnit)
using Microsoft.Extensions.Logging.Abstractions;
using Xunit;
namespace CostPerformance.Tests;
public class CostPerformanceTests
{
[Fact]
public async Task HandleAsync_WithValidRequest_ShouldReturnSuccess()
{
var validator = new RequestValidator();
var executor = new CostPerformanceExecutor(new NullLogger<CostPerformanceExecutor>());
var mapper = new ResponseMapper();
var orchestrator = new AgentOrchestrator(
validator,
executor,
mapper,
new NullLogger<AgentOrchestrator>());
var req = new AgentRequest(
SessionId: "s-001",
UserId: "u-001",
Query: "请执行CostPerformance流程");
var res = await orchestrator.HandleAsync(req);
Assert.True(res.Success);
Assert.NotNull(res.Data);
Assert.True(res.Data!.ContainsKey("topic"));
Assert.Equal("CostPerformance", res.Data["topic"]?.ToString());
}
[Fact]
public async Task HandleAsync_WithEmptyQuery_ShouldReturnBadRequest()
{
var validator = new RequestValidator();
var executor = new CostPerformanceExecutor(new NullLogger<CostPerformanceExecutor>());
var mapper = new ResponseMapper();
var orchestrator = new AgentOrchestrator(
validator,
executor,
mapper,
new NullLogger<AgentOrchestrator>());
var req = new AgentRequest(
SessionId: "s-002",
UserId: "u-002",
Query: "");
var res = await orchestrator.HandleAsync(req);
Assert.False(res.Success);
Assert.Equal("BAD_REQUEST", res.ErrorCode);
}
[Fact]
public async Task HandleAsync_WhenCanceled_ShouldReturnCanceled()
{
var validator = new RequestValidator();
var executor = new CostPerformanceExecutor(new NullLogger<CostPerformanceExecutor>());
var mapper = new ResponseMapper();
var orchestrator = new AgentOrchestrator(
validator,
executor,
mapper,
new NullLogger<AgentOrchestrator>());
using var cts = new CancellationTokenSource();
cts.Cancel();
var req = new AgentRequest(
SessionId: "s-003",
UserId: "u-003",
Query: "测试取消");
var res = await orchestrator.HandleAsync(req, cts.Token);
Assert.False(res.Success);
Assert.Equal("CANCELED", res.ErrorCode);
}
}
运行步骤
- 安装依赖:
dotnet restore - 启动服务:
dotnet run --project src/CostPerformance - 调用接口:
curl -X POST http://localhost:5000/agent/run \
-H 'Content-Type: application/json' \
-d '{
"sessionId":"s-100",
"userId":"u-200",
"query":"请处理 CostPerformance 请求"
}'
- 执行测试:
dotnet test
常见问题与排查
1. 返回 BAD_REQUEST
检查点:
- 是否传了空
query。 sessionId和userId是否为空。- 请求体字段命名是否与模型一致。
2. 返回 INTERNAL_ERROR
检查点:
- 执行器里是否抛了未处理异常。
- 依赖是否注入完整。
- 日志级别是否过滤了错误日志。
3. 偶发超时
检查点:
- 默认超时是否过短。
- 外部依赖是否慢查询。
- 是否需要缓存或并发拆分。
生产化建议
- 每个执行器都加超时、重试和断路策略。
- 审计日志记录
userId + tool + traceId。 - 错误码与文案分离,避免泄露内部细节。
- 对外统一响应结构,便于前端和调用方处理。
- 把核心规则放在
Domain层,减少横向耦合。 - 高风险动作默认二次确认。
- 先做灰度发布,再全量切换。
- 关键指标至少包含:成功率、P95、P99、成本。
- 对关键流程做回归评测集。
- 预留降级路径,避免全链路故障。
小结
CostPerformance 的核心不是“把功能写出来”,而是把输入、执行、输出、治理和运营放到同一条工程链路里。
当你把这篇里的结构固定下来,后续扩展能力时,稳定性和可维护性会明显提升。
下一篇
第15篇:多 Agent 协作。

浙公网安备 33010602011771号