mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-13 23:11:40 +00:00
fix(http_handler): add _sync_file_chunks to avoid line-based iteration for binary files
This commit is contained in:
parent
fd74311d29
commit
cc6406f16c
1 changed files with 26 additions and 3 deletions
|
|
@ -8,6 +8,7 @@ from typing import (
|
|||
AsyncIterator,
|
||||
Coroutine,
|
||||
Dict,
|
||||
Iterator,
|
||||
List,
|
||||
Literal,
|
||||
Optional,
|
||||
|
|
@ -153,6 +154,23 @@ else:
|
|||
LiteLLMLoggingObj = Any
|
||||
|
||||
|
||||
def _sync_file_chunks(fp: Any, chunk_size: int = 65536) -> Iterator[bytes]:
|
||||
"""Sync generator that reads a file-like object in explicit fixed-size chunks.
|
||||
|
||||
Passing an IO object directly as ``content=`` to httpx's **sync** client causes
|
||||
httpx to wrap it in an ``IteratorByteStream`` that uses Python's built-in file
|
||||
iteration (``__iter__`` / ``readline``). For binary files with few or no newline
|
||||
bytes (PDFs, images, etc.) a single ``readline()`` call reads the entire file as
|
||||
one chunk, defeating the streaming intent. Using this generator instead forces
|
||||
fixed-size reads regardless of file content.
|
||||
"""
|
||||
while True:
|
||||
chunk = fp.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
yield chunk
|
||||
|
||||
|
||||
async def _async_file_chunks(
|
||||
fp: Any, chunk_size: int = 65536
|
||||
) -> AsyncGenerator[bytes, None]:
|
||||
|
|
@ -3004,7 +3022,10 @@ class BaseLLMHTTPHandler:
|
|||
"timeout": timeout,
|
||||
}
|
||||
if hasattr(upload_data, "read") and hasattr(upload_data, "seek"):
|
||||
upload_kwargs["content"] = upload_data
|
||||
# Use explicit fixed-size chunks so httpx does not fall back to
|
||||
# Python's line-based __iter__ (which reads entire binary files as
|
||||
# one chunk when there are few newlines).
|
||||
upload_kwargs["content"] = _sync_file_chunks(upload_data)
|
||||
else:
|
||||
upload_kwargs["data"] = upload_data
|
||||
upload_response = getattr(sync_httpx_client, upload_method)(
|
||||
|
|
@ -3044,11 +3065,13 @@ class BaseLLMHTTPHandler:
|
|||
if hasattr(transformed_request, "read") and hasattr(
|
||||
transformed_request, "seek"
|
||||
):
|
||||
# Stream the IO object without loading it fully into memory
|
||||
# Use explicit fixed-size chunks so httpx does not fall back to
|
||||
# Python's line-based __iter__ (which reads entire binary files as
|
||||
# one chunk when there are few newlines).
|
||||
upload_kwargs: Dict[str, Any] = {
|
||||
"url": api_base,
|
||||
"headers": headers,
|
||||
"content": transformed_request,
|
||||
"content": _sync_file_chunks(transformed_request),
|
||||
"timeout": timeout,
|
||||
}
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue