mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
ocr: route mistral to Rust when enabled; keep bare-str file rejection
This commit is contained in:
parent
c697154bf3
commit
b370c1c191
1 changed files with 25 additions and 5 deletions
|
|
@ -10,7 +10,6 @@ import os
|
||||||
import re
|
import re
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from io import IOBase
|
from io import IOBase
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Coroutine, Dict, Optional, Union
|
from typing import Any, Coroutine, Dict, Optional, Union
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
@ -21,6 +20,7 @@ from litellm.constants import request_timeout
|
||||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
||||||
from litellm.llms.base_llm.ocr.transformation import BaseOCRConfig, OCRResponse
|
from litellm.llms.base_llm.ocr.transformation import BaseOCRConfig, OCRResponse
|
||||||
from litellm.llms.custom_httpx.llm_http_handler import BaseLLMHTTPHandler
|
from litellm.llms.custom_httpx.llm_http_handler import BaseLLMHTTPHandler
|
||||||
|
from litellm.ocr.rust_bridge import rust_ocr, rust_ocr_enabled
|
||||||
from litellm.types.router import GenericLiteLLMParams
|
from litellm.types.router import GenericLiteLLMParams
|
||||||
from litellm.utils import ProviderConfigManager, client
|
from litellm.utils import ProviderConfigManager, client
|
||||||
|
|
||||||
|
|
@ -262,6 +262,10 @@ def ocr(
|
||||||
if dynamic_api_base:
|
if dynamic_api_base:
|
||||||
api_base = dynamic_api_base
|
api_base = dynamic_api_base
|
||||||
|
|
||||||
|
# Optional Rust path: hand the whole Mistral OCR call to the Rust bridge.
|
||||||
|
if custom_llm_provider == "mistral" and rust_ocr_enabled():
|
||||||
|
return rust_ocr(model, document, api_key, api_base, kwargs)
|
||||||
|
|
||||||
# Get provider config
|
# Get provider config
|
||||||
ocr_provider_config: Optional[BaseOCRConfig] = (
|
ocr_provider_config: Optional[BaseOCRConfig] = (
|
||||||
ProviderConfigManager.get_provider_ocr_config(
|
ProviderConfigManager.get_provider_ocr_config(
|
||||||
|
|
@ -376,11 +380,13 @@ def convert_file_document_to_url_document(document: Dict[str, Any]) -> Dict[str,
|
||||||
with an inline base64 data URI.
|
with an inline base64 data URI.
|
||||||
|
|
||||||
Accepts document dicts like:
|
Accepts document dicts like:
|
||||||
{"type": "file", "file": "/path/to/document.pdf"} # file path string
|
|
||||||
{"type": "file", "file": Path("/path/to/doc.pdf")} # pathlib.Path
|
{"type": "file", "file": Path("/path/to/doc.pdf")} # pathlib.Path
|
||||||
{"type": "file", "file": <binary file-like object>} # file-like object (BinaryIO)
|
{"type": "file", "file": <binary file-like object>} # file-like object (BinaryIO)
|
||||||
{"type": "file", "file": b"raw bytes"} # raw bytes
|
{"type": "file", "file": b"raw bytes"} # raw bytes
|
||||||
|
|
||||||
|
Bare ``str`` paths are not accepted — pass a ``pathlib.Path`` or
|
||||||
|
``open(path, "rb")`` instead. See the str check below for the rationale.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
{"type": "document_url", "document_url": "data:<mime>;base64,<data>"}
|
{"type": "document_url", "document_url": "data:<mime>;base64,<data>"}
|
||||||
or {"type": "image_url", "image_url": "data:<mime>;base64,<data>"}
|
or {"type": "image_url", "image_url": "data:<mime>;base64,<data>"}
|
||||||
|
|
@ -389,14 +395,28 @@ def convert_file_document_to_url_document(document: Dict[str, Any]) -> Dict[str,
|
||||||
if file_input is None:
|
if file_input is None:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"document with type='file' must include a 'file' field containing "
|
"document with type='file' must include a 'file' field containing "
|
||||||
"a file path (str), pathlib.Path, file-like object, or bytes"
|
"a pathlib.Path, file-like object, or bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
file_bytes: bytes
|
file_bytes: bytes
|
||||||
mime_type: str = "application/octet-stream"
|
mime_type: str = "application/octet-stream"
|
||||||
file_name: Optional[str] = None
|
file_name: Optional[str] = None
|
||||||
|
|
||||||
if isinstance(file_input, (str, Path)):
|
if isinstance(file_input, str):
|
||||||
|
# Bare strings are rejected here. The OCR ``document`` accepts a
|
||||||
|
# ``{"type": "file", "file": <value>}`` shape, and when this helper
|
||||||
|
# runs in a proxy request handler ``<value>`` is attacker-controlled.
|
||||||
|
# Opening it as a path is an arbitrary local file read on the proxy
|
||||||
|
# host, which is then base64-encoded and forwarded to the OCR
|
||||||
|
# provider — an exfiltration primitive.
|
||||||
|
raise ValueError(
|
||||||
|
"OCR file input does not accept bare str values. Pass bytes, "
|
||||||
|
"a pathlib.Path, or a file-like object. To OCR a local file "
|
||||||
|
"from a path, call open(path, 'rb') yourself."
|
||||||
|
)
|
||||||
|
if isinstance(file_input, os.PathLike):
|
||||||
|
# os.PathLike (pathlib.Path and custom __fspath__ classes) is a
|
||||||
|
# Python-level type that HTTP form values can't fabricate.
|
||||||
file_path = str(file_input)
|
file_path = str(file_input)
|
||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
raise FileNotFoundError(f"File not found: {file_path}")
|
raise FileNotFoundError(f"File not found: {file_path}")
|
||||||
|
|
@ -417,7 +437,7 @@ def convert_file_document_to_url_document(document: Dict[str, Any]) -> Dict[str,
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Unsupported file input type: {type(file_input)}. "
|
f"Unsupported file input type: {type(file_input)}. "
|
||||||
"Expected str (file path), pathlib.Path, bytes, or a file-like object."
|
"Expected pathlib.Path, bytes, or a file-like object."
|
||||||
)
|
)
|
||||||
|
|
||||||
if not file_bytes:
|
if not file_bytes:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue