Udostępnij przez


Ocenianie agentów sztucznej inteligencji lokalnie (wersja zapoznawcza)

Uwaga / Notatka

Ten dokument odnosi się do portalu Microsoft Foundry (klasycznego).

🔄 Przejdź do dokumentacji Microsoft Foundry (nowej), jeśli korzystasz z nowego portalu.

Uwaga / Notatka

Ten dokument odnosi się do portalu Microsoft Foundry (nowy).

Ważne

Elementy oznaczone jako (wersja zapoznawcza) w tym artykule są aktualnie dostępne w publicznej wersji zapoznawczej. Ta wersja zapoznawcza jest udostępniana bez umowy dotyczącej poziomu usług i nie zalecamy korzystania z niej w przypadku obciążeń produkcyjnych. Niektóre funkcje mogą nie być obsługiwane lub mogą mieć ograniczone możliwości. Aby uzyskać więcej informacji, zobacz Uzupełniające warunki korzystania z wersji zapoznawczych platformy Microsoft Azure.

Agenci sztucznej inteligencji to zaawansowani asystenci produktywności, którzy tworzą przepływy pracy dla potrzeb biznesowych. Jednak obserwowanie jest trudne ze względu na ich złożone wzorce interakcji. Z tego artykułu dowiesz się, jak uruchamiać wbudowane ewaluatory lokalnie na prostych danych agenta lub komunikatach agenta.

Aby tworzyć aplikacje agentów gotowe do produkcji i zapewnić wgląd i przejrzystość, deweloperzy potrzebują narzędzi do oceny nie tylko końcowych danych wyjściowych przepływów pracy agenta, ale także jakości i wydajności przepływów pracy.

Zdarzenie takie jak użytkownik, który wykonuje zapytanie o "pogodę jutro", wyzwala agentyczny przepływ pracy. Aby utworzyć ostateczną odpowiedź, przepływ pracy obejmuje rozumowanie opierające się na intencjach użytkownika, wywoływanie narzędzi i używanie generowania wspomaganego wyszukiwaniem.

W tym procesie ocena każdego kroku przepływu pracy oraz jakość i bezpieczeństwo końcowych danych wyjściowych mają kluczowe znaczenie. Formułujemy te aspekty oceny w następujących ewaluatorach dla agentów:

Oceń inne aspekty jakości i bezpieczeństwa przepływów pracy agentów przy użyciu naszego kompleksowego zestawu wbudowanych ewaluatorów. Ogólnie rzecz biorąc, agenci emitują komunikaty agentów. Przekształcanie komunikatów agenta w poprawne dane ewaluacyjne dla naszych ewaluatorów może być trudne. Jeśli tworzysz agenta przy użyciu Foundry Agent Service, możesz łatwo ocenić go za pomocą naszego wsparcia konwertera. Jeśli zbudujesz agenta poza usługą Foundry Agent Service, nadal możesz użyć naszych ewaluatorów w odpowiedni sposób do przepływu pracy twojego agenta przez przeanalizowanie komunikatów agenta w wymaganych formatach danych. Zobacz przykłady oceny innych agentów.

Jako najlepsza praktyka, kluczowe jest wykonanie następujących czynności:

  • Ocena systemu: ocena ogólnej jakości i wydajności przepływu pracy agenta; i
  • Ocena procesu: ocena narzędzia wywołującego kroki przepływu pracy.

Zobacz narzędzia oceny agentów, aby uzyskać szczegółowe informacje na temat przypadków użycia tych dwóch praktyk i przykłady każdego z narzędzi oceny agenta.

Możesz również ocenić inne aspekty jakości i bezpieczeństwa przepływów pracy agentów, korzystając z naszego kompleksowego zestawu wbudowanych ewaluatorów lub pisania niestandardowych ewaluatorów.

Jeśli tworzysz Agentów Foundry, możesz bezproblemowo ich ocenić.

Jeśli tworzysz agentów poza usługą Foundry, nadal możesz używać naszych ewaluatorów odpowiednio do przepływu pracy agenta, analizujejąc komunikaty agenta w wymaganych formatach danych. Zobacz szczegóły w temacie Ocena innych agentów.

Wprowadzenie

Zainstaluj pakiet ewaluatorów z zestawu SDK oceny sztucznej inteligencji platformy Azure:

pip install azure-ai-evaluation

Zainstaluj pakiet z zestawu SDK oceny sztucznej inteligencji platformy Azure:

pip install "azure-ai-projects>=2.0.0b1" azure-identity python-dotenv

Ustaw następujące zmienne środowiskowe przy użyciu wartości w .env pliku:

AZURE_AI_PROJECT_ENDPOINT="<your-endpoint>" # The Azure AI Project project endpoint, as found in the Home page of your Microsoft Foundry portal.
AZURE_AI_MODEL_DEPLOYMENT_NAME="<your-model-deployment-name>" # The deployment name of the AI model, as found under the "Build" page in the "Models" tab in your Foundry project.

Ocena agentów Microsoft Foundry

Jeśli używasz Agent Foundry, możesz bezproblemowo ocenić swoich agentów, dzięki wsparciu konwertera dla agentów Microsoft Foundry i agentów Semantic Kernel. Następujący ewaluatorzy obsługują dane oceny zwracane przez konwerter: IntentResolution, , ToolCallAccuracyTaskAdherence, Relevancei Groundedness.

Uwaga / Notatka

Jeśli tworzysz innych agentów, którzy generują inny schemat, przekonwertuj je na ogólny schemat komunikatów agenta w stylu OpenAI i użyj powyższych ewaluatorów. Ogólnie rzecz biorąc, jeśli możesz przeanalizować komunikaty agenta w wymaganych formatach danych, możesz również użyć wszystkich naszych ewaluatorów.

Obsługa modelu dla ewaluatorów wspomaganych przez sztuczną inteligencję

Modele rozumowania AzureOpenAI i OpenAI oraz modele niezwiązane z rozumowaniem obsługują sędziego LLM w zależności od ewaluatorów:

Oceniających Modele rozumowania jako sędzia (przykład: modele serii o z usługi Azure OpenAI / OpenAI) Modele nierozumujące w roli sędziego (na przykład: gpt-4.1, gpt-4o itp.) Aby włączyć
IntentResolution, TaskAdherence, , , ToolCallAccuracyResponseCompletenessCoherenceFluencySimilarityGroundednessRetrievalRelevance Wsparte Wsparte Ustawianie dodatkowego parametru is_reasoning_model=True podczas inicjowania ewaluatorów
Inni ewaluatorzy Nie jest obsługiwany Wsparte --

W przypadku złożonej oceny wymagającej uściślenia rozumowania należy użyć silnego modelu rozumowania, takiego jak 4.1-mini w celu zrównoważenia wydajności i wydajności kosztów.

Obsługa oceny wywołań narzędzi

ToolCallAccuracyEvaluator program obsługuje ocenę w programie Microsoft Foundry Agent dla następujących narzędzi:

  • Wyszukiwanie plików
  • Wyszukiwanie AI platformy Azure
  • Uziemienia Bing
  • wyszukiwanie niestandardowe Bing
  • Podstawy programu SharePoint
  • Interpreter kodów
  • Agent danych sieci szkieletowej
  • Interfejs OpenAPI
  • Narzędzie funkcji (narzędzia zdefiniowane przez użytkownika)

Jeśli jednak używasz nieobsługiwanego narzędzia podczas uruchamiania agenta, ewaluator zwraca wynik "pass" i powód, dla którego ocena wywoływanych narzędzi nie jest obsługiwana, aby ułatwić filtrowanie tych przypadków. Aby włączyć ocenę, opakuj narzędzia nieobsługiwane jako narzędzia zdefiniowane przez użytkownika.

W tym przykładzie pokazano, jak skompilować i ocenić agenta Microsoft Foundry. Oddzielnie od oceny usługa agenta Foundry wymaga pip install azure-ai-projects azure-identity, łańcucha połączenia projektu Foundry i obsługiwanych modeli.

Tworzenie wątków i uruchamianie agenta

Agenci mogą używać narzędzi. Oto przykład tworzenia niestandardowych narzędzi do użycia przez agenta (przy użyciu fikcyjnej funkcji pogodowej jako przykładu):

from azure.ai.projects.models import FunctionTool, ToolSet
from typing import Set, Callable, Any
import json

# Define a custom Python function.
def fetch_weather(location: str) -> str:
    """
    Fetches the weather information for the specified location.

    :param location (str): The location to fetch weather for.
    :return: Weather information as a JSON string.
    :rtype: str
    """
    # In a real-world scenario, you'd integrate with a weather API.
    # In the following code snippet, we mock the response.
    mock_weather_data = {"Seattle": "Sunny, 25°C", "London": "Cloudy, 18°C", "Tokyo": "Rainy, 22°C"}
    weather = mock_weather_data.get(location, "Weather data not available for this location.")
    weather_json = json.dumps({"weather": weather})
    return weather_json

user_functions: Set[Callable[..., Any]] = {
    fetch_weather,
}

# Add tools that the agent will use. 
functions = FunctionTool(user_functions)

toolset = ToolSet()
toolset.add(functions)

AGENT_NAME = "Seattle Tourist Assistant"

Jeśli używasz projektu Foundry (niebędącego Hubem), utwórz agenta z zestawem narzędzi w następujący sposób:

Uwaga / Notatka

Jeśli używasz projektu opartego na usłudze Foundry Hub (który obsługuje tylko niższe wersje azure-ai-projects<1.0.0b10 azure-ai-agents<1.0.0b10), zdecydowanie zalecamy migrację do najnowszej biblioteki klienta zestawu SDK agenta programu Foundry w języku Python z projektem Foundry skonfigurowanym do rejestrowania wyników oceny wsadowej.

Utwórz agenta przy użyciu zestawu narzędzi w następujący sposób:

import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv

load_dotenv()

# Create an Azure AI Client from an endpoint, copied from your Foundry project.
# You need to login to Azure subscription via Azure CLI and set the environment variables
# Foundry project endpoint, example: AZURE_AI_PROJECT=https://your-account.services.ai.azure.com/api/projects/your-project
project_endpoint = os.environ["AZURE_AI_PROJECT"]  # Ensure the PROJECT_ENDPOINT environment variable is set

# Create an AIProjectClient instance
project_client = AIProjectClient(
    endpoint=project_endpoint,
    credential=DefaultAzureCredential(),  # Use Azure Default Credential for authentication
)


# Create an agent with the toolset 
agent = project_client.agents.create_agent(
    model=os.environ["MODEL_DEPLOYMENT_NAME"],  # Model deployment name
    name="my-agent",  # Name of the agent
    instructions="You are a helpful agent",  # Instructions for the agent
    toolset=toolset
)
print(f"Created agent, ID: {agent.id}")

# Create a thread for communication
thread = project_client.agents.threads.create()
print(f"Created thread, ID: {thread.id}")

# Add a message to the thread
message = project_client.agents.messages.create(
    thread_id=thread.id,
    role="user",  # Role of the message sender
    content="What is the weather in Seattle today?",  # Message content
)
print(f"Created message, ID: {message['id']}")

# Create and process an agent run
run = project_client.agents.runs.create_and_process(thread_id=thread.id, agent_id=agent.id)
print(f"Run finished with status: {run.status}")

# Check if the run failed
if run.status == "failed":
    print(f"Run failed: {run.last_error}")

# Fetch and log all messages
messages = project_client.agents.messages.list(thread_id=thread.id)
for message in messages:
    print(f"Role: {message.role}, Content: {message.content}")

Ocena uruchomienia pojedynczego agenta

Po utworzeniu uruchomień agenta możesz użyć naszego konwertera, aby przekształcić dane wątku agenta Microsoft Foundry w wymagane dane ewaluacyjne, które mogą zostać zrozumiane przez ewaluatorów.

import json, os
from azure.ai.evaluation import AIAgentConverter, IntentResolutionEvaluator

# Initialize the converter for Microsoft Foundry agents.
converter = AIAgentConverter(project_client)

# Specify the thread and run ID.
thread_id = thread.id
run_id = run.id

converted_data = converter.convert(thread_id, run_id)

To wszystko! converted_data zawiera wszystkie dane wejściowe wymagane dla tych ewaluatorów. Nie musisz odczytywać wymagań dotyczących danych wejściowych dla każdego ewaluatora ani wykonywać żadnej pracy w celu przeanalizowanie danych wejściowych. Wybierz ewaluatora i wywołaj ewaluatora w tym pojedynczym przebiegu. Obsługujemy modele rozumowania usługi Azure OpenAI lub OpenAI oraz modele niezwiązane z rozumowaniem dla sędziego w zależności od ewaluatorów:

Oceniających Modele rozumowania jako sędzia (przykład: modele serii o z usługi Azure OpenAI / OpenAI) Modele nierozumujące w roli sędziego (na przykład: gpt-4.1, gpt-4o itp.) Aby włączyć
Wszyscy ewaluatorzy jakości z wyjątkiem GroundednessProEvaluator Wsparte Wsparte Ustawianie dodatkowego parametru is_reasoning_model=True podczas inicjowania ewaluatorów
GroundednessProEvaluator Użytkownik nie musi obsługiwać modelu Użytkownik nie musi obsługiwać modelu --

W przypadku złożonych zadań wymagających zaawansowanego rozumowania do oceny zalecamy użycie silnego modelu rozumowania, takiego jak o3-mini lub mini modele serii o wydane później z równowagą pomiędzy wydajnością w zakresie rozumowania a efektywnością kosztową.

Skonfigurowaliśmy listę ewaluatorów jakości i bezpieczeństwa w quality_evaluators i safety_evaluators oraz odwołujemy się do nich podczas oceny przebiegów wielokrotnych agentów lub wątku.

# This is specific to agentic workflows.
from azure.ai.evaluation import IntentResolutionEvaluator, TaskAdherenceEvaluator, ToolCallAccuracyEvaluator 
# Other quality, risk, and safety metrics:
from azure.ai.evaluation import RelevanceEvaluator, CoherenceEvaluator, CodeVulnerabilityEvaluator, ContentSafetyEvaluator, IndirectAttackEvaluator, FluencyEvaluator
from azure.identity import DefaultAzureCredential

import os
from dotenv import load_dotenv
load_dotenv()

model_config = {
    "azure_deployment": os.getenv("AZURE_DEPLOYMENT_NAME"),
    "api_key": os.getenv("AZURE_API_KEY"),
    "azure_endpoint": os.getenv("AZURE_ENDPOINT"),
    "api_version": os.getenv("AZURE_API_VERSION"),
}

# example config for a reasoning model
reasoning_model_config = {
    "azure_deployment": "o3-mini",
    "api_key": os.getenv("AZURE_API_KEY"),
    "azure_endpoint": os.getenv("AZURE_ENDPOINT"),
    "api_version": os.getenv("AZURE_API_VERSION"),
}

# Evaluators you might want to use with reasoning models 
quality_evaluators = {evaluator.__name__: evaluator(model_config=reasoning_model_config, is_reasoning_model=True) for evaluator in [IntentResolutionEvaluator, TaskAdherenceEvaluator, ToolCallAccuracyEvaluator]}

# Other evaluators you might NOT want to use with reasoning models 
quality_evaluators.update({ evaluator.__name__: evaluator(model_config=model_config) for evaluator in [CoherenceEvaluator, FluencyEvaluator, RelevanceEvaluator]})

## Using Foundry (non-Hub) project endpoint, example: AZURE_AI_PROJECT=https://your-account.services.ai.azure.com/api/projects/your-project
azure_ai_project = os.environ.get("AZURE_AI_PROJECT")

safety_evaluators = {evaluator.__name__: evaluator(azure_ai_project=azure_ai_project, credential=DefaultAzureCredential()) for evaluator in [ContentSafetyEvaluator, IndirectAttackEvaluator, CodeVulnerabilityEvaluator]}

# Reference the quality and safety evaluator list above.
quality_and_safety_evaluators = {**quality_evaluators, **safety_evaluators}

for name, evaluator in quality_and_safety_evaluators.items():
    result = evaluator(**converted_data)
    print(name)
    print(json.dumps(result, indent=4)) 

Format wyjściowy

Ewaluatory jakości wspomagane przez sztuczną inteligencję zwracają wynik dla pary zapytań i odpowiedzi. Wynik jest słownikiem zawierającym następujące elementy:

  • {metric_name}: Zapewnia wynik liczbowy w skali Likerta (liczba całkowita od 1 do 5) lub wartość zmiennoprzecinkową w przedziale od 0 do 1.
  • {metric_name}_label: Zawiera etykietę binarną (jeśli metryka naturalnie generuje wynik binarny).
  • {metric_name}_reason: wyjaśnia, dlaczego dla każdego punktu danych podano określony wynik lub etykietę.
  • details: opcjonalne dane wyjściowe zawierające informacje debugowania dotyczące jakości pojedynczego uruchomienia agenta.

Aby zwiększyć przejrzystość, wszyscy ewaluatorzy akceptują próg binarny (chyba że ich dane wyjściowe są już binarne) i generują dwa nowe klucze. Dla progu binaryzacji ustawiono wartość domyślną, którą użytkownik może zastąpić. Dwa nowe klucze to:

  • {metric_name}_result: ciąg "pass" lub "fail" na podstawie progu binaryzacji.
  • {metric_name}_threshold: Wartość progowa binaryzacji liczbowa ustawiona domyślnie lub przez użytkownika.

Zobacz następujące przykładowe dane wyjściowe dla niektórych ewaluatorów:

