Skip to content

Commit e7e161b

Browse files
committed
Merge branch 'fix/270-openai-reasoning-effort' of https://github.com/generative-computing/mellea into fix/270-openai-reasoning-effort
2 parents f87f86b + 4d87c83 commit e7e161b

File tree

2 files changed

+56
-17
lines changed

2 files changed

+56
-17
lines changed

mellea/backends/model_ids.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class ModelIdentifier:
1717
ollama_name: str | None = None
1818
watsonx_name: str | None = None
1919
mlx_name: str | None = None
20+
openai_name: str | None = None
2021

2122
hf_tokenizer_name: str | None = None # if None, is the same as hf_model_name
2223

@@ -134,9 +135,9 @@ class ModelIdentifier:
134135

135136
QWEN3_14B = ModelIdentifier(hf_model_name="Qwen/Qwen3-14B", ollama_name="qwen3:14b")
136137

137-
######################
138-
#### OpenAI models ###
139-
######################
138+
###########################
139+
#### OpenAI open models ###
140+
###########################
140141

141142
OPENAI_GPT_OSS_20B = ModelIdentifier(
142143
hf_model_name="openai/gpt-oss-20b", ollama_name="gpt-oss:20b"
@@ -145,6 +146,12 @@ class ModelIdentifier:
145146
hf_model_name="openai/gpt-oss-120b", ollama_name="gpt-oss:120b"
146147
)
147148

149+
###########################
150+
#### OpenAI prop models ###
151+
###########################
152+
153+
OPENAI_GPT_5_1 = ModelIdentifier(openai_name="gpt-5.1")
154+
148155
#####################
149156
#### Misc models ####
150157
#####################

mellea/backends/openai.py

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class OpenAIBackend(FormatterBackend, AdapterMixin):
7272

7373
def __init__(
7474
self,
75-
model_id: str | ModelIdentifier = model_ids.IBM_GRANITE_4_MICRO_3B,
75+
model_id: str | ModelIdentifier = model_ids.OPENAI_GPT_5_1,
7676
formatter: Formatter | None = None,
7777
base_url: str | None = None,
7878
model_options: dict | None = None,
@@ -152,16 +152,21 @@ def __init__(
152152
)
153153
self._hf_model_id = model_id.hf_model_name
154154

155-
if base_url is None:
156-
self._base_url = "http://localhost:11434/v1" # ollama
157-
else:
158-
self._base_url = base_url
159155
if api_key is None:
156+
FancyLogger.get_logger().warning(
157+
"You are using an OpenAI backend with no api_key. Because no API key was provided, mellea assumes you intend to use the openai-compatible interface to your local ollama instance. If you intend to use OpenAI's platform you must specify your API key when instantiating your Mellea session/backend object."
158+
)
159+
self._base_url: str | None = "http://localhost:11434/v1" # ollama
160160
self._api_key = "ollama"
161161
else:
162+
self._base_url = base_url
162163
self._api_key = api_key
163164

164-
self._server_type = _server_type(self._base_url)
165+
self._server_type: _ServerType = (
166+
_server_type(self._base_url)
167+
if self._base_url is not None
168+
else _ServerType.OPENAI
169+
) # type: ignore
165170

166171
self._openai_client_kwargs = self.filter_openai_client_kwargs(**kwargs)
167172

@@ -598,14 +603,38 @@ async def _generate_from_chat_context_standard(
598603

599604
extra_params: dict[str, Any] = {}
600605
if _format is not None:
601-
extra_params["response_format"] = {
602-
"type": "json_schema",
603-
"json_schema": {
604-
"name": _format.__name__,
605-
"schema": _format.model_json_schema(),
606-
"strict": True,
607-
},
608-
}
606+
if self._server_type == _ServerType.OPENAI:
607+
# The OpenAI platform requires that additionalProperties=False on all response_format schemas.
608+
# However, not all schemas generates by Mellea include additionalProperties.
609+
# GenerativeSlot, in particular, does not add this property.
610+
# The easiest way to address this disparity between OpenAI and other inference providers is to
611+
# monkey-patch the response format exactly when we are actually using the OpenAI server.
612+
#
613+
# This only addresses the additionalProperties=False constraint.
614+
# Other constraints we should be checking/patching are described here:
615+
# https://platform.openai.com/docs/guides/structured-outputs?api-mode=chat
616+
monkey_patched_response_schema = _format.model_json_schema()
617+
monkey_patched_response_schema["additionalProperties"] = False
618+
extra_params["response_format"] = {
619+
"type": "json_schema",
620+
"json_schema": {
621+
"name": _format.__name__,
622+
"schema": monkey_patched_response_schema,
623+
"strict": True,
624+
},
625+
}
626+
else:
627+
FancyLogger().get_logger().warning(
628+
"Mellea assumes you are NOT using the OpenAI platform, and that other model providers have less strict requirements on support JSON schemas passed into `format=`. If you encounter a server-side error following this message, then you found an exception to this assumption. Please open an issue at github.com/generative_computing/mellea with this stack trace and your inference engine / model provider."
629+
)
630+
extra_params["response_format"] = {
631+
"type": "json_schema",
632+
"json_schema": {
633+
"name": _format.__name__,
634+
"schema": _format.model_json_schema(),
635+
"strict": True,
636+
},
637+
}
609638

610639
# Append tool call information if applicable.
611640
tools: dict[str, Callable] = dict()
@@ -982,6 +1011,9 @@ def apply_chat_template(self, chat: list[dict[str, str]]):
9821011
from transformers import AutoTokenizer
9831012

9841013
if not hasattr(self, "_tokenizer"):
1014+
assert self._base_url, (
1015+
"The OpenAI Platform does not support adapters. You must specify a _base_url when using adapters."
1016+
)
9851017
match _server_type(self._base_url):
9861018
case _ServerType.LOCALHOST:
9871019
self._tokenizer: "PreTrainedTokenizer" = ( # noqa: UP037

0 commit comments

Comments
 (0)