跟踪常见问题
入门和基本用法
问:如何开始使用 MLflow 跟踪?
最简单的入门方法是对支持的库进行自动跟踪。
import mlflow
import openai
# Enable automatic tracing for OpenAI
mlflow.openai.autolog()
# Your existing code now generates traces automatically
client = openai.OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini", messages=[{"role": "user", "content": "Hello!"}]
)
对于自定义代码,请使用 @mlflow.trace 装饰器。
@mlflow.trace
def my_function(input_data):
# Your logic here
return "processed result"
问:MLflow 跟踪自动支持哪些库?
MLflow 为 20 多个流行库提供自动跟踪(autolog)。请参阅 自动跟踪集成 处的完整列表。
用户界面和 Jupyter 集成
问:我可以在 Jupyter Notebook 中直接查看跟踪记录吗?
可以!MLflow 2.20 及更高版本提供了 Jupyter 集成。当
- 单元格代码生成跟踪记录时
- 调用
mlflow.search_traces()时 - 显示跟踪记录对象时
import mlflow
# Set tracking URI to your MLflow server
mlflow.set_tracking_uri("https://:5000")
@mlflow.trace
def my_function():
return "Hello World"
# Trace UI will appear automatically in the notebook
my_function()
要控制显示
# Disable notebook display
mlflow.tracing.disable_notebook_display()
# Enable notebook display
mlflow.tracing.enable_notebook_display()
问:如何自定义 UI 中的请求和响应预览?
您可以使用 mlflow.update_current_trace() 自定义跟踪列表的“请求”和“响应”列中显示的内容。
@mlflow.trace
def predict(messages: list[dict]) -> str:
# Customize the request preview for long message histories
custom_preview = f'{messages[0]["content"][:10]} ... {messages[-1]["content"][:10]}'
mlflow.update_current_trace(request_preview=custom_preview)
# Your model logic here
result = process_messages(messages)
# Customize response preview
mlflow.update_current_trace(response_preview=f"Result: {result[:50]}...")
return result
生产和性能
问:我可以在生产应用程序中使用 MLflow 跟踪吗?
是的,MLflow 跟踪是稳定的,并设计用于生产环境。
在生产环境中使用 MLflow 跟踪时,我们建议使用 MLflow 跟踪 SDK (mlflow-tracing),该 SDK 以最少的依赖项和更小的安装占地面积来仪器化您的代码/模型/代理。该 SDK 设计为非常适合您希望获得高效轻量级跟踪解决方案的生产环境。有关更多详细信息,请参阅 生产监控 部分。
问:如何启用异步跟踪记录?
异步记录可以显著降低性能开销(对于典型工作负载,约 80%)。
import mlflow
# Enable async logging
mlflow.config.enable_async_logging()
# Traces will be logged asynchronously
with mlflow.start_span(name="foo") as span:
span.set_inputs({"a": 1})
span.set_outputs({"b": 2})
# Manually flush if needed
mlflow.flush_trace_async_logging()
配置选项
您可以使用以下环境变量配置异步记录的详细行为:
| 环境变量 | 描述 | 默认值 |
|---|---|---|
MLFLOW_ASYNC_TRACE_LOGGING_MAX_WORKERS | 最大工作线程数 | 10 |
MLFLOW_ASYNC_TRACE_LOGGING_MAX_QUEUE_SIZE | 最大队列大小 | 1000 |
MLFLOW_ASYNC_TRACE_LOGGING_RETRY_TIMEOUT | 重试超时(秒) | 500 |
问:如何在生产环境中优化跟踪记录的大小?
MLflow 的自动跟踪集成捕获了有助于调试和评估模型/代理的丰富信息。但是,这会以跟踪记录大小为代价。例如,您可能不想记录 RAG 应用程序检索到的所有文档文本。
MLflow 支持在导出到后端之前,插入应用于跟踪数据的自定义后处理钩子。这允许您通过删除不必要的数据来减小跟踪记录的大小,或应用安全措施,如屏蔽敏感数据。
要注册自定义钩子,请使用 mlflow.tracing.configure API。例如,以下代码会过滤掉检索器 span 输出中的文档内容,以减小跟踪记录的大小。
import mlflow
from mlflow.entities.span import Span, SpanType
# Define a custom hook that takes a span as input and mutates it in-place.
def filter_retrieval_output(span: Span):
"""Filter out the document contents from the retriever span output and only keep the document ids."""
if span.span_type == SpanType.RETRIEVAL:
documents = span.outputs.get("documents")
document_ids = [doc.id for doc in documents]
span.set_outputs({"document_ids": document_ids})
# Register the hook
mlflow.tracing.configure(span_processors=[filter_retrieval_output])
# Any traces created after the configuration will be filtered by the hook.
...
有关钩子 API 和示例的更多详细信息,请参阅 屏蔽敏感数据安全 指南。
问:我能否从单个应用程序将跟踪记录记录到不同的实验?
是的,您可以从单个应用程序将跟踪记录记录到不同的实验。默认情况下,MLflow 会记录到通过 mlflow.set_experiment API 或 MLFLOW_EXPERIMENT_ID 环境变量设置的当前活动实验。
然而,有时您可能希望从单个应用程序动态地将跟踪记录路由到不同的实验。例如,您的应用程序服务器可能公开两个端点,每个端点服务于不同的模型。切换活动实验不起作用,因为活动实验是全局定义的,并且不与每个线程或异步上下文隔离。
因此,MLflow 提供了两种不同的方法来切换目标实验以记录跟踪记录。
选项 1. 在开始手动跟踪时设置 trace_destination 参数
trace_destination 参数已添加到 MLflow 3.3 中的 @mlflow.trace 装饰器和 mlflow.start_span API,允许您为每个跟踪记录显式指定目标实验。
import mlflow
from mlflow.entities.trace_location import MlflowExperimentLocation
@mlflow.trace(trace_destination=MlflowExperimentLocation(experiment_id="1234"))
def math_agent(request: Request):
# Your model logic here
...
请注意,只有当 trace_destination 参数设置为跟踪记录的根 span 时才有效。如果将其设置为子 span,MLflow 将忽略它并打印警告。
选项 2. 使用 mlflow.tracing.set_destination 和 context_local=True
mlflow.tracing.set_destination() API 是一个专门用于设置跟踪记录目标的 API,它绕过了 mlflow.set_experiment 的开销。context_local 参数允许您为每个异步任务或线程设置目标,从而在并发应用程序中提供隔离。当您使用自动跟踪并且不使用手动跟踪 API 时,此选项非常有用。
import mlflow
from mlflow.entities.trace_location import MlflowExperimentLocation
@app.get("/math-agent")
def math_agent(request: Request):
# The API is super low-overhead, so you can call it inside the request handler.
mlflow.tracing.set_destination(MlflowExperimentLocation(experiment_id="1234"))
# Your model logic here
with mlflow.start_span(name="math-agent") as span:
...
@app.get("/chat-agent")
def chat_agent(request: Request):
mlflow.tracing.set_destination(MlflowExperimentLocation(experiment_id="5678"))
# Your model logic here
with mlflow.start_span(name="chat-agent") as span:
...
故障排除
问:我无法在 MLflow UI 中打开我的跟踪记录。我该怎么办?
跟踪记录无法在 MLflow UI 中查看可能有多种原因:
-
跟踪记录尚未完成:如果跟踪记录仍在收集,MLflow 无法在 UI 中显示 span。确保所有 span 都已正确结束,并带有“OK”或“ERROR”状态。
-
浏览器缓存已过期:当您将 MLflow 升级到新版本时,浏览器缓存可能包含过时的数据,导致 UI 无法正确显示跟踪记录。请清除浏览器缓存(Shift+F5)并刷新页面。
-
MLflow 服务器连接:确保您的 MLflow 跟踪服务器正在运行且可访问。
bashmlflow server --host 0.0.0.0 --port 5000 -
实验权限:验证您是否有权访问包含跟踪记录的实验。
问:模型执行卡住了,我的跟踪记录一直处于“进行中”状态。
有时模型或代理会卡在长时间运行的操作或无限循环中,导致跟踪记录处于“进行中”状态。
为防止这种情况,您可以使用 MLFLOW_TRACE_TIMEOUT_SECONDS 环境变量为跟踪记录设置超时。如果跟踪记录超过超时时间,MLflow 将自动以 ERROR 状态中止跟踪记录并将其导出到后端,以便您可以分析 span 以找出问题。默认情况下,不设置超时。
超时仅适用于 MLflow 跟踪。即使跟踪记录被中止,主程序、模型或代理也会继续运行。
例如,以下代码将超时设置为 5 秒,并模拟 MLflow 如何处理长时间运行的操作。
import mlflow
import os
import time
# Set the timeout to 5 seconds for demonstration purposes
os.environ["MLFLOW_TRACE_TIMEOUT_SECONDS"] = "5"
# Simulate a long-running operation
@mlflow.trace
def long_running():
for _ in range(10):
child()
@mlflow.trace
def child():
time.sleep(1)
long_running()
MLflow 在后台线程中监视跟踪记录的执行时间和过期情况。默认情况下,此检查每秒执行一次,资源消耗可忽略不计。如果要调整间隔,可以设置 MLFLOW_TRACE_TIMEOUT_CHECK_INTERVAL_SECONDS 环境变量。
问:我的跟踪记录没有出现在 MLflow UI 中。可能是什么原因?
有几个问题可能导致跟踪记录未出现:
未设置跟踪 URI:确保已配置您的跟踪 URI。
import mlflow
mlflow.set_tracking_uri("https://:5000") # or your server URL
未设置实验:确保您正在记录到正确的实验。
mlflow.set_experiment("my-tracing-experiment")
未调用 Autolog:对于受支持的库,请确保在开始使用前已调用 autolog。
mlflow.openai.autolog() # Call before using OpenAI
多线程和并发
问:在进行多线程处理时,我的跟踪记录被拆分成了多个跟踪记录。如何将它们合并成一个跟踪记录?
由于 MLflow 跟踪依赖于 Python ContextVar,默认情况下每个线程都有自己的跟踪记录上下文,但可以通过一些额外的步骤为多线程应用程序生成单个跟踪记录。
这是一个简短的示例:
import contextvars
import mlflow
from concurrent.futures import ThreadPoolExecutor
@mlflow.trace
def worker_function(data):
# Worker logic here
return process_data(data)
@mlflow.trace
def main_function(data_list):
with ThreadPoolExecutor() as executor:
futures = []
for data in data_list:
# Copy context to worker thread
ctx = contextvars.copy_context()
futures.append(executor.submit(ctx.run, worker_function, data))
results = [future.result() for future in futures]
return results
问:MLflow 跟踪是否支持 async/await 代码?
是的,MLflow 跟踪支持异步函数。@mlflow.trace 装饰器可以与异步函数无缝协作。
import asyncio
import mlflow
@mlflow.trace
async def async_function(query: str):
# Async operations are traced normally
result = await some_async_operation(query)
return result
# Usage
asyncio.run(async_function("test query"))
配置和控制
问:如何暂时禁用跟踪?
要禁用跟踪,mlflow.tracing.disable() API 将停止从 MLflow 内部收集跟踪数据,并且不会将任何数据记录到 MLflow 跟踪服务中关于跟踪记录的信息。
要启用跟踪(如果已暂时禁用),mlflow.tracing.enable() API 将重新启用被仪器化的模型的跟踪功能。
import mlflow
# Disable tracing
mlflow.tracing.disable()
# Your traced functions won't generate traces
@mlflow.trace
def my_function():
return "No trace generated"
my_function()
# Re-enable tracing
mlflow.tracing.enable()
# Now traces will be generated again
my_function() # This will generate a trace
问:我能否在不修改代码的情况下启用/禁用应用程序的跟踪?
是的,您可以使用环境变量和全局配置。
环境变量:设置 MLFLOW_TRACING_ENABLED=false 以禁用所有跟踪。
export MLFLOW_TRACING_ENABLED=false
python your_app.py # No traces will be generated
条件跟踪:使用程序化控制。
import mlflow
import os
# Only trace in development
if os.getenv("ENVIRONMENT") == "development":
mlflow.openai.autolog()
MLflow 运行集成
问:如何将跟踪记录与 MLflow 运行关联起来?
如果在运行上下文中生成了跟踪记录,它将自动与该运行关联。
import mlflow
# Create and activate an experiment
mlflow.set_experiment("Run Associated Tracing")
# Start a new MLflow Run
with mlflow.start_run() as run:
# Traces created here are associated with the run
with mlflow.start_span(name="Run Span") as parent_span:
parent_span.set_inputs({"input": "a"})
parent_span.set_outputs({"response": "b"})
然后,您可以检索特定运行的跟踪记录。
# Retrieve traces associated with a specific Run
traces = mlflow.search_traces(run_id=run.info.run_id)
print(traces)
数据管理
问:如何删除跟踪记录?
您可以使用 mlflow.client.MlflowClient.delete_traces() 方法删除跟踪记录。
from mlflow.client import MlflowClient
import time
client = MlflowClient()
# Get the current timestamp in milliseconds
current_time = int(time.time() * 1000)
# Delete traces older than a specific timestamp
deleted_count = client.delete_traces(
experiment_id="1", max_timestamp_millis=current_time, max_traces=10
)
删除跟踪记录是一个不可逆的过程。请确保 delete_traces API 中提供的设置符合预期的删除范围。
有关跟踪记录删除的更多信息,请阅读 跟踪记录删除。
问:我的跟踪记录存储在哪里?
跟踪记录存储在您的 MLflow 跟踪后端。
本地文件系统:在本地使用 mlflow server 时,跟踪记录存储在 mlruns 目录中。
远程跟踪服务器:在使用远程 MLflow 服务器时,跟踪记录存储在配置的后端(数据库 + 构件存储)中。
数据库:跟踪记录元数据存储在 MLflow 跟踪数据库中。
构件存储:大型跟踪数据可能存储在构件存储(文件系统、S3 等)中。
集成和兼容性
问:MLflow 跟踪是否兼容其他可观测性工具?
是的,MLflow 跟踪基于 OpenTelemetry 标准,可以与其他可观测性工具集成。
OpenTelemetry 导出:将跟踪记录导出到 OTLP 兼容系统。
自定义导出器:为您的可观测性堆栈构建自定义集成。
标准格式:使用行业标准的跟踪格式以实现互操作性。
有关生产监控,请参阅 生产跟踪 以了解集成模式。
问:我能否创建自定义手动跟踪和 span?
是的,MLflow 提供全面的手动跟踪功能。有关使用装饰器、上下文管理器和低级 API 手动创建跟踪记录和 span 的详细信息,请参阅 手动跟踪 指南。
获取帮助
问:我在哪里可以找到更多帮助或报告问题?
文档:从 MLflow 跟踪文档 开始。
GitHub 问题:在 MLflow GitHub 上报告错误或请求功能。
社区:加入 MLflow Slack 社区 的讨论。
Stack Overflow:搜索或提问时标记 mlflow。
Databricks 支持:对于托管的 MLflow 功能,请联系 Databricks 支持。
对于此处未涵盖的额外问题或疑问,请查看 MLflow 文档 或联系社区。