Pular para o conteúdo principal

Monitoramento de produção para GenAI

info

Beta

Este recurso está em fase beta.

O monitoramento de produção para GenAI no Databricks permite que você execute automaticamente os scorers MLflow 3 em rastros de seus aplicativos de produção GenAI para monitorar continuamente a qualidade.

Você pode programar pontuadores para avaliar automaticamente uma amostra do seu tráfego de produção. Os resultados da avaliação do pontuador são automaticamente anexados como feedback aos traços avaliados.

O monitoramento da produção inclui o seguinte:

  • Avaliação de qualidade automatizada usando pontuadores integrados ou personalizados.
  • Taxas de amostragem configuráveis para que você possa controlar a compensação entre cobertura e custo computacional.
  • Use os mesmos avaliadores no desenvolvimento e na produção para garantir uma avaliação consistente.
  • Avaliação contínua da qualidade com monitoramento em segundo plano.
nota

MLflow O monitoramento da produção 3 é compatível com os registros de traços do site MLflow 2.

Para informações sobre monitoramento de produção legado, consulte Referência API de monitoramento de produção (legado).

Pré-requisitos

Antes de configurar o monitoramento de qualidade, certifique-se de que possui:

  1. ExperimentoMLflow : Um experimento MLflow onde os rastros estão sendo registrados. Se nenhum experimento for especificado, o experimento ativo será usado.
  2. Aplicação de produção instrumentada : seu aplicativo GenAI deve estar registrando rastreamentos usando o MLflow Tracing. Consulte o guia Rastreamento de produção.
  3. Pontuadores definidos:pontuadores testados que funcionam com o formato de rastreamento do seu aplicativo.
dica

Se você usou seu aplicativo de produção como predict_fn em mlflow.genai.evaluate() durante o desenvolvimento, seus marcadores provavelmente já são compatíveis.

Iniciar o monitoramento da produção

Esta seção inclui um exemplo de código que mostra como criar os diferentes tipos de marcadores.

Para mais informações sobre os pontuadores, veja o seguinte:

nota

A qualquer momento, no máximo 20 avaliadores podem estar associados a um experimento para monitoramento contínuo da qualidade.

Use juízes LLM integrados

MLflow fornece vários juízes LLM integrados que você pode usar imediatamente para monitoramento.

Python
from mlflow.genai.scorers import Safety, ScorerSamplingConfig

# Register the scorer with a name and start monitoring
safety_judge = Safety().register(name="my_safety_judge") # name must be unique to experiment
safety_judge = safety_judge.start(sampling_config=ScorerSamplingConfig(sample_rate=0.7))

Por default, cada juiz usa um LLM hospedado Databricks , projetado para realizar avaliações de qualidade do GenAI. Você pode alterar o modelo do juiz para usar um endpoint do modelo de atendimento Databricks usando o argumento model na definição do pontuador. O modelo deve ser especificado no formato databricks:/<databricks-serving-endpoint-name>.

Python
safety_judge = Safety(model="databricks:/databricks-gpt-oss-20b").register(name="my_custom_safety_judge")

Diretrizes de uso para juízes do LLM

Diretrizes Os juízes do LLM podem avaliar entradas e saídas usando critérios de aprovação/reprovação em linguagem natural.

Python
from mlflow.genai.scorers import Guidelines

# Create and register the guidelines scorer
english_judge = Guidelines(
name="english",
guidelines=["The response must be in English"]
).register(name="is_english") # name must be unique to experiment

# Start monitoring with the specified sample rate
english_judge = english_judge.start(sampling_config=ScorerSamplingConfig(sample_rate=0.7))

Assim como os juízes integrados, você pode alterar o modelo do juiz para usar um endpoint do modelo servindo Databricks .

Python
english_judge = Guidelines(
name="english",
guidelines=["The response must be in English"],
model="databricks:/databricks-gpt-oss-20b",
).register(name="custom_is_english")

Use juízes LLM com prompts personalizados

Para mais flexibilidade do que os juízes das Diretrizes, você pode usar os juízes do LLM com prompts personalizados que permitem avaliação de qualidade em vários níveis com categorias de escolha personalizáveis (por exemplo, excelente/bom/ruim) e pontuação numérica opcional.

Python
from mlflow.genai.scorers import scorer, ScorerSamplingConfig


@scorer
def formality(inputs, outputs, trace):
# Must be imported inline within the scorer function body
from mlflow.genai.judges import custom_prompt_judge
from mlflow.entities.assessment import DEFAULT_FEEDBACK_NAME

formality_prompt = """
You will look at the response and determine the formality of the response.

<request>{{request}}</request>
<response>{{response}}</response>

You must choose one of the following categories.

[[formal]]: The response is very formal.
[[semi_formal]]: The response is somewhat formal. The response is somewhat formal if the response mentions friendship, etc.
[[not_formal]]: The response is not formal.
"""

my_prompt_judge = custom_prompt_judge(
name="formality",
prompt_template=formality_prompt,
numeric_values={
"formal": 1,
"semi_formal": 0.5,
"not_formal": 0,
},
model="databricks:/databricks-gpt-oss-20b", # optional
)

result = my_prompt_judge(request=inputs, response=inputs)
if hasattr(result, "name"):
result.name = DEFAULT_FEEDBACK_NAME
return result

# Register the custom judge and start monitoring
formality_judge = formality.register(name="my_formality_judge") # name must be unique to experiment
formality_judge = formality_judge.start(sampling_config=ScorerSamplingConfig(sample_rate=0.1))

Use funções personalizadas de pontuação

Para obter flexibilidade máxima, incluindo a opção de dispensar a pontuação baseada em LLM, é possível definir e utilizar uma função de pontuação personalizada para monitoramento.

Ao definir pontuadores personalizados, não use dicas de tipo que precisem ser importadas na assinatura da função. Se o corpo da função de pontuação utiliza pacotes que precisam ser importados, importe esses pacotes inline dentro da função para uma serialização adequada.

Alguns pacotes estão disponíveis em default sem a necessidade de uma importação inline. Estes incluem databricks-agents, mlflow-skinny, openai e todos os pacotes incluídos na versão 2 do ambiente sem servidor.

Python
from mlflow.genai.scorers import scorer, ScorerSamplingConfig


# Custom metric: Check if response mentions Databricks
@scorer
def mentions_databricks(outputs):
"""Check if the response mentions Databricks"""
return "databricks" in str(outputs.get("response", "")).lower()

# Custom metric: Response length check
@scorer(aggregations=["mean", "min", "max"])
def response_length(outputs):
"""Measure response length in characters"""
return len(str(outputs.get("response", "")))

# Custom metric with multiple inputs
@scorer
def response_relevance_score(inputs, outputs):
"""Score relevance based on keyword matching"""
query = str(inputs.get("query", "")).lower()
response = str(outputs.get("response", "")).lower()

# Simple keyword matching (replace with your logic)
query_words = set(query.split())
response_words = set(response.split())

if not query_words:
return 0.0

overlap = len(query_words & response_words)
return overlap / len(query_words)

# Register and start monitoring custom scorers
databricks_scorer = mentions_databricks.register(name="databricks_mentions")
databricks_scorer = databricks_scorer.start(sampling_config=ScorerSamplingConfig(sample_rate=0.5))

length_scorer = response_length.register(name="response_length")
length_scorer = length_scorer.start(sampling_config=ScorerSamplingConfig(sample_rate=1.0))

relevance_scorer = response_relevance_score.register(name="response_relevance_score") # name must be unique to experiment
relevance_scorer = relevance_scorer.start(sampling_config=ScorerSamplingConfig(sample_rate=1.0))

Configuração de vários marcadores

Para uma configuração abrangente do monitoramento, é possível registrar e iniciar vários avaliadores individualmente.

Python
from mlflow.genai.scorers import Safety, Guidelines, ScorerSamplingConfig, list_scorers

# # Register multiple scorers for comprehensive monitoring
safety_judge = Safety().register(name="safety") # name must be unique within an MLflow experiment
safety_judge = safety_judge.start(
sampling_config=ScorerSamplingConfig(sample_rate=1.0), # Check all traces
)

guidelines_judge = Guidelines(
name="english",
guidelines=["Response must be in English"]
).register(name="english_check")
guidelines_judge = guidelines_judge.start(
sampling_config=ScorerSamplingConfig(sample_rate=0.5), # Sample 50%
)

# List and manage all scorers
all_scorers = list_scorers()
for scorer in all_scorers:
if scorer.sample_rate > 0:
print(f"{scorer.name} is active")
else:
print(f"{scorer.name} is stopped")

gerenciar pontuadores programados

Os ciclos de vida do Scorer são centrados em experimentos do MLflow. Os estados do ciclo de vida do marcador são os seguintes:

  1. Não registrado : a função do pontuador está definida, mas não é conhecida pelo servidor.
  2. Registrado : o avaliador está registrado no experimento MLflow ativo. Para registrar um pontuador, use .register().
  3. Ativo : O Scorer está sendo executado com uma taxa de amostragem > 0. Para iniciar um scorer, use .start().
  4. Parado : o Scorer está registrado, mas não está em execução (taxa de amostragem = 0). Para parar um marcador, use .stop().
  5. Excluído : o pontuador foi removido do servidor e não está mais associado ao seu experimento MLflow. Para excluir um marcador, use .delete().

Todas as operações do ciclo de vida são imutáveis . Isso significa que cada operação não modifica o marcador original. Em vez disso, ele retorna uma nova instância do scorer.

Ciclo de vida básico do scorer

Python
from mlflow.genai.scorers import Safety, scorer, ScorerSamplingConfig

# Built-in scorer lifecycle
safety_judge = Safety().register(name="safety_check")
safety_judge = safety_judge.start(
sampling_config=ScorerSamplingConfig(sample_rate=1.0),
)
safety_judge = safety_judge.update(
sampling_config=ScorerSamplingConfig(sample_rate=0.8),
)
safety_judge = safety_judge.stop()
safety_judge.delete()

# Custom scorer lifecycle
@scorer
def response_length(outputs):
return len(str(outputs.get("response", "")))

length_scorer = response_length.register(name="length_check")
length_scorer = length_scorer.start(
sampling_config=ScorerSamplingConfig(sample_rate=0.5),
)

Listar os marcadores atuais

Para view todos os avaliadores registrados para o seu experimento:

Python
from mlflow.genai.scorers import list_scorers

# List all registered scorers
scorers = list_scorers()
for scorer in scorers:
print(f"Name: {scorer._server_name}")
print(f"Sample rate: {scorer.sample_rate}")
print(f"Filter: {scorer.filter_string}")
print("---")

Atualizar um marcador

Para modificar as configurações existentes do marcador:

Python
from mlflow.genai.scorers import get_scorer

# Get existing scorer and update its configuration (immutable operation)
safety_judge = get_scorer(name="safety_monitor")
updated_judge = safety_judge.update(sampling_config=ScorerSamplingConfig(sample_rate=0.8)) # Increased from 0.5

# Note: The original scorer remains unchanged; update() returns a new scorer instance
print(f"Original sample rate: {safety_judge.sample_rate}") # Original rate
print(f"Updated sample rate: {updated_judge.sample_rate}") # New rate

Pare e exclua marcadores

Para interromper o monitoramento ou remover um avaliador completamente:

Python
from mlflow.genai.scorers import get_scorer, delete_scorer

# Get existing scorer
databricks_scorer = get_scorer(name="databricks_mentions")

# Stop monitoring (sets sample_rate to 0, keeps scorer registered)
stopped_scorer = databricks_scorer.stop()
print(f"Sample rate after stop: {stopped_scorer.sample_rate}") # 0

# Remove scorer entirely from the server
delete_scorer(name=databricks_scorer.name)

# Or restart monitoring from a stopped scorer
restarted_scorer = stopped_scorer.start(sampling_config=ScorerSamplingConfig(sample_rate=0.5))

Atualizações imutáveis

