fix(types): keep text completion, batch ids and guardrail callback on main's code

This commit is contained in:
mateo-berri 2026-10-29 01:23:13 -07:00
parent 519d8575f7
commit 8682c5d4dd
5 changed files with 37 additions and 17 deletions

View file

@ -407,16 +407,14 @@ class RedisSemanticCache(BaseCache):
# Convert string representation to Python object
try:
cached_response = json.loads(response_text)
return json.loads(response_text)
except json.JSONDecodeError:
try:
cached_response = ast.literal_eval(response_text)
return ast.literal_eval(response_text)
except (ValueError, SyntaxError) as e:
print_verbose(f"Error parsing cached response: {e}")
return None
return cached_response
def set_cache(self, key: str, value: object, **kwargs) -> None:
"""
Store a value in the semantic cache.

View file

@ -618,12 +618,12 @@ class LiteLLMResponseObjectHandler:
choices_list: Final[list[TextChoices]] = []
# Convert each choice to TextChoices
for choice in response.choices:
for choice in response["choices"]:
text_choices = TextChoices()
text_choices["text"] = choice.message.content
text_choices["index"] = choice.index
text_choices["text"] = choice["message"]["content"]
text_choices["index"] = choice["index"]
text_choices["logprobs"] = transformed_logprobs
text_choices["finish_reason"] = choice.finish_reason
text_choices["finish_reason"] = choice["finish_reason"]
choices_list.append(text_choices)
text_completion_response["choices"] = choices_list

View file

@ -1380,10 +1380,7 @@ async def resolve_input_file_id_to_unified(response, prisma_client) -> None:
pass
async def resolve_output_file_ids_to_unified(
response: "LiteLLMBatch",
prisma_client: "PrismaClient | None",
) -> None:
async def resolve_output_file_ids_to_unified(response, prisma_client) -> None:
"""
If the batch response contains raw provider output_file_id or error_file_id
(not already unified IDs), look up the corresponding unified file IDs from
@ -1392,9 +1389,7 @@ async def resolve_output_file_ids_to_unified(
if not prisma_client:
return
for attr in ("output_file_id", "error_file_id"):
if not hasattr(response, attr):
continue
raw_id = response.output_file_id if attr == "output_file_id" else response.error_file_id
raw_id = getattr(response, attr, None)
if not raw_id or is_base64_encoded_unified_file_id(raw_id):
continue
try:

View file

@ -35,7 +35,6 @@ from litellm.types.llms.base import LiteLLMBaseModel
from litellm.types.router_weights import RouterWeights
if TYPE_CHECKING:
from litellm.integrations.custom_guardrail import CustomGuardrail
from litellm.router import Router
from .completion import CompletionRequest
@ -1090,7 +1089,7 @@ class GuardrailTypedDict(TypedDict, total=False):
guardrail_name: Required[str]
litellm_params: Required[GuardrailLiteLLMParams]
callback: "ReadOnly[CustomGuardrail | None]" # The CustomGuardrail instance
callback: Any # The CustomGuardrail instance
id: str | None # Unique identifier for the guardrail deployment

View file

@ -5,6 +5,7 @@ import pytest
import litellm
from litellm import text_completion
from litellm.llms.custom_llm import CustomLLM
from litellm.types.utils import ModelResponse, TextCompletionResponse, Usage
from litellm.utils import LiteLLMResponseObjectHandler
@ -1298,3 +1299,30 @@ def mock_post(*args, **kwargs):
"usage": {"prompt_tokens": 2, "total_tokens": 18, "completion_tokens": 16},
}
return mock_response
def test_text_completion_reads_a_custom_provider_dict_reply(monkeypatch: pytest.MonkeyPatch) -> None:
class DictReplyLLM(CustomLLM):
def completion(self, *args: object, **kwargs: object) -> dict[str, object]:
return {
"id": "dict-reply",
"object": "chat.completion",
"created": 1,
"model": "x",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "hi from a dict reply"},
"finish_reason": "stop",
}
],
}
monkeypatch.setattr(litellm, "custom_provider_map", [{"provider": "dictreply", "custom_handler": DictReplyLLM()}])
monkeypatch.setattr(litellm, "provider_list", [*litellm.provider_list, "dictreply"])
monkeypatch.setattr(litellm, "_custom_providers", [*litellm._custom_providers, "dictreply"])
response = text_completion(model="dictreply/x", prompt="hi")
assert response.choices[0].text == "hi from a dict reply"
assert response.choices[0].finish_reason == "stop"