Files
2026-07-13 13:22:34 +08:00

397 lines
14 KiB
Python

from enum import Enum
# NB: These keys are placeholders and subject to change
class TraceMetadataKey:
INPUTS = "mlflow.traceInputs"
OUTPUTS = "mlflow.traceOutputs"
SOURCE_RUN = "mlflow.sourceRun"
MODEL_ID = "mlflow.modelId"
# Trace size statistics including total size, number of spans, and max span size
SIZE_STATS = "mlflow.trace.sizeStats"
# Aggregated token usage information in a single trace, stored as a dumped JSON string.
TOKEN_USAGE = "mlflow.trace.tokenUsage"
# Set by start_trace() when it writes the authoritative (DFS-dedup) TOKEN_USAGE / COST
# so that concurrent log_spans() calls do not accumulate on top of them.
# Set by start_trace() after writing authoritative trace-level values (TOKEN_USAGE,
# COST, session ID, request_time, execution_duration) so that concurrent log_spans()
# calls do not overwrite them.
TRACE_INFO_FINALIZED = "mlflow.trace.infoFinalized"
# Aggregated cost information in a single trace, stored as a dumped JSON string (USD).
COST = "mlflow.trace.cost"
# Store the user ID/name of the application request. Do not confuse this with mlflow.user
# tag, which stores "who created the trace" i.e. developer or system name.
TRACE_USER = "mlflow.trace.user"
# Store the session ID of the application request.
TRACE_SESSION = "mlflow.trace.session"
# Total size of the trace in bytes. Deprecated, use SIZE_STATS instead.
SIZE_BYTES = "mlflow.trace.sizeBytes"
# Gateway-specific metadata keys
GATEWAY_ENDPOINT_ID = "mlflow.gateway.endpointId"
GATEWAY_REQUEST_TYPE = "mlflow.gateway.requestType"
GATEWAY_CALLER = "mlflow.gateway.caller"
# Store the user ID/name from authentication
AUTH_USER_ID = "mlflow.auth.userId"
AUTH_USERNAME = "mlflow.auth.username"
class TraceTagKey:
TRACE_NAME = "mlflow.traceName"
EVAL_REQUEST_ID = "mlflow.eval.requestId"
SPANS_LOCATION = "mlflow.trace.spansLocation"
ARCHIVE_LOCATION = "mlflow.trace.archiveLocation"
ARCHIVAL_FAILURE = "mlflow.trace.archivalFailure"
# Store the source scorer name that generated the trace. This tag is used to determine if a
# trace is generated by a scorer or prediction during evaluation and filter out the scorer
# traces in the UI. This supposed to be immutable, but we use tag because we can only set this
# after the scorer is executed, which is not possible with trace metadata.
SOURCE_SCORER_NAME = "mlflow.trace.sourceScorer"
# Store a list of linked prompt versions in JSON format
# Structure: [{"name": "prompt_name", "version": "version"}]
LINKED_PROMPTS = "mlflow.linkedPrompts"
class TokenUsageKey:
"""Key for the token usage information in the `mlflow.chat.tokenUsage` span attribute."""
INPUT_TOKENS = "input_tokens"
OUTPUT_TOKENS = "output_tokens"
TOTAL_TOKENS = "total_tokens"
CACHE_READ_INPUT_TOKENS = "cache_read_input_tokens"
CACHE_CREATION_INPUT_TOKENS = "cache_creation_input_tokens"
@classmethod
def all_keys(cls):
return [
cls.INPUT_TOKENS,
cls.OUTPUT_TOKENS,
cls.TOTAL_TOKENS,
cls.CACHE_READ_INPUT_TOKENS,
cls.CACHE_CREATION_INPUT_TOKENS,
]
@classmethod
def cache_keys(cls):
return [cls.CACHE_READ_INPUT_TOKENS, cls.CACHE_CREATION_INPUT_TOKENS]
class CostKey:
"""Key for the cost information in the `mlflow.llm.cost` span attribute."""
INPUT_COST = "input_cost"
OUTPUT_COST = "output_cost"
TOTAL_COST = "total_cost"
class TraceSizeStatsKey:
TOTAL_SIZE_BYTES = "total_size_bytes"
NUM_SPANS = "num_spans"
MAX_SPAN_SIZE_BYTES = "max"
P25_SPAN_SIZE_BYTES = "p25"
P50_SPAN_SIZE_BYTES = "p50"
P75_SPAN_SIZE_BYTES = "p75"
# A set of reserved attribute keys
class SpanAttributeKey:
EXPERIMENT_ID = "mlflow.experimentId"
REQUEST_ID = "mlflow.traceRequestId"
INPUTS = "mlflow.spanInputs"
OUTPUTS = "mlflow.spanOutputs"
SPAN_TYPE = "mlflow.spanType"
# Severity level of the span (one of the SpanLogLevel members). Absent
# means the span was not classified.
LOG_LEVEL = "mlflow.spanLogLevel"
FUNCTION_NAME = "mlflow.spanFunctionName"
START_TIME_NS = "mlflow.spanStartTimeNs"
CHAT_TOOLS = "mlflow.chat.tools"
# This attribute is used to store token usage information from LLM responses.
# Stored in {"input_tokens": int, "output_tokens": int, "total_tokens": int,
# "cache_read_input_tokens"?: int, "cache_creation_input_tokens"?: int} format.
CHAT_USAGE = "mlflow.chat.tokenUsage"
# This attribute stores cost information calculated from token usage and model pricing.
# Stored in {"input_cost": float, "output_cost": float, "total_cost": float} format (USD).
LLM_COST = "mlflow.llm.cost"
# This attribute stores the model name extracted from span inputs/attributes.
MODEL = "mlflow.llm.model"
MODEL_PROVIDER = "mlflow.llm.provider"
# This attribute indicates which flavor/format generated the LLM span. This is
# used by downstream (e.g., UI) to determine the message format for parsing.
MESSAGE_FORMAT = "mlflow.message.format"
# This attribute is used to populate `intermediate_outputs` property of a trace data
# representing intermediate outputs of the trace. This attribute is not empty only on
# the root span of a trace created by the `mlflow.log_trace` API. The `intermediate_outputs`
# property of the normal trace is generated by the outputs of non-root spans.
INTERMEDIATE_OUTPUTS = "mlflow.trace.intermediate_outputs"
# This attribute is used to store prompt version information when load_prompt is called
# within an active span. Stored as a JSON list of {"name": "...", "version": "..."} objects,
# same format as LINKED_PROMPTS_TAG_KEY in traces.
LINKED_PROMPTS = "mlflow.linkedPrompts"
# This attribute stores the trace ID of the linked gateway trace, used when a gateway
# endpoint is called by a traced agent via distributed tracing (traceparent header).
LINKED_GATEWAY_TRACE_ID = "mlflow.gateway.linkedTraceId"
# User and session IDs copied from trace metadata to root span attributes for OTLP export.
# Following OTel semantic conventions:
# https://opentelemetry.io/docs/specs/semconv/registry/attributes/user/#user-id
# https://opentelemetry.io/docs/specs/semconv/registry/attributes/session/#session-id
USER_ID = "user.id"
SESSION_ID = "session.id"
# Prefix for per-tag span attributes emitted by OtelSpanProcessor so user-defined tags
# survive OTLP export and can be restored to SqlTraceTag rows on the server side.
# Each attribute is keyed as "mlflow.traceTag.<tag_key>" with the plain string value.
TRACE_TAG_PREFIX = "mlflow.traceTag."
class TraceExperimentTagKey:
ARCHIVAL_RETENTION = "mlflow.trace.archivalRetention"
ARCHIVE_NOW = "mlflow.trace.archiveNow"
class TraceArchivalFailureReason(str, Enum):
MALFORMED_TRACE = "MALFORMED_TRACE"
UNSUPPORTED_ARCHIVE_REPOSITORY = "UNSUPPORTED_ARCHIVE_REPOSITORY"
class AssessmentMetadataKey:
# When the assessment is generated by an eval run, log the run ID here.
SOURCE_RUN_ID = "mlflow.assessment.sourceRunId"
# Total LLM cost spent for generating the feedback (llm-as-a-judge).
JUDGE_COST = "mlflow.assessment.judgeCost"
# Token counts for the judge LLM call.
JUDGE_INPUT_TOKENS = "mlflow.assessment.judgeInputTokens"
JUDGE_OUTPUT_TOKENS = "mlflow.assessment.judgeOutputTokens"
# When the scorer generates a trace for assessment scoring, log the trace ID here.
SCORER_TRACE_ID = "mlflow.assessment.scorerTraceId"
# When the assessment is generated by online scoring, log the session ID here.
ONLINE_SCORING_SESSION_ID = "mlflow.assessment.onlineScoringSessionId"
# All storage backends are guaranteed to support request_metadata key/value up to 250 characters
MAX_CHARS_IN_TRACE_INFO_METADATA = 250
# All storage backends are guaranteed to support tag keys up to 250 characters,
# values up to 4096 characters
MAX_CHARS_IN_TRACE_INFO_TAGS_KEY = 250
MAX_CHARS_IN_TRACE_INFO_TAGS_VALUE = 4096
TRUNCATION_SUFFIX = "..."
TRACE_REQUEST_RESPONSE_PREVIEW_MAX_LENGTH_DBX = 10000
TRACE_REQUEST_RESPONSE_PREVIEW_MAX_LENGTH_OSS = 1000
# Trace request ID must have the prefix "tr-" appended to the OpenTelemetry trace ID
TRACE_REQUEST_ID_PREFIX = "tr-"
# Trace ID V4 format starts with "trace:/" in the format of "trace:/<location>/<trace_id>"
TRACE_ID_V4_PREFIX = "trace:/"
# Schema version of traces and spans.
TRACE_SCHEMA_VERSION = 3
# Key for the trace schema version in the trace. This key is also used in
# Databricks model serving to be careful when modifying it.
TRACE_SCHEMA_VERSION_KEY = "mlflow.trace_schema.version"
STREAM_CHUNK_EVENT_NAME_FORMAT = "mlflow.chunk.item.{index}"
STREAM_CHUNK_EVENT_VALUE_KEY = "mlflow.chunk.value"
# Key for Databricks model serving options to return the trace in the response
DATABRICKS_OPTIONS_KEY = "databricks_options"
RETURN_TRACE_OPTION_KEY = "return_trace"
DATABRICKS_OUTPUT_KEY = "databricks_output"
# Assessment constants
ASSESSMENT_ID_PREFIX = "a-"
# The location of the spans in the trace.
# This is used to determine where the spans are stored when exporting.
class SpansLocation(str, Enum):
TRACKING_STORE = "TRACKING_STORE"
ARTIFACT_REPO = "ARTIFACT_REPO"
ARCHIVE_REPO = "ARCHIVE_REPO"
# Path to the notebook trace renderer directory
TRACE_RENDERER_ASSET_PATH = "/static-files/lib/notebook-trace-renderer"
class TraceMetricKey:
"""
Keys for metrics on traces view type.
"""
TRACE_COUNT = "trace_count"
SESSION_COUNT = "session_count"
LATENCY = "latency"
INPUT_TOKENS = "input_tokens"
OUTPUT_TOKENS = "output_tokens"
TOTAL_TOKENS = "total_tokens"
CACHE_READ_INPUT_TOKENS = "cache_read_input_tokens"
CACHE_CREATION_INPUT_TOKENS = "cache_creation_input_tokens"
@classmethod
def token_usage_keys(cls) -> list[str]:
return [
cls.INPUT_TOKENS,
cls.OUTPUT_TOKENS,
cls.TOTAL_TOKENS,
cls.CACHE_READ_INPUT_TOKENS,
cls.CACHE_CREATION_INPUT_TOKENS,
]
class TraceMetricDimensionKey:
"""
Dimensions for metrics on traces view type.
"""
TRACE_NAME = "trace_name"
TRACE_STATUS = "trace_status"
class SpanMetricKey:
"""
Keys for metrics on spans view type.
"""
SPAN_COUNT = "span_count"
LATENCY = "latency"
INPUT_COST = "input_cost"
OUTPUT_COST = "output_cost"
TOTAL_COST = "total_cost"
@classmethod
def cost_keys(cls) -> list[str]:
return [cls.INPUT_COST, cls.OUTPUT_COST, cls.TOTAL_COST]
class SpanMetricDimensionKey:
"""
Dimensions for metrics on spans view type.
"""
SPAN_NAME = "span_name"
SPAN_TYPE = "span_type"
SPAN_STATUS = "span_status"
SPAN_MODEL_NAME = "span_model_name"
SPAN_MODEL_PROVIDER = "span_model_provider"
class AssessmentMetricKey:
"""
Keys for metrics on assessments view type.
"""
ASSESSMENT_COUNT = "assessment_count"
ASSESSMENT_VALUE = "assessment_value"
class AssessmentMetricDimensionKey:
"""
Dimensions for metrics on assessments view type.
"""
ASSESSMENT_NAME = "assessment_name"
ASSESSMENT_VALUE = "assessment_value"
class TraceMetricSearchKey:
"""
Search key for trace metrics view type.
VIEW_TYPE must be the prefix of the search string
e.g. "trace.<entity> = <value>" or "trace.<entity>.<key> = <value>"
"""
VIEW_TYPE = "trace"
STATUS = "status"
TAG = "tag"
METADATA = "metadata"
@classmethod
def entity_to_key_requirement(cls) -> dict[str, bool]:
"""
Mapping of entity to a boolean indicating if it requires a key
For example, "tag" requires a key: "trace.tag.<key> = <value>"
"status" does not require a key: "trace.status = <value>"
"""
return {
cls.STATUS: False,
cls.TAG: True,
cls.METADATA: True,
}
class SpanMetricSearchKey:
"""
Search key for span metrics view type.
VIEW_TYPE must be the prefix of the search string
e.g. "span.<entity> = <value>"
"""
VIEW_TYPE = "span"
NAME = "name"
STATUS = "status"
TYPE = "type"
@classmethod
def entity_to_key_requirement(cls) -> dict[str, bool]:
"""
Mapping of entity to a boolean indicating if it requires a key
For example, "name" does not require a key: "span.name = <value>"
"""
return {
cls.NAME: False,
cls.STATUS: False,
cls.TYPE: False,
}
class AssessmentMetricSearchKey:
"""
Search key for assessment metrics view type.
VIEW_TYPE must be the prefix of the search string
e.g. "assessment.<entity> = <value>"
"""
VIEW_TYPE = "assessment"
NAME = "name"
TYPE = "type"
@classmethod
def entity_to_key_requirement(cls) -> dict[str, bool]:
"""
Mapping of entity to a boolean indicating if it requires a key
For example, "name" does not require a key: "assessment.name = <value>"
"""
return {
cls.NAME: False,
cls.TYPE: False,
}
# OpenTelemetry GenAI Semantic Convention attribute keys.
# https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
class GenAiSemconvKey:
CONVERSATION_ID = "gen_ai.conversation.id"
OPERATION_NAME = "gen_ai.operation.name"
REQUEST_MODEL = "gen_ai.request.model"
RESPONSE_MODEL = "gen_ai.response.model"
RESPONSE_ID = "gen_ai.response.id"
PROVIDER_NAME = "gen_ai.provider.name"
USAGE_INPUT_TOKENS = "gen_ai.usage.input_tokens"
USAGE_OUTPUT_TOKENS = "gen_ai.usage.output_tokens"
INPUT_MESSAGES = "gen_ai.input.messages"
OUTPUT_MESSAGES = "gen_ai.output.messages"
SYSTEM_INSTRUCTIONS = "gen_ai.system_instructions"
REQUEST_TEMPERATURE = "gen_ai.request.temperature"
REQUEST_MAX_TOKENS = "gen_ai.request.max_tokens"
REQUEST_TOP_P = "gen_ai.request.top_p"
REQUEST_STOP_SEQUENCES = "gen_ai.request.stop_sequences"
RESPONSE_FINISH_REASONS = "gen_ai.response.finish_reasons"
TOOL_DEFINITIONS = "gen_ai.tool.definitions"
TOOL_CALL_ARGUMENTS = "gen_ai.tool.call.arguments"
TOOL_CALL_RESULT = "gen_ai.tool.call.result"