litellm/tests/unit/integrations/test_wandb.py
Mateo Wang 3f38730d2c
refactor(typing): clear about 1,100 basedpyright Any errors across 303 files (#49986)
* refactor(typing): clear basedpyright Any errors (wave 1)

* refactor(typing): clear basedpyright Any errors (wave 2)

* refactor(typing): clear basedpyright Any errors (wave 3)

* refactor(typing): clear basedpyright Any errors (wave 4)

* refactor(typing): clear basedpyright Any errors (wave 5)

* refactor(typing): clear basedpyright Any errors (wave 6)

* fix(typing): keep the cached-plan fallback's direct query_first calls so span naming resolves

* fix(logging): keep callbacks running when litellm_params is a params model

should_run_callback and the sync success and failure handlers read litellm_params through any object with a get method again, as they did before this branch, so a logging hook that returns a GenericLiteLLMParams no longer stops sync logging for that request

Adds behavior tests for the changed lines codecov listed as not run

* fix: read the regional uplift for every data residency again and reuse one dict TypeAdapter

The typed lookup only read the eu and us multipliers, so a deployment that set regional_processing_uplift_multiplier_fedramp stopped applying it. /model/update and the model write paths now share one module-level TypeAdapter instead of building one per call.

* fix: bill regional uplift multipliers float() accepts, bytes included

* fix: raise the in operator's own error from one shared json_contains, and name the bad uplift type
2026-11-06 13:31:15 -08:00

90 lines
2.8 KiB
Python

import importlib.util
import sys
from collections.abc import Mapping, Sequence
from dataclasses import dataclass
from types import ModuleType, SimpleNamespace
from typing import Final
from unittest.mock import MagicMock
import pytest
import respx
import litellm
from litellm import completion
def test_wandb_logging():
try:
response = completion(
model="claude-3-5-haiku-20241022",
messages=[{"role": "user", "content": "Hi 👋 - i'm claude"}],
max_tokens=10,
temperature=0.2,
)
print(response)
except litellm.Timeout as e:
pass
except Exception as e:
print(e)
@dataclass(frozen=True)
class _TraceResult:
inputs: Mapping[str, object]
outputs: Mapping[str, object]
@dataclass(frozen=True)
class _TraceSpan:
name: str
attributes: Mapping[str, object]
start_time_ms: int
end_time_ms: int
span_kind: str
results: Sequence[_TraceResult]
@dataclass(frozen=True)
class _TraceTree:
root_span: _TraceSpan
model_dict: Mapping[str, object]
def _weights_biases_with_stub_trace_tree(monkeypatch: pytest.MonkeyPatch) -> ModuleType:
data_types: Final = ModuleType("wandb.sdk.data_types")
data_types.trace_tree = SimpleNamespace(
Result=_TraceResult, Span=_TraceSpan, WBTraceTree=_TraceTree, SpanKind=SimpleNamespace(LLM="LLM")
)
for name in ("wandb", "wandb.sdk"):
monkeypatch.setitem(sys.modules, name, ModuleType(name))
monkeypatch.setitem(sys.modules, "wandb.sdk.data_types", data_types)
spec: Final = importlib.util.find_spec("litellm.integrations.weights_biases")
assert spec is not None and spec.loader is not None
module: Final = importlib.util.module_from_spec(spec)
monkeypatch.setitem(sys.modules, spec.name, module)
spec.loader.exec_module(module)
return module
def test_wandb_chat_completion_trace_lists_each_request_message_with_its_role(monkeypatch: pytest.MonkeyPatch) -> None:
weights_biases: Final = _weights_biases_with_stub_trace_tree(monkeypatch)
request: Final = {
"model": "gpt-4o",
"messages": [{"role": "system", "content": "Be brief."}, {"role": "user", "content": "Hi"}],
}
response: Final = {
"object": "chat.completion",
"model": "gpt-4o",
"created": 1767225600,
"choices": [{"message": {"role": "assistant", "content": "Hello!"}}],
}
trace: Final = weights_biases.OpenAIRequestResponseResolver()(request, response, 1.5)
assert trace.root_span.results == [
_TraceResult(
inputs={"request": "\n\n**system**: Be brief.\n\n\n**user**: Hi\n"},
outputs={"response": "\n\n**assistant**: Hello!\n"},
)
]
assert trace.root_span.end_time_ms - trace.root_span.start_time_ms == 1500