Skip to content

Commit 4d8ffec

Browse files
author
Ra's al Ghul
committed
feat: Add gpt-5.4-mini.
This just adds gpt-5.4-mini at (low/med/high/xhigh) reasoning levels.
1 parent d8ba913 commit 4d8ffec

4 files changed

Lines changed: 23 additions & 5 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ curl http://127.0.0.1:8000/v1/chat/completions \
110110

111111
# Supported models
112112
- `gpt-5.4`
113+
- `gpt-5.4-mini`
113114
- `gpt-5.2`
114115
- `gpt-5.1`
115116
- `gpt-5`
@@ -127,7 +128,7 @@ curl http://127.0.0.1:8000/v1/chat/completions \
127128

128129
- `--reasoning-effort` (choice of none,minimal,low,medium,high,xhigh)<br>
129130
GPT-5 has a configurable amount of "effort" it can put into thinking, which may cause it to take more time for a response to return, but may overall give a smarter answer. Applying this parameter after `serve` forces the server to use this reasoning effort by default, unless overrided by the API request with a different effort set. The default reasoning effort without setting this parameter is `medium`.<br>
130-
The `gpt-5.1` family (including codex) supports `low`, `medium`, and `high` while `gpt-5.1-codex-max` adds `xhigh`. The `gpt-5.2` and `gpt-5.3` families (including codex) support `low`, `medium`, `high`, and `xhigh`. GPT-5.4 supports `none`, `low`, `medium`, `high`, and `xhigh`.
131+
The `gpt-5.1` family (including codex) supports `low`, `medium`, and `high` while `gpt-5.1-codex-max` adds `xhigh`. The `gpt-5.2` and `gpt-5.3` families (including codex) support `low`, `medium`, `high`, and `xhigh`. `gpt-5.4` supports `none`, `low`, `medium`, `high`, and `xhigh`, while `gpt-5.4-mini` supports `low`, `medium`, `high`, and `xhigh`.
131132

132133
### Thinking summaries
133134

chatmock/model_registry.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ class ModelSpec:
4747
allowed_efforts=frozenset(("none", "low", "medium", "high", "xhigh")),
4848
variant_efforts=("xhigh", "high", "medium", "low", "none"),
4949
),
50+
ModelSpec(
51+
public_id="gpt-5.4-mini",
52+
upstream_id="gpt-5.4-mini",
53+
aliases=("gpt5.4-mini", "gpt-5.4-mini-latest"),
54+
allowed_efforts=frozenset(("low", "medium", "high", "xhigh")),
55+
variant_efforts=("xhigh", "high", "medium", "low"),
56+
),
5057
ModelSpec(
5158
public_id="gpt-5.3-codex",
5259
upstream_id="gpt-5.3-codex",

tests/test_models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,28 @@ class ModelRegistryTests(unittest.TestCase):
99
def test_normalizes_aliases(self) -> None:
1010
self.assertEqual(normalize_model_name("gpt5"), "gpt-5")
1111
self.assertEqual(normalize_model_name("gpt5.4"), "gpt-5.4")
12+
self.assertEqual(normalize_model_name("gpt5.4-mini"), "gpt-5.4-mini")
1213
self.assertEqual(normalize_model_name("codex"), "codex-mini-latest")
1314

1415
def test_strips_reasoning_suffixes(self) -> None:
1516
self.assertEqual(normalize_model_name("gpt-5.4-high"), "gpt-5.4")
17+
self.assertEqual(normalize_model_name("gpt-5.4-mini-high"), "gpt-5.4-mini")
1618
self.assertEqual(normalize_model_name("gpt-5.2_codemirror"), "gpt-5.2_codemirror")
1719
self.assertEqual(normalize_model_name("gpt-5.1-codex:max"), "gpt-5.1-codex:max")
1820
self.assertEqual(normalize_model_name("gpt-5.1-codex:high"), "gpt-5.1-codex")
1921

2022
def test_allowed_efforts_follow_registry(self) -> None:
2123
self.assertEqual(allowed_efforts_for_model("gpt-5.4"), frozenset(("none", "low", "medium", "high", "xhigh")))
24+
self.assertEqual(allowed_efforts_for_model("gpt-5.4-mini"), frozenset(("low", "medium", "high", "xhigh")))
2225
self.assertEqual(allowed_efforts_for_model("gpt-5.1-codex"), frozenset(("low", "medium", "high")))
2326

2427
def test_public_models_include_variants(self) -> None:
2528
model_ids = list_public_models(expose_reasoning_models=True)
2629
self.assertIn("gpt-5.4", model_ids)
30+
self.assertIn("gpt-5.4-mini", model_ids)
2731
self.assertIn("gpt-5.4-none", model_ids)
32+
self.assertIn("gpt-5.4-mini-xhigh", model_ids)
33+
self.assertNotIn("gpt-5.4-mini-none", model_ids)
2834
self.assertIn("gpt-5.1-codex-max-xhigh", model_ids)
2935
self.assertNotIn("codex-mini-high", model_ids)
3036

tests/test_routes.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,17 @@ def test_openai_models_list(self) -> None:
3333
response = self.client.get("/v1/models")
3434
body = response.get_json()
3535
self.assertEqual(response.status_code, 200)
36-
self.assertIn("gpt-5.4", [item["id"] for item in body["data"]])
36+
model_ids = [item["id"] for item in body["data"]]
37+
self.assertIn("gpt-5.4", model_ids)
38+
self.assertIn("gpt-5.4-mini", model_ids)
3739

3840
def test_ollama_tags_list(self) -> None:
3941
response = self.client.get("/api/tags")
4042
body = response.get_json()
4143
self.assertEqual(response.status_code, 200)
42-
self.assertIn("gpt-5.4", [item["name"] for item in body["models"]])
44+
model_names = [item["name"] for item in body["models"]]
45+
self.assertIn("gpt-5.4", model_names)
46+
self.assertIn("gpt-5.4-mini", model_names)
4347

4448
@patch("chatmock.routes_openai.start_upstream_request")
4549
def test_chat_completions(self, mock_start) -> None:
@@ -54,12 +58,12 @@ def test_chat_completions(self, mock_start) -> None:
5458
)
5559
response = self.client.post(
5660
"/v1/chat/completions",
57-
json={"model": "gpt5.4", "messages": [{"role": "user", "content": "hi"}]},
61+
json={"model": "gpt5.4-mini", "messages": [{"role": "user", "content": "hi"}]},
5862
)
5963
body = response.get_json()
6064
self.assertEqual(response.status_code, 200)
6165
self.assertEqual(body["choices"][0]["message"]["content"], "hello")
62-
self.assertEqual(body["model"], "gpt5.4")
66+
self.assertEqual(body["model"], "gpt5.4-mini")
6367

6468
@patch("chatmock.routes_ollama.start_upstream_request")
6569
def test_ollama_chat(self, mock_start) -> None:

0 commit comments

Comments
 (0)