跳到主要内容

追踪中的多模态内容与附件

MLflow Tracing(追踪)可以捕获并渲染来自多模态 AI 模型中的图像、音频和二进制附件。当你向 GPT-4o 或 Claude 等模型发送图像或音频时,MLflow 会自动将二进制内容提取为轻量级的附件,并将其内联显示在 MLflow UI 中。

支持的内容类型

MLflow 的追踪模式使用 OpenAI 聊天消息格式来表示多模态内容。每个内容部分都有一个 type 字段,用于决定其存储和渲染方式。

内容类型type编码UI 渲染
文本textUTF-8 字符串Markdown
图像image_urlHTTP(S) URL 或 base64 数据 URI内联图像
音频input_audioBase64 编码的 WAV 或 MP3内联音频播放器

图像

图像被表示为 mlflow.types.chat.ImageContentPart() 对象,类型为 image_urlimage_url.url 字段支持:

  • HTTP(S) URL —— 指向托管图像的直接链接(例如 https://example.com/photo.png
  • Base64 数据 URI —— 内联图像数据(例如 data:image/png;base64,iVBOR...

一个可选的 detail 字段用于控制模型处理图像的分辨率(autolowhigh)。

这两种格式都会在追踪查看器的聊天 (Chat) 选项卡中内联渲染。

音频

音频被表示为 mlflow.types.chat.AudioContentPart() 对象,类型为 input_audioinput_audio.data 字段包含 base64 编码的音频数据,input_audio.format 指定编解码器(wavmp3)。

音频内容会在追踪查看器的聊天 (Chat) 选项卡中使用内联音频播放器进行渲染。

自动 Base64 提取

默认情况下,MLflow 会自动检测 span 输入和输出中的 base64 编码二进制内容,并将其提取为追踪附件。这使得追踪 JSON 保持轻量,同时将完整的二进制内容作为可下载的人工制品 (artifacts) 保存下来。

以下模式会被自动检测并提取:

模式来源示例提取为
Base64 数据 URIdata:image/png;base64,...image/png 附件
OpenAI input_audio{"type": "input_audio", "input_audio": {"data": "...", "format": "wav"}}audio/wav 附件
DALL-E b64_json 输出{"b64_json": "...", "revised_prompt": "..."}image/png 附件
OpenAI 音频响应{"audio": {"data": "...", "transcript": "..."}}audio/wav 附件
Responses API 图像生成{"type": "image_generation_call", "result": "...", "output_format": "png"}image/<format> 附件
Anthropic 图像源{"type": "image", "source": {"type": "base64", "data": "..."}}带有原始 media_type 的附件
Bedrock 图像{"image": {"format": "png", "source": {"bytes": "..."}}}image/<format> 附件
Gemini 内联数据{"inline_data": {"mime_type": "image/png", "data": "..."}}带有原始 mime_type 的附件
Gemini 内联数据(字节表示){"inline_data": {"mime_type": "image/png", "data": "b'\\x89PNG...'"}}带有原始 mime_type 的附件

提取后,span 中的 base64 数据将被替换为轻量级的 mlflow-attachment:// 引用 URI。MLflow UI 会解析这些 URI 并内联渲染支持的内容类型(图像、音频、PDF)。

提示

自动提取默认启用。如需禁用该功能并将原始 base64 数据保留在追踪 JSON 中,请设置环境变量。

bash
export MLFLOW_TRACE_EXTRACT_ATTACHMENTS=false

自动追踪

使用自动检测 (auto-instrumentation) 时,多模态内容会被自动捕获。MLflow 会将特定于提供商的格式标准化为上述标准模式,并将 base64 内容提取为附件。

框架图像音频文件备注
OpenAI聊天补全、Responses API(包含 input_file)和 Images.generate
Anthropic原生图像块已标准化为 image_url
Bedrock图像内容已提取至附件
Geminiinline_data 已提取(base64 和 Python 字节表示)
LangChain音频格式从 LangChain 标准化为 OpenAI 模式

OpenAI — 图像 (URL)

在聊天补全中发送图像 URL,MLflow 会自动捕获它。

python
import mlflow
from openai import OpenAI

mlflow.openai.autolog()

client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{
"type": "image_url",
"image_url": {
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"
},
},
],
}
],
)

