Evaluation

Agent Framework obsahuje integrovanou zkušební architekturu, která umožňuje měřit kvalitu, bezpečnost a správnost agenta. Během vývoje můžete spouštět rychlé místní kontroly, používat cloudové vyhodnocovače Azure AI Foundry pro hodnocení na produkční úrovni nebo kombinovat obojí v jednom testovacím běhu.

Architektura hodnocení je navržená na několik klíčových principů:

  • Nezávislé na poskytovateli – základní typy vyhodnocení a funkce orchestrace pracují s libovolným poskytovatelem vyhodnocení.
  • Nulové tření – Přejděte z "Mám agenta" na "Mám výsledky hodnocení" s minimálním kódem.
  • Progresivní zpřístupnění – jednoduché scénáře vyžadují téměř nulový kód. Pokročilé scénáře vycházejí ze stejných primitiv.

Klíčové koncepty

Architektura vyhodnocení je založená na třech typech:

Typ Purpose
EvalItem Jedna položka, která se má vyhodnotit – zabalí celou konverzaci a odvodí dotaz/odpověď prostřednictvím rozdělené strategie.
Hodnotitel Poskytovatel, který hodnotí položky – kontroly na místní úrovni, Azure AI Foundry, nebo jakoukoli vlastní implementaci.
EvalResults Agregované výsledky ze zkušebního spuštění – počty průchodů a selhání, podrobnosti o položce a volitelné odkazy na portál.

V .NET se architektura hodnocení staví na Microsoft. Extensions.AI.Evaluation. Vyhodnocovače implementují IAgentEvaluator rozhraní a orchestrace je poskytována prostřednictvím metod rozšíření nad AIAgent a Run.

Základní typy jsou aktivní v oboru názvů Microsoft.Agents.AI:

using Microsoft.Agents.AI;

V Python je testovací architektura součástí základního balíčku agent_framework. Vyhodnocovače implementují Evaluator protokol a orchestrace se poskytuje prostřednictvím evaluate_agent() funkcí a evaluate_workflow() funkcí.

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

Místní vyhodnocovače

LocalEvaluator spouští ověření místně bez volání API – ideální pro vývoj v rámci uzavřené smyčky, CI smoke testy a rychlé cykly iterací. Přijme libovolný počet kontrolních funkcí a každý z nich se použije pro každou položku.

Integrované kontroly

Agent Framework se dodává s integrovanými kontrolami běžných scénářů:

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

Vlastní vyhodnocovače funkcí

Slouží FunctionEvaluator.Create() k zabalení jakékoli funkce jako kontroly vyhodnocovače. V závislosti na tom, jaká data potřebujete, je k dispozici různé možnosti přetížení.

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

Integrované kontroly

Agent Framework se dodává s integrovanými kontrolami běžných scénářů:

Zkontrolujte Jak funguje
keyword_check(*keywords) Odpověď musí obsahovat všechna zadaná klíčová slova.
tool_called_check(*tool_names) Agent musel zavolat zadané nástroje.
tool_calls_present Všechna expected_tool_calls jména se zobrazí v konverzaci (v libovolném pořadí, nevadí, pokud jsou některá jména navíc)
tool_call_args_match Očekávaná volání nástroje odpovídají názvu a argumentům (shoda na podmnožině argumentů)
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
)

Vlastní vyhodnocovače funkcí

@evaluator Dekorátor použijte ke zabalování jakékoli funkce pro kontrolu vyhodnocování. Názvy parametrů funkce určují, jaká data přijímá z 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)

Podporované názvy parametrů: query, response, expected_output, expected_tool_callsconversation, , tools, . context

Návratové typy: bool, float (≥ 0,5 = úspěch), dict s klíčem score nebo klíčem passed, nebo CheckResult. Asynchronní funkce se zpracovávají automaticky.

hodnotitelé Azure AI Foundry

FoundryEvals se připojí ke zkušební službě Azure AI Foundry pro hodnocení LLM jako soudce založené na cloudu. Výsledky se dají zobrazit na portálu Foundry s řídicími panely a zobrazeními porovnání.

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

Ve výchozím nastavení FoundryEvals spouští vyhodnocovače relevance, soudržnosti a dodržování úkolů . Pokud položky obsahují definice nástrojů, automaticky přidává přesnost volání nástroje.

