fa45d8aa5f
- health_checklist.json: 192.168.1.122→node122
- ocr_client.py: docstring IP→node122
- docs/market-data-requirements.md: IP→node122
- 所有API调用通过ProxyHandler({})绕过系统代理
Privoxy对node122:18003返回500,直连正常
113 lines
4.8 KiB
Python
113 lines
4.8 KiB
Python
"""Baggage promotion: request-identity values carried across child spans.
|
|
|
|
A bounded set of identity values is written into OpenTelemetry Baggage on the
|
|
LLM-call span so that child spans (guardrail, service) inherit them.
|
|
``providers.LiteLLMBaggageSpanProcessor`` reads Baggage at span start and stamps
|
|
the allowlisted keys onto every span.
|
|
|
|
This module is the single place baggage is defined: ``_PROMOTABLE`` maps each
|
|
promotable attribute key to how its value is read, and the ``*_KEYS`` defaults
|
|
select what is promoted unless the config overrides them. ``TEAM_METADATA``'s
|
|
extractor filters the team's free-form metadata to the sub-keys an operator
|
|
allowlists via ``baggage_team_metadata_keys`` (default none), so the blob is
|
|
never promoted whole.
|
|
"""
|
|
|
|
import json
|
|
from collections.abc import Callable, Mapping
|
|
from typing import Final
|
|
|
|
from litellm.integrations.otel.model.metadata import RequestIdentity
|
|
from litellm.integrations.otel.model.semconv import GenAI, LiteLLM
|
|
|
|
# Attribute key -> value extractor over (identity, request_model,
|
|
# team_metadata_keys). The single definition of what may be promoted and under
|
|
# which key. Only the ``TEAM_METADATA`` extractor consults team_metadata_keys
|
|
# (to filter the team's metadata to an allowlist); the rest ignore it.
|
|
_PROMOTABLE: Final[
|
|
dict[str, Callable[[RequestIdentity, str | None, tuple[str, ...]], str | None]]
|
|
] = {
|
|
LiteLLM.TEAM_ID: lambda identity, model, team_metadata_keys: identity.team_id,
|
|
LiteLLM.TEAM_ALIAS: lambda identity, model, team_metadata_keys: identity.team_alias,
|
|
LiteLLM.TEAM_METADATA: lambda identity, model, team_metadata_keys: _filtered_team_metadata_json(
|
|
identity.team_metadata, team_metadata_keys
|
|
),
|
|
LiteLLM.KEY_HASH: lambda identity, model, team_metadata_keys: identity.key_hash,
|
|
LiteLLM.END_USER: lambda identity, model, team_metadata_keys: identity.end_user,
|
|
GenAI.REQUEST_MODEL: lambda identity, model, team_metadata_keys: model,
|
|
LiteLLM.PROVIDER_MODEL: lambda identity, model, team_metadata_keys: identity.provider_model,
|
|
}
|
|
|
|
# Keys promoted by default (a subset of ``_PROMOTABLE``). ``END_USER`` is
|
|
# promotable but off by default — it identifies an individual user, so stamping
|
|
# it onto every span is opt-in via ``config.baggage_promoted_keys``.
|
|
BAGGAGE_PROMOTED_KEYS: Final[tuple[str, ...]] = (
|
|
LiteLLM.TEAM_ID,
|
|
LiteLLM.TEAM_ALIAS,
|
|
LiteLLM.TEAM_METADATA,
|
|
LiteLLM.KEY_HASH,
|
|
GenAI.REQUEST_MODEL,
|
|
LiteLLM.PROVIDER_MODEL,
|
|
)
|
|
|
|
# Metadata sub-keys eligible for promotion under the ``litellm.metadata.*``
|
|
# namespace. The full metadata blob is never promoted; only this allowlist is.
|
|
DEFAULT_BAGGAGE_METADATA_KEYS: Final[tuple[str, ...]] = (
|
|
"user_api_key_org_id",
|
|
"user_api_key_user_id",
|
|
"user_api_key_alias",
|
|
"user_api_key_end_user_id",
|
|
"requester_ip_address",
|
|
)
|
|
|
|
# Sub-keys of the team's free-form metadata eligible for promotion under
|
|
# ``litellm.team.metadata``. Empty by default: a team's metadata can hold
|
|
# arbitrary operator data, so none of it is promoted until each key is
|
|
# explicitly allowlisted via ``config.baggage_team_metadata_keys``.
|
|
DEFAULT_BAGGAGE_TEAM_METADATA_KEYS: Final[tuple[str, ...]] = ()
|
|
|
|
|
|
def promoted_baggage(
|
|
identity: RequestIdentity,
|
|
request_model: str | None,
|
|
promoted_keys: tuple[str, ...],
|
|
metadata_keys: tuple[str, ...] = DEFAULT_BAGGAGE_METADATA_KEYS,
|
|
team_metadata_keys: tuple[str, ...] = DEFAULT_BAGGAGE_TEAM_METADATA_KEYS,
|
|
) -> dict[str, str]:
|
|
"""Identity values to write into Baggage, filtered to ``promoted_keys``.
|
|
|
|
``promoted_keys`` selects from ``_PROMOTABLE``; ``metadata_keys`` selects
|
|
sub-keys of ``identity.metadata`` to promote under ``litellm.metadata.*``;
|
|
``team_metadata_keys`` selects sub-keys of the team's metadata to promote
|
|
under ``litellm.team.metadata``. Empty values are dropped.
|
|
"""
|
|
out: dict[str, str] = {}
|
|
for key, extract in _PROMOTABLE.items():
|
|
if key in promoted_keys:
|
|
value = extract(identity, request_model, team_metadata_keys)
|
|
if value:
|
|
out[key] = value
|
|
for meta_key in metadata_keys:
|
|
value = identity.metadata.get(meta_key)
|
|
if value:
|
|
out[f"{LiteLLM.METADATA_PREFIX}{meta_key}"] = value
|
|
return out
|
|
|
|
|
|
def _filtered_team_metadata_json(
|
|
metadata: Mapping[str, object] | None,
|
|
allowed_keys: tuple[str, ...],
|
|
) -> str | None:
|
|
"""JSON-serialize only the allowlisted sub-keys of a team's metadata.
|
|
|
|
Returns ``None`` when nothing is allowlisted or no allowlisted key is
|
|
present, so the empty case is dropped rather than promoting ``"{}"``. Keys
|
|
are sorted for a stable, diff-friendly value.
|
|
"""
|
|
if not isinstance(metadata, Mapping) or not allowed_keys:
|
|
return None
|
|
filtered = {key: metadata[key] for key in allowed_keys if key in metadata}
|
|
if not filtered:
|
|
return None
|
|
return json.dumps(filtered, default=str, sort_keys=True)
|