{
    "intent_resolution": 5.0, # likert scale: 1-5 integer 
    "intent_resolution_threshold": 3,
    "intent_resolution_result": "pass", # pass because 5 > 3 the threshold
    "intent_resolution_reason": "The assistant correctly understood the user's request to fetch the weather in Seattle. It used the appropriate tool to get the weather information and provided a clear and accurate response with the current weather conditions in Seattle. The response fully resolves the user's query with all necessary information."
}
{
    "task_adherence": 5.0, # likert scale: 1-5 integer 
    "task_adherence_threshold": 3,
    "task_adherence_result": "pass", # pass because 5 > 3 the threshold
    "task_adherence_reason": "The response accurately follows the instructions, fetches the correct weather information, and relays it back to the user without any errors or omissions."
}
{
    "tool_call_accuracy": 5,  # a score between 1-5, higher is better
    "tool_call_accuracy_threshold": 3,
    "tool_call_accuracy_result": "pass", # pass because 5 > 3 the threshold
    "details": { ... } # helpful details for debugging the tool calls made by the agent
}

Ocena wielu przebiegów agentów lub wątków

Do oceny wielu przebiegów agentów lub wątków, użyj Batch API evaluate() do oceny asynchronicznej. Najpierw przekonwertuj dane wątku agenta na plik za pomocą naszego narzędzia konwertera.

import json
from azure.ai.evaluation import AIAgentConverter

# Initialize the converter.
converter = AIAgentConverter(project_client)

# Specify a file path to save the agent output (evaluation input data) to.
filename = os.path.join(os.getcwd(), "evaluation_input_data.jsonl")

evaluation_data = converter.prepare_evaluation_data(thread_ids=thread_id, filename=filename) 

print(f"Evaluation data saved to {filename}")

Dzięki danym oceny przygotowanym w jednym wierszu kodu możesz wybrać oceniających, aby ocenić jakość agenta i przeprowadzić wsadową ocenę. W poniższym przykładzie odwołujemy się do tej samej listy ewaluatorów jakości i bezpieczeństwa w sekcji Ocena pojedynczego uruchomieniaquality_and_safety_evaluators agenta:

import os
from dotenv import load_dotenv
load_dotenv()


# Batch evaluation API (local):
from azure.ai.evaluation import evaluate

response = evaluate(
    data=filename,
    evaluation_name="agent demo - batch run",
    evaluators=quality_and_safety_evaluators,
    # optionally, log your results to your Foundry project for rich visualization 
    azure_ai_project=os.environ.get("AZURE_AI_PROJECT"),  # example: https://your-account.services.ai.azure.com/api/projects/your-project
)
# Inspect the average scores at a high level.
print(response["metrics"])
# Use the URL to inspect the results on the UI.
print(f'Foundry URL: {response.get("studio_url")}')

Po wybraniu adresu URL nastąpi przekierowanie do witryny Foundry. Wyświetl wyniki oceny w projekcie Foundry i debuguj aplikację. Użyj pól przyczynowych i wyników pass/fail, aby ocenić jakość i bezpieczeństwo aplikacji. Możesz uruchomić i porównać wiele przebiegów w celu przetestowania pod kątem regresji lub ulepszeń.

Skorzystaj z biblioteki klienta zestawu SDK do oceny sztucznej inteligencji platformy Azure, aby ocenić agentów Microsoft Foundry z obsługą konwerterów, dzięki czemu można obserwować i zapewnić przejrzystość przepływów pracy agentów.

Możesz bezproblemowo oceniać agentów usługi Foundry, korzystając z ewaluatorów agentów i ewaluatorów RAG. W tej sekcji opisano proces tworzenia agenta i oceniania go.

Uwaga / Notatka

Jeśli tworzysz innych agentów, którzy generują inny schemat, przekonwertuj je na ogólny schemat komunikatów agenta w stylu OpenAI i użyj powyższych ewaluatorów. Ogólnie rzecz biorąc, jeśli możesz przeanalizować komunikaty agenta w wymaganych formatach danych, możesz również użyć wszystkich naszych ewaluatorów.

Wymagania wstępne

import json
from azure.ai.projects.models import Tool, FunctionTool

# Define a function tool for the model to use
func_tool = fetch_weather(
    name="fetch_weather",
    parameters={
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The location to fetch weather for.",
            },
        },
        "required": ["location"],
        "additionalProperties": False,
    },
    description="Get the current weather for a location.",
    strict=True,
)

tools: list[Tool] = [func_tool]

# Define a custom Python function.
async def fetch_weather(location: str) -> str:
    """
    Fetches the weather information for the specified location.

    :param location (str): The location to fetch weather for.
    :return: Weather information as a JSON string.
    :rtype: str
    """
    # In a real-world scenario, you'd integrate with a weather API.
    # In the following code snippet, we mock the response.
    mock_weather_data = {"Seattle": "Sunny, 25°C", "London": "Cloudy, 18°C", "Tokyo": "Rainy, 22°C"}
    weather = mock_weather_data.get(location, "Weather data not available for this location.")
    weather_json = json.dumps({"weather": weather})
    return weather_json

Skonfiguruj agenta przy użyciu zestawu narzędzi i utwórz przebieg odpowiedzi w celu oceny.

Utwórz agenta przy użyciu zestawu narzędzi w następujący sposób:

import os
import json
from dotenv import load_dotenv
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import PromptAgentDefinition
from azure.identity import DefaultAzureCredential
from openai.types.responses.response_input_param import FunctionCallOutput, ResponseInputParam

credential = DefaultAzureCredential()


project_client = AIProjectClient(
    endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
    credential=DefaultAzureCredential(),
)