OpenAI — 图像 (Base64)

将本地图像文件编码为 base64 数据 URI。MLflow 会自动将 base64 数据提取为附件。

python
import base64
import mlflow
from openai import OpenAI

mlflow.openai.autolog()


def encode_image(image_path):
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")


base64_image = encode_image("photo.png")
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image in detail."},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{base64_image}",
"detail": "high",
},
},
],
}
],
)

OpenAI — 音频

使用 gpt-4o-audio-preview 模型发送音频输入。

python
import base64
import mlflow
from openai import OpenAI

mlflow.openai.autolog()


def encode_audio(audio_path):
with open(audio_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")


client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-audio-preview",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "What does this audio say?"},
{
"type": "input_audio",
"input_audio": {
"data": encode_audio("recording.wav"),
"format": "wav",
},
},
],
}
],
)

OpenAI — 图像生成

DALL-E 图像生成也会被自动追踪。b64_json 输出会被提取为图像附件。

python
import mlflow
from openai import OpenAI

mlflow.openai.autolog()

client = OpenAI()
response = client.images.generate(
model="dall-e-3",
prompt="a white siamese cat",
n=1,
response_format="b64_json",
)

Anthropic — 图像

Anthropic 使用不同的消息格式,但 MLflow 会自动将其标准化为标准的 image_url 模式。

python
import base64
import mlflow
from anthropic import Anthropic

mlflow.anthropic.autolog()


def encode_image(image_path):
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")


client = Anthropic()
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": encode_image("photo.png"),
},
},
{"type": "text", "text": "Describe this image."},
],
}
],
)

手动追踪

你可以使用 mlflow.start_span()set_inputs() / set_outputs() 手动将多模态内容附加到追踪中。请按照 OpenAI API 使用的相同格式,用内容部分列表构建消息。

python
import mlflow

with mlflow.start_span(name="multimodal-call") as span:
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{
"type": "image_url",
"image_url": {"url": "https://example.com/photo.png"},
},
],
}
]
span.set_inputs({"messages": messages})

# Call your model here
result = "A photo of a cat."

span.set_outputs({"content": result})

当调用 set_inputs()set_outputs() 时,image_url.url 字段和 input_audio.data 字段中的 base64 数据 URI 会被自动提取为附件。

在 UI 中查看

MLflow 追踪查看器会在 UI 中渲染多模态内容。

  • 图像 —— 内联显示,点击可放大预览全尺寸图像。
  • 音频 —— 使用内置音频播放器渲染,可直接在 UI 中播放。
  • PDF —— 在嵌入式查看器中显示。

图像 URL 在聊天 (Chat) 视图中渲染。追踪附件(图像、音频、PDF)在所有视图中内联渲染——聊天详细信息 (Details)时间轴 (Timeline)

Image content rendered inline in the trace viewer
Audio content rendered with an inline player in the trace viewer

当 base64 内容被提取为附件时,内容 (Content) 选项卡会显示轻量级的 mlflow-attachment:// 引用 URI,而不是庞大的 base64 负载。UI 会自动获取并渲染附件内容。

超大附件将显示为下载链接,而不是内联渲染,以防止浏览器性能问题。阈值如下:

内容类型最大内联大小
image/*10 MB
audio/*50 MB
application/pdf20 MB

追踪附件

MLflow 将二进制内容作为独立的人工制品文件与追踪数据存储在一起,在保持追踪 JSON 轻量化的同时支持富媒体。有两种创建附件的方法:

  1. 自动提取(默认)—— 检测 span 输入/输出中的 base64 编码内容,进行提取并替换为 mlflow-attachment:// 引用 URI。详见自动 Base64 提取
  2. 手动创建 Attachment —— 针对不符合识别出的自动记录格式的二进制内容(例如自定义追踪用例)。操作说明请参阅创建附件

工作原理

当二进制内容存储为附件时,MLflow 会:

  1. 将 span 数据中的内容替换为轻量级的引用 URI (mlflow-attachment://...)
  2. 在导出追踪时,将二进制内容作为独立的人工制品文件上传。

这意味着追踪 JSON 可以保持很小,而与附件大小无关,且 MLflow UI 可以内联渲染支持的内容类型。

支持的内容类型

附件支持任何二进制内容类型。MLflow UI 会内联渲染以下类型(超过大小阈值的文件将显示下载链接):

内容类型UI 渲染最大内联大小
image/*内联图像10 MB
audio/*内联音频播放器50 MB
application/pdf嵌入式 PDF 查看器20 MB
其他下载链接--

创建附件

使用 Attachment 类来封装带有显式内容类型的二进制内容,或使用 Attachment.from_file() 从文件路径加载(内容类型会自动推断)。

python
from mlflow.tracing.attachments import Attachment

# From raw bytes with explicit content type
image_attachment = Attachment(content_type="image/png", content_bytes=png_bytes)

# From a file path (content type is inferred from the file extension)
pdf_attachment = Attachment.from_file("report.pdf")

# From a file path with explicit content type override
audio_attachment = Attachment.from_file("recording.bin", content_type="audio/wav")

在 Span 中使用附件

Attachment 对象直接传递给 set_inputs()set_outputs()。MLflow 会自动处理提取和替换,包括在嵌套字典、列表和元组中。

python
import mlflow
from mlflow.tracing.attachments import Attachment


@mlflow.trace
def generate_image(prompt: str) -> dict:
# Call your image generation model
image_bytes = my_model.generate(prompt)

return {"image": Attachment(content_type="image/png", content_bytes=image_bytes)}


# The trace will show:
# - Input: {"prompt": "a sunset over mountains"}
# - Output: {"image": "mlflow-attachment://<uuid>?content_type=image/png&trace_id=..."}
# The actual image bytes are uploaded as a separate artifact.
result = generate_image("a sunset over mountains")

你也可以在上下文管理器 API 中使用附件。

python
import mlflow
from mlflow.tracing.attachments import Attachment

with mlflow.start_span(name="text-to-speech") as span:
span.set_inputs({"text": "Hello, world!"})

# Generate audio
audio_bytes = tts_model.synthesize("Hello, world!")

span.set_outputs({
"audio": Attachment(content_type="audio/wav", content_bytes=audio_bytes),
})

多个附件

你可以在单个 span 中包含多个附件。每个附件都会被独立提取和上传。

python
import mlflow
from mlflow.tracing.attachments import Attachment

with mlflow.start_span(name="multi-output") as span:
span.set_outputs({
"image": Attachment(content_type="image/png", content_bytes=image_bytes),
"audio": Attachment(content_type="audio/mp3", content_bytes=audio_bytes),
"report": Attachment.from_file("output.pdf"),
})

何时使用显式附件

在大多数情况下,无需手动创建 Attachment 对象。自动提取功能会自动处理聊天消息中的 base64 内容。请在以下情况下使用显式的 Attachment 包装:

  • 二进制内容未进行 base64 编码(例如来自 API 响应的原始字节)
  • 内容格式未被自动提取识别(请参阅支持的模式
  • 你希望附加文件,如 PDF、CSV 或其他文档。
提示

如果你正在使用 OpenAI、Anthropic 或 LangChain 的自动追踪功能,聊天消息中的图像和音频会被自动捕获并提取为附件,无需进行 Attachment 包装。

限制

  • 视频不受支持——视频内容不会被捕获或渲染。
  • 大附件在超过在 UI 中查看列出的阈值时,会显示为下载链接,而不是内联渲染。