mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(guardrails): carry Anthropic url and file image sources through to guardrails
_image_sources returned source["data"] only. An Anthropic image block has three
shapes (types/llms/anthropic.py:259) and only the base64 one carries "data", so
{"type": "url", "url": ...} yielded nothing and the image never reached any
guardrail at all.
This is not Bedrock-specific. Five guardrails consume
GenericGuardrailAPIInputs["images"] (vigil_guard, custom_code, deepkeep, straiker,
generic_guardrail_api) and every one of them was blind to url sources on
/v1/messages.
base64 now returns a data URI rather than the bare payload. A consumer otherwise
has no way to recover media_type, and an API like Bedrock's ApplyGuardrail needs
the format to build its request.
The file shape stays unresolvable here: the bytes live behind the Files API and
this extractor has no client to fetch them. Documented rather than silently
dropped, so a consumer treating a missing entry as "no image to scan" is a known
gap and not a surprise.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
735e560c11
commit
589086dc5b
1 changed files with 30 additions and 2 deletions
|
|
@ -788,12 +788,40 @@ class AnthropicMessagesHandler(BaseTranslation):
|
|||
|
||||
@staticmethod
|
||||
def _image_sources(block: Mapping[str, object]) -> tuple[str, ...]:
|
||||
"""Normalize an Anthropic image block into strings a guardrail can read.
|
||||
|
||||
`source` is one of three shapes (types/llms/anthropic.py:259):
|
||||
|
||||
{"type": "base64", "media_type": "image/png", "data": "<b64>"}
|
||||
{"type": "url", "url": "https://..."}
|
||||
{"type": "file", "file_id": "..."}
|
||||
|
||||
base64 is returned as a data URI rather than the bare payload: consumers of
|
||||
``GenericGuardrailAPIInputs["images"]`` otherwise have no way to know the
|
||||
format, and an API like Bedrock's ApplyGuardrail requires it. url is passed
|
||||
through so the consumer can fetch it under its own SSRF policy.
|
||||
|
||||
file is not resolvable here (the bytes live behind the Files API), so it
|
||||
yields nothing. That is a silent gap for any consumer that treats a missing
|
||||
entry as "no image to scan"; scanning a file_id needs a fetch this extractor
|
||||
has no client for.
|
||||
"""
|
||||
source: Final = block.get("source")
|
||||
if not isinstance(source, Mapping):
|
||||
return ()
|
||||
# Could be base64 or url
|
||||
|
||||
source_type: Final = source.get("type")
|
||||
if source_type == "url":
|
||||
url: Final = source.get("url")
|
||||
return (url,) if isinstance(url, str) and url else ()
|
||||
|
||||
data: Final = source.get("data")
|
||||
return (data,) if data else ()
|
||||
if not isinstance(data, str) or not data:
|
||||
return ()
|
||||
media_type: Final = source.get("media_type")
|
||||
if isinstance(media_type, str) and media_type:
|
||||
return (f"data:{media_type};base64,{data}",)
|
||||
return (data,)
|
||||
|
||||
async def _apply_guardrail_responses_to_input(
|
||||
self,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue