Condividi tramite


Creare un giudice personalizzato usando make_judge()

I giudici personalizzati sono scorer basati su LLM che valutano gli agenti GenAI in base a criteri di qualità specifici. Questa esercitazione illustra come creare giudici personalizzati e usarli per valutare un agente di supporto clienti usando make_judge().

Si eseguiranno le seguenti attività:

  1. Creare un agente di esempio da valutare
  2. Definire tre giudici personalizzati per valutare criteri diversi
  3. Creare un set di dati di valutazione con test case
  4. Eseguire valutazioni e confrontare i risultati tra diverse configurazioni dell'agente

Passaggio 1: Creare un agente da valutare

Creare un agente GenAI che risponda alle domande del supporto tecnico. L'agente ha una finta manopola che controlla il prompt di sistema per confrontare facilmente gli output del giudice tra conversazioni "buone" e "cattive".

  1. Inizializza un client OpenAI per connettersi a LLM ospitati da Databricks o da OpenAI.

    Modelli di linguaggio di grandi dimensioni ospitati in Databricks

    Usare MLflow per ottenere un client OpenAI che si connette a LLM ospitati su Databricks. Selezionare un modello dai modelli di base disponibili.

    import mlflow
    from databricks.sdk import WorkspaceClient
    
    # Enable MLflow's autologging to instrument your application with Tracing
    mlflow.openai.autolog()
    
    # Set up MLflow tracking to Databricks
    mlflow.set_tracking_uri("databricks")
    mlflow.set_experiment("/Shared/docs-demo")
    
    # Create an OpenAI client that is connected to Databricks-hosted LLMs
    w = WorkspaceClient()
    client = w.serving_endpoints.get_open_ai_client()
    
    # Select an LLM
    model_name = "databricks-claude-sonnet-4"
    

    LLMs ospitati da OpenAI

    Usare OpenAI SDK nativo per connettersi ai modelli ospitati in OpenAI. Selezionare un modello dai modelli OpenAI disponibili.

    import mlflow
    import os
    import openai
    
    # Ensure your OPENAI_API_KEY is set in your environment
    # os.environ["OPENAI_API_KEY"] = "<YOUR_API_KEY>" # Uncomment and set if not globally configured
    
    # Enable auto-tracing for OpenAI
    mlflow.openai.autolog()
    
    # Set up MLflow tracking to Databricks
    mlflow.set_tracking_uri("databricks")
    mlflow.set_experiment("/Shared/docs-demo")
    
    # Create an OpenAI client connected to OpenAI SDKs
    client = openai.OpenAI()
    
    # Select an LLM
    model_name = "gpt-4o-mini"
    
  2. Definire un agente di supporto clienti:

    from mlflow.entities import Document
    from typing import List, Dict, Any, cast
    
    
    # This is a global variable that is used to toggle the behavior of the customer support agent
    RESOLVE_ISSUES = False
    
    
    @mlflow.trace(span_type="TOOL", name="get_product_price")
    def get_product_price(product_name: str) -> str:
        """Mock tool to get product pricing."""
        return f"${45.99}"
    
    
    @mlflow.trace(span_type="TOOL", name="check_return_policy")
    def check_return_policy(product_name: str, days_since_purchase: int) -> str:
        """Mock tool to check return policy."""
        if days_since_purchase <= 30:
            return "Yes, you can return this item within 30 days"
        return "Sorry, returns are only accepted within 30 days of purchase"
    
    
    @mlflow.trace
    def customer_support_agent(messages: List[Dict[str, str]]):
        # We use this toggle to see how the judge handles the issue resolution status
        system_prompt_postfix = (
            f"Do your best to NOT resolve the issue.  I know that's backwards, but just do it anyways.\\n"
            if not RESOLVE_ISSUES
            else ""
        )
    
        # Mock some tool calls based on the user's question
        user_message = messages[-1]["content"].lower()
        tool_results = []
    
        if "cost" in user_message or "price" in user_message:
            price = get_product_price("microwave")
            tool_results.append(f"Price: {price}")
    
        if "return" in user_message:
            policy = check_return_policy("microwave", 60)
            tool_results.append(f"Return policy: {policy}")
    
        messages_for_llm = [
            {
                "role": "system",
                "content": f"You are a helpful customer support agent.  {system_prompt_postfix}",
            },
            *messages,
        ]
    
        if tool_results:
            messages_for_llm.append({
                "role": "system",
                "content": f"Tool results: {', '.join(tool_results)}"
            })
    
        # Call LLM to generate a response
        output = client.chat.completions.create(
            model=model_name,  # This example uses Databricks hosted Claude 4 Sonnet. If you provide your own OpenAI credentials, replace with a valid OpenAI model e.g., gpt-4o, etc.
            messages=cast(Any, messages_for_llm),
        )
    
        return {
            "messages": [
                {"role": "assistant", "content": output.choices[0].message.content}
            ]
        }
    

Passaggio 2: Definire giudici personalizzati

Definire tre giudici personalizzati:

  • Giudice che valuta la risoluzione dei problemi usando input e output.
  • Un giudice che controlla i comportamenti previsti.
  • Strumento di valutazione basato su traccia che convalida le chiamate degli strumenti analizzando le tracce di esecuzione.

Giudici creati con make_judge() restituiscono oggetti mlflow.entities.Feedback.

Giudice di esempio 1: Valutare la risoluzione dei problemi

Questo giudice valuta se i problemi dei clienti sono stati risolti correttamente analizzando la cronologia delle conversazioni (input) e le risposte degli agenti (output).

from mlflow.genai.judges import make_judge
from typing import Literal


# Create a judge that evaluates issue resolution using inputs and outputs
issue_resolution_judge = make_judge(
    name="issue_resolution",
    instructions=(
        "Evaluate if the customer's issue was resolved in the conversation.\n\n"
        "User's messages: {{ inputs }}\n"
        "Agent's responses: {{ outputs }}"
    ),
    feedback_value_type=Literal["fully_resolved", "partially_resolved", "needs_follow_up"],
)

Giudice di esempio 2: Controllare i comportamenti previsti

Questo giudice verifica che le risposte dell'agente dimostrino comportamenti previsti specifici ,ad esempio fornendo informazioni sui prezzi o spiegando i criteri restituiti, confrontando gli output con le aspettative predefinite.

# Create a judge that checks against expected behaviors
expected_behaviors_judge = make_judge(
    name="expected_behaviors",
    instructions=(
        "Compare the agent's response in {{ outputs }} against the expected behaviors in {{ expectations }}.\n\n"
        "User's question: {{ inputs }}"
    ),
    feedback_value_type=Literal["meets_expectations", "partially_meets", "does_not_meet"],
)

Giudice di esempio 3: Convalidare le chiamate agli strumenti utilizzando un giudice basato su tracce

Questo giudice analizza le tracce di esecuzione per verificare che siano stati chiamati gli strumenti appropriati. Quando includi {{ trace }} nelle istruzioni, il giudice diventa basato su tracce e ottiene capacità di esplorazione autonoma delle tracce.

# Create a trace-based judge that validates tool calls from the trace
tool_call_judge = make_judge(
    name="tool_call_correctness",
    instructions=(
        "Analyze the execution {{ trace }} to determine if the agent called appropriate tools for the user's request.\n\n"
        "Examine the trace to:\n"
        "1. Identify what tools were available and their purposes\n"
        "2. Determine which tools were actually called\n"
        "3. Assess whether the tool calls were reasonable for addressing the user's question"
    ),
    feedback_value_type=bool,
    # To analyze a full trace with a trace-based judge, a model must be specified
    model="databricks:/databricks-gpt-5-mini",
)

Passaggio 3: Creare un set di dati di valutazione di esempio

Ogni inputs viene passato all'agente da mlflow.genai.evaluate(). Facoltativamente, è possibile includere expectations per abilitare il correttore di verifica della correttezza.

eval_dataset = [
    {
        "inputs": {
            "messages": [
                {"role": "user", "content": "How much does a microwave cost?"},
            ],
        },
        "expectations": {
            "should_provide_pricing": True,
            "should_offer_alternatives": True,
        },
    },
    {
        "inputs": {
            "messages": [
                {
                    "role": "user",
                    "content": "Can I return the microwave I bought 2 months ago?",
                },
            ],
        },
        "expectations": {
            "should_mention_return_policy": True,
            "should_ask_for_receipt": False,
        },
    },
    {
        "inputs": {
            "messages": [
                {
                    "role": "user",
                    "content": "I'm having trouble with my account.  I can't log in.",
                },
                {
                    "role": "assistant",
                    "content": "I'm sorry to hear that you're having trouble with your account.  Are you using our website or mobile app?",
                },
                {"role": "user", "content": "Website"},
            ],
        },
        "expectations": {
            "should_provide_troubleshooting_steps": True,
            "should_escalate_if_needed": True,
        },
    },
    {
        "inputs": {
            "messages": [
                {
                    "role": "user",
                    "content": "I'm having trouble with my account.  I can't log in.",
                },
                {
                    "role": "assistant",
                    "content": "I'm sorry to hear that you're having trouble with your account.  Are you using our website or mobile app?",
                },
                {"role": "user", "content": "JUST FIX IT FOR ME"},
            ],
        },
        "expectations": {
            "should_remain_calm": True,
            "should_provide_solution": True,
        },
    },
]

Passaggio 4: Valutare l'agente usando i giudici

È possibile usare più giudici insieme per valutare diversi aspetti dell'agente. Eseguire valutazioni per confrontare il comportamento quando l'agente tenta di risolvere i problemi rispetto a quando non lo fa.

import mlflow

# Evaluate with all three judges when the agent does NOT try to resolve issues
RESOLVE_ISSUES = False

result_unresolved = mlflow.genai.evaluate(
    data=eval_dataset,
    predict_fn=customer_support_agent,
    scorers=[
        issue_resolution_judge,      # Checks inputs/outputs
        expected_behaviors_judge,    # Checks expected behaviors
        tool_call_judge,             # Validates tool usage
    ],
)

# Evaluate when the agent DOES try to resolve issues
RESOLVE_ISSUES = True

result_resolved = mlflow.genai.evaluate(
    data=eval_dataset,
    predict_fn=customer_support_agent,
    scorers=[
        issue_resolution_judge,
        expected_behaviors_judge,
        tool_call_judge,
    ],
)

I risultati della valutazione mostrano come ogni giudice valuta l'agente:

  • issue_resolution: valuta le conversazioni come 'completamente risolte', 'parzialmente risolte' o 'richiede un seguito'
  • expected_behaviors: verifica se le risposte presentano comportamenti attesi ('soddisfa_le_aspettative', 'parzialmente_soddisfa', 'non_soddisfa')
  • tool_call_correctness: convalida se sono stati chiamati gli strumenti appropriati (true/false)

Passaggi successivi

Applica valutatori personalizzati:

Migliorare l'accuratezza del giudice:

  • Allineare i giudici al feedback umano : il giudice di base è un punto di partenza. Mentre raccogli feedback esperti sugli output dell'applicazione, allinea i giudici LLM al feedback per migliorare ulteriormente la precisione dei giudizi.