Evaluation

Agent Framework incluye un marco de evaluación integrado que permite medir la calidad, la seguridad y la corrección del agente. Puede ejecutar comprobaciones locales rápidas durante el desarrollo, usar los evaluadores basados en la nube de Fundición de IA de Azure para la evaluación de nivel de producción o combinar ambos en una sola ejecución de evaluación.

El marco de evaluación está diseñado en torno a algunos principios clave:

  • Independiente del proveedor : los tipos de evaluación principales y las funciones de orquestación funcionan con cualquier proveedor de evaluación.
  • Cero fricción — vaya de "Tengo un agente" a "Tengo resultados de evaluación" con código mínimo.
  • Divulgación progresiva : los escenarios simples requieren código casi cero. Los escenarios avanzados se basan en los mismos primitivos.

Conceptos principales

El marco de evaluación se basa en tres tipos:

Tipo propósito
EvalItem Un único elemento que se va a evaluar: envuelve la conversación completa y deriva la consulta/respuesta a través de una estrategia dividida.
Evaluador Proveedor que puntúa los elementos( comprobaciones locales, Fundición de IA de Azure o cualquier implementación personalizada.
EvalResults Resultados agregados de una ejecución de evaluación: recuentos de pasos y errores, detalles por elemento y vínculos del portal opcionales.

En .NET, el marco de evaluación se basa en Microsoft. Extensions.AI.Evaluation. Los evaluadores implementan la interfaz IAgentEvaluator y la orquestación se proporciona mediante métodos de extensión en AIAgent y Run.

Los tipos principales residen en el espacio de nombres Microsoft.Agents.AI:

using Microsoft.Agents.AI;

En Python, el marco de evaluación forma parte del paquete principal agent_framework. Los evaluadores implementan el Evaluator protocolo, y la orquestación se proporciona a través de evaluate_agent() y evaluate_workflow() funciones.

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

Evaluadores locales

LocalEvaluator ejecuta comprobaciones localmente sin llamadas API: ideal para el desarrollo de bucles internos, las pruebas de humo de CI y la iteración rápida. Acepta cualquier número de funciones de verificación y aplica cada una a cada elemento.

Comprobaciones integradas

Agent Framework se incluye con comprobaciones integradas para escenarios comunes:

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

Evaluadores de funciones personalizados

Use FunctionEvaluator.Create() para envolver cualquier función como una comprobación del evaluador. Hay varias sobrecargas disponibles en función de los datos que necesite:

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

Comprobaciones integradas

Agent Framework se incluye con comprobaciones integradas para escenarios comunes:

Check Qué hace
keyword_check(*keywords) La respuesta debe contener todas las palabras clave especificadas.
tool_called_check(*tool_names) El agente debe haber invocado las herramientas especificadas.
tool_calls_present Todos los expected_tool_calls nombres aparecen en la conversación (sin ordenar, extras OK)
tool_call_args_match Las llamadas a herramientas esperadas coinciden con el nombre y los argumentos (coincidencia de subconjuntos en argumentos)
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
)

Evaluadores de funciones personalizados

Usa el @evaluator decorador para envolver cualquier función como verificación del evaluador. Los nombres de parámetro de la EvalItemfunción determinan qué datos recibe de :

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)

Nombres de parámetro admitidos: query, response, expected_output, expected_tool_callsconversation, , tools, . context

Tipos devueltos: bool, float (≥ 0,5 = aprobado), dict con la clave score o passed, o CheckResult. Las funciones asincrónicas se controlan automáticamente.

evaluadores de Fundición de IA de Azure

FoundryEvals se conecta al servicio de evaluación de Fundición de IA de Azure para la evaluación en la nube de LLM como juez. Los resultados se pueden ver en el portal de Foundry con paneles y vistas de comparación.

using Microsoft.Agents.AI.AzureAI;

var foundry = new FoundryEvals(chatConfiguration, FoundryEvals.Relevance, FoundryEvals.Coherence);
from agent_framework_azure_ai import FoundryEvals

evals = FoundryEvals(
    project_client=project_client,
    model_deployment="gpt-4o",
    evaluators=[FoundryEvals.RELEVANCE, FoundryEvals.COHERENCE],
)

