Evaluation

O Agent Framework inclui um framework de avaliação incorporado que lhe permite medir a qualidade, segurança e correção dos agentes. Pode fazer verificações locais rápidas durante o desenvolvimento, usar os avaliadores na cloud do Microsoft Foundry para avaliação de produção, ou combinar ambos numa única execução de avaliação.

O quadro de avaliação é concebido em torno de alguns princípios-chave:

  • Agnóstico ao prestador — Os tipos principais de avaliação e as funções de orquestração funcionam com qualquer prestador de avaliação.
  • Zero atritos — Passa de "tenho um agente" para "tenho resultados de avaliação" com código mínimo.
  • Divulgação progressiva — Cenários simples requerem código quase zero. Cenários avançados baseiam-se nos mesmos primitivos.

Conceitos-chave

O quadro de avaliação baseia-se em três tipos:

Tipo Purpose
EvalItem Um único item a avaliar — abrange toda a conversa e gera a consulta/resposta através de uma estratégia de divisão.
Avaliador Um fornecedor que atribui pontuações a itens — verificações locais, Microsoft Foundry ou qualquer implementação personalizada.
EvalResults Resultados agregados de uma execução de avaliação — contagens de sucesso/insucesso, detalhes por item e links opcionais para o portal.

Em .NET, o quadro de avaliação baseia-se em Microsoft. Extensões.AI.Avaliação. Os avaliadores implementam a IAgentEvaluator interface, e a orquestração é fornecida através de métodos de extensão em AIAgent e Run.

Os tipos principais estão no espaço de nomes Microsoft.Agents.AI:

using Microsoft.Agents.AI;

Em Python, o quadro de avaliação faz parte do pacote central agent_framework. Os avaliadores implementam o protocolo Evaluator, e a orquestração é fornecida através das funções evaluate_agent() e evaluate_workflow().

from agent_framework import (
    evaluate_agent,
    evaluate_workflow,
    EvalItem,
    EvalResults,
    LocalEvaluator,
)

Avaliadores locais

LocalEvaluator executa verificações localmente sem chamadas de API — ideal para desenvolvimento em circuito interno, testes de fumo de CI e iteração rápida. Aceita qualquer número de funções de verificação e aplica cada uma a cada item.

Verificações incorporadas

O Agent Framework inclui verificações integradas para cenários comuns:

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
);

Avaliadores de funções personalizados

Use FunctionEvaluator.Create() para envolver qualquer função como uma verificação do avaliador. Existem múltiplas sobrecargas disponíveis dependendo dos dados de que precisa:

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))
);

Verificações incorporadas

O Agent Framework inclui verificações integradas para cenários comuns:

Verificar O que faz
keyword_check(*keywords) A resposta deve conter todas as palavras-chave especificadas
tool_called_check(*tool_names) O agente deve ter chamado as ferramentas especificadas
tool_calls_present Todos os nomes expected_tool_calls aparecem na conversa (não ordenados, extras são permitidos)
tool_call_args_match Chamadas de ferramenta esperadas correspondem pelo nome e argumentos (correspondência de subconjunto em args)
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
)

Avaliadores de funções personalizados

Use o decorador @evaluator para envolver qualquer função como uma avaliação do avaliador. Os nomes dos parâmetros da função determinam que dados recebe dos 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)

Nomes de parâmetros suportados: query, response, expected_outputexpected_tool_calls, , conversation, tools, . context

Tipos de retorno: bool, float (≥ 0,5 = passar), dict com a chave score ou passed, ou CheckResult. As funções assíncronas são tratadas automaticamente.

Avaliadores Microsoft Foundry

FoundryEvalsliga-se ao serviço de avaliação da Microsoft Foundry para avaliação de LLM como juiz baseada na cloud. Os resultados podem ser visualizados no portal Foundry com painéis e vistas de comparação.

Para configuração do projeto, avaliação de rastreios, avaliadores por rubrica e exemplos executáveis específicos do serviço, consulte avaliação no 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],
)

Por defeito, FoundryEvals executa avaliadores de relevância, coerência e adesão às tarefas . Quando os itens contêm definições de ferramentas, adicionam automaticamente precisão nas chamadas de ferramenta.

Avaliadores disponíveis

FoundryEvals fornece constantes para todos os nomes de avaliadores incorporados:

Category Avaliadores
Comportamento do agente intent_resolution, task_adherence, task_completion, task_navigation_efficiency
Utilização da ferramenta tool_call_accuracy, tool_selection, tool_input_accuracy, tool_output_utilization, tool_call_success
Qualidade coherence, fluency, relevance, groundedness, response_completeness, similarity
Safety violence, sexual, self_harm, hate_unfairness

Observação

FoundryEvals requer um projeto Microsoft Foundry com implementação de modelo de IA. O model parâmetro especifica qual modelo usar como juiz do LLM.

Avalie um agente

O cenário de avaliação mais simples executa um agente com consultas de teste e pontua as respostas. Forneça múltiplas consultas diversas para uma avaliação estatisticamente significativa.

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 é um método de extensão em AIAgent. Executa o agente uma vez por consulta, converte cada interação para um EvalItem, e passa o lote ao avaliador.

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 executa o agente uma vez por consulta, converte cada interação para um EvalItem, e passa o lote ao avaliador. Retorna um EvalResults por provedor de avaliação.

Consistência de medidas com repetições

Execute cada consulta várias vezes para detetar comportamentos não determinísticos:

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)

Avaliar, comparando com os resultados esperados

Forneça respostas de verdade básica para avaliar a correção. As saídas esperadas são emparelhadas posicionalmente com as consultas:

AgentEvaluationResults results = await agent.EvaluateAsync(
    new[] { "What's 2+2?", "Capital of France?" },
    foundry,
    expectedOutput: new[] { "4", "Paris" });

Também pode especificar chamadas de ferramenta esperadas:

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,
)

Também pode especificar chamadas de ferramenta esperadas:

results = await evaluate_agent(
    agent=my_agent,
    queries=["What's the weather in NYC?"],
    expected_tool_calls=[ExpectedToolCall("get_weather", {"location": "NYC"})],
    evaluators=local,
)

Avaliar respostas pré-existentes

Quando já tiver respostas de agentes a partir de registos ou execuções anteriores, avalie-as diretamente sem repetir a execução do agente:

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,
)

As respostas de agentes em Python mantêm instantâneos apenas de esquema das ferramentas funcionais expostas durante a execução, incluindo ferramentas provenientes de provedores de contexto. evaluate_agent utiliza estes instantâneos automaticamente para avaliação com reconhecimento da ferramenta. Os snapshots sobrevivem à serialização JSON e pickle e não incluem implementações de ferramentas executáveis.

Forneça tools= a evaluate_agent para sobrepor as definições capturadas apenas para avaliação. Forneça tools=[] para avaliar sem definições de ferramenta. A descoberta automática gera ValueError se uma ferramenta chamada usou diferentes esquemas de entrada sob o mesmo nome durante a conversa capturada. Utilize nomes de ferramentas distintos, avalie os segmentos separadamente ou transmita definições explícitas de ferramentas.

Observação

Os esquemas de entrada de ferramentas devem conter valores compatíveis com JSON. Capturar um esquema personalizado pode gerar um erro durante a execução do agente se o esquema não puder ser serializado.

Estratégias de divisão de conversa

As conversas com múltiplas voltas devem ser divididas em metades de consulta e resposta para avaliação. A forma como divides determina o que estás a avaliar.

Strategy Comportamento Melhor para
Último turno (padrão) Dividir na última mensagem do utilizador. Tudo até lá é contexto de consulta; tudo depois disso é a resposta. Qualidade da resposta num ponto específico
Completo A primeira mensagem do utilizador é a consulta; O resto inteiro é a resposta. Conclusão da tarefa e trajetória geral
Por turno Cada interação entre o utilizador e o assistente é pontuada independentemente, considerando o contexto acumulado. Análise detalhada
// 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);

Também pode implementar um divisor personalizado implementando 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)

Também pode disponibilizar um divisor personalizado — qualquer dispositivo de chamada que receba uma conversa e retorne (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,
)

Avaliar fluxos de trabalho

Avaliação dos fluxos de trabalho de múltiplos agentes com um desdobramento por agente. A estrutura extrai as interações de cada subagente e avalia-as individualmente, juntamente com a saída global do fluxo de trabalho.

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}")

Também pode passar queries diretamente e o framework irá executar o fluxo de trabalho por si:

eval_results = await evaluate_workflow(
    workflow=workflow,
    queries=["Plan a trip to Paris", "Book a flight to London"],
    evaluators=evals,
)

Misture múltiplos avaliadores

Execute verificações locais e avaliadores baseados na cloud em conjunto numa única avaliação. Cada avaliador produz o seu próprio 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}")

Avaliadores MEAI

O quadro de avaliação .NET integra-se diretamente com Microsoft.Extensions.AI.Evaluation. Os avaliadores de qualidade e segurança da MEAI trabalham sem qualquer adaptador:

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));

Tip

Ao utilizar avaliadores MEAI, forneça um chatConfiguration parâmetro com um cliente de chat configurado para o modelo de avaliação. Este cliente é utilizado pelos avaliadores do LLM como juízes para pontuar respostas.

Observação

O suporte para esta funcionalidade do go está a chegar em breve. Consulte o repositório Agent Framework Go para o estado mais recente.

Passos seguintes