Marcadores
Os pontuadores avaliam a qualidade do aplicativo GenAI analisando os resultados e produzindo feedback estruturado. Escreva uma vez, use em qualquer lugar - no desenvolvimento e na produção.
Referência rápida
Tipo de retorno | Exibição de interface | Caso de uso |
---|---|---|
| Aprovar/falhar | Avaliação binária |
| verdadeiro/falso | Boolean cheques |
| Valor numérico | Pontuações, contagens |
| Valor + justificativa | Avaliação detalhada |
| Múltiplas métricas | Avaliação multifacetada |
Escreva uma vez, use em qualquer lugar
Um key princípio de design dos MLflow scorers é escrever uma vez, usar em qualquer lugar. A mesma função de marcador funciona perfeitamente em:
- Desenvolvimento : avalie diferentes versões do seu aplicativo usando
mlflow.genai.evaluate()
- Produção : Monitore a qualidade do tráfego ao vivo com o serviço de monitoramento de produçãodo MLflow
Essa abordagem unificada significa que o senhor pode desenvolver e testar suas métricas de qualidade localmente e, em seguida, implantar exatamente a mesma lógica na produção sem modificações.
from mlflow.genai.scorers import scorer
from mlflow.entities import Feedback
# Define your scorer once
@scorer
def response_completeness(outputs: str) -> Feedback:
# Outputs is return value of your app. Here we assume it's a string.
if len(outputs.strip()) < 10:
return Feedback(
value=False,
rationale="Response too short to be meaningful"
)
if outputs.lower().endswith(("...", "etc", "and so on")):
return Feedback(
value=False,
rationale="Response appears incomplete"
)
return Feedback(
value=True,
rationale="Response appears complete"
)
# Directly call the scorer function for spot testing
response_completeness(outputs="This is a test response...")
# Use in development evaluation
mlflow.genai.evaluate(
data=test_dataset,
predict_fn=my_app,
scorers=[response_completeness]
)
Como funcionam os marcadores
Os pontuadores analisam traços de seu aplicativo GenAI e produzem avaliações de qualidade. Aqui está o fluxo:
- Seu aplicativo é executado e produz um rastreamento que captura sua execução
- O MLflow passa o rastreamento para sua função de marcador
- Os pontuadores analisam as entradas, saídas e etapas intermediárias de execução do rastreamento usando lógica personalizada
- O feedback é produzido com pontuações e explicações
- Os feedbacks são anexados ao rastreamento para análise
Entradas
Os avaliadores recebem o rastreamento completo do MLflow contendo todos os intervalos, atributos e saídas. Por conveniência, o MLflow também extrai dados comumente necessários e os passa como argumentos nomeados:
@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 metadata
) -> Union[int, float, bool, str, Feedback, List[Feedback]]:
# Your evaluation logic here
Todos os parâmetros são opcionais — declare somente o que seu marcador precisa:
- entradas : a solicitação enviada ao seu aplicativo (por exemplo, consulta do usuário, contexto).
- saídas : a resposta do seu aplicativo (por exemplo, texto gerado, chamadas de ferramentas)
- expectativas : A verdade básica ou rótulo (por exemplo, resposta esperada, diretrizes etc.)
- trace : O rastreamento completo da execução com todos os intervalos, permitindo a análise de etapas intermediárias, latência, uso de ferramentas, etc.
Ao executar mlflow.genai.evaluate()
, os parâmetros inputs
, outputs
e expectations
podem ser especificados no argumento data
ou analisados a partir do rastreamento.
Ao executar mlflow.genai.create_monitor()
, os parâmetros inputs
e outputs
são sempre analisados a partir do rastreamento. expectations
não está disponível.
Saídas
Os pontuadores podem retornar tipos diferentes, dependendo de suas necessidades de avaliação:
Valores simples
Retorne valores primitivos para avaliações diretas de aprovação/reprovação ou numéricas.
- Aprovado/reprovado strings :
"yes"
ou"no"
renderizado como "Aprovado" ou "Reprovado" na UI - Boolean Valores :
True
ouFalse
para avaliações binárias - Valores numéricos : números inteiros ou flutuantes para pontuações, contagens ou medidas
# These example assumes your app returns a string as a response.
@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"
Feedback rico
Retorne objetos Feedback
para avaliações detalhadas com explicações:
from mlflow.entities import Feedback, AssessmentSource
@scorer
def content_quality(outputs):
return Feedback(
value=0.85, # Can be numeric, boolean, or string
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",
}
)
Vários objetos de feedback podem ser retornados como uma lista. Cada feedback será exibido como uma métrica separada nos resultados da avaliação.
@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")
]
Comportamento de nomeação de métricas
Ao usar o decorador @scorer
, os nomes das métricas nos resultados da avaliação seguem estas regras:
-
Valor primitivo ou feedback único sem nome: o nome da função do marcador se torna o nome do feedback
Python@scorer
def word_count(outputs: str) -> int:
# "word_count" will be used as a metric name
return len(outputs).split()
@scorer
def response_quality(outputs: Any) -> Feedback:
# "response_quality" will be used as a metric name
return Feedback(value=True, rationale="Good quality") -
Feedback único com um nome explícito : o nome especificado no objeto Feedback é usado como o nome métrico
Python@scorer
def assess_factualness(outputs: Any) -> Feedback:
# Name "factual_accuracy" is explicitly specfied, it will be used as a metric name
return Feedback(name="factual_accuracy", value=True, rationale="Factual accuracy is high") -
Vários feedbacks: os nomes especificados em cada objeto de feedback são preservados. Você deve especificar um nome exclusivo para cada feedback.
Python@scorer
def multi_aspect_check(outputs) -> list[Feedback]:
# These names ARE used since multiple feedbacks are returned
return [
Feedback(name="grammar", value=True, rationale="No errors"),
Feedback(name="clarity", value=0.9, rationale="Very clear"),
Feedback(name="completeness", value="yes", rationale="All points addressed")
]
Esse comportamento de nomenclatura garante nomes de métricas consistentes em seus resultados de avaliação e painéis.
Tratamento de erros
Quando um avaliador encontra um erro, o MLflow oferece duas abordagens:
Permitir que as exceções se propaguem (recomendado)
A abordagem mais simples é permitir que as exceções ocorram naturalmente. O MLflow captura automaticamente a exceção e cria um objeto Feedback com os detalhes do erro:
import mlflow
from mlflow.entities import Feedback
from mlflow.genai.scorers import scorer
@scorer
def is_valid_response(outputs: str) -> Feedback:
import json
# Let json.JSONDecodeError propagate if response isn't valid JSON
data = json.loads(outputs)
# Let KeyError propagate if required fields are missing
summary = data["summary"]
confidence = data["confidence"]
return Feedback(
value=True,
rationale=f"Valid JSON with confidence: {confidence}"
)
# Run the scorer on invalid data that triggers exceptions
invalid_data = [
{
# Valid JSON
"outputs": '{"summary": "this is a summary", "confidence": 0.95}'
},
{
# Invalid JSON
"outputs": "invalid json",
},
{
# Missing required fields
"outputs": '{"summary": "this is a summary"}'
},
]
mlflow.genai.evaluate(
data=invalid_data,
scorers=[is_valid_response],
)
Quando ocorre uma exceção, o MLflow cria um feedback com:
value
:None
error
: os detalhes da exceção, como objeto de exceção, mensagem de erro e rastreamento de pilha
As informações sobre o erro serão exibidas nos resultados da avaliação. Abra a linha correspondente para ver os detalhes do erro.
Lidar com exceções de forma explícita
Para tratamento personalizado de erros ou para fornecer mensagens de erro específicas, detecte exceções e retorne um feedback com o valor None
e os detalhes do erro:
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
O parâmetro error
aceita:
- Exceção do Python : Passar o objeto de exceção diretamente
- AssessmentError : para relatórios de erros estruturados com códigos de erro
Quando as expectativas estão disponíveis
As expectativas (verdade básica ou rótulo) são normalmente importantes para a avaliação off-line. Você pode especificá-los de duas maneiras ao executar mlflow.genai.evaluate()
:
- Inclua a coluna (ou campo)
expectations
no argumento de entradadata
. - Associe
Expectation
aos Traces e passe-os para o argumentodata
.
@scorer
def exact_match(outputs: str, expectations: dict[str, Any]) -> Feedback:
expected = expectations.get("expected_response")
is_correct = outputs == expected
return Feedback(
value=is_correct,
rationale=f"Response {'matches' if is_correct else 'differs from'} expected"
)
data = [
{
"inputs": {"question": "What is the capital of France?"},
"outputs": "Paris",
# Specify expected response in the expectations field
"expectations": {
"expected_response": "Paris"
}
},
]
mlflow.genai.evaluate(
data=data,
scorers=[exact_match],
)
Normalmente, o monitoramento da produção não tem expectativas, pois o senhor está avaliando o tráfego ao vivo sem a verdade básica. Se você pretende usar o mesmo marcador para avaliação offline e on-line, projete-o para lidar com as expectativas com elegância.
Usando dados de rastreamento
Os pontuadores podem acessar o rastreamento completo para avaliar o comportamento complexo do aplicativo:
from mlflow.entities import Feedback, Trace
from mlflow.genai.scorers import scorer
@scorer
def tool_call_efficiency(trace: Trace) -> Feedback:
"""Evaluate how effectively the app uses tools"""
# Retrieve all tool call spans from the trace
tool_calls = trace.search_spans(span_type="TOOL")
if not tool_calls:
return Feedback(
value=None,
rationale="No tool usage to evaluate"
)
# Check for redundant calls
tool_names = [span.name for span in tool_calls]
if len(tool_names) != len(set(tool_names)):
return Feedback(
value=False,
rationale=f"Redundant tool calls detected: {tool_names}"
)
# Check for errors
failed_calls = [s for s in tool_calls if s.status.status_code != "OK"]
if failed_calls:
return Feedback(
value=False,
rationale=f"{len(failed_calls)} tool calls failed"
)
return Feedback(
value=True,
rationale=f"Efficient tool usage: {len(tool_calls)} successful calls"
)
Ao executar a avaliação offline com mlflow.genai.evaluate()
, os rastreamentos são:
- especificados no argumento
data
se eles já estiverem disponíveis. - gerado executando
predict_fn
contrainputs
no argumentodata
.
Ao executar o monitoramento de produção com mlflow.genai.create_monitor()
, os traços coletados pelo monitor são passados diretamente para a função de pontuador, com os critérios de amostragem e filtragem especificados.
Abordagens de implementação do Scorer
O MLflow oferece duas maneiras de implementar marcadores:
Abordagem do decorador (recomendada)
Use o decorador @scorer
para pontuadores simples e baseados em funções:
from mlflow.genai.scorers import scorer
from mlflow.entities import Feedback
@scorer
def response_tone(outputs: str) -> Feedback:
"""Check if response maintains professional tone"""
informal_phrases = ["hey", "gonna", "wanna", "lol", "btw"]
found = [p for p in informal_phrases if p in outputs.lower()]
if found:
return Feedback(
value=False,
rationale=f"Informal language detected: {', '.join(found)}"
)
return Feedback(
value=True,
rationale="Professional tone maintained"
)
Abordagem baseada em classes
Use a classe base Scorer
para pontuadores mais complexos que exigem estado. A classe Scorer
é um objeto Pydantic, então você pode definir campos adicionais e usá-los no método __call__
.
from mlflow.genai.scorers import Scorer
from mlflow.entities import Feedback
from typing import Optional
# Scorer class is a Pydantic object
class ResponseQualityScorer(Scorer):
# The `name` field is mandatory
name: str = "response_quality"
# Define additiona lfields
min_length: int = 50
required_sections: Optional[list[str]] = None
# Override the __call__ method to implement the scorer logic
def __call__(self, outputs: str) -> Feedback:
issues = []
# Check length
if len(outputs.split()) < self.min_length:
issues.append(f"Too short (minimum {self.min_length} words)")
# Check required sections
missing = [s for s in self.required_sections if s not in outputs]
if missing:
issues.append(f"Missing sections: {', '.join(missing)}")
if issues:
return Feedback(
value=False,
rationale="; ".join(issues)
)
return Feedback(
value=True,
rationale="Response meets all quality criteria"
)
Custom scorer development fluxo de trabalho
Ao desenvolver pontuadores personalizados, você geralmente precisa iterar rapidamente sem executar novamente seu aplicativo a cada vez. O MLflow oferece suporte a um fluxo de trabalho eficiente:
- Gere rastreamentos uma vez executando seu aplicativo com
mlflow.genai.evaluate()
- Armazene os traços usando
mlflow.search_traces()
- Itere os marcadores passando os rastreamentos armazenados para
evaluate()
sem executar seu aplicativo novamente
Essa abordagem economiza tempo e recursos durante o desenvolvimento do marcador:
# Step 1: Generate traces with a placeholder scorer
initial_results = mlflow.genai.evaluate(
data=test_dataset,
predict_fn=my_app,
scorers=[lambda **kwargs: 1] # Placeholder scorer
)
# Step 2: Store traces for reuse
traces = mlflow.search_traces(run_id=initial_results.run_id)
# Step 3: Iterate on your scorer without re-running the app
@scorer
def my_custom_scorer(outputs):
# Your evaluation logic here
pass
# Test scorer on stored traces (no predict_fn needed)
results = mlflow.genai.evaluate(
data=traces,
scorers=[my_custom_scorer]
)
Pegadinhas comuns
Nomeação de marcadores com decoradores
from mlflow.genai.scorers import scorer
from mlflow.entities import Feedback
# GOTCHA: Function name becomes feedback name for single returns
@scorer
def quality_check(outputs):
# This 'name' parameter is IGNORED
return Feedback(name="ignored", value=True)
# Feedback will be named "quality_check"
# CORRECT: Use function name meaningfully
@scorer
def response_quality(outputs):
return Feedback(value=True, rationale="Good quality")
# Feedback will be named "response_quality"
# EXCEPTION: Multiple feedbacks preserve their names
@scorer
def multi_check(outputs):
return [
Feedback(name="grammar", value=True), # Name preserved
Feedback(name="spelling", value=True), # Name preserved
Feedback(name="clarity", value=0.9) # Name preserved
]
Gestão estadual em marcadores
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!
def __call__(self, outputs, **kwargs):
self.results.append(outputs) # Causes issues
return Feedback(value=True)
# CORRECT: Use instance attributes
class GoodScorer(Scorer):
def __init__(self):
super().__init__(name="good_scorer")
self.results = [] # Per-instance state
def __call__(self, outputs, **kwargs):
self.results.append(outputs) # Safe
return Feedback(value=True)
Próximas etapas
- Criar marcadores personalizados baseados em código - Criar marcadores específicos de domínio usando funções Python
- Avalie com os juízes do LLM - Use os avaliadores pré-construídos baseados no LLM para métricas de qualidade comuns
- scorers de execução na produção - Aplique os mesmos scorers para monitorar o tráfego de produção