范围概念

Span 对象是跟踪数据模型中的基本构建基块。 它充当一个容器,用于存储关于追踪各个步骤的信息,例如 LLM 调用、工具执行、检索操作等。

Span在追踪中层次化组织,以表示应用程序的执行流。 每个区段捕捉:

  • 输入和输出数据
  • 计时信息(开始和结束时间)
  • 状态(成功或错误)
  • 有关操作的元数据和属性
  • 与其他跨度的关系(父子连接)

Span 体系结构

Span 对象架构

MLflow 的 Span 设计与 OpenTelemetry 规范保持兼容性。 架构包括 11 个核心属性:

资产 类型 Description
span_id str 追踪中此范围的唯一标识符
trace_id str 链接跨度到其父追踪
parent_id Optional[str] 建立分层关系;None 根跨度
name str 用户定义的或自动生成的跨度名称
start_time_ns int 跨度开始时的 Unix 时间戳(纳秒)
end_time_ns int 跨度结束时的 Unix 时间戳(纳秒)
status SpanStatus 跨度状态: OKUNSETERROR 具有可选说明
inputs Optional[Any] 输入此操作的数据
outputs Optional[Any] 输出从该操作生成的数据
attributes Dict[str, Any] 提供行为见解的元数据键值对
events List[SpanEvent] 系统级异常和堆栈跟踪信息

有关完整详细信息,请参阅 MLflow API 参考

Span 属性

属性是键值对,用于深入了解函数和方法调用的行为修改。 它们捕获有关操作配置和执行上下文的元数据。

可以添加特定于平台的属性,例如 Unity 目录信息 详细信息和 基础结构元数据 ,以提高可观测性。

LLM 调用的示例属性:

span.set_attributes({
    "ai.model.name": "claude-3-5-sonnet-20250122",
    "ai.model.version": "2025-01-22",
    "ai.model.provider": "anthropic",
    "ai.model.temperature": 0.7,
    "ai.model.max_tokens": 1000,
})

范围类型

MLflow 为分类提供十种预定义跨度类型。 您还可以使用自定义字符串值用于专门的操作。

类型 Description
CHAT_MODEL 查询聊天模型(专用 LLM 交互)
CHAIN 操作链
AGENT 自主代理操作
TOOL 工具的执行(通常由代理程序完成),例如搜索查询
EMBEDDING 文本嵌入操作
RETRIEVER 上下文检索操作,例如矢量数据库查询
PARSER 解析操作将文本转换为结构化格式
RERANKER 按相关性对上下文重新排序
MEMORY 将内存操作的上下文持久化到长期存储中
UNKNOWN 未指定其他类型时的默认类型

设置跨度类型

span_type 参数与修饰器或上下文管理器配合使用:

import mlflow
from mlflow.entities import SpanType

# Using a built-in span type
@mlflow.trace(span_type=SpanType.RETRIEVER)
def retrieve_documents(query: str):
    ...

# Using a custom span type
@mlflow.trace(span_type="ROUTER")
def route_request(request):
    ...

# With context manager
with mlflow.start_span(name="process", span_type=SpanType.TOOL) as span:
    span.set_inputs({"data": data})
    result = process_data(data)
    span.set_outputs({"result": result})

按类型搜索范围

使用 SDK 以编程方式进行查询:

import mlflow
from mlflow.entities import SpanType

trace = mlflow.get_trace("<trace_id>")
retriever_spans = trace.search_spans(span_type=SpanType.RETRIEVER)

还可以在查看跟踪时按 MLflow UI 中的范围类型进行筛选。

专用范围架构

某些跨度类型具有特定的输出架构,可实现增强的 UI 功能和评估功能。

RETRIEVER 范围

RETRIEVER 范围类型处理涉及从数据存储中检索数据的操作,例如查询向量存储中的文档。 输出应是文档列表,其中每个文档都是一个字典,其中包含:

  • page_contentstr):检索到的文档区块的文本内容
  • metadataOptional[Dict[str, Any]]):其他元数据,包括:
    • doc_uristr):文档源 URI
    • chunk_idstr):标识文档是否为较大分块文档的一部分
  • idOptional[str]):文档区块的唯一标识符

示例实现

import mlflow
from mlflow.entities import SpanType, Document

def search_store(query: str) -> list[tuple[str, str]]:
    # Simulate retrieving documents from a vector database
    return [
        ("MLflow Tracing helps debug GenAI applications...", "docs/mlflow/tracing_intro.md"),
        ("Key components of a trace include spans...", "docs/mlflow/tracing_datamodel.md"),
        ("MLflow provides automatic instrumentation...", "docs/mlflow/auto_trace.md"),
    ]

@mlflow.trace(span_type=SpanType.RETRIEVER)
def retrieve_relevant_documents(query: str):
    docs = search_store(query)
    span = mlflow.get_current_active_span()

    # Set outputs in the expected format
    outputs = [
        Document(page_content=doc, metadata={"doc_uri": uri})
        for doc, uri in docs
    ]
    span.set_outputs(outputs)

    return docs

# Usage
user_query = "MLflow Tracing benefits"
retrieved_docs = retrieve_relevant_documents(user_query)

CHAT_MODEL覆盖范围

类型为 CHAT_MODELLLM 的范围表示与聊天完成 API 的交互(例如 OpenAI 的 聊天完成 或 Anthropic 的 消息 API)。

尽管输入和输出没有严格的格式要求,但 MLflow 提供实用工具函数来标准化聊天消息和工具定义,以便实现丰富的 UI 可视化和评估:

import mlflow
from mlflow.entities import SpanType
from mlflow.tracing.constant import SpanAttributeKey
from mlflow.tracing import set_span_chat_messages, set_span_chat_tools

# Example messages and tools
messages = [
    {
        "role": "system",
        "content": "please use the provided tool to answer the user's questions",
    },
    {"role": "user", "content": "what is 1 + 1?"},
]

tools = [
    {
        "type": "function",
        "function": {
            "name": "add",
            "description": "Add two numbers",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {"type": "number"},
                    "b": {"type": "number"},
                },
                "required": ["a", "b"],
            },
        },
    }
]

@mlflow.trace(span_type=SpanType.CHAT_MODEL)
def call_chat_model(messages, tools):
    # Simulate a response with tool calls
    response = {
        "role": "assistant",
        "tool_calls": [
            {
                "id": "123",
                "function": {"arguments": '{"a": 1,"b": 2}', "name": "add"},
                "type": "function",
            }
        ],
    }

    combined_messages = messages + [response]

    # Use MLflow utilities to standardize the format
    span = mlflow.get_current_active_span()
    set_span_chat_messages(span, combined_messages)
    set_span_chat_tools(span, tools)

    return response

# Usage
call_chat_model(messages, tools)

# Retrieve the standardized data
trace = mlflow.get_last_active_trace()
span = trace.data.spans[0]

print("Messages:", span.get_attribute(SpanAttributeKey.CHAT_MESSAGES))
print("Tools:", span.get_attribute(SpanAttributeKey.CHAT_TOOLS))

后续步骤