代理框架包含一个内置的评估框架,可用于衡量代理质量、安全性和正确性。 可以在开发期间运行快速本地检查,使用 Microsoft Foundry 的基于云的评估器进行生产级评估,或在单个评估运行中合并两者。
评估框架围绕几个关键原则进行设计:
- 与提供程序无关 - 核心评估类型和业务流程函数适用于任何评估提供程序。
- 零摩擦 - 从“我有代理”到“我有一个评估结果”,只需最少的代码。
- 渐进式披露 - 简单方案需要接近零的代码。 高级方案基于同一基元生成。
核心概念
评估框架基于三种类型构建:
| 类型 | Purpose |
|---|---|
| EvalItem | 要评估的单项 - 包装整个对话并通过拆分策略派生查询/响应。 |
| 评估器 | 对项进行评分的提供程序-本地检查、Microsoft Foundry 或任何自定义实现。 |
| EvalResults | 评估运行的聚合结果:通过/失败计数、逐项详细信息和可选门户链接。 |
在.NET中,评估框架基于 Microsoft。Extensions.AI.Evaluation。 评估程序实现 IAgentEvaluator 接口,并通过 AIAgent 和 Run 上的扩展方法提供业务流程。
核心类型位于 Microsoft.Agents.AI 命名空间中:
using Microsoft.Agents.AI;
在 Python 中,评估框架是核心 agent_framework 包的一部分。 评估者实现Evaluator协议,并通过evaluate_agent()和evaluate_workflow()函数提供编排。
from agent_framework import (
evaluate_agent,
evaluate_workflow,
EvalItem,
EvalResults,
LocalEvaluator,
)
本地评估者
LocalEvaluator 在没有 API 调用的情况下在本地运行检查 - 非常适合内部循环开发、CI 冒烟测试和快速迭代。 它接受任意数量的检查函数,并将每个函数应用于每个项。
内置检查
代理框架附带了针对常见场景的内置检查:
using Microsoft.Agents.AI;
var local = new LocalEvaluator(
EvalChecks.KeywordCheck("weather", "temperature"), // Response must contain these keywords
EvalChecks.ToolCalledCheck("get_weather") // Agent must have called this tool
);
自定义函数评估器
使用 FunctionEvaluator.Create() 包装任何函数作为评估程序检查。 根据您需要的数据,可使用多个重载方法。
using Microsoft.Agents.AI;
var local = new LocalEvaluator(
// Simple: check only the response text
FunctionEvaluator.Create("is_concise",
(string response) => response.Split(' ').Length < 500),
// With expected output: compare against ground truth
FunctionEvaluator.Create("mentions_city",
(string response, string? expectedOutput) =>
expectedOutput != null && response.Contains(expectedOutput, StringComparison.OrdinalIgnoreCase)),
// Full context: access the complete EvalItem
FunctionEvaluator.Create("used_search",
(EvalItem item) => item.Conversation.Any(m =>
m.Text?.Contains("search", StringComparison.OrdinalIgnoreCase) == true))
);
内置检查
代理框架附带了针对常见场景的内置检查:
| 检查 | 它的作用是什么 |
|---|---|
keyword_check(*keywords) |
响应必须包含所有指定的关键字 |
tool_called_check(*tool_names) |
代理必须已调用指定的工具 |
tool_calls_present |
所有 expected_tool_calls 名字都出现在对话中(无序,可以有额外的名字) |
tool_call_args_match |
预期工具调用的名称和参数匹配(参数上的子集匹配) |
from agent_framework import (
LocalEvaluator,
keyword_check,
tool_called_check,
tool_calls_present,
tool_call_args_match,
)
local = LocalEvaluator(
keyword_check("weather", "temperature"), # Response must contain these keywords
tool_called_check("get_weather"), # Agent must have called this tool
tool_calls_present, # All expected tool call names were made
tool_call_args_match, # Expected tool calls match on name + args
)
自定义函数评估器
使用 @evaluator 修饰器包装任何函数作为评估程序检查。 函数参数名称决定了它接收来自EvalItem的数据。
from agent_framework import evaluator, LocalEvaluator
@evaluator
def is_concise(response: str) -> bool:
"""Check response is under 500 words."""
return len(response.split()) < 500
@evaluator
def mentions_city(response: str, expected_output: str) -> bool:
"""Check response contains the expected city name."""
return expected_output.lower() in response.lower()
@evaluator
def used_tools(conversation: list, tools: list) -> float:
"""Score based on tool usage. Returns 0.0–1.0 (>= 0.5 passes)."""
tool_calls = [c for m in conversation for c in (m.contents or []) if c.type == "function_call"]
return min(len(tool_calls) / max(len(tools), 1), 1.0)
local = LocalEvaluator(is_concise, mentions_city, used_tools)
支持的参数名称:query、、、responseexpected_outputexpected_tool_calls、conversationtools、。 context
返回类型: bool、 float (≥ 0.5 = pass)、 dict 带 score 或 passed 键或 CheckResult。 异步函数会自动处理。
Microsoft Foundry 计算器
FoundryEvals连接到 Microsoft Foundry 的评估服务,用于基于云的 LLM 即评评估。 可以通过仪表板和比较视图在 Foundry 门户中查看结果。
有关项目设置、跟踪评估、标准评估器和可运行的服务特定示例,请参阅 Microsoft Foundry 评估。
using Microsoft.Agents.AI.AzureAI;
var foundry = new FoundryEvals(chatConfiguration, FoundryEvals.Relevance, FoundryEvals.Coherence);
from agent_framework.foundry import FoundryEvals
evals = FoundryEvals(
project_client=project_client,
model="gpt-4o",
evaluators=[FoundryEvals.RELEVANCE, FoundryEvals.COHERENCE],
)
默认情况下, FoundryEvals 运行 相关性、 一致性和 任务遵循 评估程序。 当项包含工具定义时,它会自动添加 工具调用准确性。
可用的评估器
FoundryEvals 为所有内置计算器名称提供常量:
| 类别 | 评估者 |
|---|---|
| 代理行为 |
intent_resolution、task_adherence、task_completion、task_navigation_efficiency |
| 工具用法 |
tool_call_accuracy、tool_selection、tool_input_accuracy、tool_output_utilization、tool_call_success |
| Quality |
coherence、fluency、relevance、groundedness、response_completeness、similarity |
| Safety |
violence、sexual、self_harm、hate_unfairness |
注释
FoundryEvals需要使用 AI 模型部署Microsoft Foundry 项目。 该 model 参数指定要用作 LLM 判断的模型。
评估代理
最简单的评估方案针对测试查询运行代理并评分响应。 为统计有意义的评估提供多个不同的查询。
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Foundry;
var foundry = new FoundryEvals(chatConfiguration, FoundryEvals.Relevance, FoundryEvals.Coherence);
AgentEvaluationResults results = await agent.EvaluateAsync(
new[]
{
"What's the weather in Seattle?",
"Plan a weekend trip to Portland",
"What restaurants are near Pike Place?",
},
foundry);
results.AssertAllPassed(); // Throws if any item failed
EvaluateAsync 是 AIAgent 的扩展方法。 它为每个查询运行代理一次,将每个交互转换为一个 EvalItem,并将批处理传递给计算器。
from agent_framework import evaluate_agent
from agent_framework.foundry import FoundryEvals
evals = FoundryEvals(
project_client=project_client,
model="gpt-4o",
evaluators=[FoundryEvals.RELEVANCE, FoundryEvals.COHERENCE],
)
results = await evaluate_agent(
agent=my_agent,
queries=[
"What's the weather in Seattle?",
"Plan a weekend trip to Portland",
"What restaurants are near Pike Place?",
],
evaluators=evals,
)
for r in results:
print(f"{r.provider}: {r.passed}/{r.total}")
r.raise_for_status() # Raises EvalNotPassedError if any item failed
evaluate_agent 每个查询运行代理一次,将每个交互转换为一个 EvalItem,并将批处理传递给计算器。 它为每个评估器提供者返回一个 EvalResults 。
使用重复性来衡量一致性
多次运行每个查询以检测非确定性行为:
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's the weather in Seattle?" },
foundry,
numRepetitions: 3); // Each query runs 3 times independently
// Results contain 3 items (1 query × 3 repetitions)
results = await evaluate_agent(
agent=my_agent,
queries=["What's the weather in Seattle?"],
evaluators=evals,
num_repetitions=3, # Each query runs 3 times independently
)
# Results contain 3 items (1 query × 3 repetitions)
使用预期输出进行评估
提供真实预期答案来评估正确性。 预期输出根据位置与查询配对。
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's 2+2?", "Capital of France?" },
foundry,
expectedOutput: new[] { "4", "Paris" });
还可以指定预期的工具调用:
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's the weather in NYC?" },
new LocalEvaluator(EvalChecks.ToolCalledCheck("get_weather")),
expectedToolCalls: new[]
{
new[] { new ExpectedToolCall("get_weather") },
});
from agent_framework import evaluate_agent, ExpectedToolCall
results = await evaluate_agent(
agent=my_agent,
queries=["What's 2+2?", "Capital of France?"],
expected_output=["4", "Paris"],
evaluators=evals,
)
还可以指定预期的工具调用:
results = await evaluate_agent(
agent=my_agent,
queries=["What's the weather in NYC?"],
expected_tool_calls=[ExpectedToolCall("get_weather", {"location": "NYC"})],
evaluators=local,
)
评估预先存在的响应
如果已有来自日志或以前的运行的代理响应,请直接评估它们,而无需重新运行代理:
var response = await agent.RunAsync(new[] { new ChatMessage(ChatRole.User, "What's the weather?") });
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { response },
new[] { "What's the weather?" },
foundry);
from agent_framework import Message, evaluate_agent
response = await agent.run([Message("user", ["What's the weather?"])])
results = await evaluate_agent(
agent=agent,
responses=response,
queries="What's the weather?",
evaluators=evals,
)
对话拆分策略
多轮次对话必须拆分为查询和响应的半部分以供评估。 拆分方式决定了要 评估的内容。
| 策略 | 行为 | 最适用于 |
|---|---|---|
| 最后一轮 (默认值) | 在最后一条用户消息处拆分。 一切在它之前的内容都是查询上下文;一切在它之后的内容是响应。 | 特定点的响应质量 |
| 完整 | 第一条用户消息是查询;其余部分是响应。 | 任务完成和总体轨迹 |
| 每回合 | 每次用户→助手交流都会在累积上下文的基础上独立评分。 | 细粒度分析 |
// Full conversation as context
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "Plan a 3-day trip to Paris" },
foundry,
splitter: ConversationSplitters.Full);
// Per-turn: each exchange scored independently
var items = EvalItem.PerTurnItems(conversation);
var perTurnResults = await evaluator.EvaluateAsync(items);
还可以通过实现以下方法实现 IConversationSplitter自定义拆分器:
public class SplitBeforeToolCall : IConversationSplitter
{
public (IReadOnlyList<ChatMessage> QueryMessages, IReadOnlyList<ChatMessage> ResponseMessages) Split(
IReadOnlyList<ChatMessage> conversation)
{
// Custom split logic
for (int i = 0; i < conversation.Count; i++)
{
if (conversation[i].Text?.Contains("tool_call") == true)
return (conversation.Take(i).ToList(), conversation.Skip(i).ToList());
}
return ConversationSplitters.LastTurn.Split(conversation);
}
}
from agent_framework import evaluate_agent, ConversationSplit
# Full conversation as context
results = await evaluate_agent(
agent=agent,
queries=["Plan a 3-day trip to Paris"],
evaluators=evals,
conversation_split=ConversationSplit.FULL,
)
# Per-turn: each exchange scored independently
from agent_framework import EvalItem
items = EvalItem.per_turn_items(conversation)
# Pass items directly to an evaluator
per_turn_results = await evaluator.evaluate(items)
您还可以提供一个自定义拆分器,即任何可以接收会话并返回结果的可调用对象(query_messages, response_messages)。
def split_before_memory(conversation):
"""Split just before a memory-retrieval tool call."""
for i, msg in enumerate(conversation):
for c in msg.contents or []:
if c.type == "function_call" and c.name == "retrieve_memory":
return conversation[:i], conversation[i:]
# Fallback to default
return EvalItem._split_last_turn_static(conversation)
results = await evaluate_agent(
agent=agent,
queries=queries,
evaluators=evals,
conversation_split=split_before_memory,
)
评估工作流
使用每个智能体细分评估多智能体工作流。 框架会提取每个子智能体的交互,并逐个进行评估,还会评估工作流的总体输出。
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.AzureAI;
Run run = await workflowRunner.RunAsync(workflow, "Plan a trip to Paris");
AgentEvaluationResults results = await run.EvaluateAsync(
new FoundryEvals(chatConfiguration, FoundryEvals.Relevance));
Console.WriteLine($"Overall: {results.Passed}/{results.Total}");
// Per-agent breakdown
if (results.SubResults != null)
{
foreach (var (name, sub) in results.SubResults)
{
Console.WriteLine($" {name}: {sub.Passed}/{sub.Total}");
}
}
results.AssertAllPassed();
from agent_framework import evaluate_workflow
from agent_framework.foundry import FoundryEvals
evals = FoundryEvals(project_client=project_client, model="gpt-4o")
result = await workflow.run("Plan a trip to Paris")
eval_results = await evaluate_workflow(
workflow=workflow,
workflow_result=result,
evaluators=evals,
)
for r in eval_results:
print(f"{r.provider}: {r.passed}/{r.total}")
for name, sub in r.sub_results.items():
print(f" {name}: {sub.passed}/{sub.total}")
还可以直接传递 queries ,框架将为你运行工作流:
eval_results = await evaluate_workflow(
workflow=workflow,
queries=["Plan a trip to Paris", "Book a flight to London"],
evaluators=evals,
)
混合多个评估器
在单个评估中一起运行本地检查和基于云的评估程序。 每个评估器生成自己的 EvalResults。
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.AzureAI;
IReadOnlyList<AgentEvaluationResults> results = await agent.EvaluateAsync(
new[] { "What's the weather in Seattle?" },
evaluators: new IAgentEvaluator[]
{
new LocalEvaluator(
EvalChecks.KeywordCheck("weather"),
FunctionEvaluator.Create("is_helpful", (string r) => r.Split(' ').Length > 10)),
new FoundryEvals(chatConfiguration, FoundryEvals.Relevance, FoundryEvals.Coherence),
});
// results[0] = local evaluator results
// results[1] = Foundry evaluator results
foreach (var r in results)
{
Console.WriteLine($"{r.Provider}: {r.Passed}/{r.Total}");
}
from agent_framework import evaluate_agent, evaluator, LocalEvaluator, keyword_check
from agent_framework.foundry import FoundryEvals
@evaluator
def is_helpful(response: str) -> bool:
return len(response.split()) > 10
foundry = FoundryEvals(
project_client=project_client,
model="gpt-4o",
evaluators=[FoundryEvals.RELEVANCE, FoundryEvals.COHERENCE],
)
results = await evaluate_agent(
agent=agent,
queries=["What's the weather in Seattle?"],
evaluators=[
LocalEvaluator(is_helpful, keyword_check("weather")),
foundry,
],
)
# results[0] = local evaluator results
# results[1] = Foundry evaluator results
for r in results:
print(f"{r.provider}: {r.passed}/{r.total}")
MEAI 评估器
.NET评估框架直接与Microsoft.Extensions.AI.Evaluation评估器集成。 MEAI 的质量和安全评估器无需任何适配器即可工作:
using Microsoft.Extensions.AI.Evaluation;
using Microsoft.Extensions.AI.Evaluation.Quality;
using Microsoft.Extensions.AI.Evaluation.Safety;
// Quality evaluators
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's the weather?" },
new CompositeEvaluator(
new RelevanceEvaluator(),
new CoherenceEvaluator(),
new GroundednessEvaluator()),
chatConfiguration: new ChatConfiguration(evalClient));
// Safety evaluators
AgentEvaluationResults safetyResults = await agent.EvaluateAsync(
new[] { "What's the weather?" },
new ContentHarmEvaluator(),
chatConfiguration: new ChatConfiguration(evalClient));
小窍门
使用 MEAI 评估程序时,提供 chatConfiguration 参数以及为评估模型配置的聊天客户端。 LLM 即裁判评估程序将使用此客户端对响应进行评分。
注释
Go 语言对该功能的支持即将推出。 有关最新状态,请参阅 Agent Framework Go 存储库 。