本文档详细概述了 MLflow 跟踪数据模型。 了解此模型是利用 MLflow 跟踪来观察性和分析生成 AI 应用程序的关键。
MLflow 跟踪旨在 与 OpenTelemetry 规范兼容,这是一种广为采用的可观测性行业标准。 这可确保互作性并允许导出 MLflow 跟踪,并将其与其他 OpenTelemetry 兼容的系统一起使用。 MLflow 通过定义生成 AI 用例的特定结构和属性来增强基本的 OpenTelemetry Span 模型,从而提供更丰富的上下文和更深入的质量和性能见解。
跟踪的结构
概括而言,MLflow 追踪 由两个主要对象组成:
小窍门
有关这些数据类对象的帮助程序方法的详细信息,请查看 API 文档,了解有关如何从这些对象转换或提取数据的详细信息。
1. 跟踪信息
MLflow TraceInfo
的跟踪功能旨在提供有关整个跟踪的关键数据的轻型快照。
TraceInfo
是包含有关跟踪的元数据的 dataclass 对象。
此元数据包括有关跟踪的来源、状态以及各种其他数据信息,这些信息在与mlflow.client.MlflowClient.search_traces
一起使用时,有助于在 MLflow UI 中进行跟踪的检索、筛选和导航。 若要详细了解元数据如何 TraceInfo
用于搜索,可 在此处查看示例。
参数 | 数据类型 | DESCRIPTION |
---|---|---|
trace_id |
str |
跟踪的主要标识符。 |
trace_location |
TraceLocation |
存储跟踪的位置,表示为 :p y:class:~mlflow.entities.TraceLocation 对象。 MLflow 目前支持将 MLflow 试验或 Databricks 推理表设置为跟踪位置。 |
request_time |
int |
跟踪的开始时间(以毫秒为单位)。 |
state |
TraceState |
跟踪的状态,表示为 :py:class:~mlflow.entities.TraceState 枚举。 可以是 [OK ,ERROR ,IN_PROGRESS ,STATE_UNSPECIFIED ] 之一。 |
request_preview |
Optional[str] |
对模型/代理的请求,其等同于根范围的输入,经过 JSON 编码,且可以被截断。 |
response_preview |
Optional[str] |
来自模型/代理的响应,相当于根级范围的输出,以 JSON 编码形式呈现,并且可能被截断。 |
client_request_id |
Optional[str] |
客户端提供与跟踪关联的请求 ID。 这可用于标识来自生成跟踪的外部系统的跟踪/请求,例如 Web 应用程序中的会话 ID。 |
execution_duration |
Optional[int] |
跟踪的持续时间(以毫秒为单位)。 |
trace_metadata |
dict[str, str] |
与跟踪关联的键值对。 它们专为不可变值而设计,例如与跟踪关联的运行 ID。 |
tags |
dict[str, str] |
与跟踪关联的标记。 它们专为可变值而设计,可在通过 MLflow UI 或 API 创建跟踪后进行更新。 |
assessments |
list[Assessment] |
与跟踪关联的评估列表。 |
对象中包含的 TraceInfo
数据用于填充 MLflow 跟踪 UI 中的跟踪视图页,如下所示。
下面列出了 MLflow TraceInfo
对象的主要组件。
元数据
评估
评估对于确定在跟踪中捕获的 GenAI 应用程序行为的质量和正确性至关重要。 它们允许您将结构化标签、分数或真实信息附加到跟踪或跟踪内的特定范围。
MLflow 定义了两种主要类型的评估,这两种评估都继承自基本 Assessment
概念:
- 反馈:表示对操作输出的定性和/或定量判断。 这可以来自人工审阅者、LLM 即评委或自定义评分函数。
- 预期:表示给定作的基础真相或预期结果,通常用于与实际输出的直接比较。
评估通常使用类似 mlflow.log_feedback()
、mlflow.log_expectation()
或更通用的 mlflow.log_assessment()
的函数记录在跟踪日志中。
评估源
每个评估都与源相关联,以跟踪其源。
-
source_type
:一个mlflow.entities.AssessmentSourceType
枚举。 关键价值包括:-
HUMAN
:人类提供的反馈或期望。 -
LLM_JUDGE
:由充当法官的 LLM 生成的评估。 -
CODE
:由编程规则、启发式或自定义记分器生成的评估。
-
-
source_id
:特定源的字符串标识符(例如,用户 ID、LLM 法官的模型名称、脚本名称)。
from mlflow.entities import AssessmentSource, AssessmentSourceType
# Example: Human source
human_source = AssessmentSource(
source_type=AssessmentSourceType.HUMAN,
source_id="reviewer_alice@example.com"
)
# Example: LLM Judge source
llm_judge_source = AssessmentSource(
source_type=AssessmentSourceType.LLM_JUDGE,
source_id="gpt-4o-mini-evaluator"
)
# Example: Code-based scorer source
code_source = AssessmentSource(
source_type=AssessmentSourceType.CODE,
source_id="custom_metrics/flesch_kincaid_scorer.py"
)
反馈
反馈收集对跟踪或跨度输出的质量或特征的评估。
键字段:
参数 | 数据类型 | DESCRIPTION |
---|---|---|
name |
str |
评估的名称。 如果未提供名称,将使用默认名称“feedback”。 |
value |
Optional[FeedbackValueType] |
反馈值。 可以是 float、int、str、bool、这些类型的列表,或是具有字符串键和这些类型值的字典。 |
error |
Optional[Union[Exception, AssessmentError]] |
与反馈关联的可选错误。 这用于指示反馈无效或无法处理。 接受一个异常对象、一个 :py:class:~mlflow.entities.Exception 对象或一个 AssessmentError . |
rationale |
Optional[str] |
反馈的理由/正当性。 |
source |
Optional[AssessmentSource] |
评估的来源。 如果未提供,则默认源为 CODE。 |
trace_id |
Optional[str] |
与评估关联的跟踪的 ID。 如果未设置,则评估尚未与任何追踪相关联。 |
metadata |
Optional[dict[str, str]] |
与评估关联的元数据。 |
span_id |
Optional[str] |
与评估关联的范围 ID(如果评估应与跟踪中的特定范围相关联)。 |
create_time_ms |
Optional[int] |
评估的创建时间(以毫秒为单位)。 如果未设置,则使用当前时间。 |
last_update_time_ms |
Optional[int] |
评估的最后一次更新时间(以毫秒为单位)。 如果未设置,则使用当前时间。 |
示例:
import mlflow
from mlflow.entities import Feedback, AssessmentSource, AssessmentSourceType
# Log simple binary feedback
mlflow.log_feedback(
trace_id="trace_123",
name="is_correct",
value=True,
source=AssessmentSource(source_type=AssessmentSourceType.HUMAN, source_id="user_bob"),
rationale="The answer provided was factually accurate."
)
# Log a numeric score from an LLM judge
llm_judge_feedback = Feedback(
name="relevance_score",
value=0.85,
source=AssessmentSource(source_type=AssessmentSourceType.LLM_JUDGE, source_id="claude-3-sonnet"),
rationale="The response directly addressed the user's core question.",
metadata={"judge_prompt_version": "v1.2"}
)
# Assuming trace_id is known, you can also use log_assessment
# mlflow.log_assessment(trace_id="trace_456", assessment=llm_judge_feedback)
预期
期望定义操作的基准真实值或目标输出。
键字段:
参数 | 数据类型 | DESCRIPTION |
---|---|---|
name |
str |
评估的名称。 |
value |
Any |
操作的预期值。 这可以是任何 JSON 可序列化的值。 |
source |
Optional[AssessmentSource] |
评估的来源。 如果未提供,则默认源为 HUMAN。 (有关更多详细信息,请参阅 评估源 )。 |
trace_id |
Optional[str] |
与评估关联的跟踪的 ID。 如果未设置,则评估尚未与任何跟踪相关联。 |
metadata |
Optional[dict[str, str]] |
与评估关联的元数据。 |
span_id |
Optional[str] |
与评估关联的范围 ID(如果评估应与跟踪中的特定范围相关联)。 |
create_time_ms |
Optional[int] |
评估的创建时间(以毫秒为单位)。 如果未设置,则使用当前时间。 |
last_update_time_ms |
Optional[int] |
评估的最后一次更新时间(以毫秒为单位)。 如果未设置,则使用当前时间。 |
示例:
import mlflow
from mlflow.entities import Expectation, AssessmentSource, AssessmentSourceType
# Log a ground truth answer
mlflow.log_expectation(
trace_id="trace_789",
name="ground_truth_response",
value="The Battle of Hastings was in 1066.",
source=AssessmentSource(source_type=AssessmentSourceType.HUMAN, source_id="history_expert_01")
)
# Log an expected structured output for a tool call
expected_tool_output = Expectation(
name="expected_tool_call_result",
value={"result": {"status": "success", "data": "item_abc_123"}},
metadata={"tool_name": "inventory_check"}
)
# Assuming trace_id is known:
# mlflow.log_assessment(trace_id="trace_101", assessment=expected_tool_output)
评估错误
用于记录在生成或计算反馈或期望期间发生的错误(例如 LLM 判断失败)。
关键字段:
-
error_code
(str):错误的代码(例如“RATE_LIMIT_EXCEEDED”、“JUDGE_ERROR”)。 -
error_message
(可选[str]):详细的错误消息。 -
stack_trace
(可选[str]):堆栈跟踪(如果可用)。
示例:
import mlflow
from mlflow.entities import AssessmentError, Feedback, AssessmentSource, AssessmentSourceType
judge_error = AssessmentError(
error_code="LLM_JUDGE_TIMEOUT",
error_message="The LLM judge timed out after 30 seconds while assessing relevance."
)
mlflow.log_feedback(
trace_id="trace_error_example",
name="relevance_with_judge_v2",
source=AssessmentSource(source_type=AssessmentSourceType.LLM_JUDGE, source_id="custom_judge_model"),
error=judge_error
# Note: `value` is typically None when an error is provided
)
这些实体提供了一种灵活的结构化方法,用于将丰富的定性和定量数据与跟踪相关联,从而构成 MLflow 跟踪中可观测性和评估功能的关键部分。
标记
MLflow TraceInfo
对象中的tags
属性用于为追踪提供额外的上下文。 这些标记可用于搜索、筛选或提供有关跟踪的其他信息。
标记是键值对,它们是可变的。 这意味着,即使在跟踪记录到实验之后,也可以随时添加、修改或删除标记。
要了解如何添加自定义标签来捕获自定义元数据,请查看附加自定义标签/元数据。
标准标记
MLflow 使用一组标准标记来获取有关用户、会话和环境的常见上下文信息,从而在 MLflow UI 和 SDK 中启用增强的筛选和分组功能:
-
mlflow.trace.session
: 跟踪用户和会话中引入的会话 ID 的标准标记。 -
mlflow.trace.user
: 跟踪用户和会话中引入的用户 ID 的标准标记。 -
mlflow.source.name
:生成跟踪的入口点或脚本。 -
mlflow.source.git.commit
:如果从 Git 仓库中运行,该源代码的提交哈希值。 -
mlflow.source.type
:生成跟踪的源类型,通常PROJECT
(对于 MLflow 项目运行)或NOTEBOOK
(如果从笔记本运行)。
可以在跟踪 用户和会话 和 跟踪环境和上下文的指南中详细了解如何实现这些内容。
2. 跟踪数据
MLflow TraceData
对象可通过 Trace.data
访问,包含跟踪的核心有效负载。 它主要包含操作序列(跨度),以及触发追踪的初始请求和生成的最终响应。
键字段:
spans
(列表[Span
]):- 这是一个对象列表
Span
,这些对象(符合mlflow.entities.Span
和 OpenTelemetry 规范)表示跟踪中的各个步骤、操作或函数调用。 每个范围详细介绍了一个特定的工作单元。 - 跨度按分层
parent_id
方式进行组织,以表示执行流。 - 请参阅下面的 Span Schema 部分,以获取有关
Span
对象的详细信息。
- 这是一个对象列表
注释
request
和 response
属性被保留以保持向后兼容。 它们的值是从根范围的相应 inputs
和 outputs
属性中查找的,而不是由用户直接在 TraceData
对象上设置的。
request
(str):- 表示追踪根跨度输入数据的 JSON 序列化字符串。 这通常是最终用户的请求或调用跟踪的应用程序或工作流的初始参数。
-
示例:
'{"query": "What is MLflow Tracing?", "user_id": "user123"}'
response
(str):- 一个 JSON 序列化字符串,表示来自跟踪应用程序或工作流根范围的最终输出数据。
-
示例:
'{"answer": "MLflow Tracing provides observability...", "confidence": 0.95}'
概念表示形式:
虽然通常通过客户端mlflow.entities.Trace
检索到的对象(TraceData
例如),但从概念上讲,client.get_trace(trace_id).data
它会捆绑这些核心组件:
# Conceptual structure (not direct instantiation like this)
class TraceData:
def __init__(self, spans: list[Span], request: str, response: str):
self.spans = spans # List of Span objects
self.request = request # JSON string: Overall input to the trace
self.response = response # JSON string: Overall output of the trace
了解 TraceData
是以编程方式分析整个 GenAI 应用程序生命周期内的详细执行路径和数据转换的关键。
跨度
MLflow 跟踪功能中的 Span 对象提供有关跟踪的各个步骤的详细信息。
它符合 OpenTelemetry Span 规范。每个 Span 对象都包含有关正在检测的步骤的信息,包括span_id、名称、start_time、parent_id、状态、输入、输出、属性和事件。
跨度架构
跨度是跟踪数据的核心。 它们记录有关 genai 应用程序中每个步骤的关键关键数据。
当您在 MLflow 用户界面中查看跟踪时,您会看到一个跨度的集合,如下所示。
以下部分提供了跨度结构的详细说明。
范围类型
跨度类型是对跟踪中的跨度进行分类的方法。 默认情况下,使用跟踪修饰器时,范围类型将设置为 "UNKNOWN"
。 MLflow 为常见用例提供了一组预定义的跨度类型,同时允许你设置自定义跨度类型。
以下跨度类型可用。 此外,还可以将范围类型设置为任何开发人员指定的 str
值。
范围类型 | 说明 |
---|---|
"CHAT_MODEL" |
代表对聊天模型的查询。 这是 LLM 交互的一种特殊情况。 |
"CHAIN" |
表示一系列操作。 |
"AGENT" |
自主代理运作。 |
"TOOL" |
表示工具执行(通常由代理执行),例如查询搜索引擎。 |
"EMBEDDING" |
表示文本嵌入操作。 |
"RETRIEVER" |
表示上下文检索作,例如查询向量数据库。 |
"PARSER" |
表示分析作,将文本转换为结构化格式。 |
"RERANKER" |
表示重新排名作,根据相关性对检索的上下文进行排序。 |
"UNKNOWN" |
未指定其他跨度类型时使用的默认范围类型。 |
若要设置范围类型,可以将参数mlflow.trace
传递给span_type
修饰器或mlflow.start_span
上下文管理器。 使用 自动跟踪时,范围类型由 MLflow 自动设置。
import mlflow
from mlflow.entities import SpanType
# Using a built-in span type
@mlflow.trace(span_type=SpanType.RETRIEVER)
def retrieve_documents(query: str):
...
# Setting a custom span type
with mlflow.start_span(name="add", span_type="MATH") as span:
span.set_inputs({"x": z, "y": y})
z = x + y
span.set_outputs({"z": z})
print(span.span_type)
# Output: MATH
特定跨度类型的架构
MLflow 具有一组预定义的跨度类型(请参阅 mlflow.entities.SpanType
),某些范围类型具有属性,以便启用 UI 和下游任务(例如评估)中的其他功能。
检索器范围区间
范围 RETRIEVER
类型用于涉及从数据存储中检索数据的操作(例如,从向量存储库查询文档)。
RETRIEVER
范围的输出应为一个文档列表。
列表中的每个文档都应是字典(或可使用以下键序列化到字典的对象),理想情况下包括:
-
page_content
(str
):检索到的文档区块的文本内容。 -
metadata
(Optional[Dict[str, Any]]
):与文档关联的其他元数据的字典。- MLflow UI 和评估指标可能会特别查找
doc_uri
(用于文档源的字符串 URI)和chunk_id
(如果该文档是较大分块文档的一部分的字符串标识符),以增强显示和功能。
- MLflow UI 和评估指标可能会特别查找
-
id
(Optional[str]
):文档区块本身的可选唯一标识符。
检索器跨度实例操作示例:
import mlflow
from mlflow.entities import SpanType, Document
def search_store(query: str) -> list[(str, str)]:
# Simulate retrieving documents (e.g., 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):
# Get documents from the search store
docs = search_store(query)
# Get the current active span (created by @mlflow.trace)
span = mlflow.get_current_active_span()
# Set the outputs of the span in accordance with the tracing schema
outputs = [Document(page_content=doc, metadata={"doc_uri": uri}) for doc, uri in docs]
span.set_outputs(outputs)
# Return the original format for downstream usage
return docs
# Example usage
user_query = "MLflow Tracing benefits"
retrieved_docs = retrieve_relevant_documents(user_query)
# Read path: Reconstructing the document list from the span outputs
trace_id = mlflow.get_last_active_trace_id()
trace = mlflow.get_trace(trace_id)
span = trace.search_spans(name="retrieve_relevant_documents")[0]
documents = [Document(**doc) for doc in span.outputs]
print(documents)
符合此结构,特别是包括page_content
和相关metadata
如doc_uri
,将确保RETRIEVER
跨度在 MLflow UI 中能够信息丰富地呈现,例如显示文档内容和提供链接,并且下游评估任务可以正确处理检索的上下文。
聊天完成和工具呼叫范围
类型 CHAT_MODEL
或 LLM
的范围用于表示与聊天完成 API 的交互(例如,OpenAI 的 聊天完成 API,或 Anthropic 的 messages API)。 这些范围还可以捕获模型提供给或使用的工具(函数)的相关信息。
由于提供程序的 API 可以具有不同的架构,因此对原始 LLM 调用本身的跨度输入和输出的格式没有严格的限制。 但是,若要启用丰富的 UI 功能(如聊天显示和工具调用可视化),并标准化数据进行评估,MLflow 定义了聊天消息和工具定义的特定属性。
有关如何使用上述实用工具函数以及如何使用函数 span.get_attribute()
检索这些函数的快速演示,请参阅以下示例:
import mlflow
from mlflow.entities.span import SpanType # Corrected from mlflow.entities.span 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):
# mocking a response
response = {
"role": "assistant",
"tool_calls": [
{
"id": "123",
"function": {"arguments": '{"a": 1,"b": 2}', "name": "add"},
"type": "function",
}
],
}
combined_messages = messages + [response]
span = mlflow.get_current_active_span()
set_span_chat_messages(span, combined_messages)
set_span_chat_tools(span, tools)
return response
call_chat_model(messages, tools)
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))
后续步骤
继续您的旅程,并参考这些推荐的行动和教程。
- 为应用程序设置跟踪 - 应用这些数据模型概念以向应用程序添加跟踪
- 通过 SDK 查询跟踪 - 使用数据模型以编程方式分析跟踪
- 附加自定义标记/元数据 - 使用上下文信息丰富跟踪
参考指南
浏览有关相关概念的详细文档。