De forma predeterminada, FoundryEvals ejecuta evaluadores de relevancia, coherencia y cumplimiento de tareas. Cuando los elementos contienen definiciones de herramientas, agrega automáticamente la precisión de la llamada a la herramienta.

Evaluadores disponibles

FoundryEvals proporciona constantes para todos los nombres de evaluador integrados:

Categoría Evaluadores
Comportamiento del agente intent_resolution, task_adherence, , task_completion, task_navigation_efficiency
Uso de herramientas 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

Nota:

FoundryEvals requiere un proyecto de Fundición de IA de Azure con una implementación de modelos de IA. El model_deployment parámetro especifica qué modelo se va a usar como juez LLM.

Evaluación de un agente

El escenario de evaluación más sencillo ejecuta un agente en las consultas de prueba y puntúa las respuestas. Proporcione varias consultas diversas para la evaluación estadísticamente 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 es un método de extensión en AIAgent. Ejecuta el agente una vez por consulta, convierte cada interacción en EvalItemy pasa el lote al evaluador.

from agent_framework import evaluate_agent
from agent_framework_azure_ai import FoundryEvals

evals = FoundryEvals(
    project_client=project_client,
    model_deployment="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.assert_passed()  # Raises AssertionError if any item failed

evaluate_agent ejecuta el agente una vez por consulta, convierte cada interacción en EvalItemy pasa el lote al evaluador. Devuelve uno EvalResults por proveedor evaluador.

Medición de la coherencia con repeticiones

Ejecute cada consulta varias veces para detectar el comportamiento no determinista:

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)

Evaluación con salidas esperadas

Proporcione respuestas esperadas de verdad básica para evaluar la corrección. Las salidas esperadas se emparejan de forma posicional con las consultas:

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

También puede especificar las llamadas a herramientas 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,
)

También puede especificar las llamadas a herramientas 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,
)

Evaluación de respuestas preexistentes

Cuando ya tenga respuestas de agente de registros o ejecuciones anteriores, evalúelas directamente sin volver a ejecutar el 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,
)

Estrategias de división de conversación

Las conversaciones de varios turnos deben dividirse en partes de consulta y respuesta para la evaluación. La manera en que se realiza la división determina lo que se está evaluando.

Estrategia Comportamiento Más adecuado para
Último turno (valor predeterminado) Dividir en el último mensaje del usuario. Todo lo que precede es contexto de consulta; todo lo que sigue es la respuesta. Calidad de respuesta en un punto específico
Completa El primer mensaje de usuario es la consulta; el resto completo es la respuesta. Finalización de tareas y trayectoria general
Por turno Cada intercambio de usuario→asistente se puntúa independientemente con el contexto acumulativo. Análisis detallado
// 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);

También puede implementar un 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)

También puede proporcionar un divisor personalizado, cualquier invocable que tome una conversación y devuelva (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,
)

Evaluación de flujos de trabajo

Evalúe los flujos de trabajo de varios agentes con el desglose por agente. El marco extrae las interacciones de cada subagente y las evalúa individualmente, junto con la salida general del flujo de trabajo.

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_azure_ai import FoundryEvals

evals = FoundryEvals(project_client=project_client, model_deployment="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}")

También puede pasar queries directamente y el marco ejecutará el flujo de trabajo por usted:

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

Combinación de varios evaluadores

Ejecute comprobaciones locales y evaluadores basados en la nube juntos en una sola evaluación. Cada evaluador genera su propio 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_azure_ai import FoundryEvals

@evaluator
def is_helpful(response: str) -> bool:
    return len(response.split()) > 10

foundry = FoundryEvals(
    project_client=project_client,
    model_deployment="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}")

Evaluadores de MEAI

El marco de evaluación de .NET se integra directamente con Microsoft. Extensions.AI.Evaluation evaluadores. Los evaluadores de calidad y seguridad de MEAI funcionan sin ningún 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));

Sugerencia

Al usar evaluadores MEAI, proporcione un chatConfiguration parámetro con un cliente de chat configurado para el modelo de evaluación. Evaluadores de LLM como juez utilizan este cliente para puntuar respuestas.

Pasos siguientes