Langfuse 文档 中文 英文原文 ↗
文档 / 多模态与附件

多模态与附件

Langfuse 支持多模态 traces,包括文本、图像、音频和其他附件

默认情况下,base64 编码的 data URI 由 Langfuse SDK 自动处理。它们从多模态 LLM 常用的负载中提取,上传到 Langfuse 的对象存储,并链接到 trace。

如果你执行以下操作,这也有效:

  1. 通过外部 URL 引用媒体文件。
  2. 通过 LangfuseMedia 类在 SDK 中自定义媒体文件的处理。
  3. 直接通过 Langfuse API 集成。

关于如何开始以及这在底层如何工作,在下方了解更多。

示例

可用性

Langfuse Cloud

Langfuse Cloud 上的多模态附件目前在 Langfuse Cloud 上免费。我们保留在近期推出新定价指标的权利,以核算与大型多模态 traces 相关的额外存储和计算成本。

自托管

多模态附件今天即可用。你需要通过 Langfuse 环境变量(LANGFUSE_S3_MEDIA_UPLOAD_*)配置你自己的对象存储桶。关于这些环境变量的细节参见自托管文档。所有主要云提供商都支持 S3 兼容的 API,并可以通过 minio 自托管。请注意,配置的存储桶必须具有可公开解析的主机名,以支持通过我们的 SDK 直接上传以及直接从浏览器获取媒体资产。

支持的媒体格式

Langfuse 支持广泛的媒体类型,包括:

支持的 MIME 类型完整列表
类别 MIME 类型 文件扩展名
图像 image/png .png
图像 image/jpegimage/jpg .jpg.jpeg
图像 image/webp .webp
图像 image/gif .gif
图像 image/svg+xml .svg
图像 image/tiff .tiff
图像 image/bmp .bmp
图像 image/avif .avif
图像 image/heic .heic
音频 audio/mpegaudio/mp3 .mp3
音频 audio/wav .wav
音频 audio/ogg .ogg
音频 audio/oga .oga
音频 audio/aac .aac
音频 audio/mp4 .m4a
音频 audio/flac .flac
音频 audio/opus .opus
音频 audio/webm .weba
视频 video/mp4 .mp4
视频 video/webm .webm
视频 video/ogg .ogv
视频 video/mpeg .mpeg
视频 video/quicktime .mov
视频 video/x-msvideo .avi
视频 video/x-matroska .mkv
文本与代码 text/plain .txt
文本与代码 text/html .html
文本与代码 text/css .css
文本与代码 text/csv .csv
文本与代码 text/markdown .md
文本与代码 text/x-python .py
文本与代码 application/javascript .js
文本与代码 text/x-typescript .ts
文本与代码 application/x-yaml .yaml
文档 application/pdf .pdf
文档 application/msword .doc
文档 application/vnd.openxmlformats-officedocument.wordprocessingml.document .docx
文档 application/vnd.ms-excel .xls
文档 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet .xlsx
文档 application/vnd.openxmlformats-officedocument.presentationml.presentation .pptx
文档 application/rtf .rtf
数据与归档 application/json .json
数据与归档 application/x-ndjson .jsonl
数据与归档 application/xml .xml
数据与归档 application/vnd.apache.parquet .parquet
数据与归档 application/zip .zip
数据与归档 application/gzip .gz
数据与归档 application/x-tar .tar
数据与归档 application/x-7z-compressed .7z
数据与归档 application/octet-stream .bin

如果你需要支持额外的文件类型,请在我们的 GitHub Discussion 中告知我们,我们正在那里积极收集关于多模态支持的反馈。

开始使用

Base64 data URI 编码的媒体

如果你的 LLM 应用中使用 base64 编码的图像、音频或其他文件,请升级到最新版本的 Langfuse SDK。Langfuse SDK 通过提取 base64 编码的媒体、将其作为 Langfuse Media 文件单独上传,并在 trace 中包含引用,来自动检测和处理它们。

如果大型 base64 编码媒体未经客户端处理就到达 Langfuse,Langfuse 会在服务端处理它以保持其完整并可在 UI 中检查。这是一种降级方案。我们强烈建议在客户端或 Langfuse SDK 中处理媒体。

这适用于标准 Data URI(MDN)格式的媒体(如 OpenAI 和其他 LLM 使用的那些)。

notebook 包含几个使用 OpenAI SDK 和 LangChain 的示例。

外部媒体(URL)

如果媒体文件遵循常见格式,Langfuse 支持通过 URL 内联渲染媒体文件。在这种情况下,媒体文件不会上传到 Langfuse 的对象存储,而是直接在 UI 中从源渲染。

支持的格式:

Markdown 图像

md
![Alt text](https://example.com/image.jpg)

OpenAI content parts

json
{
  "content": [
    {
      "role": "system",
      "content": "You are an AI trained to describe and interpret images. Describe the main objects and actions in the image."
    },
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "What's happening in this image?"
        },
        {
          "type": "image_url",
          "image_url": {
            "url": "https://example.com/image.jpg"
          }
        }
      ]
    }
  ]
}

自定义附件

如果你想拥有更多控制,或你的媒体不是 base64 编码的,你可以使用新的 LangfuseMedia 类通过 SDK 将任意媒体附件上传到 Langfuse。在将媒体包含到 trace 输入、输出、元数据或数据集条目之前,用 LangfuseMedia 包装媒体。示例参见多模态文档。

