mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
* feat(decisions): send images to Cloudflare Clef OpenAI-format input_image parts and the System One images field now reach Cloudflare clef and clef-flash in its images field, with remote URLs downloaded and inlined first. Providers that cannot take images drop them under drop_params and answer 400 otherwise. * fix(decisions): follow drop_params for images and use the call timeout for image downloads * fix(decisions): drop a malformed images entry on its own under drop_params * fix(decisions): refuse images next to input whatever drop_params says * fix(decisions): bound clef image fetches, honor drop_params for images, and log caller URLs Refuse more than 4 images for Cloudflare clef before any download, keep the caller's timeout as one deadline across image fetch retries, accept images next to input under drop_params, validate image strings and objects, and pass the caller's image URLs (not inlined bytes) to logging callbacks. * fix(decisions): check input_image URLs and clef image sizes * fix(decisions): accept data URL media type parameters and check clef image types * fix(decisions): count clef images after dropping unsupported types and flag clef vision --------- Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
125 lines
3.8 KiB
Python
125 lines
3.8 KiB
Python
from collections.abc import Mapping
|
|
from typing import Final
|
|
|
|
import httpx
|
|
|
|
from litellm.decisions.call import (
|
|
DecisionsAudioClips,
|
|
DecisionsCall,
|
|
DecisionsImages,
|
|
DecisionsVideoClips,
|
|
SystemOneQuestions,
|
|
SystemOneRequestFields,
|
|
asend,
|
|
prepare_call,
|
|
reject_other_format,
|
|
send,
|
|
)
|
|
from litellm.types.decisions import DecisionsJSON, DecisionsResponse
|
|
from litellm.utils import client # pyright: ignore[reportUnknownVariableType] # client is an untyped decorator
|
|
|
|
|
|
def _prepare_systemone_call(
|
|
*,
|
|
model: str,
|
|
state: DecisionsJSON | None,
|
|
questions: SystemOneQuestions | None,
|
|
images: DecisionsImages | None,
|
|
safety_identifier: str | None,
|
|
audio: DecisionsAudioClips | None,
|
|
videos: DecisionsVideoClips | None,
|
|
api_key: str | None,
|
|
api_base: str | None,
|
|
timeout: float | httpx.Timeout | None,
|
|
custom_llm_provider: str | None,
|
|
extra_headers: Mapping[str, str] | None,
|
|
kwargs: Mapping[str, object],
|
|
) -> DecisionsCall:
|
|
reject_other_format(model=model, kwargs=kwargs, field_name="input", other_function="decisions")
|
|
return prepare_call(
|
|
model=model,
|
|
fields=SystemOneRequestFields(state=state, questions=questions, images=images, audio=audio, videos=videos),
|
|
safety_identifier=safety_identifier,
|
|
api_key=api_key,
|
|
api_base=api_base,
|
|
timeout=timeout,
|
|
custom_llm_provider=custom_llm_provider,
|
|
extra_headers=extra_headers,
|
|
kwargs=kwargs,
|
|
)
|
|
|
|
|
|
def _systemone_response(response: object) -> DecisionsResponse:
|
|
assert isinstance(response, DecisionsResponse)
|
|
return response
|
|
|
|
|
|
@client
|
|
async def asystemone(
|
|
model: str,
|
|
state: DecisionsJSON | None = None,
|
|
questions: SystemOneQuestions | None = None,
|
|
api_key: str | None = None,
|
|
api_base: str | None = None,
|
|
timeout: float | httpx.Timeout | None = None,
|
|
custom_llm_provider: str | None = None,
|
|
extra_headers: Mapping[str, str] | None = None,
|
|
safety_identifier: str | None = None,
|
|
audio: DecisionsAudioClips | None = None,
|
|
videos: DecisionsVideoClips | None = None,
|
|
images: DecisionsImages | None = None,
|
|
**kwargs: object, # kwargs-ok: litellm_params forwarded by @client
|
|
) -> DecisionsResponse:
|
|
call: Final = _prepare_systemone_call(
|
|
model=model,
|
|
state=state,
|
|
questions=questions,
|
|
images=images,
|
|
safety_identifier=safety_identifier,
|
|
audio=audio,
|
|
videos=videos,
|
|
api_key=api_key,
|
|
api_base=api_base,
|
|
timeout=timeout,
|
|
custom_llm_provider=custom_llm_provider,
|
|
extra_headers=extra_headers,
|
|
kwargs=kwargs,
|
|
)
|
|
return _systemone_response(await asend(call))
|
|
|
|
|
|
@client
|
|
def systemone(
|
|
model: str,
|
|
state: DecisionsJSON | None = None,
|
|
questions: SystemOneQuestions | None = None,
|
|
api_key: str | None = None,
|
|
api_base: str | None = None,
|
|
timeout: float | httpx.Timeout | None = None,
|
|
custom_llm_provider: str | None = None,
|
|
extra_headers: Mapping[str, str] | None = None,
|
|
safety_identifier: str | None = None,
|
|
audio: DecisionsAudioClips | None = None,
|
|
videos: DecisionsVideoClips | None = None,
|
|
images: DecisionsImages | None = None,
|
|
**kwargs: object, # kwargs-ok: litellm_params forwarded by @client
|
|
) -> DecisionsResponse:
|
|
call: Final = _prepare_systemone_call(
|
|
model=model,
|
|
state=state,
|
|
questions=questions,
|
|
images=images,
|
|
safety_identifier=safety_identifier,
|
|
audio=audio,
|
|
videos=videos,
|
|
api_key=api_key,
|
|
api_base=api_base,
|
|
timeout=timeout,
|
|
custom_llm_provider=custom_llm_provider,
|
|
extra_headers=extra_headers,
|
|
kwargs=kwargs,
|
|
)
|
|
return _systemone_response(send(call))
|
|
|
|
|
|
__all__ = ["asystemone", "systemone"]
|