Evaluation

Framework agenta zawiera wbudowany framework oceny, który pozwala na mierzenie jakości, bezpieczeństwa i poprawności agenta. Możesz uruchomić szybkie kontrole lokalne podczas programowania, użyć ewaluatorów opartych na chmurze Azure AI Foundry do oceny klasy produkcyjnej lub połączyć oba te elementy w jednym przebiegu oceny.

Struktura oceny została zaprojektowana zgodnie z kilkoma kluczowymi zasadami:

  • Niezależny od dostawcy — podstawowe typy ewaluacji i funkcje orkiestracji współpracują z dowolnym dostawcą oceny.
  • Zero tarć — przejdź od "Mam agenta" do "Mam wyniki oceny" z minimalnym kodem.
  • Stopniowe ujawnianie — proste scenariusze wymagają kodu bliskiego zera. Zaawansowane scenariusze bazują na tych samych elementach pierwotnych.

Podstawowe pojęcia

Struktura oceny jest oparta na trzech typach:

Typ Purpose
EvalItem Pojedynczy element do oceny — zawija pełną konwersację i generuje zapytanie/odpowiedź za pomocą strategii podziału.
Ewaluator Dostawca, który ocenia elementy — kontrole lokalne, Azure AI Foundry lub dowolną implementację niestandardową.
EvalResults Zagregowane wyniki z przebiegu oceny — liczba wyników pomyślnych/niepomyślnych, szczegóły poszczególnych elementów i opcjonalne linki do portalu.

W .NET struktura oceny opiera się na Microsoft. Extensions.AI.Evaluation. Oceniacze wdrażają interfejs IAgentEvaluator, a orchestracja jest udostępniana za pomocą metod rozszerzeń na AIAgent i Run.

Podstawowe typy są aktywne w przestrzeni nazw Microsoft.Agents.AI:

using Microsoft.Agents.AI;

W Python struktura oceny jest częścią podstawowego pakietu agent_framework. Ewaluatorzy implementują protokół Evaluator, a orkiestracja jest zapewniana za pośrednictwem funkcji evaluate_agent() i evaluate_workflow().

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

Lokalni ewaluatorzy

LocalEvaluator uruchamia sprawdzenia lokalnie bez wywołań interfejsu API — idealne rozwiązanie do rozwoju w pętli wewnętrznej, testów inspekcyjnych ciągłej integracji i szybkiej iteracji. Akceptuje dowolną liczbę funkcji sprawdzania i stosuje je do każdego elementu.

Wbudowane kontrole

Framework agenta posiada wbudowane mechanizmy kontroli typowych scenariuszy.

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

Ewaluatory funkcji niestandardowych

Użyj polecenia FunctionEvaluator.Create(), aby owinąć dowolną funkcję jako kontrola ewaluatora. Dostępnych jest wiele przeciążeń w zależności od potrzebnych danych:

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

Wbudowane kontrole

Framework agenta posiada wbudowane mechanizmy kontroli typowych scenariuszy.

Sprawdź Do czego służy
keyword_check(*keywords) Odpowiedź musi zawierać wszystkie określone słowa kluczowe
tool_called_check(*tool_names) Agent musi wywołać określone narzędzia
tool_calls_present Wszystkie expected_tool_calls nazwy są wyświetlane w konwersacji (nieurządkowane, dodatki OK)
tool_call_args_match Oczekiwane wywołania narzędzi są zgodne z nazwami i argumentami (dopasowanie podzestawu w elementach 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
)

Ewaluatory funkcji niestandardowych

Użyj dekoratora @evaluator, aby opakować dowolną funkcję jako kontrolę ewaluatora. Nazwy parametrów funkcji określają, jakie dane odbierane z elementu 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)

Obsługiwane nazwy parametrów: query, , responseexpected_outputexpected_tool_callsconversation, tools, . context

Typy zwracane: bool, float (≥ 0,5 = pass), dict z kluczem score lub passed, CheckResult. Funkcje asynchroniczne są obsługiwane automatycznie.

Azure AI Foundry Oceniający

FoundryEvals łączy się z usługą ewaluacyjną Azure AI Foundry na potrzeby oceny opartej na chmurze LLM jako Sędzia. Wyniki są widoczne w portalu Foundry z widżetami i widokami porównawczymi.

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

Domyślnie program uruchamia ewaluatory FoundryEvals, spójności i dostosowania do zadań. Gdy elementy zawierają definicje narzędzi, automatycznie dodaje dokładność wywołań narzędzi.

Dostępne ewaluatory

FoundryEvals zapewnia stałe dla wszystkich wbudowanych nazw ewaluatorów:

Kategoria Ewaluatorzy
Zachowanie agenta intent_resolution, , task_adherence, , task_completiontask_navigation_efficiency
Użycie narzędzia tool_call_accuracy, , tool_selection, tool_input_accuracy, , tool_output_utilizationtool_call_success
Jakości coherence, , fluency, relevance, groundedness, , response_completenesssimilarity
Safety violence, , sexual, , self_harmhate_unfairness

Uwaga / Notatka

FoundryEvals wymaga projektu Azure AI Foundry z wdrożeniem modelu AI. Parametr model wskazuje, który model ma być używany jako oceniający LLM.

Oceń agenta

Najprostszy scenariusz oceny polega na testowaniu agenta przy użyciu zapytań testowych i ocenie skuteczności odpowiedzi. Zapewnij wiele różnorodnych zapytań na potrzeby statystycznie ważnej oceny.

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 to metoda rozszerzenia w metodzie AIAgent. Agent jest uruchamiany raz dla każdego zapytania, konwertuje każdą interakcję na EvalItem, i przekazuje partię do oceny.

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 uruchamia agenta raz na zapytanie, konwertuje każdą interakcję na element EvalItemi przekazuje partię do ewaluatora. Zwraca jednego EvalResults na dostawcę ewaluatora.

Mierzenie spójności za pomocą powtórzeń

Uruchom każde zapytanie wiele razy, aby wykryć zachowanie niedeterministyczne:

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)

Ocena przy użyciu oczekiwanych danych wyjściowych

Podaj podstawowe informacje oczekiwane odpowiedzi na ocenę poprawności. Oczekiwane dane wyjściowe są sparowane pozycjonalnie z zapytaniami:

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

Można również określić oczekiwane wywołania narzędzi:

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

Można również określić oczekiwane wywołania narzędzi:

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

Ocena wcześniej istniejących odpowiedzi

Jeśli masz już odpowiedzi agenta z dzienników lub poprzednich przebiegów, oceń je bezpośrednio bez ponownego uruchomienia 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 podziału konwersacji

Konwersacje wielozwrotne muszą być podzielone na części zapytań i odpowiedzi do oceny. Sposób dzielenia określa, co oceniasz.

Strategia Zachowanie Najlepsze dla
Ostatni ruch (wartość domyślna) Podziel na ostatni komunikat użytkownika. Wszystko przed nim to kontekst zapytania; wszystko po nim to odpowiedź. Jakość odpowiedzi w określonym punkcie
Pełny Pierwszym komunikatem użytkownika jest zapytanie; Cała reszta to odpowiedź. Ukończenie zadania i ogólna trajektoria
Na kolei Każda wymiana między użytkownikiem a asystentem jest oceniana niezależnie z uwzględnieniem kontekstu skumulowanego. Szczegółowa analiza
// 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);

Można również zaimplementować niestandardowy rozdzielacz, implementując metodę 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)

Możesz również podać niestandardowy rozdzielacz — dowolny obiekt wywołujący, który przyjmuje konwersację i zwraca wartość (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,
)

Ocena przepływów pracy

Ocenianie przepływów pracy z wieloma agentami przy użyciu podziału na agenta. Struktura wyodrębnia interakcje poszczególnych pod agentów i ocenia je indywidualnie wraz z ogólnymi danymi wyjściowymi przepływu pracy.

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

Możesz również przekazać queries bezpośrednio, a platforma uruchomi przepływ pracy dla Ciebie:

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

Mieszanie wielu ewaluatorów

Uruchamianie lokalnych kontroli i ewaluatorów opartych na chmurze w ramach jednej oceny. Każdy ewaluator tworzy własny 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}")

Ewaluatorzy MEAI

Struktura ewaluacji .NET integruje się bezpośrednio z ewaluatorami Microsoft.Extensions.AI.Evaluation. Ewaluatory jakości i bezpieczeństwa z MEAI działają bez adaptera:

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

Wskazówka

W przypadku korzystania z ewaluatorów MEAI podaj chatConfiguration parametr z klientem czatu skonfigurowanym dla modelu oceny. Ten klient jest używany przez ewaluatorów LLM jako sędzia do oceniania odpowiedzi.

Uwaga / Notatka

Obsługa tej funkcji w języku Go będzie dostępna wkrótce. Aktualny status znajdziesz w repozytorium Agent Framework dla Go.

Następne kroki