LLM-Richter an menschlichem Feedback ausrichten

Richterausrichtung lehrt LLM-Richter, menschliche Bewertungsstandards durch systematisches Feedback zu erfüllen. Dieser Prozess wandelt generische Bewertungen in domänenspezifische Experten um, die Ihre einzigartigen Qualitätskriterien verstehen und die Übereinstimmung mit menschlichen Bewertungen um 30 bis 50 Prozent im Vergleich zu den Basisrichtern verbessern.

Derselbe Workflow zur Ausrichtung gilt sowohl für integrierte Bewerter (z. B. RelevanceToQuery, Safety oder Correctness) als auch für benutzerdefinierte Bewerter, die mit make_judge() erstellt wurden. Verwenden Sie die Abstimmung mit integrierten Bewertern, um deren generische Kriterien an Ihre Domäne anzupassen, oder die Abstimmung mit benutzerdefinierten Bewertern, um spezialisierte Bewertungslogik zu verfeinern.

Die Ausrichtung des Richters folgt einem dreistufigen Workflow:

  1. Erste Bewertungen erstellen: Verwenden Sie einen integrierten oder benutzerdefinierten Bewerter, um Traces auszuwerten und eine Baseline festzulegen.
  2. Sammeln Sie menschliches Feedback: Domänenexperten überprüfen und korrigieren Bewertungen.
  3. Ausrichten und Bereitstellen: Rufen Sie die Methode des Richters align() auf, um einen neuen Richter zu erstellen, der stärker auf menschliches Feedback ausgerichtet ist.

Das System unterstützt die Optimierer, die im Paket mlflow.genai.judges.optimizersverfügbar sind.

Anforderungen

  • MLflow 3.4.0 oder höher zur Nutzung der Ausrichtungsbeurteilungsfunktionen

    %pip install --upgrade "mlflow[databricks]>=3.4.0" databricks_openai dspy
    dbutils.library.restartPython()
    
  • Ein Richter, der ausgerichtet werden soll. Dies kann ein integrierter Bewerter (z. B. RelevanceToQuery oder Correctness) oder ein benutzerdefinierter Bewerter sein, der mit make_judge() erstellt wurde.

  • Der Name der Bewertung des menschlichen Feedbacks muss exakt mit dem Attribut des Richters name übereinstimmen. Bei integrierten Richtern ist dies standardmäßig der snake_case-Name (zum Beispiel relevance_to_query für RelevanceToQuery), sofern Sie ihn nicht überschreiben, indem Sie beim Instanziieren der Klasse name= übergeben. Bei benutzerdefinierten Richtern ist es das name, das Sie an make_judge() übergeben haben (z. B. product_quality).

  • Ausrichtung wird für Richter auf Sitzungsebene (mehrere Runden) wie ConversationCompleteness nicht unterstützt.

Schritt 1: Richter einrichten und Ablaufverfolgungen generieren

Richten Sie Ihren ersten Richter ein und generieren Sie Ablaufverfolgungen einschließlich Bewertungen. Sie können eine angemessene Ausrichtung mit mindestens 10 Spuren erzielen, aber 50-100 Spuren erzielen bessere Ergebnisse.

Integrierte LLM-Richter

Instanziieren Sie einen integrierten Richter direkt. Integrierte Bewerter stellen ein name-Attribut bereit (standardmäßig eine snake_case-Zeichenfolge wie relevance_to_query), das Sie beim Protokollieren menschlichen Feedbacks in Schritt 2 verwenden.

from mlflow.genai.scorers import RelevanceToQuery
import mlflow

# Create or set an MLflow experiment for alignment.
# Use a workspace path such as /Shared/<name> or /Users/<your-email>/<name>.
experiment = mlflow.set_experiment("/Shared/relevance-alignment")
experiment_id = experiment.experiment_id

# Use a built-in judge
initial_judge = RelevanceToQuery()

Benutzerdefinierter Richter

Erstellen Sie einen benutzerdefinierten Richter mit make_judge(). Das name Argument ist derselbe Name, den Sie beim Protokollieren von menschlichem Feedback in Schritt 2 verwenden.

from mlflow.genai.judges import make_judge
import mlflow

# Create or set an MLflow experiment for alignment.
# Use a workspace path such as /Shared/<name> or /Users/<your-email>/<name>.
experiment = mlflow.set_experiment("/Shared/product-quality-alignment")
experiment_id = experiment.experiment_id

# Create initial judge with template-based evaluation
initial_judge = make_judge(
    name="product_quality",
    instructions=(
        "Evaluate if the product description in {{ outputs }} "
        "is accurate and helpful for the query in {{ inputs }}. "
        "Rate as: excellent, good, fair, or poor"
    ),
    model="databricks:/databricks-gpt-oss-120b",
)

Definieren Sie Ihre Anwendungslogik. Im folgenden Beispiel wird ein vom Databricks gehostetes Foundation-Modell verwendet, um eine Produktbeschreibung aus einer Abfrage zu generieren. Ersetzen Sie dies durch Ihren eigenen Anwendungscode:

import mlflow
from databricks_openai import DatabricksOpenAI

# Enable automatic tracing of OpenAI calls
mlflow.openai.autolog()

# Create an OpenAI client connected to Databricks-hosted LLMs
client = DatabricksOpenAI()
model_name = "databricks-claude-sonnet-4"


def generate_product_description(query: str) -> str:
    response = client.chat.completions.create(
        model=model_name,
        messages=[
            {
                "role": "system",
                "content": "You write concise, accurate product descriptions.",
            },
            {"role": "user", "content": query},
        ],
    )
    return response.choices[0].message.content

Erzeugen Sie Ablaufverfolgungen und führen Sie den Richter aus. Verwenden Sie das Attribut name des Judge (z. B. relevance_to_query für den integrierten Judge oben oder product_quality für den benutzerdefinierten Judge oben) als Feedback-name:

# Generate traces for alignment (minimum 10, recommended 50+)
for i in range(50):
    query = f"Tell me about product {i}"
    description = generate_product_description(query)

    # Retrieve the ID of the most recent finished trace
    trace_id = mlflow.get_last_active_trace_id()
    trace = mlflow.get_trace(trace_id)

    # Generate judge assessment
    judge_result = initial_judge(trace=trace)

    # Log judge feedback to the trace using the judge's name
    mlflow.log_feedback(
        trace_id=trace_id,
        name=initial_judge.name,
        value=judge_result.value,
        rationale=judge_result.rationale,
    )

Schritt 2: Sammeln von menschlichem Feedback

Sammeln Sie menschliches Feedback, um dem Richter Ihre Qualitätsstandards zu vermitteln. Wählen Sie aus den folgenden Ansätzen aus:

Databricks UI-Überprüfung

Sammeln Sie menschliches Feedback, wenn:

  • Sie benötigen Domänenexperten, um Ausgaben zu überprüfen.
  • Sie möchten Feedbackkriterien iterativ verfeinern.
  • Sie arbeiten mit einem kleineren Dataset (< 100 Beispiele).

Verwenden Sie die MLflow-Benutzeroberfläche, um Manuell zu überprüfen und Feedback zu geben:

  1. Navigieren Sie zum MLflow-Experiment im Databricks-Arbeitsbereich.
  2. Klicken Sie auf den Tab „Traces“, um Traces anzuzeigen.
  3. Überprüfen Sie jede Ablaufverfolgung und die zugehörige Bewertung durch den Richter.
  4. Fügen Sie mithilfe der Feedbackschnittstelle der Benutzeroberfläche menschliches Feedback hinzu.
  5. Stellen Sie sicher, dass der Name des Feedbacks genau mit dem name-Attribut Ihres Judge übereinstimmt (z. B. relevance_to_query für eine integrierte RelevanceToQuery-Instanz oder product_quality für den oben genannten benutzerdefinierten Judge).

Programmgesteuertes Feedback

Programmgesteuertes Feedback verwenden, wenn:

  • Sie haben bereits vorhandene Ground-Truth-Labels.
  • Sie arbeiten mit großen Datasets (100+ Beispiele).
  • Sie benötigen reproduzierbare Feedbacksammlung.

Wenn Sie über vorhandene grundierte Wahrheitsbezeichnungen verfügen, protokollieren Sie sie programmgesteuert:

from mlflow.entities import AssessmentSource, AssessmentSourceType

# Your ground truth data
ground_truth_data = [
    {"trace_id": "<trace_id_1>", "label": "excellent", "rationale": "Comprehensive and accurate description"},
    {"trace_id": "<trace_id_2>", "label": "poor", "rationale": "Missing key product features"},
    {"trace_id": "<trace_id_3>", "label": "good", "rationale": "Accurate but could be more detailed"},
    # ... more ground truth labels
]

# Log human feedback for each trace
for item in ground_truth_data:
    mlflow.log_feedback(
        trace_id=item["trace_id"],
        name=initial_judge.name,  # Must match judge name (built-in or custom)
        value=item["label"],
        rationale=item.get("rationale", ""),
        source=AssessmentSource(
            source_type=AssessmentSourceType.HUMAN,
            source_id="ground_truth_dataset"
        ),
    )

Bewährte Methoden für die Feedbacksammlung

  • Verschiedene Prüfer: Fügen Sie mehrere Domänenexperten ein, um vielfältige Perspektiven zu erfassen
  • Ausgewogene Beispiele: Schließen Sie mindestens 30% negative Beispiele ein (schlechte/faire Bewertungen)
  • Klare Gründe: Detaillierte Erläuterungen für Bewertungen bereitstellen
  • Repräsentative Beispiele: Abdecken von Randfällen und gängigen Szenarien

Schritt 3: Ausrichten und Registrieren des Richters

Sobald Sie über ausreichendes menschliches Feedback verfügen, richten Sie den Richter daran aus. Die gleiche align() Methode wird sowohl für integrierte als auch für benutzerdefinierte Richter verwendet.

Wenn Sie align() aufrufen, ohne einen Optimierer anzugeben, wird der MemAlign-Optimierer automatisch verwendet:

# Retrieve traces with both judge and human assessments
traces_for_alignment = mlflow.search_traces(
    experiment_ids=[experiment_id],
    max_results=100,
    return_type="list"
)

if len(traces_for_alignment) >= 10:
    # Align the judge based on human feedback using the default optimizer
    aligned_judge = initial_judge.align(traces_for_alignment)

    # Register the aligned judge for production use.
    # Use a new name to distinguish it from the original judge.
    aligned_judge.register(
        experiment_id=experiment_id,
        name=f"{initial_judge.name}_aligned",
        tags={"alignment_date": "2025-10-23", "num_traces": str(len(traces_for_alignment))}
    )

    print(f"Successfully aligned judge using {len(traces_for_alignment)} traces")
else:
    print(f"Insufficient traces for alignment. Found {len(traces_for_alignment)}, need at least 10")

Expliziter Optimierer

from mlflow.genai.judges.optimizers import MemAlignOptimizer

# Retrieve traces with both judge and human assessments
traces_for_alignment = mlflow.search_traces(
    experiment_ids=[experiment_id], max_results=15, return_type="list"
)

# Align the judge using human corrections (minimum 10 traces recommended)
if len(traces_for_alignment) >= 10:
    # Explicitly specify optimizer with custom model configuration
    optimizer = MemAlignOptimizer(model="databricks:/databricks-gpt-oss-120b")
    aligned_judge = initial_judge.align(traces_for_alignment, optimizer)

    # Register the aligned judge
    aligned_judge.register(experiment_id=experiment_id)
    print("Judge aligned successfully with human feedback")
else:
    print(f"Need at least 10 traces for alignment, have {len(traces_for_alignment)}")

Aktivieren der detaillierten Protokollierung

Aktivieren Sie zum Überwachen des Ausrichtungsprozesses die Debugprotokollierung für den Optimierer:

import logging

# Enable detailed logging
logging.getLogger("mlflow.genai.judges.optimizers.memalign").setLevel(logging.DEBUG)

# Run alignment with verbose output
aligned_judge = initial_judge.align(traces_for_alignment)

Überprüfen der Ausrichtung

Überprüfen Sie, ob die Ausrichtung den Richter verbessert hat:


def test_alignment_improvement(
    original_judge, aligned_judge, test_traces: list
) -> dict:
    """Compare judge performance before and after alignment."""

    original_correct = 0
    aligned_correct = 0

    for trace in test_traces:
        # Get human ground truth from trace assessments
        feedbacks = trace.search_assessments(type="feedback")
        human_feedback = next(
            (f for f in feedbacks if f.source.source_type == "HUMAN"), None
        )

        if not human_feedback:
            continue

        # Get judge evaluations
        # Judges can evaluate entire traces instead of individual inputs/outputs
        original_eval = original_judge(trace=trace)
        aligned_eval = aligned_judge(trace=trace)

        # Check agreement with human
        if original_eval.value == human_feedback.value:
            original_correct += 1
        if aligned_eval.value == human_feedback.value:
            aligned_correct += 1

    total = len(test_traces)
    return {
        "original_accuracy": original_correct / total,
        "aligned_accuracy": aligned_correct / total,
        "improvement": (aligned_correct - original_correct) / total,
    }


Erstellen benutzerdefinierter Ausrichtungsoptimierer

Erweitern Sie für spezialisierte Ausrichtungsstrategien die AlignmentOptimizer Basisklasse:

from mlflow.genai.judges.base import AlignmentOptimizer, Judge
from mlflow.entities.trace import Trace

class MyCustomOptimizer(AlignmentOptimizer):
    """Custom optimizer implementation for judge alignment."""

    def __init__(self, model: str = None, **kwargs):
        """Initialize your optimizer with custom parameters."""
        self.model = model
        # Add any custom initialization logic

    def align(self, judge: Judge, traces: list[Trace]) -> Judge:
        """
        Implement your alignment algorithm.

        Args:
            judge: The judge to be optimized
            traces: List of traces containing human feedback

        Returns:
            A new Judge instance with improved alignment
        """
        # Your custom alignment logic here
        # 1. Extract feedback from traces
        # 2. Analyze disagreements between judge and human
        # 3. Generate improved instructions
        # 4. Return new judge with better alignment

        # Example: Return judge with modified instructions
        from mlflow.genai.judges import make_judge

        improved_instructions = self._optimize_instructions(judge.instructions, traces)

        return make_judge(
            name=judge.name,
            instructions=improved_instructions,
            model=judge.model,
        )

    def _optimize_instructions(self, instructions: str, traces: list[Trace]) -> str:
        """Your custom optimization logic."""
        # Implement your optimization strategy
        pass

# Create your custom optimizer
custom_optimizer = MyCustomOptimizer(model="your-model")

# Use it for alignment
aligned_judge = initial_judge.align(traces_with_feedback, custom_optimizer)

Einschränkungen

  • Die Richterausrichtung unterstützt keine agentbasierte oder erwartungsbasierte Auswertung.

Nächste Schritte