Os avaliadores, incluindo os juízes do LLM, são objetos imutáveis: atualizar um avaliador não modifica o avaliador original, mas retorna uma cópia atualizada do avaliador. Essa imutabilidade é útil para garantir que os marcadores destinados à produção não sejam modificados acidentalmente. O trecho de código abaixo demonstra como as atualizações imutáveis funcionam.

Python
# Demonstrate immutability
original_judge = Safety().register(name="safety")
original_judge = original_judge.start(
sampling_config=ScorerSamplingConfig(sample_rate=0.3),
)

# Update returns new instance
updated_judge = original_judge.update(
sampling_config=ScorerSamplingConfig(sample_rate=0.8),
)

# Original remains unchanged
print(f"Original: {original_judge.sample_rate}") # 0.3
print(f"Updated: {updated_judge.sample_rate}") # 0.8

Avaliar traços históricos (preenchimento de métricas)

É possível aplicar retroativamente métricas novas ou atualizadas a rastreamentos históricos.

Preenchimento básico de métricas utilizando taxas de amostragem atuais

Python
from databricks.agents.scorers import backfill_scorers

safety_judge = Safety()
safety_judge.register(name="safety_check")
safety_judge.start(sampling_config=ScorerSamplingConfig(sample_rate=0.5))

#custom scorer
@scorer(aggregations=["mean", "min", "max"])
def response_length(outputs):
"""Measure response length in characters"""
return len(outputs)

response_length.register(name="response_length")
response_length.start(sampling_config=ScorerSamplingConfig(sample_rate=0.5))

# Use existing sample rates for specified scorers
job_id = backfill_scorers(
scorers=["safety_check", "response_length"]
)

Preenchimento de métricas utilizando taxas de amostragem e intervalos de tempo personalizados

Python
from databricks.agents.scorers import backfill_scorers, BackfillScorerConfig
from datetime import datetime
from mlflow.genai.scorers import Safety, Correctness

safety_judge = Safety()
safety_judge.register(name="safety_check")
safety_judge.start(sampling_config=ScorerSamplingConfig(sample_rate=0.5))

#custom scorer
@scorer(aggregations=["mean", "min", "max"])
def response_length(outputs):
"""Measure response length in characters"""
return len(outputs)

response_length.register(name="response_length")
response_length.start(sampling_config=ScorerSamplingConfig(sample_rate=0.5))

# Define custom sample rates for backfill
custom_scorers = [
BackfillScorerConfig(scorer=safety_judge, sample_rate=0.8),
BackfillScorerConfig(scorer=response_length, sample_rate=0.9)
]

job_id = backfill_scorers(
experiment_id=YOUR_EXPERIMENT_ID,
scorers=custom_scorers,
start_time=datetime(2024, 6, 1),
end_time=datetime(2024, 6, 30)
)

Preenchimento de dados recentes

Python
from datetime import datetime, timedelta

# Backfill last week's data with higher sample rates
one_week_ago = datetime.now() - timedelta(days=7)

job_id = backfill_scorers(
scorers=[
BackfillScorerConfig(scorer=safety_judge, sample_rate=0.8),
BackfillScorerConfig(scorer=response_length, sample_rate=0.9)
],
start_time=one_week_ago
)

visualizar resultados

Após programar os avaliadores, aguarde 15 a 20 minutos para o processamento inicial. Então:

  1. Navegue até o seu experimento MLflow.
  2. Abra o Traces tab para visualizar as avaliações anexadas aos traços.
  3. Utilize os painéis de monitoramento para acompanhar as tendências de qualidade.

Melhores práticas

Gestão do estado do marcador

  • Verifique o estado do marcador antes das operações usando a propriedade sample_rate .
  • Use o padrão imutável. Atribuir resultados de .start(), .update(), .stop() às variáveis.
  • Entenda o ciclo de vida do marcador. .stop() preserva o registro, .delete() remove o marcador completamente.

métricas de preenchimento

  • começar pequeno. Comece com intervalos de tempo menores para estimar a duração do trabalho e a utilização dos recursos.
  • Use taxas de amostragem apropriadas. Considere as implicações de custo e tempo do uso de altas taxas de amostragem.

