mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-25 01:02:15 +00:00
Each route now has litellm/rust_bridge/<route>/{entrypoints,callbacks}.py and a
public dispatch module (litellm/chat_completions/dispatch.py,
litellm/responses/dispatch.py, litellm/messages/dispatch.py) that binds the
public call to the legacy Python signature, builds a frozen request, and asks
the runtime to pick Rust or Python from the catalog. The legacy implementations
stay in litellm/main.py, litellm/responses/main.py and the anthropic messages
handler, and litellm/__init__.py re-exports the dispatch names over them the
same way it already does for ocr
The per-handler shims in rust_bridge/chat_completions/native.py and
rust_bridge/messages/native.py are removed along with their call sites in the
anthropic and bedrock chat handlers and the http handler. The exception
mapping that every callbacks module repeated moves to rust_bridge/failures.py
and the signature binding helpers to rust_bridge/public_call.py
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
"""Bind a public LiteLLM call to its legacy Python signature without running it."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import inspect
|
|
from collections.abc import Callable, Mapping, Sequence
|
|
from typing import Final, cast # noqa: TID251 # narrows caller-owned containers without copying them
|
|
|
|
|
|
def signature(legacy: Callable[..., object]) -> inspect.Signature:
|
|
return inspect.signature(legacy)
|
|
|
|
|
|
def bind(
|
|
legacy: inspect.Signature, args: tuple[object, ...], kwargs: Mapping[str, object]
|
|
) -> Mapping[str, object] | None:
|
|
try:
|
|
bound: Final = legacy.bind(*args, **kwargs)
|
|
except TypeError:
|
|
return None
|
|
bound.apply_defaults()
|
|
return bound.arguments
|
|
|
|
|
|
def optional_str(value: object) -> str | None:
|
|
return value if isinstance(value, str) else None
|
|
|
|
|
|
def optional_bool(value: object) -> bool | None:
|
|
return value if isinstance(value, bool) else None
|
|
|
|
|
|
def optional_mapping(value: object) -> Mapping[str, object] | None:
|
|
if not isinstance(value, Mapping):
|
|
return None
|
|
return cast("Mapping[str, object]", value) # cast-ok: the same caller-owned object is handed on unchanged
|
|
|
|
|
|
def optional_sequence(value: object) -> Sequence[object] | None:
|
|
if isinstance(value, str | bytes) or not isinstance(value, Sequence):
|
|
return None
|
|
return cast("Sequence[object]", value) # cast-ok: the same caller-owned object is handed on unchanged
|