mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(apodex): satisfy CI quality gates
This commit is contained in:
parent
bb6cf2e2ef
commit
a665d2e336
8 changed files with 48 additions and 12 deletions
|
|
@ -644,7 +644,7 @@ snowflake_models: Set = set()
|
|||
gradient_ai_models: Set = set()
|
||||
llama_models: Set = set()
|
||||
nscale_models: Set = set()
|
||||
apodex_models: Set = set()
|
||||
apodex_models: Set = set() # mutable-ok: provider model registry is populated during initialization
|
||||
nebius_models: Set = set()
|
||||
nebius_embedding_models: Set = set()
|
||||
aiml_models: Set = set()
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class AnthropicResponsesStreamWrapper:
|
|||
if self._open_block_index is None:
|
||||
return
|
||||
self._chunk_queue.append(
|
||||
{
|
||||
{ # mutable-ok: queued Anthropic event payload
|
||||
"type": "content_block_stop",
|
||||
"index": self._open_block_index,
|
||||
}
|
||||
|
|
@ -88,7 +88,7 @@ class AnthropicResponsesStreamWrapper:
|
|||
{
|
||||
"type": "content_block_start",
|
||||
"index": block_idx,
|
||||
"content_block": dict(content_block),
|
||||
"content_block": dict(content_block), # mutable-ok: queued Anthropic event payload
|
||||
}
|
||||
)
|
||||
self._open_block_index = block_idx
|
||||
|
|
@ -143,7 +143,11 @@ class AnthropicResponsesStreamWrapper:
|
|||
block_idx = self._next_block_index()
|
||||
if item_id:
|
||||
self._item_id_to_block_index[item_id] = block_idx
|
||||
self._start_block(block_idx, "text", {"type": "text", "text": ""})
|
||||
self._start_block(
|
||||
block_idx,
|
||||
"text",
|
||||
{"type": "text", "text": ""}, # mutable-ok: Anthropic content block payload
|
||||
)
|
||||
elif item_type == "function_call":
|
||||
call_id: Final = (
|
||||
getattr(item, "call_id", None) or (item.get("call_id") if isinstance(item, dict) else None) or ""
|
||||
|
|
@ -172,7 +176,7 @@ class AnthropicResponsesStreamWrapper:
|
|||
text_block_idx: Final = self._get_or_start_block(
|
||||
item_id=item_id,
|
||||
block_type="text",
|
||||
content_block={"type": "text", "text": ""},
|
||||
content_block={"type": "text", "text": ""}, # mutable-ok: Anthropic content block payload
|
||||
)
|
||||
self._chunk_queue.append(
|
||||
{
|
||||
|
|
@ -192,7 +196,11 @@ class AnthropicResponsesStreamWrapper:
|
|||
thinking_block_idx: Final = self._get_or_start_block(
|
||||
item_id=item_id,
|
||||
block_type="thinking",
|
||||
content_block={"type": "thinking", "thinking": "", "signature": ""},
|
||||
content_block={ # mutable-ok: Anthropic content block payload
|
||||
"type": "thinking",
|
||||
"thinking": "",
|
||||
"signature": "",
|
||||
},
|
||||
)
|
||||
self._chunk_queue.append(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,13 +125,15 @@ class ApodexChatConfig(OpenAIGPTConfig):
|
|||
def transform_request(
|
||||
self,
|
||||
model: str,
|
||||
messages: list[AllMessageValues],
|
||||
messages: list[AllMessageValues], # mutable-ok: matches the base-class signature
|
||||
optional_params: dict, # mutable-ok: matches the base-class signature
|
||||
litellm_params: dict, # mutable-ok: matches the base-class signature
|
||||
headers: dict, # mutable-ok: matches the base-class signature
|
||||
) -> dict: # mutable-ok: JSON request body
|
||||
pin_non_streaming: Final = bool(optional_params.get(_PIN_NON_STREAMING, False))
|
||||
forwarded_params: Final = {key: value for key, value in optional_params.items() if key != _PIN_NON_STREAMING}
|
||||
forwarded_params: Final = { # mutable-ok: base transformer requires a request dict
|
||||
key: value for key, value in optional_params.items() if key != _PIN_NON_STREAMING
|
||||
}
|
||||
transformed: Final = super().transform_request(
|
||||
model=model,
|
||||
messages=messages,
|
||||
|
|
|
|||
|
|
@ -117,13 +117,13 @@ class ApodexResponsesConfig(OpenAIResponsesAPIConfig):
|
|||
status_code=raw_response.status_code,
|
||||
# Content-Encoding and Content-Length describe the body being replaced here;
|
||||
# carrying them over makes httpx try to decompress plain JSON on read.
|
||||
headers={
|
||||
headers={ # mutable-ok: httpx requires mutable response headers
|
||||
name: value for name, value in raw_response.headers.items() if name.lower() not in _BODY_FRAMING_HEADERS
|
||||
},
|
||||
json={
|
||||
json={ # mutable-ok: httpx requires a JSON-compatible response dict
|
||||
**payload,
|
||||
"created_at": payload.get("created_at", int(time())),
|
||||
"output": payload.get("output", []),
|
||||
"output": payload.get("output", []), # mutable-ok: Responses payload requires an array default
|
||||
},
|
||||
)
|
||||
return super().transform_cancel_response_api_response(
|
||||
|
|
|
|||
|
|
@ -245,10 +245,16 @@ class TestProcessEventTextDeltaWithoutOutputItemAdded:
|
|||
assert chunks[1]["delta"] == {"type": "text_delta", "text": "Hel"}
|
||||
|
||||
def test_process_event_delta_without_item_id_never_yields_negative_index(self):
|
||||
chunks = _process_all([{"type": "response.output_text.delta", "delta": "Hi"}])
|
||||
chunks = _process_all(
|
||||
[
|
||||
{"type": "response.output_text.delta", "delta": "Hi"},
|
||||
{"type": "response.output_text.delta", "delta": " again"},
|
||||
]
|
||||
)
|
||||
assert [(c["type"], c["index"]) for c in chunks] == [
|
||||
("content_block_start", 0),
|
||||
("content_block_delta", 0),
|
||||
("content_block_delta", 0),
|
||||
]
|
||||
|
||||
def test_process_event_unregistered_item_id_opens_new_text_block(self):
|
||||
|
|
|
|||
|
|
@ -72,6 +72,13 @@ def _chat_config(model: str):
|
|||
|
||||
|
||||
class TestProviderResolution:
|
||||
def test_openai_compatible_provider_info_uses_apodex_credentials(self):
|
||||
config = _chat_config("apodex-1.1")
|
||||
assert config._get_openai_compatible_provider_info("https://override.test/v1", "sk-override") == (
|
||||
"https://override.test/v1",
|
||||
"sk-override",
|
||||
)
|
||||
|
||||
def test_prefixed_model_resolves_to_the_default_base(self):
|
||||
model, provider, api_key, api_base = litellm.get_llm_provider(model=CORE_MODEL)
|
||||
assert (model, provider, api_key, api_base) == (
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class TestNativePassthroughRouting:
|
|||
assert config is not None
|
||||
assert type(config).__name__ == "ApodexAnthropicMessagesConfig"
|
||||
assert config.custom_llm_provider == "apodex"
|
||||
assert config.should_strip_billing_metadata() is True
|
||||
|
||||
@pytest.mark.parametrize("model", DEEP_RESEARCH_MODELS)
|
||||
def test_deep_research_models_fall_back_to_translation(self, model: str):
|
||||
|
|
|
|||
|
|
@ -367,6 +367,18 @@ class TestDeepResearchKeepsState:
|
|||
|
||||
assert event.type == "response.swarm.llm_delta"
|
||||
|
||||
def test_non_string_delta_is_not_claimed(self):
|
||||
config = _responses_config("apodex-1-1-deep-research")
|
||||
assert (
|
||||
config._map_swarm_delta(
|
||||
{
|
||||
"type": "response.swarm.llm_delta",
|
||||
"swarm": {"data": {"channel": "output_text", "delta": None}},
|
||||
}
|
||||
)
|
||||
is None
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"event_type",
|
||||
(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue