MLflow Tracing pour les agents
Important
Cette fonctionnalité est disponible en préversion publique.
Cet article décrit le suivi MLflow sur Databricks et explique comment l’utiliser pour ajouter l’observabilité à vos applications IA génératives.
Qu’est-ce que le MLflow Tracing ?
MLflow Tracing capture des informations détaillées sur l’exécution d’applications IA générative. Traçage des journaux d'entrées, des sorties et des métadonnées associées à chaque étape intermédiaire d’une requête afin de pouvoir identifier la source des bogues ou un comportement inattendu. Par exemple, si votre modèle hallucine, vous pouvez rapidement inspecter chaque étape qui a conduit à l’hallucination.
Le suivi MLflow est intégré aux outils et à l’infrastructure Databricks, ce qui vous permet de stocker et d’afficher des traces dans les notebooks Databricks ou l’interface utilisateur de l’expérience MLflow.
Pourquoi utiliser MLflow Tracing ?
Le suivi MLflow offre plusieurs avantages :
- Passez en revue une visualisation de trace interactive et utilisez l’outil d’investigation pour diagnostiquer les problèmes.
- Vérifiez que les modèles d’invite et les garde-fous produisent des résultats raisonnables.
- Analysez la latence des différents frameworks, modèles et tailles de blocs.
- Estimer les coûts de l’application en mesurant l’utilisation des jetons sur différents modèles.
- Établissez des jeux de données « golden » de référence pour évaluer les performances des différentes versions.
- Stockez les traces des points de terminaison de modèle de production pour déboguer les problèmes et effectuer une révision et une évaluation hors connexion.
Ajouter des traces à votre agent
Le suivi MLflow prend en charge trois méthodes pour ajouter des traces à vos applications IA génératives. Pour des exemples de référence API, consultez la documentation sur MLflow.
API | Cas d’usage recommandé | Description |
---|---|---|
Journalisation automatique MLflow | Développement avec des bibliothèques GenAI intégrées | La journalisation automatique enregistre automatiquement les traces pour les frameworks open source pris en charge comme LangChain, LlamaIndex et OpenAI. |
API fluides | Agent personnalisé avec Pyfunc | API low code pour ajouter des traces sans se préoccuper de la gestion de l’arborescence de la trace. MLflow détermine automatiquement les relations d’étendue parent-enfant appropriées à l’aide de la pile Python. |
API client MLflow | Cas d’usage avancés tels que le multithreading | MLflowClient fournit des API granulaires et thread-safe pour les cas d’usage avancés. Vous devez gérer manuellement la relation de parenté des portées. Cela vous permet de mieux contrôler le cycle de vie des traces, en particulier pour les scénarios multi-thread. |
Installer MLflow Tracing
Le suivi MLflow est disponible dans les versions 2.13.0 et ultérieures de MLflow, qui est préinstallé dans <DBR< 15.4 LTS ML et versions ultérieures. Si nécessaire, installez MLflow avec le code suivant :
%pip install mlflow>=2.13.0 -qqqU
%restart_python
Vous pouvez également installer la dernière version de databricks-agents
, qui inclut une version MLflow compatible :
%pip install databricks-agents
Utiliser l'autologging pour ajouter des traces à vos agents
Si votre bibliothèque GenAI prend en charge le suivi, comme LangChain ou OpenAI, activez l'autologging en ajoutant mlflow.<library>.autolog()
à votre code. Par exemple:
mlflow.langchain.autolog()
Remarque
À partir de Databricks Runtime 15.4 LTS ML, le suivi MLflow est activé par défaut dans les notebooks. Pour désactiver le suivi, par exemple, avec LangChain, vous pouvez exécuter mlflow.langchain.autolog(log_traces=False)
dans votre bloc-notes.
MLflow prend en charge des bibliothèques supplémentaires pour la journalisation automatique de trace. Pour obtenir la liste complète des bibliothèques intégrées, consultez la documentation de suivi MLflow.
Utiliser des API Fluent pour ajouter manuellement des traces à votre agent
Les API Fluent dans MLflow créent automatiquement des hiérarchies de trace en fonction du flux d’exécution de votre code.
Décorer votre fonction
Utilisez le décorateur @mlflow.trace
pour créer une étendue pour la portée de la fonction décorée.
L’objet MLflow Span organise les étapes de suivi. Spans capture des informations sur des opérations ou des étapes individuelles, telles que les appels d’API ou les requêtes de magasin de vecteurs, au sein d’un workflow.
La portée démarre lorsque la fonction est appelée et se termine lorsqu’elle est retournée. MLflow enregistre l’entrée et la sortie de la fonction et toutes les exceptions levées à partir de la fonction.
Par exemple, le code suivant crée une étendue nommée my_function
qui capture les arguments d’entrée x
et y
et la sortie.
@mlflow.trace(name="agent", span_type="TYPE", attributes={"key": "value"})
def my_function(x, y):
return x + y
Utilisez le gestionnaire de contexte de traçage
Si vous souhaitez créer une étendue pour un bloc de code arbitraire, pas seulement une fonction, vous pouvez utiliser mlflow.start_span()
en tant que gestionnaire de contexte qui encapsule le bloc de code. La portée commence lorsque le contexte est entré et se termine lorsque le contexte est arrêté. Les entrées et sorties de la plage doivent être fournies manuellement à l’aide de méthodes setter de l’objet de plage généré par le gestionnaire de contexte.
with mlflow.start_span("my_span") as span:
span.set_inputs({"x": x, "y": y})
result = x + y
span.set_outputs(result)
span.set_attribute("key", "value")
Envelopper une fonction externe
Pour tracer les fonctions de bibliothèque externe, encapsulez la fonction avec mlflow.trace
.
from sklearn.metrics import accuracy_score
y_pred = [0, 2, 1, 3]
y_true = [0, 1, 2, 3]
traced_accuracy_score = mlflow.trace(accuracy_score)
traced_accuracy_score(y_true, y_pred)
Exemple d’API Fluent
L’exemple suivant montre comment utiliser les API Fluent mlflow.trace
et mlflow.start_span
pour suivre l'quickstart-agent
:
import mlflow
from mlflow.deployments import get_deploy_client
class QAChain(mlflow.pyfunc.PythonModel):
def __init__(self):
self.client = get_deploy_client("databricks")
@mlflow.trace(name="quickstart-agent")
def predict(self, model_input, system_prompt, params):
messages = [
{
"role": "system",
"content": system_prompt,
},
{
"role": "user",
"content": model_input[0]["query"]
}
]
traced_predict = mlflow.trace(self.client.predict)
output = traced_predict(
endpoint=params["model_name"],
inputs={
"temperature": params["temperature"],
"max_tokens": params["max_tokens"],
"messages": messages,
},
)
with mlflow.start_span(name="_final_answer") as span:
# Initiate another span generation
span.set_inputs({"query": model_input[0]["query"]})
answer = output["choices"][0]["message"]["content"]
span.set_outputs({"generated_text": answer})
# Attributes computed at runtime can be set using the set_attributes() method.
span.set_attributes({
"model_name": params["model_name"],
"prompt_tokens": output["usage"]["prompt_tokens"],
"completion_tokens": output["usage"]["completion_tokens"],
"total_tokens": output["usage"]["total_tokens"]
})
return answer
Après avoir ajouté la trace, exécutez la fonction. L’exemple suivant poursuit l’exemple avec la fonction predict()
dans la section précédente. Les traces s’affichent automatiquement lorsque vous exécutez la méthode d’appel, predict()
.
SYSTEM_PROMPT = """
You are an assistant for Databricks users. You answer Python, coding, SQL, data engineering, spark, data science, DW and platform, API, or infrastructure administration questions related to Databricks. If the question is unrelated to one of these topics, kindly decline to answer. If you don't know the answer, say that you don't know; don't try to make up an answer. Keep the answer as concise as possible. Use the following pieces of context to answer the question at the end:
"""
model = QAChain()
prediction = model.predict(
[
{"query": "What is in MLflow 5.0"},
],
SYSTEM_PROMPT,
{
# Using Databricks Foundation Model for easier testing, feel free to replace it.
"model_name": "databricks-dbrx-instruct",
"temperature": 0.1,
"max_tokens": 1000,
}
)
API client MLflow
MlflowClient
expose des API granulaires et thread safe pour démarrer et terminer les traces, gérer les portées et définir des champs de portée. Il fournit un contrôle complet du cycle de vie et de la structure de trace. Ces API sont utiles lorsque les API Fluent ne suffisent pas à vos besoins, par exemple pour des applications multithreading et des rappels.
Les étapes suivantes permettent de créer une trace complète à l’aide du client MLflow.
Créez une instance de MLflowClient par
client = MlflowClient()
.Démarrez une trace à l’aide de la méthode
client.start_trace()
. Cette opération lance le contexte de trace et démarre une étendue racine absolue et retourne un objet d’étendue racine. Cette méthode doit être exécutée avant l’APIstart_span()
.- Définissez vos attributs, entrées et sorties pour la trace dans
client.start_trace()
.
Remarque
Il n’existe pas d’équivalent à la méthode
start_trace()
dans les API Fluent. Cela est dû au fait que les API Fluent initialisent automatiquement le contexte de trace et déterminent s’il s’agit de l’étendue racine en fonction de l’état managé.- Définissez vos attributs, entrées et sorties pour la trace dans
L’API start_trace() retourne une portée. Obtenez l’ID de requête, un identificateur unique de la trace également appelé
trace_id
et l’ID de l’étendue retournée à l’aide despan.request_id
et despan.span_id
.Démarrez une portée enfant en utilisant
client.start_span(request_id, parent_id=span_id)
pour définir vos attributs, entrées et sorties pour la portée.- Cette méthode nécessite
request_id
etparent_id
d’associer l’étendue à la position correcte dans la hiérarchie de trace. Elle retourne un autre objet de portée.
- Cette méthode nécessite
Terminez la portée enfant en appelant
client.end_span(request_id, span_id)
.Répétez les étapes 3 à 5 pour créer toutes les portées enfant que vous souhaitez.
Une fois toutes les sous-étendues terminées, appelez
client.end_trace(request_id)
pour fermer la trace et l’enregistrer.
from mlflow.client import MlflowClient
mlflow_client = MlflowClient()
root_span = mlflow_client.start_trace(
name="simple-rag-agent",
inputs={
"query": "Demo",
"model_name": "DBRX",
"temperature": 0,
"max_tokens": 200
}
)
request_id = root_span.request_id
# Retrieve documents that are similar to the query
similarity_search_input = dict(query_text="demo", num_results=3)
span_ss = mlflow_client.start_span(
"search",
# Specify request_id and parent_id to create the span at the right position in the trace
request_id=request_id,
parent_id=root_span.span_id,
inputs=similarity_search_input
)
retrieved = ["Test Result"]
# You must explicitly end the span
mlflow_client.end_span(request_id, span_id=span_ss.span_id, outputs=retrieved)
root_span.end_trace(request_id, outputs={"output": retrieved})
Examen des traces
Pour passer en revue les traces après l’exécution de l’agent, utilisez l’une des options suivantes :
- La visualisation des traces est affichée en ligne dans la sortie de la cellule.
- Les traces sont consignées dans votre expérience MLflow. Vous pouvez consulter et rechercher la liste complète des traces historiques dans l’onglet Traces de la page Expérience. Lorsque l’agent s’exécute dans un Run MLflow actif, les traces s’affichent sur la page Run.
- Récupérez les traces par programmation à l’aide de l’API search_traces().
Utiliser MLflow Tracing en production
MLflow Tracing est également intégré à Mosaic AI Model Serving, ce qui vous permet de déboguer efficacement les problèmes, de surveiller les performances et de créer un jeu de données golden pour une évaluation hors ligne. Lorsque le suivi MLflow est activé pour votre point de terminaison de service, les traces sont enregistrées dans unetable d’inférence sous la colonne response
.
Vous pouvez visualiser les traces journalisées dans les tables d’inférence en interrogeant la table et en affichant les résultats dans un bloc-notes. Utilisez display(<the request logs table>)
dans votre bloc-notes et sélectionnez les lignes individuelles des traces que vous souhaitez visualiser.
Pour activer le suivi MLflow pour votre point de terminaison de service, vous devez définir la variable d’environnement ENABLE_MLFLOW_TRACING
sur True
dans la configuration du point de terminaison. Pour savoir comment déployer un point de terminaison avec des variables d’environnement personnalisées, consultez Ajouter des variables d’environnement de texte brut. Si vous avez déployé votre agent à l’aide de l’API deploy()
, les traces sont automatiquement enregistrées dans une table d’inférence. Consultez Déployer un agent pour une application d’IA générative.
Remarque
L’écriture de traces dans une table d’inférence s’effectue de façon asynchrone. Elle n’ajoute donc pas la même surcharge que dans l’environnement de notebook pendant le développement. Cependant, cela peut encore entraîner une certaine surcharge au niveau de la vitesse de réponse du point de terminaison, en particulier lorsque la taille de la trace pour chaque demande d’inférence est importante. Databricks ne garantit aucun contrat de niveau de service (SLA) pour l’impact réel de la latence sur votre point de terminaison de modèle, car il dépend fortement de l’environnement et de l’implémentation du modèle. Databricks vous recommande de tester les performances de votre point de terminaison et d’obtenir des insights sur la surcharge de suivi avant le déploiement sur une application de production.
Le tableau suivant fournit une indication approximative de l’impact sur la latence d’inférence pour différentes tailles de trace.
Taille de trace par requête | Impact sur la latence (ms) |
---|---|
~10 Ko | ~ 1 ms |
~ 1 Mo | 50 ~ 100 ms |
10 Mo | 150 ms ~ |
Limites
- Le suivi MLflow est disponible dans les notebooks Databricks et les tâches de notebooks et la mise en service de modèle.
L’enregistrement automatique LangChain peut ne pas prendre en charge toutes les API de prédiction LangChain. Pour obtenir la liste complète des API prises en charge, consultez documentation MLflow.