Aller au contenu principal

Aligner les juges LLM avec les retours humains

L'alignement des juges apprend aux juges LLM à correspondre aux standards d'évaluation humaine grâce à un feedback systématique. Ce processus transforme les évaluateurs génériques en experts du domaine qui comprennent vos critères de qualité uniques, améliorant l'accord avec les évaluations humaines de 30 à 50 % par rapport aux juges de référence.

Le même workflow d’alignement s’applique aux juges intégrés (tels que RelevanceToQuery, Safety ou Correctness) et aux juges personnalisés créés avec make_judge(). Utilisez l'alignement avec des juges intégrés pour adapter leurs critères génériques à votre domaine, ou avec des juges personnalisés pour affiner la logique d'évaluation spécialisée.

L'alignement du juge suit un workflow en trois étapes :

  1. Générez les évaluations initiales : Utilisez un juge intégré ou personnalisé pour évaluer les traces et établir une référence.
  2. Recueillir les commentaires humains : Les experts du domaine examinent et corrigent les évaluations des juges.
  3. Aligner et déployer : Invoquez la méthode align() du juge pour créer un nouveau juge qui est davantage aligné avec le feedback humain.

Le système prend en charge les optimiseurs qui sont disponibles dans le package mlflow.genai.judges.optimizers.

Exigences

  • MLflow 3.4.0 ou supérieur pour utiliser les fonctionnalités d'alignement des juges

    Python
    %pip install --upgrade "mlflow[databricks]>=3.4.0" databricks_openai dspy
    dbutils.library.restartPython()
  • Un juge à aligner. Il peut s'agir d'un juge intégré (par exemple, RelevanceToQuery ou Correctness) ou d'un juge personnalisé créé avec make_judge().

  • Le nom de l'évaluation du feedback humain doit correspondre exactement à l'attribut name du juge. Pour les juges intégrés, il s'agit du nom par default en snake_case (par exemple, relevance_to_query pour RelevanceToQuery), sauf si vous le remplacez en passant name= lors de l'instanciation de la classe. Pour les juges personnalisés, c'est le name que vous avez transmis à make_judge() (par exemple, product_quality).

  • L'alignement n'est pas pris en charge pour les juges au niveau de la session (multi-tour) tels que ConversationCompleteness.

Étape 1 : Configurez le juge et générez des traces.

Configurez votre premier juge et générez des traces avec des évaluations. Vous pouvez obtenir un alignement raisonnable avec au moins 10 traces, mais 50 à 100 traces donnent de meilleurs résultats.

Instancier un juge intégré directement. Les juges intégrés exposent un attribut name (la valeur default est une chaîne de caractères snake_case telle que relevance_to_query) que vous utiliserez lors de l’enregistrement des retours humains à l’étape 2.

Python
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()

Définissez votre logique d'application. L'exemple suivant utilise un modèle de fondation hébergé par Databricks pour générer une description de produit à partir d'une query. Remplacez ceci par votre propre code d'application :

Python
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

Générez des traces et exécutez le juge. Utilisez l'attribut name du juge (par exemple, relevance_to_query pour le juge intégré ci-dessus, ou product_quality pour le juge personnalisé ci-dessus) comme feedback name:

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

Étape 2 : Recueillir les commentaires des utilisateurs

Recueillez les retours humains pour enseigner au juge vos standards de qualité. Choisissez parmi les approches suivantes :

Recueillez le feedback humain lorsque :

  • Vous avez besoin d'experts du domaine pour examiner les sorties.
  • Vous souhaitez affiner de manière itérative les critères de feedback.
  • Vous travaillez avec un plus petit dataset (< 100 exemples).

Utilisez l'interface utilisateur MLflow pour examiner manuellement et fournir des commentaires :

  1. Accédez à votre experimentation MLflow dans le Workspace Databricks.
  2. Cliquez sur l'onglet **Traces** pour afficher les traces.
  3. Examinez chaque trace et son évaluation par le juge.
  4. Ajoutez un feedback humain à l'aide de l'interface de feedback de l'interface utilisateur.
  5. Assurez-vous que le nom de la rétroaction correspond exactement à l'attribut name de votre juge (par exemple, relevance_to_query pour une instance RelevanceToQuery intégrée ou product_quality pour le juge personnalisé ci-dessus).

Bonnes pratiques pour la collecte de commentaires

  • Relecteurs variés : Incluez de multiples experts du domaine afin de saisir diverses perspectives.
  • Exemples équilibrés : incluez au moins 30 % d'exemples négatifs (évaluations médiocres/passables)
  • Justifications claires : Fournissez des explications détaillées pour les évaluations
  • Échantillons représentatifs : Couvrez les cas limites et les scénarios courants

Étape 3 : Alignez et enregistrez le juge

Une fois que vous disposez d'un feedback humain suffisant, alignez le juge. La même méthode align() est utilisée pour les juges intégrés et personnalisés.

Lorsque vous appelez align() sans spécifier d'optimiseur, l'optimiseur MemAlign est utilisé automatiquement :

Python
# 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={&quot;alignment_date&quot;: &quot;2025-10-23&quot;, &quot;num_traces&quot;: 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")

Activer la journalisation détaillée

Pour surveiller le processus d'alignement, activez la journalisation de débogage pour l'optimiseur :

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

Valider l'alignement

Vérifiez que l'alignement a amélioré le juge :

Python

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


Créer des optimiseurs d’alignement personnalisés

Pour les stratégies d'alignement spécialisées, étendez la classe de base AlignmentOptimizer :

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

Limitations

  • L'alignement des juges ne prend pas en charge l'évaluation basée sur l'agent ou les attentes.

Étapes suivantes