Dostupné vyhodnocovače

FoundryEvals poskytuje konstanty pro všechny předdefinované názvy vyhodnocovače:

Kategorie Hodnotitelé
Chování agenta intent_resolution, task_adherence, , task_completiontask_navigation_efficiency
Využití nástrojů tool_call_accuracy, tool_selection, tool_input_accuracy, , tool_output_utilizationtool_call_success
Kvality coherence, fluency, relevance, groundedness, , response_completenesssimilarity
Safety violence, sexual, , self_harmhate_unfairness

Poznámka:

FoundryEvals vyžaduje projekt Azure AI Foundry s nasazením modelu AI. Parametr model určuje, který model se má použít jako posuzovatel LLM.

Vyhodnocení agenta

Nejjednodušší scénář vyhodnocení spustí agenta proti testovacím dotazům a vyhodnotí odpovědi. Poskytuje několik různorodých dotazů pro statisticky smysluplné vyhodnocení.

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 je rozšiřující metoda v AIAgent. Spustí agenta jednou za dotaz, převede každou interakci na EvalItem, a předá dávku vyhodnocovači.

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 spustí agenta jednou za dotaz, převede každou interakci na objekt EvalItema předá dávku vyhodnocovaci. Vrátí jeden EvalResults na poskytovatele vyhodnocovače.

Měření konzistence s opakováním

Spusťte každý dotaz několikrát, abyste zjistili nedeterministické chování:

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)

Vyhodnocení s očekávanými výstupy

Zadejte základní očekávané odpovědi k vyhodnocení správnosti. Očekávané výstupy se spárují s dotazy podle pozice:

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

Můžete také zadat očekávaná volání nástrojů:

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

Můžete také zadat očekávaná volání nástrojů:

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

Vyhodnocení existujících odpovědí

Pokud už máte odpovědi agenta z protokolů nebo předchozích spuštění, vyhodnoťte je přímo bez opětovného spuštění agenta:

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

Strategie rozdělení konverzací

Konverzace s více tahy musí být rozdělené na části dotazů a odpovědí pro vyhodnocení. Způsob rozdělení určuje , co vyhodnocujete.

Strategie Chování Nejvhodnější pro
Poslední otočení (výchozí) Rozdělte v místě poslední zprávy uživatele. Vše, co je na něm, je kontext dotazu; vše, co následuje, je odpověď. Kvalita odezvy v určitém okamžiku
Plný První uživatelská zpráva je dotaz; celý zbytek je odpověď. Dokončení úkolu a celková trajektorie
Zatáčí Každá interakce uživatele→asistenta je vyhodnocena nezávisle s přihlédnutím ke kumulativnímu kontextu. Jemně odstupňovaná analýza
// 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);

Vlastní rozdělovač můžete implementovat také implementací 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)

Můžete také zadat vlastní rozdělovač – jakýkoli volatelný, který přijímá konverzaci a vrací:(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,
)

Vyhodnocení pracovních postupů

Vyhodnoťte pracovní postupy s více agenty s rozpisem výkonu v rámci jednotlivých agentů. Architektura extrahuje interakce jednotlivých dílčích agentů a vyhodnocuje je jednotlivě spolu s celkovým výstupem pracovního postupu.

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

Můžete také předat queries přímo a architektura spustí pracovní postup za vás:

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

Kombinace více vyhodnocovačů

Spusťte místní kontroly a cloudové vyhodnocovače společně v jednom vyhodnocení. Každý vyhodnocovač vytváří svůj vlastní 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}")

Vyhodnocovače MEAI

Rámec vyhodnocení .NET se integruje přímo s Microsoft.Extensions.AI.Evaluation vyhodnocovači. Hodnotitelé kvality a bezpečnosti od MEAI pracují bez adaptéru.

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

Návod

Při použití vyhodnocovačů MEAI zadejte chatConfiguration parametr s chatovacím klientem nakonfigurovaným pro model vyhodnocení. Tento klient používají vyhodnocovatelé používající LLM jako soudce k hodnocení odpovědí.

Poznámka:

Podpora této funkce v Go již brzy. Nejnovější stav najdete v úložišti Agent Framework Go .

Další kroky