Commit graph

34 commits

Author SHA1 Message Date
yuneng-jiang
6a0d03914c
test: drop the cwd-relative sys.path.insert calls from the test suite (#37802)
* test: drop the cwd-relative sys.path.insert calls from the test suite

TQ003 stands at 1,077 across 1,058 files, and 1,015 of them are the same shape:
sys.path.insert(0, os.path.abspath("../..")) and its deeper siblings. The
argument resolves against the working directory rather than the file, so from
the repo root, where every job runs pytest, it inserts the directory two levels
above the checkout. It has never pointed at litellm. The package is installed
into the environment anyway, which is what actually makes the import work, and
what the rule's message has said all along.

Removing them leaves 1,634 imports of sys and os with no remaining reference,
and those go too, except where another test module imports the name back out of
the file. The rest of TQ003 is 62 call sites that resolve against __file__ or a
variable, which are a different question and are left alone.

Collection is identical either way: 45,871 tests and the same 51 pre-existing
collection errors before and after, and ruff reports no new undefined name.

* test: drop the duplicate imports the sys.path sweep exposed to F811

* test(pre-call-utils): restore the os import the new bedrock tests need
2026-08-22 09:25:58 -07:00
yuneng-jiang
de1bc29dc7
test: unshadow the module handles the F811 sweep left behind (#37914)
* test: unshadow the module handles the F811 sweep left behind, and pin the two live tests that went red with it

The F811 sweep in #37878 removed the fixture-local `import litellm` from four
conftests, but the bare `import litellm.proxy.proxy_server` a few lines below
still binds `litellm` as a function local, so `importlib.reload(litellm)` runs
before the name is assigned and every test in those directories errors at
setup. The `hasattr` guard on the line above already proves the module is
loaded, so the import only ever bound the name. Drop it, and enable F823 in
ruff-tests.toml, which flags all four sites at the failing line and would have
blocked the sweep

The same sweep renamed the `check_non_streaming_response` parameter but left
one read of `completion`, which now resolves to `litellm.completion`, and
removed an import whose side effect was the only thing making
`litellm.proxy.proxy_server` reachable in the moderation hook test. That test
already takes `monkeypatch`, so patch the router through it and stop leaking
the router into later tests

`test_content_policy_exception_openai` passed vacuously until #37887 turned it
into a real `pytest.raises`, and OpenAI no longer rejects a lyrics prompt with
a content policy error. Inject an AsyncOpenAI client whose transport answers
with OpenAI's own `content_policy_violation` rejection so the mapping to
ContentPolicyViolationError is exercised every run

`test_async_create_batch` hit a 409 cancelling a batch OpenAI had already
marked failed. The cancel step tolerated a completed batch but not a failed
one. Fold both guards into one helper that tolerates a failed batch only when
OpenAI's recorded error is the org's enqueued token limit, and prints the
batch's errors so the reason is in the log either way

* test: close the injected AsyncOpenAI client after the content policy test

* chore(lint): ratchet TQ005 down by the global mutation this branch cleared

* chore(lint): ratchet TQ005 to 2660 on the merged tree

* chore(lint): ratchet TQ005 to 2561 on the merged tree

* chore(lint): ratchet TQ005 to 2548 on the merged tree
2026-08-22 16:16:38 +00:00
mubashir1osmani
85840aef51
fix(vertex_ai/files): single media upload for batch files to fix 499s on large uploads (#31653)
* fix(vertex_ai/files): upload batch files in a single media request to fix 499s on large uploads

PR #31036 switched the vertex batch file upload from a single GCS media
upload to a chunked resumable session. The resumable path sends the body as
many sequential PUTs, each waiting a full round-trip to GCS before the next,
so a multi-GB upload accumulates hundreds of round-trips and overruns the
client/load-balancer request timeout, surfacing as 499s (client closed
connection) on files as small as 500MB. This was a regression from the
last-known-good commit, where the upload completed as one continuous request.

Revert the batch upload to a single uploadType=media request, but stage the
transformed payload to a temp file first so peak memory stays bounded (the
goal of the resumable rewrite) without the per-chunk round-trips. The temp
file is closed deterministically (TemporaryFile unlinks on close), not left
to the GC. The now-unused resumable chunked-upload plumbing is removed.

Also swap the per-row transform's stdlib json for orjson (parse + serialize),
which is ~4x faster on this hot path; the streaming body now emits compact
orjson bytes.

The request stays synchronous, so the returned file object is real and
POST /v1/batches keeps working immediately against the uploaded object.

Tests: single media request carries the whole payload with a real
Content-Length (no chunked transfer-encoding); failed upload raises; the
staged temp file is closed deterministically; byte-for-byte transform parity.

* test(vertex_ai/files): mock single media upload POST instead of removed resumable method

test_avertex_batch_prediction patched BaseLLMHTTPHandler._aresumable_chunked_upload, which was removed when the batch jsonl upload moved from a chunked resumable GCS session to a single uploadType=media request. Patch the raw httpx.AsyncClient.post that _astage_and_upload_media issues so the real staging, upload and response transform run while the GCS object response is mocked, and assert the media URL and Content-Type.

* fix(vertex_ai/files): forward request timeout to media upload, drop orjson, sort imports

Forward the per-request timeout through _stage_and_upload_media /
_astage_and_upload_media to the GCS POST. Every other upload branch forwards
it; the new media path was dropping it, so a caller-provided timeout was
silently ignored (the files path passes 600s by default, but a custom
request_timeout would not have reached this upload). Regression test asserts
the resolved timeout reaches the request (mutation-verified).

Revert the orjson swap in the batch transform: importing orjson at module load
in this core-path file broke `import litellm` on environments without orjson
(the Windows import test). Back to stdlib json; the upload leg dominates large
uploads anyway, so the transform-side win was marginal.

Fix import ordering in llm_http_handler.py (I001) introduced by the new imports.

* fix(vertex_ai/files): stream batch upload to GCS instead of staging to a temp file

Addresses a disk-exhaustion concern: staging the full transformed batch body to
a local temp file before the GCS request meant an authenticated user could fill
the proxy's temp volume with large concurrent uploads (on top of Starlette's
input spool).

GCS's simple/media upload accepts chunked transfer-encoding, so stream the
transform straight to the single media request instead. Each block is produced
on a worker thread (the transform never runs on the event loop) and sent
chunked, so the body is neither buffered in memory nor written to disk, and the
upload is still one continuous request (no per-chunk round-trips, no 499). Drops
the temp-file staging, the tempfile/IO imports, and Content-Length computation.

Regression test asserts the upload streams (chunked transfer-encoding, no
Content-Length) and creates no temp file; mutation-verified that reintroducing
staging fails it.
2026-06-29 17:31:32 -07:00
mubashir1osmani
56825926af
fix(vertex/files): stream OpenAI->Vertex batch JSONL uploads (#31036)
* fix(vertex/files): stream OpenAI->Vertex batch JSONL uploads to fix OOM on large files

Large (1GB+) batch JSONL uploads to Vertex AI / GCS caused OOM or killed the worker
because the request body was buffered and multiplied 2-3x in size. The create-file
path is now streaming end-to-end: transform_create_file_request returns a
ResumableChunkedUploadConfig carrying a lazy _OpenAIToVertexBatchUploadStream, and the
HTTP handler opens a GCS resumable session and PUTs the body in bounded 8 MiB chunks
(Content-Range, 308 between chunks) so the transformed payload is never held in full.
The proxy /v1/files endpoint streams from Starlette's spooled upload handle instead of
reading the whole body, and batch rate limiting counts tokens and models in a single
streaming pass.

Only gcs_bucket_name is supported for the GCS target; the legacy bucket_name key is
intentionally not read.

Also removes the unreachable VertexAIFilesHandler create path and everything only it
kept alive (VertexAIJsonlFilesTransformation, _stream_openai_jsonl_to_vertex, the legacy
transform helpers), plus the orphaned batch_utils helpers the streaming rewrite replaced.

* fix(batches): return original JSONL on unparseable row to avoid silent batch truncation

The streaming rewrite of replace_model_in_jsonl accumulated physical lines and
skipped a row on JSONDecodeError to support multi-line objects, but a genuinely
malformed or truncated row never completes: it poisons the buffer, swallows every
following row, and the function still returned the partial rewrite (the rows before
the bad one, already model-rewritten) as if the batch were complete. That turned the
pre-rewrite behavior of returning the original file unchanged (so the provider rejects
the bad batch loudly) into a silent partial submission.

Restore the original-content fallback: when an unparseable remainder is left after the
loop, return the original file_content (rewinding a consumed seekable source) instead of
the truncated output. The multi-line happy path is unchanged.

* test(batches): mock resumable GCS upload in vertex batch prediction test

The vertex batch file-create path now streams to a GCS resumable session via
_aresumable_chunked_upload (httpx send) instead of AsyncHTTPHandler.post, so the
existing test's post mock no longer intercepted the upload and a real request hit
GCS (401). Mock _aresumable_chunked_upload to return the GCS object response; the
resumable protocol itself is covered in test_vertex_ai_files_streaming.py.

* fix(batches): resilient per-row token accounting; no hard-block on count failure

The batch input-file pass iterated a generator whose json.loads raised on a
malformed line; the outer except caught it and stopped the loop, so any body.model
on rows after a bad line was never collected and the model allowlist check ran
against a partial set. It also hard-blocked the batch with a 400 whenever token
counting raised, a backwards-incompatible change from the prior swallow-and-proceed
behavior that breaks legitimate rows the token counter cannot measure (e.g. some
multimodal content).

Iterate the JSONL line-by-line and account each row independently. A malformed line
is skipped (its request cannot run upstream anyway) and a row the counter cannot
measure falls back to a conservative size-based estimate. The loop never aborts, so
the allowlist check always sees every parseable model, and the token total is never
zeroed, so a crafted uncountable row still cannot evade the TPM limit, without
hard-rejecting a legitimate batch.

* perf(vertex/files): unblock async upload; drop empty finalize; widen batch MIME types

Three review follow-ups on the resumable batch upload:
- _aresumable_chunked_upload pulled chunks from a synchronous generator that runs
  the per-row transform inline on the event loop thread, blocking other requests
  between PUTs on large uploads. Each chunk is now produced via asyncio.to_thread.
- _iter_resumable_chunks no longer yields a trailing empty chunk, so an exactly
  chunk-aligned upload finalizes on its last data chunk instead of an extra
  zero-byte PUT; a 0-byte stream still finalizes via the caller's empty request.
- valid_content_type now accepts the MIME types clients label .jsonl batch uploads
  with (text/plain, application/json, ndjson, ...), so such a batch file no longer
  silently bypasses the streaming path into the buffered media upload.

* fix(vertex/files): keep legacy bucket_name as GCS bucket fallback

The rename to gcs_bucket_name dropped the legacy bucket_name key entirely, so an SDK caller passing bucket_name to a Vertex AI file create/retrieve/content call with GCS_BUCKET_NAME unset got ValueError("GCS bucket_name is required") where it previously resolved the bucket. _get_configured_bucket_name now reads gcs_bucket_name, then bucket_name, then the env var, and bucket_name is restored to OPTIONAL_KWARGS_KEYS so it survives get_litellm_params on the retrieve and content paths. gcs_bucket_name keeps precedence when both are present

* style: sort imports in llm_http_handler to satisfy I001 budget

---------

Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
2026-06-24 13:19:57 -07:00
Mateo Wang
6a9f542f81
test: stabilize batch VCR coverage and stop live upload/network leaks (#29477)
* test: stabilize batch VCR coverage

* test: replay bedrock batch s3 uploads

* test: stop batch tests leaking live uploads

* test: keep bedrock batch workflow off live s3

* test: mock bedrock batch workflow network

* test: accept realtime guardrail refusal wording

* test: update gemini thought signature model

* test: quiet logging worker atexit flush

* test: address Greptile review on batch VCR fixes

Handle content= bodies in the bedrock batch post stub so payload
extraction does not raise a TypeError when a request omits json and
data. Restore litellm list state faithfully by preserving None instead
of coercing it to an empty list, so callbacks that start as None are not
turned into [] after a test. Set logging.raiseExceptions inside the try
block in the atexit flush so the finally always restores the previous
value.

* test: scope atexit logging suppression to the drain loop

Wrap only the queue drain loop in LoggingWorker._flush_on_exit with the
logging.raiseExceptions toggle so the process-wide global is suppressed for
the smallest possible window, keeping other threads' logging error reporting
intact outside the loop.

* test: cover atexit flush error-swallow branch in LoggingWorker

The _flush_on_exit drain loop was wrapped in a try/finally to scope the
logging.raiseExceptions toggle, which reindented the existing edge-case
branches into the diff and dropped patch coverage below target. Add a
regression test that enqueues a coroutine which raises during the atexit
flush and asserts the failure is swallowed while later queued events are
still drained, exercising the silent-failure path directly.
2026-06-02 16:11:52 -07:00
mateo-berri
456cb495de Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_scim_virtual_key_deactivation 2026-05-01 20:29:19 -07:00
Claude
dc123d9f12
test(vertex_batch): set is_redirect=False on mocked AsyncHTTPHandler responses
Some checks are pending
Unit Tests: Caching (Redis) / caching-redis (push) Waiting to run
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / schema-migration (push) Blocked by required conditions
Unit Tests: Security / security (push) Waiting to run
The redirect-following added to async_safe_get checks response.is_redirect
on every hop. Two vertex batch tests stub AsyncHTTPHandler.get with a bare
MagicMock, whose default-truthy is_redirect made the redirect path fire,
then crashed in httpx.URL().join() because headers.get('location') was
also a MagicMock instead of a string. Set is_redirect=False explicitly so
the mocked response models a non-redirect terminal response.

Also tighten _extract_redirect_url to raise SSRFError on non-string
Location values (defense-in-depth — a real httpx Response always returns
str|None, but this avoids a confusing TypeError if anything else ever
slips through).

This is an unrelated CI fix piggybacked on the SCIM PR to unblock the
batches test suite.
2026-04-30 06:22:49 +00:00
Yuneng Jiang
5975d69ea5
test(vertex-batches): set is_redirect=False on mocked retrieve response
After dedaf74a5e, _async_retrieve_batch wraps the GET in async_safe_get,
which inspects response.is_redirect. test_avertex_batch_prediction's
MagicMock response left is_redirect unset, so it auto-generated a truthy
mock, sent the redirect-follow loop into _extract_redirect_url, and
httpx.URL().join(<MagicMock>) raised TypeError. Set is_redirect=False
so the response is treated as terminal.
2026-04-29 19:01:49 -07:00
Krrish Dholakia
c7e2bfc577 fix: cleanup tests 2026-03-30 16:24:35 -07:00
Krrish Dholakia
9e070143fb test: update key names 2026-03-28 21:13:16 -07:00
Krrish Dholakia
cdcab8a243 refactor: cleanup deprecated models 2026-03-28 19:39:11 -07:00
yuneng-jiang
f2edc52cef Fix flaky batch tests: mock vertex auth and skip on DNS failure
- test_avertex_batch_prediction: Add google.auth.default mock and env vars
  so the test doesn't depend on real GCP credentials (was already a unit
  test with mocked HTTP, just missing auth mock)
- test_async_create_batch[openai]: Add DNS pre-check that skips gracefully
  when api.openai.com is unreachable instead of failing after 4 retries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 18:37:40 -07:00
Ephrim Stanley
b16397ae1a Managed batches fixes for Gemini/Vertex 2026-02-28 20:45:16 -05:00
Sameer Kankute
6a3f0a8baf Add output file id in managed objects for batches 2025-12-16 15:52:07 +05:30
naaa760
2cf86e8ef8 new mocked 2025-11-25 17:28:02 +05:30
Ishaan Jaff
3e13f8dd0f openai.ConflictError 2025-07-12 17:07:21 -07:00
Krish Dholakia
6ba3c4a4f8
VertexAI non-jsonl file storage support (#9781)
* test: add initial e2e test

* fix(vertex_ai/files): initial commit adding sync file create support

* refactor: initial commit of vertex ai non-jsonl files reaching gcp endpoint

* fix(vertex_ai/files/transformation.py): initial working commit of non-jsonl file call reaching backend endpoint

* fix(vertex_ai/files/transformation.py): working e2e non-jsonl file upload

* test: working e2e jsonl call

* test: unit testing for jsonl file creation

* fix(vertex_ai/transformation.py): reset file pointer after read

allow multiple reads on same file object

* fix: fix linting errors

* fix: fix ruff linting errors

* fix: fix import

* fix: fix linting error

* fix: fix linting error

* fix(vertex_ai/files/transformation.py): fix linting error

* test: update test

* test: update tests

* fix: fix linting errors

* fix: fix test

* fix: fix linting error
2025-04-09 14:01:48 -07:00
Ishaan Jaff
1bac18a98c cleanup_azure_files 2025-02-15 15:32:42 -08:00
Ishaan Jaff
0ffd99afff test_avertex_batch_prediction 2025-02-14 22:03:24 -08:00
Ishaan Jaff
0bdebe36d8 test fix openai batches and files 2025-02-14 19:03:30 -08:00
Ishaan Jaff
8a235e7d38
(Refactor / QA) - Use LoggingCallbackManager to append callbacks and ensure no duplicate callbacks are added (#8112)
* LoggingCallbackManager

* add logging_callback_manager

* use logging_callback_manager

* add add_litellm_failure_callback

* use add_litellm_callback

* use add_litellm_async_success_callback

* add_litellm_async_failure_callback

* linting fix

* fix logging callback manager

* test_duplicate_multiple_loggers_test

* use _reset_all_callbacks

* fix testing with dup callbacks

* test_basic_image_generation

* reset callbacks for tests

* fix check for _add_custom_logger_to_list

* fix test_amazing_sync_embedding

* fix _get_custom_logger_key

* fix batches testing

* fix _reset_all_callbacks

* fix _check_callback_list_size

* add callback_manager_test

* fix test gemini-2.0-flash-thinking-exp-01-21
2025-01-30 19:35:50 -08:00
Ishaan Jaff
5a7dc11432 test fix test_async_create_batch use only openai for testing, hitting azure limits 2025-01-28 22:17:49 -08:00
Ishaan Jaff
b60efd4646 fix test_async_create_batch 2025-01-22 22:15:49 -08:00
Ishaan Jaff
13f364682d
(Feat - Batches API) add support for retrieving vertex api batch jobs (#7661)
* add _async_retrieve_batch

* fix aretrieve_batch

* fix _get_batch_id_from_vertex_ai_batch_response

* fix batches docs
2025-01-09 18:35:03 -08:00
Ishaan Jaff
3110bb0723 use pathrise-convert-1606954137718 2025-01-05 14:14:43 -08:00
Ishaan Jaff
137879ffea vertex testing use pathrise-convert-1606954137718 2025-01-05 14:00:17 -08:00
Ishaan Jaff
32e8bdef6f update clean up jobs 2024-12-28 19:45:19 -08:00
Ishaan Jaff
6409de6291 fix ft job test - add resource cleanup 2024-12-28 19:28:54 -08:00
Ishaan Jaff
f719743d4a cleanup_azure_ft_models 2024-12-28 19:10:23 -08:00
Ishaan Jaff
d36152f9eb fix ft testing 2024-12-27 14:33:16 -08:00
Ishaan Jaff
81be0b4090
(Feat) add `"/v1/batches/{batch_id:path}/cancel" endpoint (#7406)
* use 1 file for azure batches handling

* add cancel_batch endpoint

* add a cancel batch on open ai

* add cancel_batch endpoint

* add cancel batches to test

* remove unused imports

* test_batches_operations

* update test_batches_operations
2024-12-24 20:23:50 -08:00
Ishaan Jaff
08a4c72692
(feat) /batches - track user_api_key_alias, user_api_key_team_alias etc for /batch requests (#7401)
* run azure testing on ci/cd

* update docs on azure batches endpoints

* add input azure.jsonl

* refactor - use separate file for batches endpoints

* fixes for passing custom llm provider to /batch endpoints

* pass custom llm provider to files endpoints

* update azure batches doc

* add info for azure batches api

* update batches endpoints

* use simple helper for raising proxy exception

* update config.yml

* fix imports

* add type hints to get_litellm_params

* update get_litellm_params

* update get_litellm_params

* update get slp

* QOL - stop double logging a create batch operations on custom loggers

* re use slp from og event

* _create_standard_logging_object_for_completed_batch

* fix linting errors

* reduce num changes in PR

* update BATCH_STATUS_POLL_MAX_ATTEMPTS
2024-12-24 17:44:28 -08:00
Ishaan Jaff
47e12802df
(feat) /batches Add support for using /batches endpoints in OAI format (#7402)
* run azure testing on ci/cd

* update docs on azure batches endpoints

* add input azure.jsonl

* refactor - use separate file for batches endpoints

* fixes for passing custom llm provider to /batch endpoints

* pass custom llm provider to files endpoints

* update azure batches doc

* add info for azure batches api

* update batches endpoints

* use simple helper for raising proxy exception

* update config.yml

* fix imports

* update tests

* use existing settings

* update env var used

* update configs

* update config.yml

* update ft testing
2024-12-24 16:58:05 -08:00
Ishaan Jaff
05b0d2026f
(feat) Add cost tracking for /batches requests OpenAI (#7384)
* add basic logging for create`batch`

* add create_batch as a call type

* add basic dd logging for batches

* basic batch creation logging on DD

* batch endpoints add cost calc

* fix batches_async_logging

* separate folder for batches testing

* new job for batches tests

* test batches logging

* fix validation logic

* add vertex_batch_completions.jsonl

* test test_async_create_batch

* test_async_create_batch

* update tests

* test_completion_with_no_model

* remove dead code

* update load_vertex_ai_credentials

* test_avertex_batch_prediction

* update get async httpx client

* fix get_async_httpx_client

* update test_avertex_batch_prediction

* fix batches testing config.yaml

* add google deps

* fix vertex files handler
2024-12-23 17:47:26 -08:00
Renamed from tests/local_testing/test_openai_batches_and_files.py (Browse further)