From 4a78bfcd289da4f0506fe6807a8f11ef033e278b Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 12 May 2026 13:51:32 -0700 Subject: [PATCH 1/4] fix(proxy): always merge caller-supplied tags into request metadata Caller-supplied tags (`x-litellm-tags` header, body `tags`, `metadata.tags`) were silently dropped unless the key/team had `metadata.allow_client_tags: true` set. Restore the documented behavior: tags from the request always flow into `metadata.tags` and union with any admin-configured static tags from key/team/project metadata. Removes the `allow_client_tags` opt-in flag from the pre-call pipeline. The flag was only ever read here; it has no schema or endpoint footprint, so leftover values in existing key metadata are inert. Test cleanup mirrors the simplification: drop the three tests that verified the strip-when-not-opted-in path, drop the `allow_client_tags` fixture lines from the merge/union tests. --- litellm/proxy/litellm_pre_call_utils.py | 54 +---- tests/proxy_unit_tests/test_proxy_utils.py | 9 +- .../proxy/test_litellm_pre_call_utils.py | 220 +----------------- 3 files changed, 18 insertions(+), 265 deletions(-) diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index b97e7c5e693..929ef040637 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -1437,46 +1437,8 @@ async def add_litellm_data_to_request( # noqa: PLR0915 if not _key_or_team_allows_client_pricing_override(user_api_key_dict): _strip_client_pricing_overrides(data) - # Strip caller-supplied routing/budget tags unless the admin has opted - # this key or team in via metadata.allow_client_tags=True. Tags drive - # tag-based routing and tag budget attribution — accepting them from - # untrusted callers lets an attacker reach restricted deployments or - # misattribute spend to a victim team's tag. - _admin_allow_client_tags = False - for _admin_meta in ( - user_api_key_dict.metadata, - user_api_key_dict.team_metadata, - ): - if ( - isinstance(_admin_meta, dict) - and _admin_meta.get("allow_client_tags") is True - ): - _admin_allow_client_tags = True - break - if not _admin_allow_client_tags: - _stripped_from: List[str] = [] - for _meta_key in ("metadata", "litellm_metadata"): - _user_meta = data.get(_meta_key) - if isinstance(_user_meta, dict) and "tags" in _user_meta: - _user_meta.pop("tags", None) - _stripped_from.append(_meta_key) - # Also strip the root-level `tags` field. get_tags_from_request_body - # reads request_body["tags"] directly and feeds it to the policy - # engine, so leaving it in place here would let the strip-in-metadata - # above be trivially bypassed by moving the tags to the body root. - if "tags" in data: - data.pop("tags", None) - _stripped_from.append("tags (root)") - if _stripped_from: - verbose_proxy_logger.warning( - "Stripped caller-supplied tags from %s: this key/team does " - "not have `allow_client_tags: true` in its metadata. Set it " - "to opt into client-supplied routing/budget tags.", - ", ".join(_stripped_from), - ) - # Fill in the proxy_server_request body snapshot now that metadata has - # been parsed and stripped. Consumers (standard_logging_payload, lago, + # been parsed. Consumers (standard_logging_payload, lago, # spend_tracking_utils, streaming_iterator) read `body` to audit the # request; taking the snapshot here ensures they see cleaned metadata. # @@ -1665,27 +1627,19 @@ async def add_litellm_data_to_request( # noqa: PLR0915 user_agent = request.headers["user-agent"] data[_metadata_variable_name]["user_agent"] = user_agent - # Check if using tag based routing. The helper reads caller-controlled - # sources (x-litellm-tags header, data["tags"] root-level), so its result - # is still gated by the same allow_client_tags flag that gated the - # body-metadata tag strip above. Otherwise the strip is trivially - # bypassed by sending tags via header or at the root of the body. + # Merge caller-supplied tags (x-litellm-tags header, data["tags"] root-level) + # into request metadata for tag-based routing and spend attribution. tags = LiteLLMProxyRequestSetup.add_request_tag_to_metadata( llm_router=llm_router, headers=_headers, data=data, ) - if tags is not None and _admin_allow_client_tags: + if tags is not None: data[_metadata_variable_name]["tags"] = LiteLLMProxyRequestSetup._merge_tags( request_tags=data[_metadata_variable_name].get("tags"), tags_to_add=tags, ) - elif tags is not None: - verbose_proxy_logger.warning( - "Ignored caller-supplied tags from header/root body: this " - "key/team does not have `allow_client_tags: true` in its metadata." - ) # Team Callbacks controls callback_settings_obj = _get_dynamic_logging_metadata( diff --git a/tests/proxy_unit_tests/test_proxy_utils.py b/tests/proxy_unit_tests/test_proxy_utils.py index 68aff36038b..ff695d4a57e 100644 --- a/tests/proxy_unit_tests/test_proxy_utils.py +++ b/tests/proxy_unit_tests/test_proxy_utils.py @@ -167,13 +167,9 @@ async def test_add_key_or_team_level_spend_logs_metadata_to_request( print(f"team_sl_metadata: {team_sl_metadata}") mock_request.url.path = "/chat/completions" - # Opt the key into client-supplied tags so request_tags are preserved - # and merged with admin-configured key/team tags. Without this flag, - # request_tags would be stripped by add_litellm_data_to_request. key_metadata = { "tags": key_tags, "spend_logs_metadata": key_sl_metadata, - "allow_client_tags": True, } team_metadata = { "tags": team_tags, @@ -909,13 +905,12 @@ async def test_add_litellm_data_to_request_duplicate_tags( mock_request.headers = {} mock_request.state = State() - # Setup key with tags in metadata. Opt into client-supplied tags so the - # request_tags are preserved for the merge under test. + # Setup key with tags in metadata. user_api_key_dict = UserAPIKeyAuth( api_key="test_api_key", user_id="test_user_id", org_id="test_org_id", - metadata={"tags": key_tags, "allow_client_tags": True}, + metadata={"tags": key_tags}, ) # Setup request data with tags diff --git a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py index b803dfb709a..5412bf3a569 100644 --- a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py +++ b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py @@ -874,101 +874,8 @@ async def test_add_litellm_data_to_request_allows_redaction_opt_out_with_admin_o @pytest.mark.asyncio -async def test_add_litellm_data_to_request_ignores_x_litellm_tags_header_without_permission(): - """Regression: the `x-litellm-tags` header bypassed the body-metadata - tag strip. Header tags must also be gated by `allow_client_tags`.""" - from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request - - request_mock = MagicMock(spec=Request) - request_mock.url.path = "/v1/chat/completions" - request_mock.url = MagicMock() - request_mock.url.__str__.return_value = "http://localhost/v1/chat/completions" - request_mock.method = "POST" - request_mock.query_params = {} - request_mock.headers = { - "Content-Type": "application/json", - "x-litellm-tags": "restricted-tier,victim-team", - } - request_mock.client = MagicMock() - request_mock.client.host = "127.0.0.1" - - data = {"model": "gpt-3.5-turbo"} - - user_api_key_dict = UserAPIKeyAuth( - api_key="hashed-key", - metadata={}, - team_metadata={}, - spend=0.0, - max_budget=100.0, - model_max_budget={}, - team_spend=0.0, - team_max_budget=200.0, - ) - - updated = await add_litellm_data_to_request( - data=data, - request=request_mock, - user_api_key_dict=user_api_key_dict, - proxy_config=MagicMock(), - general_settings={}, - version="test-version", - ) - - assert "tags" not in (updated.get("metadata") or {}) - - -@pytest.mark.asyncio -async def test_add_litellm_data_to_request_ignores_root_level_tags_without_permission(): - """Regression: root-level `data["tags"]` bypassed the body-metadata - tag strip. Root-level tags must also be gated by `allow_client_tags`.""" - from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request - - request_mock = MagicMock(spec=Request) - request_mock.url.path = "/v1/chat/completions" - request_mock.url = MagicMock() - request_mock.url.__str__.return_value = "http://localhost/v1/chat/completions" - request_mock.method = "POST" - request_mock.query_params = {} - request_mock.headers = {"Content-Type": "application/json"} - request_mock.client = MagicMock() - request_mock.client.host = "127.0.0.1" - - data = { - "model": "gpt-3.5-turbo", - "tags": ["restricted-tier", "victim-team"], - } - - user_api_key_dict = UserAPIKeyAuth( - api_key="hashed-key", - metadata={}, - team_metadata={}, - spend=0.0, - max_budget=100.0, - model_max_budget={}, - team_spend=0.0, - team_max_budget=200.0, - ) - - updated = await add_litellm_data_to_request( - data=data, - request=request_mock, - user_api_key_dict=user_api_key_dict, - proxy_config=MagicMock(), - general_settings={}, - version="test-version", - ) - - assert "tags" not in (updated.get("metadata") or {}) - # Also ensure the root-level tags are removed. get_tags_from_request_body - # reads request_body["tags"] directly, so leaving it in place would let - # the policy engine see caller-supplied tags even after the metadata - # strip. - assert "tags" not in updated - - -@pytest.mark.asyncio -async def test_add_litellm_data_to_request_honors_header_tags_when_opted_in(): - """When allow_client_tags=True, header-supplied tags flow through.""" +async def test_add_litellm_data_to_request_honors_header_tags(): + """Header-supplied tags flow through to request metadata.""" from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request request_mock = MagicMock(spec=Request) @@ -988,7 +895,7 @@ async def test_add_litellm_data_to_request_honors_header_tags_when_opted_in(): user_api_key_dict = UserAPIKeyAuth( api_key="hashed-key", - metadata={"allow_client_tags": True}, + metadata={}, team_metadata={}, spend=0.0, max_budget=100.0, @@ -1010,11 +917,8 @@ async def test_add_litellm_data_to_request_honors_header_tags_when_opted_in(): @pytest.mark.asyncio -async def test_add_litellm_data_to_request_strips_user_tags_without_permission(): - """Caller-supplied metadata.tags must be stripped when the key/team - metadata does not opt in via allow_client_tags=True. Otherwise an - attacker can reach restricted tag-routed deployments or attribute - spend to a victim team's tag.""" +async def test_add_litellm_data_to_request_preserves_caller_metadata_tags(): + """Caller-supplied metadata.tags are preserved and reach the router.""" from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request request_mock = MagicMock(spec=Request) @@ -1029,8 +933,7 @@ async def test_add_litellm_data_to_request_strips_user_tags_without_permission() data = { "model": "gpt-3.5-turbo", - "metadata": {"tags": ["restricted-tier", "victim-team"]}, - "litellm_metadata": {"tags": ["also-stripped"]}, + "metadata": {"tags": ["caller-tag"]}, } user_api_key_dict = UserAPIKeyAuth( @@ -1053,101 +956,13 @@ async def test_add_litellm_data_to_request_strips_user_tags_without_permission() version="test-version", ) - assert "tags" not in (updated.get("metadata") or {}) - assert "tags" not in (updated.get("litellm_metadata") or {}) - - -@pytest.mark.asyncio -async def test_add_litellm_data_to_request_preserves_user_tags_when_key_opts_in(): - """When key.metadata.allow_client_tags=True, caller-supplied tags are - preserved and reach the router.""" - from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request - - request_mock = MagicMock(spec=Request) - request_mock.url.path = "/v1/chat/completions" - request_mock.url = MagicMock() - request_mock.url.__str__.return_value = "http://localhost/v1/chat/completions" - request_mock.method = "POST" - request_mock.query_params = {} - request_mock.headers = {"Content-Type": "application/json"} - request_mock.client = MagicMock() - request_mock.client.host = "127.0.0.1" - - data = { - "model": "gpt-3.5-turbo", - "metadata": {"tags": ["opted-in-tag"]}, - } - - user_api_key_dict = UserAPIKeyAuth( - api_key="hashed-key", - metadata={"allow_client_tags": True}, - team_metadata={}, - spend=0.0, - max_budget=100.0, - model_max_budget={}, - team_spend=0.0, - team_max_budget=200.0, - ) - - updated = await add_litellm_data_to_request( - data=data, - request=request_mock, - user_api_key_dict=user_api_key_dict, - proxy_config=MagicMock(), - general_settings={}, - version="test-version", - ) - - assert updated["metadata"].get("tags") == ["opted-in-tag"] - - -@pytest.mark.asyncio -async def test_add_litellm_data_to_request_preserves_user_tags_when_team_opts_in(): - """Team-level allow_client_tags is also honored (not just key-level).""" - from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request - - request_mock = MagicMock(spec=Request) - request_mock.url.path = "/v1/chat/completions" - request_mock.url = MagicMock() - request_mock.url.__str__.return_value = "http://localhost/v1/chat/completions" - request_mock.method = "POST" - request_mock.query_params = {} - request_mock.headers = {"Content-Type": "application/json"} - request_mock.client = MagicMock() - request_mock.client.host = "127.0.0.1" - - data = { - "model": "gpt-3.5-turbo", - "metadata": {"tags": ["team-allowed"]}, - } - - user_api_key_dict = UserAPIKeyAuth( - api_key="hashed-key", - metadata={}, - team_metadata={"allow_client_tags": True}, - spend=0.0, - max_budget=100.0, - model_max_budget={}, - team_spend=0.0, - team_max_budget=200.0, - ) - - updated = await add_litellm_data_to_request( - data=data, - request=request_mock, - user_api_key_dict=user_api_key_dict, - proxy_config=MagicMock(), - general_settings={}, - version="test-version", - ) - - assert updated["metadata"].get("tags") == ["team-allowed"] + assert updated["metadata"].get("tags") == ["caller-tag"] @pytest.mark.asyncio async def test_add_litellm_data_to_request_unions_caller_header_tags_with_static_key_tags(): """Caller-supplied `x-litellm-tags` must union with static key-level - tags, not overwrite them, when `allow_client_tags=True`.""" + tags, not overwrite them.""" from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request request_mock = MagicMock(spec=Request) @@ -1167,10 +982,7 @@ async def test_add_litellm_data_to_request_unions_caller_header_tags_with_static user_api_key_dict = UserAPIKeyAuth( api_key="hashed-key", - metadata={ - "allow_client_tags": True, - "tags": ["team:platform", "env:prod"], - }, + metadata={"tags": ["team:platform", "env:prod"]}, team_metadata={}, spend=0.0, max_budget=100.0, @@ -1217,10 +1029,7 @@ async def test_add_litellm_data_to_request_unions_caller_header_tags_with_static user_api_key_dict = UserAPIKeyAuth( api_key="hashed-key", metadata={}, - team_metadata={ - "allow_client_tags": True, - "tags": ["team:eng", "owner:platform"], - }, + team_metadata={"tags": ["team:eng", "owner:platform"]}, spend=0.0, max_budget=100.0, model_max_budget={}, @@ -1266,10 +1075,7 @@ async def test_add_litellm_data_to_request_unions_dedups_overlapping_caller_and_ user_api_key_dict = UserAPIKeyAuth( api_key="hashed-key", - metadata={ - "allow_client_tags": True, - "tags": ["env:prod", "team:platform"], - }, + metadata={"tags": ["env:prod", "team:platform"]}, team_metadata={}, spend=0.0, max_budget=100.0, @@ -1364,11 +1170,9 @@ async def test_add_litellm_data_to_request_audio_transcription_multipart(): "file": b"Fake audio bytes", } - # Opt the key in to client-supplied tags so the parsed tags from the - # JSON-string multipart body aren't stripped by the admin-injection strip. user_api_key_dict = UserAPIKeyAuth( api_key="hashed-key", - metadata={"allow_client_tags": True}, + metadata={}, team_metadata={}, spend=0.0, max_budget=100.0, From 96c62c17a82d413ae87151becd7ae07f85944aaf Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 12 May 2026 16:00:57 -0700 Subject: [PATCH 2/4] docs(proxy): refresh stale comments referencing removed tag strip The tag-strip block was removed in the parent commit but two surrounding comments still referenced "tags without opt-in" and "runs AFTER the strip". Update them to describe the remaining user_api_key_* and _pipeline_managed_guardrails strip that the snapshot/merge ordering actually protects against. --- litellm/proxy/litellm_pre_call_utils.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index 929ef040637..00735e6be55 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -1448,19 +1448,21 @@ async def add_litellm_data_to_request( # noqa: PLR0915 _body_snapshot = {k: v for k, v in data.items() if k != "secret_fields"} data["proxy_server_request"]["body"] = _body_snapshot - # Snapshot the (now-cleaned) requester-supplied metadata for downstream - # consumers. Taking the deepcopy AFTER the strip prevents attacker- - # injected admin slots (user_api_key_*, tags without opt-in, - # _pipeline_managed_guardrails) from surviving in requester_metadata - # where guardrails and audit paths may read from it. + # Snapshot the requester-supplied metadata for downstream consumers. + # Taking the deepcopy after the user_api_key_* / _pipeline_managed_guardrails + # strip above prevents those proxy-internal slots — if a caller forged + # them — from leaking into requester_metadata where guardrails and audit + # paths may read from it. if "metadata" in data and isinstance(data["metadata"], dict): data[_metadata_variable_name]["requester_metadata"] = copy.deepcopy( data["metadata"] ) - # Now merge litellm_metadata into the metadata variable (preserving existing - # values) — runs AFTER the strip so attacker injections in litellm_metadata - # cannot cross-contaminate the admin-authoritative metadata dict. + # Merge litellm_metadata into the metadata variable (preserving existing + # values). Runs after the user_api_key_* / _pipeline_managed_guardrails + # strip above so those proxy-internal slots — if a caller forged them + # into litellm_metadata — cannot cross-contaminate the admin-authoritative + # metadata dict. if "litellm_metadata" in data and isinstance(data["litellm_metadata"], dict): for key, value in data["litellm_metadata"].items(): if key not in data[_metadata_variable_name]: From 8c8621ece38636543ca77b02e5d4274a368345f8 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 12 May 2026 16:07:59 -0700 Subject: [PATCH 3/4] fix(tests): swap dall-e to gpt-image-1 after openai deprecation DALL-E 2 and DALL-E 3 were removed from the OpenAI API on 2026-05-12, causing e2e image-generation tests to fail with "model does not exist". Swap all live-API DALL-E references in proxy-backed tests to gpt-image-1 and update the dall-e-2 alias in proxy_server_config.yaml to point at openai/gpt-image-1 (preserves any historical dall-e-2 callers). --- proxy_server_config.yaml | 4 ++-- tests/otel_tests/test_otel.py | 2 +- tests/test_health.py | 2 +- tests/test_keys.py | 4 ++-- tests/test_openai_endpoints.py | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/proxy_server_config.yaml b/proxy_server_config.yaml index 5d3d810926a..d9838c852a2 100644 --- a/proxy_server_config.yaml +++ b/proxy_server_config.yaml @@ -38,9 +38,9 @@ model_list: model_info: mode: embedding base_model: text-embedding-ada-002 - - model_name: dall-e-2 # some tests use dall-e-2 which is now deprecated, alias to dall-e-3 + - model_name: dall-e-2 # dall-e-2 and dall-e-3 were deprecated 2026-05-12; alias to gpt-image-1 litellm_params: - model: openai/dall-e-3 + model: openai/gpt-image-1 - model_name: openai-dall-e-3 litellm_params: model: dall-e-3 diff --git a/tests/otel_tests/test_otel.py b/tests/otel_tests/test_otel.py index a0f58dd5b85..9ded859eb9d 100644 --- a/tests/otel_tests/test_otel.py +++ b/tests/otel_tests/test_otel.py @@ -13,7 +13,7 @@ async def generate_key( models=[ "gpt-4", "text-embedding-ada-002", - "dall-e-2", + "gpt-image-1", "fake-openai-endpoint", "mistral-embed", ], diff --git a/tests/test_health.py b/tests/test_health.py index 15dc2330ffb..cc551fd9380 100644 --- a/tests/test_health.py +++ b/tests/test_health.py @@ -31,7 +31,7 @@ async def generate_key(session): url = "http://0.0.0.0:4000/key/generate" headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} data = { - "models": ["gpt-4", "text-embedding-ada-002", "dall-e-2"], + "models": ["gpt-4", "text-embedding-ada-002", "gpt-image-1"], "duration": None, } diff --git a/tests/test_keys.py b/tests/test_keys.py index 6d4c24aa80d..e6bda59c2cc 100644 --- a/tests/test_keys.py +++ b/tests/test_keys.py @@ -62,7 +62,7 @@ async def generate_key( i, budget=None, budget_duration=None, - models=["azure-models", "gpt-4", "dall-e-3"], + models=["azure-models", "gpt-4", "gpt-image-1"], max_parallel_requests: Optional[int] = None, user_id: Optional[str] = None, team_id: Optional[str] = None, @@ -235,7 +235,7 @@ async def chat_completion(session, key, model="gpt-4"): pass -async def image_generation(session, key, model="dall-e-3"): +async def image_generation(session, key, model="gpt-image-1"): url = "http://0.0.0.0:4000/v1/images/generations" headers = { "Authorization": f"Bearer {key}", diff --git a/tests/test_openai_endpoints.py b/tests/test_openai_endpoints.py index 8a3f9361ba1..e898b88a556 100644 --- a/tests/test_openai_endpoints.py +++ b/tests/test_openai_endpoints.py @@ -23,7 +23,7 @@ async def generate_key( models=[ "gpt-4", "text-embedding-ada-002", - "dall-e-2", + "gpt-image-1", "fake-openai-endpoint-2", "mistral-embed", ], @@ -56,7 +56,7 @@ async def new_user(session): url = "http://0.0.0.0:4000/user/new" headers = {"Authorization": "Bearer sk-1234", "Content-Type": "application/json"} data = { - "models": ["gpt-4", "text-embedding-ada-002", "dall-e-2"], + "models": ["gpt-4", "text-embedding-ada-002", "gpt-image-1"], "duration": None, } @@ -264,7 +264,7 @@ async def image_generation(session, key): "Content-Type": "application/json", } data = { - "model": "dall-e-2", + "model": "gpt-image-1", "prompt": "A cute baby sea otter", } From 945b10ded467e53fc3c9b8df0329dbc55591a56e Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Tue, 12 May 2026 16:16:59 -0700 Subject: [PATCH 4/4] fix(tests): drop dall-e-only test classes; route live image tests via gpt-image-1 Second wave of failures from the 2026-05-12 DALL-E shutdown: - tests/image_gen_tests/test_image_edits.py::TestOpenAIImageEditDallE2 and tests/image_gen_tests/test_image_generation.py::TestOpenAIDalle3 are explicitly named for the deprecated models and can't pass; remove. gpt-image-1 coverage already exists in sibling classes. - tests/local_testing/test_router.py image gen tests use dall-e-3 only as a routing example; swap to gpt-image-1. - tests/local_testing/test_custom_callback_input.py image_generation success/failure paths swapped to gpt-image-1. --- tests/image_gen_tests/test_image_edits.py | 14 -------------- tests/image_gen_tests/test_image_generation.py | 5 ----- tests/local_testing/test_custom_callback_input.py | 4 ++-- tests/local_testing/test_router.py | 12 ++++++------ 4 files changed, 8 insertions(+), 27 deletions(-) diff --git a/tests/image_gen_tests/test_image_edits.py b/tests/image_gen_tests/test_image_edits.py index dcb04c597e2..6900bacdb90 100644 --- a/tests/image_gen_tests/test_image_edits.py +++ b/tests/image_gen_tests/test_image_edits.py @@ -133,20 +133,6 @@ class TestOpenAIImageEditGPTImage1(BaseLLMImageEditTest): } -class TestOpenAIImageEditDallE2(BaseLLMImageEditTest): - """ - Concrete implementation of BaseLLMImageEditTest for OpenAI DALL-E-2 image edits. - DALL-E-2 only supports a single image (not an array). - """ - - def get_base_image_edit_call_args(self) -> dict: - """Return base call args for OpenAI DALL-E-2 image edit (single image only)""" - return { - "model": "dall-e-2", - "image": SINGLE_TEST_IMAGE, - } - - class TestAzureAIFlux2ImageEdit(BaseLLMImageEditTest): """ Concrete implementation of BaseLLMImageEditTest for Azure AI FLUX 2 image edits. diff --git a/tests/image_gen_tests/test_image_generation.py b/tests/image_gen_tests/test_image_generation.py index 5152e3e0129..873777189c9 100644 --- a/tests/image_gen_tests/test_image_generation.py +++ b/tests/image_gen_tests/test_image_generation.py @@ -163,11 +163,6 @@ class TestBedrockNovaCanvasColorGuidedGeneration(BaseImageGenTest): } -class TestOpenAIDalle3(BaseImageGenTest): - def get_base_image_generation_call_args(self) -> dict: - return {"model": "dall-e-3"} - - class TestOpenAIGPTImage1(BaseImageGenTest): def get_base_image_generation_call_args(self) -> dict: return {"model": "gpt-image-1"} diff --git a/tests/local_testing/test_custom_callback_input.py b/tests/local_testing/test_custom_callback_input.py index 15a2975becc..545039e60ba 100644 --- a/tests/local_testing/test_custom_callback_input.py +++ b/tests/local_testing/test_custom_callback_input.py @@ -930,7 +930,7 @@ def test_image_generation_openai(): response = litellm.image_generation( prompt="A cute baby sea otter", - model="openai/dall-e-3", + model="openai/gpt-image-1", api_key=os.getenv("OPENAI_API_KEY"), ) @@ -948,7 +948,7 @@ def test_image_generation_openai(): try: response = litellm.image_generation( prompt="A cute baby sea otter", - model="dall-e-2", + model="gpt-image-1", api_key="my-bad-api-key", ) except Exception: diff --git a/tests/local_testing/test_router.py b/tests/local_testing/test_router.py index f7885fb8a03..d6b239c79cc 100644 --- a/tests/local_testing/test_router.py +++ b/tests/local_testing/test_router.py @@ -995,15 +995,15 @@ async def test_aimg_gen_on_router(): try: model_list = [ { - "model_name": "dall-e-3", + "model_name": "gpt-image-1", "litellm_params": { - "model": "dall-e-3", + "model": "gpt-image-1", }, } ] router = Router(model_list=model_list, num_retries=3) response = await router.aimage_generation( - model="dall-e-3", prompt="A cute baby sea otter" + model="gpt-image-1", prompt="A cute baby sea otter" ) print(response) assert len(response.data) > 0 @@ -1030,15 +1030,15 @@ def test_img_gen_on_router(): try: model_list = [ { - "model_name": "dall-e-3", + "model_name": "gpt-image-1", "litellm_params": { - "model": "dall-e-3", + "model": "gpt-image-1", }, } ] router = Router(model_list=model_list) response = router.image_generation( - model="dall-e-3", prompt="A cute baby sea otter" + model="gpt-image-1", prompt="A cute baby sea otter" ) print(response) assert len(response.data) > 0