From 127aeac4aa1e248a793e3958a0e27efd209edb62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?0x=CF=84ensor?= Date: Tue, 12 May 2026 03:03:47 -0700 Subject: [PATCH] fix: expose gpt-5.5 and gpt-5.4 in OpenAI model list (#14828) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What problem does this PR solve? OpenAI model catalogs used in provider selection flows were missing the latest GPT models (`gpt-5.5` and `gpt-5.4`). Because model availability is driven by seeded catalog data (`conf/llm_factories.json` → DB seed → API response), these models were not selectable in the UI or `/llm/list` responses. This PR updates and synchronizes the OpenAI catalog definitions across configuration sources and ensures the new models are correctly exposed through the API layer and validated in tests. --- ### Type of change * [x] New Feature (non-breaking change which adds functionality) --- ### Changes Made * Added `gpt-5.5` and `gpt-5.4` to OpenAI catalog definitions in: * `conf/llm_factories.json` * `conf/models/openai.json` (chat + vision support) * Ensured consistency between DB-seeded factory config and provider model configuration * Updated test coverage in: * `test_llm_list_unit.py` * seeded OpenAI catalog entries * added response-level assertion validating `/llm/list` includes both new model IDs under OpenAI grouping --- ### Root Cause OpenAI model listings in selection flows are generated from catalog data seeded via `conf/llm_factories.json`. The catalog had not been updated to include the latest GPT models, resulting in missing availability in UI and API responses. --- ### Testing * Created isolated test environment: * `python -m venv .venv-review` * installed `pytest` * Ran targeted and full test suite: * `test_list_app_grouping_availability_and_merge`: ✅ passed * Full `test_llm_list_unit.py`: ✅ 10 passed --- ### Risks / Limitations * Adding models to the catalog does not guarantee upstream provider availability or account entitlement. * Environments with pre-seeded DB catalogs may require reseed or refresh to reflect updated configuration. --- ### Notes * Changes are minimal and scoped strictly to catalog configuration and related test coverage. * Ensures `/llm/list` API remains aligned with expected latest OpenAI model availability. * Closes #14827 --- conf/llm_factories.json | 14 ++++++++ conf/models/openai.json | 16 ++++++++++ .../test_llm_app/test_llm_list_unit.py | 32 ++++++++++++++++++- 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/conf/llm_factories.json b/conf/llm_factories.json index 2fc12803d7..09273fe245 100644 --- a/conf/llm_factories.json +++ b/conf/llm_factories.json @@ -8,6 +8,20 @@ "rank": "999", "url": "https://api.openai.com/v1", "llm": [ + { + "llm_name": "gpt-5.5", + "tags": "LLM,CHAT,400k,IMAGE2TEXT", + "max_tokens": 400000, + "model_type": "chat", + "is_tools": true + }, + { + "llm_name": "gpt-5.4", + "tags": "LLM,CHAT,400k,IMAGE2TEXT", + "max_tokens": 400000, + "model_type": "chat", + "is_tools": true + }, { "llm_name": "gpt-5.2-pro", "tags": "LLM,CHAT,400k,IMAGE2TEXT", diff --git a/conf/models/openai.json b/conf/models/openai.json index c78a82b4c2..ae252fdccc 100644 --- a/conf/models/openai.json +++ b/conf/models/openai.json @@ -10,6 +10,22 @@ }, "class": "gpt", "models": [ + { + "name": "gpt-5.5", + "max_tokens": 400000, + "model_types": [ + "chat", + "vision" + ] + }, + { + "name": "gpt-5.4", + "max_tokens": 400000, + "model_types": [ + "chat", + "vision" + ] + }, { "name": "gpt-5.2-pro", "max_tokens": 400000, diff --git a/test/testcases/test_web_api/test_llm_app/test_llm_list_unit.py b/test/testcases/test_web_api/test_llm_app/test_llm_list_unit.py index 53a8705f31..e0442e0aa7 100644 --- a/test/testcases/test_web_api/test_llm_app/test_llm_list_unit.py +++ b/test/testcases/test_web_api/test_llm_app/test_llm_list_unit.py @@ -252,6 +252,28 @@ def _load_llm_app(monkeypatch): return module +@pytest.mark.p2 +def test_openai_catalog_contains_latest_gpt_models_unit(): + repo_root = Path(__file__).resolve().parents[4] + + openai_provider_path = repo_root / "conf" / "llm_factories.json" + openai_model_path = repo_root / "conf" / "models" / "openai.json" + + with open(openai_provider_path, "r", encoding="utf-8") as f: + factories = json.load(f)["factory_llm_infos"] + + openai_factory = next(item for item in factories if item["name"] == "OpenAI") + factory_model_names = {item["llm_name"] for item in openai_factory["llm"]} + + with open(openai_model_path, "r", encoding="utf-8") as f: + openai_models = json.load(f)["models"] + model_file_names = {item["name"] for item in openai_models} + + for model_name in ["gpt-5.5", "gpt-5.4"]: + assert model_name in factory_model_names + assert model_name in model_file_names + + @pytest.mark.p2 def test_list_app_grouping_availability_and_merge(monkeypatch): module = _load_llm_app(monkeypatch) @@ -262,12 +284,16 @@ def test_list_app_grouping_availability_and_merge(monkeypatch): tenant_rows = [ _TenantLLMRow(id=1, llm_name="fast-emb", llm_factory="FastEmbed", model_type="embedding", api_key="k1", status="1"), _TenantLLMRow(id=2, llm_name="tenant-only", llm_factory="CustomFactory", model_type="chat", api_key="k2", status="1"), + _TenantLLMRow(id=3, llm_name="gpt-5.5", llm_factory="OpenAI", model_type="chat", api_key="k3", status="1"), + _TenantLLMRow(id=4, llm_name="gpt-5.4", llm_factory="OpenAI", model_type="chat", api_key="k4", status="1"), ] monkeypatch.setattr(module.TenantLLMService, "query", lambda **_kwargs: tenant_rows) all_llms = [ _LLMRow(llm_name="tei-embed", fid="Builtin", model_type="embedding", status="1"), _LLMRow(llm_name="fast-emb", fid="FastEmbed", model_type="embedding", status="1"), + _LLMRow(llm_name="gpt-5.5", fid="OpenAI", model_type="chat", status="1"), + _LLMRow(llm_name="gpt-5.4", fid="OpenAI", model_type="chat", status="1"), _LLMRow(llm_name="not-in-status", fid="Other", model_type="chat", status="1"), ] monkeypatch.setattr(module.LLMService, "get_all", lambda: all_llms) @@ -281,7 +307,7 @@ def test_list_app_grouping_availability_and_merge(monkeypatch): assert ensure_calls == ["tenant-1"] data = res["data"] - assert {"Builtin", "FastEmbed", "CustomFactory"}.issubset(set(data.keys())) + assert {"Builtin", "FastEmbed", "CustomFactory", "OpenAI"}.issubset(set(data.keys())) builtin = data["Builtin"][0] assert builtin["llm_name"] == "tei-embed" @@ -295,6 +321,10 @@ def test_list_app_grouping_availability_and_merge(monkeypatch): assert tenant_only["llm_name"] == "tenant-only" assert tenant_only["available"] is True + # Response-level assertion: /llm/list output includes latest OpenAI IDs. + openai_names = {item["llm_name"] for item in data["OpenAI"]} + assert {"gpt-5.5", "gpt-5.4"}.issubset(openai_names) + @pytest.mark.p2 def test_list_app_model_type_filter(monkeypatch):