with project_client:

    openai_client = project_client.get_openai_client()

    agent = await project_client.agents.create_version(
        agent_name="MyAgent",
        definition=PromptAgentDefinition(
            model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
            instructions="You are a helpful assistant that can use function tools.",
            tools=tools,
        ),
    )

    print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})")

    conversation = openai_client.conversations.create(
        items=[{"type": "message", "role": "user", "content": "What is the weather in Seattle?"}],
    )
    print(f"Created conversation with initial user message (id: {conversation.id})")

    response = openai_client.responses.create(
        conversation=conversation.id,
        extra_body={"agent": {"name": agent.name, "type": "agent_reference"}},
    )
    print(f"Response output: {response.output_text} (id: {response.id})")


    # Now create evaluation for the response
    data_source_config = {"type": "azure_ai_source", "scenario": "responses"}

    # add your desired evaluators here
    testing_criteria = [
        {"type": "azure_ai_evaluator", "name": "task_adherence", "evaluator_name": "builtin.task_adherence"},
        {"type": "azure_ai_evaluator", "name": "groundedness", "evaluator_name": "builtin.groundedness"},
    ]
    eval_object = openai_client.evals.create(
        name="Agent Response Evaluation",
        data_source_config=data_source_config,
        testing_criteria=testing_criteria,
    )
    print(f"Evaluation created (id: {eval_object.id}, name: {eval_object.name})")

    data_source = {
        "type": "azure_ai_responses",
        "item_generation_params": {
            "type": "response_retrieval",
            "data_mapping": {"response_id": "{{item.resp_id}}"},
            "source": {"type": "file_content", "content": [{"item": {"resp_id": response.id}}]},
        },
    }

    response_eval_run = openai_client.evals.runs.create(
        eval_id=eval_object.id, name=f"Evaluation Run for Agent {agent.name}", data_source=data_source
    )
    print(f"Evaluation run created (id: {response_eval_run.id})")

    while response_eval_run.status not in ["completed", "failed"]:
        response_eval_run = openai_client.evals.runs.retrieve(run_id=response_eval_run.id, eval_id=eval_object.id)
        print(f"Waiting for eval run to complete... current status: {response_eval_run.status}")
        time.sleep(5)

    if response_eval_run.status == "completed":
        print("\n✓ Evaluation run completed successfully!")
        print(f"Result Counts: {response_eval_run.result_counts}")
        print(f"Eval Run Report URL: {response_eval_run.report_url}")
        output_items = list(
            openai_client.evals.runs.output_items.list(run_id=response_eval_run.id, eval_id=eval_object.id)
        )
        print(f"\nOUTPUT ITEMS (Total: {len(output_items)})")
        print(f"{'-'*60}")
        pprint(output_items)
        print(f"{'-'*60}")
    else:
        print("\n✗ Evaluation run failed.")

Interpretacja wyników

W przypadku pojedynczego przykładu danych wszyscy ewaluatorzy zawsze generują następujący schemat:

  • Etykieta: binarna etykieta "pass" lub "fail", podobna do danych wyjściowych testu jednostkowego. Użyj tego wyniku, aby ułatwić porównania między ewaluatorami.
  • Wynik: wynik z naturalnej skali każdego ewaluatora. Niektórzy ewaluatorzy używają szczegółowej rubryki, oceniają na 5-punktowej skali (ewaluatorzy jakości) lub 7-punktowej skali (ewaluatorzy bezpieczeństwa treści). Inne, takie jak ewaluatory podobieństw tekstowych, używają wyników F1, które są liczbami zmiennoprzecinkowymi w zakresie od 0 do 1. Pole "etykieta" przypisuje wartość binarną dowolnemu niebinarnemu "wynikowi" na "zaliczony" lub "niezaliczony" na podstawie wartości "progu".
  • Próg: wszystkie wyniki inne niż dwuwartościowe są przekształcane w "przekazanie" lub "niepowodzenie" na podstawie domyślnej wartości progu, którą można zmienić w środowisku SDK.
  • Powód: Aby zwiększyć zrozumiałość, wszyscy ewaluatorzy LLM-judge również wyświetlają pole rozumowania, aby wyjaśnić, dlaczego dany wynik jest podany.
  • Szczegóły: (opcjonalnie) W przypadku niektórych ewaluatorów, takich jak tool_call_accuracy, może istnieć pole lub flagi zawierające dodatkowe informacje ułatwiające użytkownikom debugowanie aplikacji. W przypadku agregowania wyników z wielu przykładów (zestawu danych), średni współczynnik przykładów z "zdaniem" stanowi współczynnik zdawalności dla tego zestawu danych.

Po adresie URL nastąpi przekierowanie do usługi Foundry. Wyniki oceny można wyświetlić w projekcie foundry i debugować aplikację. Użyj pól "reason" i pass/fail, aby ocenić jakość i bezpieczeństwo aplikacji. Możesz uruchomić i porównać wiele przebiegów w celu przetestowania pod kątem regresji lub ulepszeń.

Skorzystaj z biblioteki klienta zestawu Microsoft Foundry SDK języka Python, aby ocenić agentów rozwiązania Microsoft Foundry, umożliwiając obserwowanie i przejrzystość w przepływach pracy agenta.

Ocena innych agentów

Jeśli używasz agentów spoza Agent Service, nadal możesz ich ocenić, przygotowując odpowiednie dane dla wybranych ewaluatorów.

Agenci zazwyczaj emitują komunikaty w celu interakcji z użytkownikiem lub innymi agentami. Wbudowane ewaluatory akceptują proste typy danych, takie jak ciągi w query, response i ground_truth zgodnie z wymaganiami dotyczącymi jednokrotnego wprowadzania danych. Jednak wyodrębnianie tych prostych typów danych z komunikatów agenta może być trudne ze względu na złożone wzorce interakcji agentów i różnic w strukturze. Na przykład pojedyncze zapytanie użytkownika może wyzwolić długą listę komunikatów agenta, zazwyczaj z wieloma wywołaniami narzędzi.

Agenci zazwyczaj emitują komunikaty w celu interakcji z użytkownikiem lub innymi agentami. Wbudowane oceniające mogą akceptować proste typy danych, takie jak ciągi w query, response i ground_truth zgodnie z wymaganiami dotyczącymi jednoprzekazowych danych wejściowych. Jednak może to stanowić wyzwanie, aby wyodrębnić te proste typy danych z komunikatów agenta ze względu na złożone wzorce interakcji agentów i różnic w strukturze. Na przykład pojedyncze zapytanie użytkownika może wyzwolić długą listę komunikatów agenta, zazwyczaj z wieloma wywołaniami narzędzi.

Jak pokazano w poniższym przykładzie, włączamy obsługę komunikatów agenta dla następujących wbudowanych ewaluatorów, aby ocenić te aspekty przepływu pracy agenta. Ci ewaluatorzy mogą przyjmować tool_calls lub tool_definitions jako parametry unikatowe dla agentów podczas oceniania agentów.

Oceniacz query response tool_calls tool_definitions
IntentResolutionEvaluator Wymagane: Union[str, list[Message]] Wymagane: Union[str, list[Message]] Nie ma zastosowania Fakultatywny: list[ToolCall]
ToolCallAccuracyEvaluator Wymagane: Union[str, list[Message]] Fakultatywny: Union[str, list[Message]] Fakultatywny: Union[dict, list[ToolCall]] Wymagane: list[ToolDefinition]
TaskAdherenceEvaluator Wymagane: Union[str, list[Message]] Wymagane: Union[str, list[Message]] Nie ma zastosowania Fakultatywny: list[ToolCall]
GroundednessEvaluator Wymagane: Union[str, list[Message]] Wymagane: Union[str, list[Message]] Nie ma zastosowania Wymagane: list[ToolCall]
  • Message: dict komunikat typu OpenAI, który opisuje interakcje agenta z użytkownikiem, gdzie query musi zawierać komunikat systemowy jako pierwszy komunikat.
  • ToolCall: dict określa wywołania narzędzi wywoływane podczas interakcji agenta z użytkownikiem.
  • ToolDefinition: dict opis narzędzi dostępnych dla agenta.

W przypadku ToolCallAccuracyEvaluatorelementu należy podać wartość response lub tool_calls.

GroundednessEvaluator wymaga tool_definitions oceny solidności odpowiedzi agenta w odniesieniu do wyników narzędzi otrzymywanych przez agenta.

W poniższych przykładach przedstawiono dwa formaty danych: proste dane agenta i komunikaty agenta. Jednak ze względu na unikatowe wymagania tych ewaluatorów zalecamy odwołanie się do przykładowych notesów, które ilustrują możliwe ścieżki wejściowe dla każdego ewaluatora.

Podobnie jak inne wbudowane ewaluatory jakości wspomagane sztuczną inteligencją, IntentResolutionEvaluator oraz TaskAdherenceEvaluator generują wyniki w skali Likerta (liczba całkowita 1–5; wyższe wyniki oznaczają lepszą jakość). ToolCallAccuracyEvaluator Generuje współczynnik przejścia wszystkich wykonanych wywołań narzędziowych (wartość zmiennoprzecinkowa z zakresu od 0 do 1) na podstawie zapytania użytkownika. Aby jeszcze bardziej zwiększyć zrozumiałość, wszyscy ewaluatorzy akceptują próg binarny i generują dwa nowe klucze. Dla progu binaryzacji ustawiono wartość domyślną i można ją zastąpić. Dwa nowe klucze to:

  • {metric_name}_result: ciąg "pass" lub "fail" na podstawie progu binaryzacji.
  • {metric_name}_threshold: Wartość progowa binaryzacji liczbowa ustawiona domyślnie lub przez użytkownika.

Proste dane agenta

W prostym formacie danych agenta query i response to proste ciągi języka Python. Przykład:

import os
import json
from azure.ai.evaluation import AzureOpenAIModelConfiguration
from azure.identity import DefaultAzureCredential
from azure.ai.evaluation import IntentResolutionEvaluator, ResponseCompletenessEvaluator

model_config = AzureOpenAIModelConfiguration(
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    api_key=os.environ["AZURE_OPENAI_API_KEY"],
    api_version=os.environ["AZURE_OPENAI_API_VERSION"],
    azure_deployment=os.environ["MODEL_DEPLOYMENT_NAME"],
)

intent_resolution_evaluator = IntentResolutionEvaluator(model_config)

# Evaluate the query and response as strings.
# The following is a positive example. Intent is identified and understood and the response correctly resolves user intent.
result = intent_resolution_evaluator(
    query="What are the opening hours of the Eiffel Tower?",
    response="Opening hours of the Eiffel Tower are 9:00 AM to 11:00 PM.",
)
print(json.dumps(result, indent=4))

Aby uzyskać szczegółowe informacje, zobacz następujące dane wyjściowe (zobacz Format danych wyjściowych ):

{
    "intent_resolution": 5.0,
    "intent_resolution_result": "pass",
    "intent_resolution_threshold": 3,
    "intent_resolution_reason": "The response provides the opening hours of the Eiffel Tower, which directly addresses the user's query. The information is clear, accurate, and complete, fully resolving the user's intent.",
}

Wywołania i definicje narzędzi agenta

Zobacz następujące przykłady elementów tool_calls i tool_definitions dla ToolCallAccuracyEvaluator:

import json 

query = "How is the weather in Seattle?"
tool_calls = [{
                    "type": "tool_call",
                    "tool_call_id": "call_CUdbkBfvVBla2YP3p24uhElJ",
                    "name": "fetch_weather",
                    "arguments": {
                        "location": "Seattle"
                    }
            },
            {
                    "type": "tool_call",
                    "tool_call_id": "call_CUdbkBfvVBla2YP3p24uhElJ",
                    "name": "fetch_weather",
                    "arguments": {
                        "location": "London"
                    }
            }]

tool_definitions = [{
                    "name": "fetch_weather",
                    "description": "Fetches the weather information for the specified location.",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "location": {
                                "type": "string",
                                "description": "The location to fetch weather for."
                            }
                        }
                    }
                }]

from azure.ai.evaluation import ToolCallAccuracyEvaluator

tool_call_accuracy = ToolCallAccuracyEvaluator(model_config) # reuse the config defined above
response = tool_call_accuracy(query=query, tool_calls=tool_calls, tool_definitions=tool_definitions)
print(json.dumps(response, indent=4))

Aby uzyskać szczegółowe informacje, zobacz następujące dane wyjściowe ( format referencyjny danych wyjściowych ):

{
    "tool_call_accuracy": 3,  # a score between 1-5, higher is better
    "tool_call_accuracy_result": "fail",
    "tool_call_accuracy_threshold": 4,
    "details": { ... } # helpful details for debugging the tool calls made by the agent
}

Zobacz następujące przykłady elementów tool_calls i tool_definitions dla tool_call_accuracy:

import json 

query = "How is the weather in Seattle?"
tool_calls = [{
                    "type": "tool_call",
                    "tool_call_id": "call_CUdbkBfvVBla2YP3p24uhElJ",
                    "name": "fetch_weather",
                    "arguments": {
                        "location": "Seattle"
                    }
            },
            {
                    "type": "tool_call",
                    "tool_call_id": "call_CUdbkBfvVBla2YP3p24uhElJ",
                    "name": "fetch_weather",
                    "arguments": {
                        "location": "London"
                    }
            }]

tool_definitions = [{
                    "name": "fetch_weather",
                    "description": "Fetches the weather information for the specified location.",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "location": {
                                "type": "string",
                                "description": "The location to fetch weather for."
                            }
                        }
                    }
                }]

Schemat komunikatu agenta

Format wiadomości agenta, query i response to lista wiadomości stylu OpenAI. W szczególności query prowadzi wcześniejsze interakcje agenta-użytkownika prowadzące do ostatniego zapytania użytkownika i wymaga komunikatu systemowego (agenta) w górnej części listy. response zawiera ostatni komunikat agenta w odpowiedzi na ostatnie zapytanie użytkownika.

Oczekiwany format danych wejściowych dla ewaluatorów to lista komunikatów w języku Python w następujący sposób:

[
  {
    "role": "system" | "user" | "assistant" | "tool",
    "createdAt": "ISO 8601 timestamp",     // Optional for 'system'
    "run_id": "string",                    // Optional, only for assistant/tool in tool call context
    "tool_call_id": "string",              // Optional, only for tool/tool_result
    "name": "string",                      // Present if it's a tool call
    "arguments": { ... },                  // Parameters passed to the tool (if tool call)
    "content": [
      {
        "type": "text" | "tool_call" | "tool_result",
        "text": "string",                  // if type == text
        "tool_call_id": "string",         // if type == tool_call
        "name": "string",                 // tool name if type == tool_call
        "arguments": { ... },             // tool args if type == tool_call
        "tool_result": { ... }            // result if type == tool_result
      }
    ]
  }
]

Przykładowe obiekty zapytań i odpowiedzi:

query = [
    {
        "role": "system",
        "content": "You are an AI assistant interacting with Azure Maps services to serve user requests."
    },
    {
        "createdAt": "2025-04-25T23:55:43Z",
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "Find the address for coordinates 41.8781,-87.6298."
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:45Z",
        "run_id": "run_DGE8RWPS8A9SmfCg61waRx9u",
        "role": "assistant",
        "content": [
            {
                "type": "tool_call",
                "tool_call_id": "call_nqNyhOFRw4FmF50jaCCq2rDa",
                "name": "azure_maps_reverse_address_search",
                "arguments": {
                    "lat": "41.8781",
                    "lon": "-87.6298"
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:47Z",
        "run_id": "run_DGE8RWPS8A9SmfCg61waRx9u",
        "tool_call_id": "call_nqNyhOFRw4FmF50jaCCq2rDa",
        "role": "tool",
        "content": [
            {
                "type": "tool_result",
                "tool_result": {
                    "address": "300 South Federal Street, Chicago, IL 60604",
                    "position": {
                        "lat": "41.8781",
                        "lon": "-87.6298"
                    }
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:48Z",
        "run_id": "run_DGE8RWPS8A9SmfCg61waRx9u",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "The address for the coordinates 41.8781, -87.6298 is 300 South Federal Street, Chicago, IL 60604."
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:50Z",
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "What timezone corresponds to 41.8781,-87.6298?"
            }
        ]
    },
]

response = [
    {
        "createdAt": "2025-04-25T23:55:52Z",
        "run_id": "run_DmnhUGqYd1vCBolcjjODVitB",
        "role": "assistant",
        "content": [
            {
                "type": "tool_call",
                "tool_call_id": "call_qi2ug31JqzDuLy7zF5uiMbGU",
                "name": "azure_maps_timezone",
                "arguments": {
                    "lat": 41.878100000000003,
                    "lon": -87.629800000000003
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:54Z",
        "run_id": "run_DmnhUGqYd1vCBolcjjODVitB",
        "tool_call_id": "call_qi2ug31JqzDuLy7zF5uiMbGU",
        "role": "tool",
        "content": [
            {
                "type": "tool_result",
                "tool_result": {
                    "ianaId": "America/Chicago",
                    "utcOffset": None,
                    "abbreviation": None,
                    "isDaylightSavingTime": None
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:55Z",
        "run_id": "run_DmnhUGqYd1vCBolcjjODVitB",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "The timezone for the coordinates 41.8781, -87.6298 is America/Chicago."
            }
        ]
    }
]

Uwaga / Notatka

Oceniacz wyświetla ostrzeżenie, jeśli zapytanie (historia konwersacji aż do bieżącego uruchomienia) lub odpowiedź agenta (odpowiedź na zapytanie) nie jest w oczekiwanym formacie.

Zobacz przykład oceny komunikatów agenta za pomocą polecenia ToolCallAccuracyEvaluator:

import json

# The user asked a question.
query = [
    {
        "role": "system",
        "content": "You are a friendly and helpful customer service agent."
    },
    # Past interactions are omitted. 
    # ...
    {
        "createdAt": "2025-03-14T06:14:20Z",
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "Hi, I need help with the last 2 orders on my account #888. Could you please update me on their status?"
            }
        ]
    }
]
# The agent emits multiple messages to fulfill the request.
response = [
    {
        "createdAt": "2025-03-14T06:14:30Z",
        "run_id": "0",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "Hello! Let me quickly look up your account details."
            }
        ]
    },
    {
        "createdAt": "2025-03-14T06:14:35Z",
        "run_id": "0",
        "role": "assistant",
        "content": [
            {
                "type": "tool_call",
                "tool_call_id": "tool_call_20250310_001",
                "name": "get_orders",
                "arguments": {
                    "account_number": "888"
                }
            }
        ]
    },
    # Many more messages are omitted. 
    # ...
    # Here is the agent's final response:
    {
        "createdAt": "2025-03-14T06:15:05Z",
        "run_id": "0",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "The order with ID 123 has been shipped and is expected to be delivered on March 15, 2025. However, the order with ID 124 is delayed and should now arrive by March 20, 2025. Is there anything else I can help you with?"
            }
        ]
    }
]

# An example of tool definitions available to the agent:
tool_definitions = [
    {
        "name": "get_orders",
        "description": "Get the list of orders for a given account number.",
        "parameters": {
            "type": "object",
            "properties": {
                "account_number": {
                    "type": "string",
                    "description": "The account number to get the orders for."
                }
            }
        }
    },
    # Other tool definitions are omitted. 
    # ...
]

result = tool_call_accuracy(
    query=query,
    response=response,
    tool_definitions=tool_definitions 
)
print(json.dumps(result, indent=4))

Aby uzyskać szczegółowe informacje, zobacz następujące dane wyjściowe ( format referencyjny danych wyjściowych ):

{
    "tool_call_accuracy": 2,  # a score between 1-5, higher is better
    "tool_call_accuracy_result": "fail",
    "tool_call_accuracy_threshold": 3,
    "details": { ... } # helpful details for debugging the tool calls made by the agent
}
query = [
    {
        "role": "system",
        "content": "You are an AI assistant interacting with Azure Maps services to serve user requests."
    },
    {
        "createdAt": "2025-04-25T23:55:43Z",
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "Find the address for coordinates 41.8781,-87.6298."
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:45Z",
        "run_id": "run_DGE8RWPS8A9SmfCg61waRx9u",
        "role": "assistant",
        "content": [
            {
                "type": "tool_call",
                "tool_call_id": "call_nqNyhOFRw4FmF50jaCCq2rDa",
                "name": "azure_maps_reverse_address_search",
                "arguments": {
                    "lat": "41.8781",
                    "lon": "-87.6298"
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:47Z",
        "run_id": "run_DGE8RWPS8A9SmfCg61waRx9u",
        "tool_call_id": "call_nqNyhOFRw4FmF50jaCCq2rDa",
        "role": "tool",
        "content": [
            {
                "type": "tool_result",
                "tool_result": {
                    "address": "300 South Federal Street, Chicago, IL 60604",
                    "position": {
                        "lat": "41.8781",
                        "lon": "-87.6298"
                    }
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:48Z",
        "run_id": "run_DGE8RWPS8A9SmfCg61waRx9u",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "The address for the coordinates 41.8781, -87.6298 is 300 South Federal Street, Chicago, IL 60604."
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:50Z",
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "What timezone corresponds to 41.8781,-87.6298?"
            }
        ]
    },
]

response = [
    {
        "createdAt": "2025-04-25T23:55:52Z",
        "run_id": "run_DmnhUGqYd1vCBolcjjODVitB",
        "role": "assistant",
        "content": [
            {
                "type": "tool_call",
                "tool_call_id": "call_qi2ug31JqzDuLy7zF5uiMbGU",
                "name": "azure_maps_timezone",
                "arguments": {
                    "lat": 41.878100000000003,
                    "lon": -87.629800000000003
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:54Z",
        "run_id": "run_DmnhUGqYd1vCBolcjjODVitB",
        "tool_call_id": "call_qi2ug31JqzDuLy7zF5uiMbGU",
        "role": "tool",
        "content": [
            {
                "type": "tool_result",
                "tool_result": {
                    "ianaId": "America/Chicago",
                    "utcOffset": None,
                    "abbreviation": None,
                    "isDaylightSavingTime": None
                }
            }
        ]
    },
    {
        "createdAt": "2025-04-25T23:55:55Z",
        "run_id": "run_DmnhUGqYd1vCBolcjjODVitB",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "The timezone for the coordinates 41.8781, -87.6298 is America/Chicago."
            }
        ]
    }
]

Uwaga / Notatka

Ewaluator ostrzega, że nie może przeanalizować zapytania (historia konwersacji aż do bieżącego uruchomienia) lub odpowiedzi agenta (odpowiedź na zapytanie), gdy ich format nie jest zgodny z oczekiwaniami.

Więcej przykładów komunikatów agenta:

import json

# The user asked a question.
query = [
    {
        "role": "system",
        "content": "You are a friendly and helpful customer service agent."
    },
    # Past interactions are omitted. 
    # ...
    {
        "createdAt": "2025-03-14T06:14:20Z",
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "Hi, I need help with the last 2 orders on my account #888. Could you please update me on their status?"
            }
        ]
    }
]
# The agent emits multiple messages to fulfill the request.
response = [
    {
        "createdAt": "2025-03-14T06:14:30Z",
        "run_id": "0",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "Hello! Let me quickly look up your account details."
            }
        ]
    },
    {
        "createdAt": "2025-03-14T06:14:35Z",
        "run_id": "0",
        "role": "assistant",
        "content": [
            {
                "type": "tool_call",
                "tool_call_id": "tool_call_20250310_001",
                "name": "get_orders",
                "arguments": {
                    "account_number": "888"
                }
            }
        ]
    },
    # Many more messages are omitted. 
    # ...
    # Here is the agent's final response:
    {
        "createdAt": "2025-03-14T06:15:05Z",
        "run_id": "0",
        "role": "assistant",
        "content": [
            {
                "type": "text",
                "text": "The order with ID 123 has been shipped and is expected to be delivered on March 15, 2025. However, the order with ID 124 is delayed and should now arrive by March 20, 2025. Is there anything else I can help you with?"
            }
        ]
    }
]

# An example of tool definitions available to the agent:
tool_definitions = [
    {
        "name": "get_orders",
        "description": "Get the list of orders for a given account number.",
        "parameters": {
            "type": "object",
            "properties": {
                "account_number": {
                    "type": "string",
                    "description": "The account number to get the orders for."
                }
            }
        }
    },
    # Other tool definitions are omitted. 
    # ...
]

Ten schemat oceny pomaga przetwarzać dane agenta poza usługą agenta, umożliwiając korzystanie z wbudowanych ewaluatorów w celu wspierania obserwowalności w przepływach pracy agenta.

Przykładowe notesy

Wypróbuj przykład dla każdego z tych ewaluatorów:

Wypróbuj przykład dla każdego z tych ewaluatorów w repozytorium przykładowym.