Evaluation

Agent Framework enthält ein integriertes Evaluierungsframework, mit dem Sie die Qualität, Sicherheit und Korrektheit von Agenten messen können. Sie können schnelle lokale Prüfungen während der Entwicklung ausführen, die cloudbasierten Evaluatoren Azure AI Foundry für die Bewertung der Produktionsqualität verwenden oder beide in einem einzigen Auswertungslauf kombinieren.

Der Evaluierungsrahmen richtet sich nach einigen Grundprinzipien:

  • Anbieteragnostisch – Kernauswertungstypen und Orchestrierungsfunktionen arbeiten mit jedem Auswertungsanbieter zusammen.
  • Null Reibung – Wechseln Sie von "Ich habe einen Agenten" zu "Ich habe Eval-Ergebnisse" mit minimalem Code.
  • Progressive Offenlegung – Einfache Szenarien erfordern nahezu keinen Code. Erweiterte Szenarien basieren auf denselben Grundtypen.

Wichtige Konzepte

Das Evaluierungsframework basiert auf drei Typen:

Typ Purpose
EvalItem Ein einzelnes Element, das ausgewertet werden soll – umschließt die gesamte Unterhaltung und leitet Abfrage/Antwort über eine geteilte Strategie ab.
Evaluator Ein Anbieter, der Elemente bewertet – lokale Prüfungen, Azure AI Foundry oder eine benutzerdefinierte Implementierung.
EvalResults Aggregierte Ergebnisse aus einer Auswertungsausführung – Pass-/Fail-Anzahl, Detaildetails pro Element und optionale Portallinks.

In .NET baut das Evaluierungsframework auf Microsoft.Extensions.AI.Evaluation auf. Evaluatoren implementieren die IAgentEvaluator Schnittstelle, und die Orchestrierung erfolgt über Erweiterungsmethoden für AIAgent und Run.

Die Kerntypen befinden sich im namespace Microsoft.Agents.AI:

using Microsoft.Agents.AI;

In Python ist das Evaluierungsframework Teil des Kernpakets agent_framework. Evaluatoren implementieren das Evaluator Protokoll, und die Orchestrierung wird über evaluate_agent() und evaluate_workflow() Funktionen bereitgestellt.

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

Lokale Auswertungen

LocalEvaluator führt Prüfungen lokal und ohne API-Aufrufe durch – ideal für die Innerschleifenentwicklung, CI-Smoke-Tests und schnelle Iterationen. Sie akzeptiert eine beliebige Anzahl von Überprüfungsfunktionen und wendet jede auf jedes Element an.

Integrierte Prüfungen

Agent Framework wird mit integrierten Prüfungen für allgemeine Szenarien ausgeliefert:

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

Benutzerdefinierte Funktionsauswerter

Wird verwendet FunctionEvaluator.Create() , um eine beliebige Funktion als Evaluator-Überprüfung umzuschließen. Je nachdem, welche Daten Sie benötigen, stehen mehrere Überladungen zur Verfügung:

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

Integrierte Prüfungen

Agent Framework wird mit integrierten Prüfungen für allgemeine Szenarien ausgeliefert:

Prüfen Was es tut
keyword_check(*keywords) Antwort muss alle angegebenen Schlüsselwörter enthalten
tool_called_check(*tool_names) Agent muss die angegebenen Tools aufgerufen haben
tool_calls_present Alle expected_tool_calls Namen werden in der Unterhaltung angezeigt (nicht angeordnet, Extras OK)
tool_call_args_match Erwartete Übereinstimmung von Toolaufrufen für Name und Argumente (Teilmengeübereinstimmung für Argen)
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
)

Benutzerdefinierte Funktionsauswerter

Verwenden Sie den @evaluator Dekorator, um eine beliebige Funktion als Bewertungsprüfung zu umschließen. Die Funktion bestimmt durch ihre Parameternamen, welche Daten sie von der EvalItem erhält.

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)

Unterstützte Parameternamen: query, , response, expected_outputexpected_tool_calls, conversation, . toolscontext

Rückgabetypen: bool, ( float ≥ 0,5 = Pass), dict mit score oder passed Schlüssel oder CheckResult. Asynchrone Funktionen werden automatisch behandelt.

Azure AI Foundry Evaluatoren

FoundryEvals stellt eine Verbindung mit dem Auswertungsdienst Azure AI Foundry für die cloudbasierte LLM-as-judge-Bewertung her. Ergebnisse können im Foundry-Portal mit Dashboards und Vergleichsansichten angezeigt werden.

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

Führt standardmäßig FoundryEvalsRelevanz-, Kohärenz- und Aufgabenerfüllungsfähigkeits-Evaluatoren aus. Wenn Elemente Tooldefinitionen enthalten, wird automatisch die Genauigkeit des Toolaufrufs hinzugefügt.

Verfügbare Bewertende

FoundryEvals stellt Konstanten für alle integrierten Evaluatornamen bereit:

Kategorie Bewerter
Agentverhalten intent_resolution, task_adherence, task_completion, task_navigation_efficiency
Toolverwendung tool_call_accuracy, , tool_selectiontool_input_accuracy, , tool_output_utilizationtool_call_success
Quality coherence, , fluencyrelevance, groundedness, , response_completenesssimilarity
Sicherheit violence, sexual, self_harm, hate_unfairness

Hinweis

FoundryEvals erfordert ein Azure AI Foundry Projekt mit einer KI-Modellbereitstellung. Der model_deployment Parameter gibt an, welches Modell als LLM-Richter verwendet werden soll.

Agenten auswerten

Das einfachste Auswertungsszenario führt einen Agenten gegenüber Testabfragen aus und bewertet die Antworten. Stellen Sie mehrere verschiedene Abfragen zur statistisch sinnvollen Auswertung bereit.

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 ist eine Erweiterungsmethode für AIAgent. Er führt den Agent einmal pro Abfrage aus, konvertiert jede Interaktion in einen EvalItem, und übergibt den Batch an den Evaluator.

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 führt den Agent einmal pro Abfrage aus, konvertiert jede Interaktion in einen EvalItemUnd übergibt den Batch an den Evaluator. Er liefert einen EvalResults für jeden Evaluator-Provider zurück.

Konsistenz messen mit Wiederholungen

Führen Sie jede Abfrage mehrmals aus, um nicht deterministisches Verhalten zu erkennen:

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)

Mit erwarteten Ergebnissen auswerten

Geben Sie bodenwahre Antworten, die erwartet werden, um die Korrektheit zu bewerten. Erwartete Ausgaben werden positionell mit Abfragen gekoppelt:

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

Sie können auch erwartete Toolaufrufe angeben:

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

Sie können auch erwartete Toolaufrufe angeben:

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

Bewertet vorhandene Antworten

Wenn Sie bereits über Agentantworten aus Protokollen oder vorherigen Ausführungen verfügen, bewerten Sie sie direkt, ohne den Agent erneut auszuführen:

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

Strategien zur Gesprächstrennung

Mehrstufige Unterhaltungen müssen zur Auswertung in Abfrage- und Antworthälften aufgeteilt werden. Wie Sie teilen, bestimmt , was Sie auswerten.

Strategie Verhalten Am besten geeignet für:
Letzte Drehung (Standard) Trennen bei der letzten Benutzernachricht. Alles bis dahin gehört zum Abfragekontext; alles danach ist die Antwort. Antwortqualität an einem bestimmten Punkt
Vollständig Die erste Benutzernachricht ist die Abfrage; der gesamte Rest ist die Antwort. Vorgangsabschluss und Gesamtverlauf
Pro Schritt Jeder Benutzer→Assistenten-Austausch wird unabhängig und mit kumulativem Kontext bewertet. Feinkörnige Analyse
// 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);

Sie können auch einen benutzerdefinierten Splitter implementieren, indem Sie Folgendes implementieren 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)

Sie können auch einen benutzerdefinierten Splitter bereitstellen – jede aufrufbare Funktion, die eine Unterhaltung als Parameter nimmt und folgendes zurückgibt (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,
)

Auswerten von Workflows

Bewerten Sie Multi-Agent-Workflows mit einer Aufschlüsselung pro Agent. Das Framework extrahiert die Interaktionen jedes Unter-Agents und wertet sie einzeln zusammen mit der Gesamtausgabe des Workflows aus.

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

Sie können auch queries direkt übergeben, und das Framework führt den Workflow für Sie aus.

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

Kombinieren mehrerer Bewerter

Führen Sie lokale Prüfungen und cloudbasierte Bewertungen in einer einzigen Auswertung aus. Jeder Bewerter erzeugt einen eigenen EvalResultsWert.

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

MEAI-Bewerter

Das .NET Evaluierungsframework integriert sich direkt mit Microsoft.Extensions.AI.Evaluation Evaluatoren. Qualitäts- und Sicherheitsbewertungen von MEAI funktionieren ohne Adapter:

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

Tipp

Stellen Sie bei der Verwendung von MEAI-Bewertungen einen Parameter mit einem für das Auswertungsmodell konfigurierten chatConfiguration-Chatclient bereit. Dieser Client wird von den LLM-as-judge-Evaluatoren verwendet, um Antworten zu bewerten.

Nächste Schritte