Estratégia de amostragem

  • Para pontuações críticas, como verificações de segurança, use sample_rate=1.0.

  • Para avaliadores caros, como juízes LLM complexos, use taxas de amostragem mais baixas (0,05-0,2).

  • Para melhoria iterativa durante o desenvolvimento, use taxas moderadas (0,3-0,5).

  • Equilibre a cobertura com o custo, conforme mostrado nos exemplos a seguir:

    Python
    # High-priority scorers: higher sampling
    safety_judge = Safety().register(name="safety")
    safety_judge = safety_judge.start(sampling_config=ScorerSamplingConfig(sample_rate=1.0)) # 100% coverage for critical safety

    # Expensive scorers: lower sampling
    complex_scorer = ComplexCustomScorer().register(name="complex_analysis")
    complex_scorer = complex_scorer.start(sampling_config=ScorerSamplingConfig(sample_rate=0.05)) # 5% for expensive operations

Design de marcador personalizado

Mantenha os marcadores personalizados independentes, conforme mostrado no exemplo a seguir:

Python
@scorer
def well_designed_scorer(inputs, outputs):
# ✅ All imports inside the function
import re
import json

# ✅ Handle missing data gracefully
response = outputs.get("response", "")
if not response:
return 0.0

# ✅ Return consistent types
return float(len(response) > 100)

Solução de problemas

Os marcadores não estão correndo

Se os marcadores não estiverem em execução, verifique o seguinte:

  1. Verifique o experimento : certifique-se de que os rastreamentos são registros do experimento, e não de execuções individuais.
  2. Taxa de amostragem : com baixas taxas de amostragem, pode levar algum tempo para ver os resultados.

Problemas de serialização

Ao criar um marcador personalizado, inclua as importações na definição da função.

Python
# ❌ Avoid external dependencies
import external_library # Outside function

@scorer
def bad_scorer(outputs):
return external_library.process(outputs)

# ✅ Include imports in the function definition
@scorer
def good_scorer(outputs):
import json # Inside function
return len(json.dumps(outputs))

# ❌ Avoid using type hints in scorer function signature that requires imports
from typing import List

@scorer
def scorer_with_bad_types(outputs: List[str]):
return False

problemas de preenchimento de métricas

" Marcador programado 'X' não encontrado no experimento "

  • Certifique-se de que o nome do marcador corresponda a um marcador registrado em seu experimento
  • Verifique os marcadores disponíveis usando o método list_scorers

Rastros de arquivo

O senhor pode salvar traços e suas avaliações associadas em uma tabela Delta do Unity Catalog para armazenamento de longo prazo e análise avançada. Isso é útil para criar painéis personalizados, realizar análises detalhadas dos dados de rastreamento e manter um registro duradouro do comportamento do seu aplicativo.

nota

O senhor deve ter as permissões necessárias para gravar na tabela Delta do Unity Catalog especificada. A tabela de destino será criada se ainda não existir.

Se a tabela já existir, os traços serão anexados a ela.

Habilitar rastreamentos de arquivamento

Para começar a arquivar rastreamentos para um experimento, use a função enable_databricks_trace_archival. O senhor deve especificar o nome completo da tabela Delta de destino, incluindo o catálogo e o esquema. Se você não fornecer um experiment_id, o arquivamento de rastreamentos será habilitado para o experimento atualmente ativo.

Python
from mlflow.tracing.archival import enable_databricks_trace_archival

# Archive traces from a specific experiment to a Unity Catalog Delta table
enable_databricks_trace_archival(
delta_table_fullname="my_catalog.my_schema.archived_traces",
experiment_id="YOUR_EXPERIMENT_ID",
)

Desativar rastreamentos de arquivamento

Você pode parar de arquivar rastreamentos para um experimento a qualquer momento usando a função disable_databricks_trace_archival.

Python
from mlflow.tracing.archival import disable_databricks_trace_archival

# Stop archiving traces for the specified experiment
disable_databricks_trace_archival(experiment_id="YOUR_EXPERIMENT_ID")

Próximos passos

Guia de referência

Explore a documentação detalhada sobre os conceitos e recursos mencionados neste guia.