python
from langfuse import get_client, observe, propagate_attributes
from langfuse.media import LangfuseMedia

# Create a LangfuseMedia object from a file

with open("static/bitcoin.pdf", "rb") as pdf_file:
pdf_bytes = pdf_file.read()

# Wrap media in LangfuseMedia class

pdf_media = LangfuseMedia(content_bytes=pdf_bytes, content_type="application/pdf")

# Using with the decorator

@observe()
def process_document():
    langfuse = get_client()

    # Propagate metadata (including media) to all child observations
    with propagate_attributes(
        metadata={"document": pdf_media}
    ):
        pass

    # Or update the current span
    langfuse.update_current_span(
        input={"document": pdf_media}
    )

# Using with context managers

langfuse = get_client()

with langfuse.start_as_current_observation(as_type="span", name="analyze-document") as span: # Include media in the span input, output, or metadata
    span.update(
        input={"document": pdf_media},
        metadata={"file_size": len(pdf_bytes)}
    )

    # Process document...

    # Add results with media to the output
    span.update(output={
        "summary": "This document explains Bitcoin...",
        "original": pdf_media
    })

typescript
import fs from "fs";
import { LangfuseMedia } from "@langfuse/core";

// Wrap media in LangfuseMedia class
const wrappedMedia = new LangfuseMedia({
  source: "bytes",
  contentBytes: fs.readFileSync(new URL("./bitcoin.pdf", import.meta.url)),
  contentType: "application/pdf",
});

// Optionally, access media via wrappedMedia.obj
console.log(wrappedMedia.obj);

// Include media in any trace or observation
const span3 = startObservation("media-pdf-generation");

const generation3 = span3.startObservation('llm-call', {
  model: 'gpt-4',
  input: wrappedMedia,
}, {asType: "generation"});

generation3.end();

span3.end();

API

如果你直接使用 API 将 traces 记录到 Langfuse,你需要遵循以下步骤:

它如何工作?

当使用媒体文件(非通过外部 URL 引用)时,Langfuse 按以下方式处理它们:

1. 媒体上传过程

检测与提取

安全与优化

实现细节

2. 媒体引用系统

Langfuse traces 中的 base64 data URI 和包装的 LangfuseMedia 对象被替换为对 mediaId 的引用,采用以下标准化 token 格式,这有助于在需要时重建原始负载:

@@@langfuseMedia:type={MIME_TYPE}|id={LANGFUSE_MEDIA_ID}|source={SOURCE_TYPE}@@@

基于此 token,Langfuse UI 可以自动检测 mediaId 并内联渲染媒体文件。LangfuseMedia 类提供从引用字符串提取 mediaId 的实用函数。

对于多模态数据集,使用通过 SDK 做实验获取带已解析 LangfuseMediaReference 对象的数据集条目,并将媒体传递给你的模型提供商。

3. 解析媒体引用

当处理包含媒体引用的 traces、observations 或数据集条目时,你可以使用 Langfuse 客户端提供的 resolve_media_references 实用方法将它们转换回 base64 data URI 格式。这在微调、数据集运行或重放 generation 期间重新插入原始内容时特别有用。该实用方法遍历解析后的对象,并返回一个深拷贝,其中所有媒体引用字符串被替换为相应的 base64 data URI 表示。

python
from langfuse import get_client

# Initialize Langfuse client
langfuse = get_client()

# Example object with media references
obj = {
    "image": "@@@langfuseMedia:type=image/jpeg|id=some-uuid|source=bytes@@@",
    "nested": {
        "pdf": "@@@langfuseMedia:type=application/pdf|id=some-other-uuid|source=bytes@@@"
    }
}

# Resolve media references to base64 data URIs
resolved_obj = langfuse.resolve_media_references(
    obj=obj,
    resolve_with="base64_data_uri"
)

# Result:
# {
#     "image": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
#     "nested": {
#         "pdf": "data:application/pdf;base64,JVBERi0xLjcK..."
#     }
# }
python
from langfuse import Langfuse

# Initialize Langfuse client
langfuse = Langfuse()

# Example object with media references
obj = {
    "image": "@@@langfuseMedia:type=image/jpeg|id=some-uuid|source=bytes@@@",
    "nested": {
        "pdf": "@@@langfuseMedia:type=application/pdf|id=some-other-uuid|source=bytes@@@"
    }
}

# Resolve media references to base64 data URIs
resolved_trace = langfuse.resolve_media_references(
    obj=obj,
    resolve_with="base64_data_uri"
)

# Result:
# {
#     "image": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
#     "nested": {
#         "pdf": "data:application/pdf;base64,JVBERi0xLjcK..."
#     }
# }
typescript
import { LangfuseClient } from "@langfuse/client";

const langfuse = new LangfuseClient()

// Example object with media references
const obj = {
  image: "@@@langfuseMedia:type=image/jpeg|id=some-uuid|source=bytes@@@",
  nested: {
    pdf: "@@@langfuseMedia:type=application/pdf|id=some-other-uuid|source=bytes@@@",
  },
};

// Resolve media references to base64 data URIs
const resolvedTrace = await langfuse.resolveMediaReferences({
  obj: obj,
  resolveWith: "base64DataUri",
});

// Result:
// {
//     image: "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
//     nested: {
//         pdf: "data:application/pdf;base64,JVBERi0xLjcK..."
//     }
// }
非官方中文翻译 · 图片/视频/代码均链接官方资源 · 版权归 Langfuse GmbH 所有 查看英文原文 ↗