Référence de l'évaluateur basé sur le code
Définissez des évaluateurs personnalisés basés sur le code dans MLflow à l’aide du décorateur @scorer ou de la classe Scorer. Cette référence couvre leurs signatures de fonction et de classe, les entrées, les sorties, la dénomination des métriques, la gestion des erreurs et la manière d’accéder aux secrets.
décorateur @scorer
La plupart des évaluateurs basés sur du code doivent être définis à l'aide du décorateur@scorer. La signature pour de tels évaluateurs est la suivante :
from mlflow.genai.scorers import scorer
from typing import Optional, Any
from mlflow.entities import Feedback
@scorer
def my_custom_scorer(
*, # All arguments are keyword-only
inputs: Optional[dict[str, Any]], # App's raw input, a dictionary of input argument names and values
outputs: Optional[Any], # App's raw output
expectations: Optional[dict[str, Any]], # Ground truth, a dictionary of label names and values
trace: Optional[mlflow.entities.Trace] # Complete trace with all spans and metadata
) -> Union[int, float, bool, str, Feedback, List[Feedback]]:
# Your evaluation logic here
Pour une plus grande flexibilité que ne le permet le décorateur @scorer, définissez des évaluateurs à l'aide de la classeScorer.
Entrées
Les évaluateurs reçoivent la trace MLflow complète contenant toutes les portées, attributs et sorties. MLflow extrait également les données couramment nécessaires et les transmet en tant qu'arguments nommés. Tous les arguments d'entrée sont facultatifs, alors déclarez uniquement ce dont votre évaluateur a besoin :
inputs: La requête envoyée à votre application (par exemple, query utilisateur, contexte).outputs: La réponse de votre application (par exemple, texte généré, appels d'outils).expectations: vérité terrain ou étiquettes (par exemple, réponse attendue, consignes).trace: La trace MLflow complète, y compris tous les spans, permettant l'analyse des étapes intermédiaires, de la latence, de l'utilisation des outils, et plus encore. La trace est transmise à l’évaluateur personnalisé sous la forme d’unemlflow.entities.traceclass instanciée.
Lors de l'exécution de mlflow.genai.evaluate(), les paramètres inputs, outputs et expectations peuvent être spécifiés dans l'argument data, ou extraits de la trace.
Scorers enregistrés pour le monitoring de la production analysent toujours les inputs et outputs parameter de la trace. expectations n'est pas disponible.
Résultats
Les évaluateurs peuvent renvoyer différents types de valeurs simples ou d'objets Feedback riches en fonction de vos besoins d'évaluation.
Type renvoyé | Affichage de l'interface utilisateur MLflow | Cas d'usage |
|---|---|---|
| Réussite/Échec | Évaluation binaire |
| Vrai/Faux | Vérifications booléennes |
| Valeur numérique | Scores, comptages |
Valeur + justification | Évaluation détaillée | |
| Plusieurs métriques | Évaluation multi-aspects |
Valeurs simples
Des valeurs simples sont utilisées pour des évaluations numériques ou de réussite/échec directes. Les exemples suivants présentent des évaluateurs simples pour une application d'IA qui renvoie une chaîne de caractères en guise de réponse.
@scorer
def response_length(outputs: str) -> int:
# Return a numeric metric
return len(outputs.split())
@scorer
def contains_citation(outputs: str) -> str:
# Return pass/fail string
return "yes" if "[source]" in outputs else "no"
Rétroaction riche
Renvoie un objet Feedback ou une liste de Feedback objets pour des évaluations détaillées avec des scores, des justifications et des métadonnées.
from mlflow.entities import Feedback, AssessmentSource
@scorer
def content_quality(outputs):
return Feedback(
value=0.85, # Can be numeric, boolean, string, or other types
rationale="Clear and accurate, minor grammar issues",
# Optional: source of the assessment. Several source types are supported,
# such as "HUMAN", "CODE", "LLM_JUDGE".
source=AssessmentSource(
source_type="HUMAN",
source_id="grammar_checker_v1"
),
# Optional: additional metadata about the assessment.
metadata={
"annotator": "me@example.com",
}
)
Plusieurs objets de feedback peuvent être renvoyés sous forme de liste. Chaque retour doit avoir le champ name spécifié, et ces noms s’affichent comme des métriques distinctes dans les résultats de l’évaluation.
@scorer
def comprehensive_check(inputs, outputs):
return [
Feedback(name="relevance", value=True, rationale="Directly addresses query"),
Feedback(name="tone", value="professional", rationale="Appropriate for audience"),
Feedback(name="length", value=150, rationale="Word count within limits")
]
Comportement de nommage des métriques
Lorsque vous définissez des évaluateurs, utilisez des noms clairs et cohérents qui indiquent l'objectif de l'évaluateur. Ces noms apparaissent comme noms de métriques dans vos résultats d'évaluation et de monitoring et dans vos tableaux de bord. Suivez les conventions de dénomination MLflow telles que safety_check ou relevance_monitor.
Lorsque vous définissez des évaluateurs à l'aide du décorateur @scorer ou de la Scorer classe, les noms de métriques dans les exécutions d'évaluation créées par l'évaluation et le monitoring suivent ces règles :
- Si l'évaluateur renvoie un ou plusieurs objets
Feedback, alors les champsFeedback.nameprennent la priorité, si spécifié. - Pour les valeurs de retour primitives ou les
Feedbacks sans nom, le nom de la fonction (pour le décorateur@scorer) ou le champScorer.name(pour la classeScorer) est utilisé.
Le tableau suivant résume le comportement de nommage des métriques :
Valeur de retour |
|
|
|---|---|---|
Valeur primitive ( | Nom de la fonction |
|
Commentaires sans nom | Nom de la fonction |
|
Commentaires avec le nom |
|
|
|
|
|
Pour l'évaluation et le monitoring, toutes les métriques doivent avoir des noms distincts. Si un évaluateur renvoie List[Feedback], alors chaque Feedback dans le List doit avoir un nom distinct.
Pour des exemples de comportement de nommage, consultez les Conventions de nommage dans les évaluateurs.
Accéder aux secrets dans les évaluateurs
Les évaluateurs personnalisés peuvent accéder aux secrets Databricks pour utiliser en toute sécurité les clés API et les identifiants. Ceci est utile lors de l'intégration de services externes, tels que des Endpoints LLM personnalisés nécessitant une authentification, comme Azure OpenAI, AWS Bedrock, et d'autres. Cette approche fonctionne à la fois pour l'évaluation de développement et le monitoring de production.
Par default, dbutils n'est pas disponible dans l'environnement d'exécution du scorer. Pour accéder aux secrets dans l'environnement d'exécution de l'évaluateur, appelez from databricks.sdk.runtime import dbutils depuis l'intérieur de la fonction d'évaluateur.
L'exemple suivant montre comment accéder à un secret dans un évaluateur personnalisé :
import mlflow
from mlflow.genai.scorers import scorer, ScorerSamplingConfig
from mlflow.entities import Trace, Feedback
@scorer
def custom_llm_scorer(trace: Trace) -> Feedback:
# Explicitly import dbutils to access secrets
from databricks.sdk.runtime import dbutils
# Retrieve your API key from Databricks secrets
api_key = dbutils.secrets.get(scope='my-scope', key='api-key')
# Use the API key to call your custom LLM endpoint
# ... your custom evaluation logic here ...
return Feedback(
value="yes",
rationale="Evaluation completed using custom endpoint"
)
# Register and start the scorer
custom_llm_scorer.register()
custom_llm_scorer.start(sampling_config = ScorerSamplingConfig(sample_rate=1))
Gestion des erreurs
Lorsqu’un évaluateur rencontre une erreur pour une trace, MLflow peut capturer les détails de l’erreur pour cette trace et poursuivre son exécution normalement. Pour la capture des détails d'erreur, MLflow propose deux approches :
- Laissez les exceptions se propager (recommandé) afin que MLflow puisse capturer les messages d'erreur pour vous.
- Gérez les exceptions explicitement.
Permettre la propagation des exceptions (recommandé)
L'approche la plus simple est de laisser les exceptions être levées naturellement. MLflow capture automatiquement l'exception et crée un objet Feedback avec les détails d'erreur suivants :
value:Noneerror: Les détails de l'exception, tels que l'objet d'exception, le message d'erreur et la trace de la pile
L'information sur l'erreur s'affiche dans les résultats de l'évaluation. Ouvrez la ligne correspondante pour voir les détails de l'erreur.

Gérer les exceptions explicitement
Pour la gestion personnalisée des erreurs ou pour fournir des messages d'erreur spécifiques, interceptez les exceptions et retournez un Feedback avec la valeur None et les détails de l'erreur :
from mlflow.entities import AssessmentError, Feedback
@scorer
def is_valid_response(outputs):
import json
try:
data = json.loads(outputs)
required_fields = ["summary", "confidence", "sources"]
missing = [f for f in required_fields if f not in data]
if missing:
return Feedback(
error=AssessmentError(
error_code="MISSING_REQUIRED_FIELDS",
error_message=f"Missing required fields: {missing}",
),
)
return Feedback(
value=True,
rationale="Valid JSON with all required fields"
)
except json.JSONDecodeError as e:
return Feedback(error=e) # Can pass exception object directly to the error parameter
Le paramètre error accepte les types d'erreurs suivants :
- Exception Python : Transmettez directement l'objet d'exception.
AssessmentError: Pour un rapport d'erreurs structuré avec des codes d'erreur.
Scorer classe
Dans la plupart des cas, le @scorer décorateur est recommandé. Si votre logique nécessite un état interne ou une personnalisation supplémentaire, utilisez plutôt la classe de base Scorer. La classe Scorer est un objet Pydantic, vous pouvez donc définir des champs supplémentaires et les utiliser dans la méthode __call__.
Les évaluateurs définis à l'aide de la classe Scorer ne sont pas pris en charge pour le monitoring de production. Pour plus de détails, veuillez consulter les évaluateurs basés sur le code.
Vous devez définir le champ name pour définir le nom de la métrique. Si vous renvoyez une liste de Feedback objets, vous devez définir le champ name dans chaque Feedback pour éviter les conflits de noms.
from mlflow.genai.scorers import Scorer
from mlflow.entities import Feedback
from typing import Optional
# Scorer class is a Pydantic object
class CustomScorer(Scorer):
# The `name` field is mandatory
name: str = "response_quality"
# Define additional fields
my_custom_field_1: int = 50
my_custom_field_2: Optional[list[str]] = None
# Override the __call__ method to implement the scorer logic
def __call__(self, outputs: str) -> Feedback:
# Your logic here
return Feedback(
value=True,
rationale="Response meets all quality criteria"
)
Gestion de l'état
Lorsque vous écrivez des évaluateurs à l’aide de la classe Scorer, tenez compte des règles de gestion de l’état avec les classes Python. En particulier, veillez à utiliser des attributs d’instance, et non des attributs de classe mutables. L'exemple ci-dessous illustre le partage erroné d'état entre les instances de scoreurs.
from mlflow.genai.scorers import Scorer
from mlflow.entities import Feedback
# WRONG: Don't use mutable class attributes
class BadScorer(Scorer):
results = [] # Shared across all instances!
name: str = "bad_scorer"
def __call__(self, outputs, **kwargs):
self.results.append(outputs) # Causes issues
return Feedback(value=True)
# CORRECT: Use instance attributes
class GoodScorer(Scorer):
results: list[str] = None
name: str = "good_scorer"
def __init__(self):
self.results = [] # Per-instance state
def __call__(self, outputs, **kwargs):
self.results.append(outputs) # Safe
return Feedback(value=True)