From 8e50008f96b64b05e57c2ea2c0e698c7b6acefb5 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 16:05:38 +0000 Subject: [PATCH] Fix Gemini 4 Argon failing every request on temperature=None Gemini 4 Argon is registered with supports_temperature=False, so the backend passed temperature=None. Every other langchain- package reads None as "omit the field", but langchain-google-genai types temperature as a plain float and rejects None at construction, so each Argon request died with a pydantic ValidationError (HTTP 500) before reaching Google. Construct the Google model without temperature and clear it afterwards; a None temperature is dropped from the GenerationConfig, so the request carries no temperature, as the flag intends. The existing registry-wide TestTemperatureOmission test already failed on this; added an Argon case that also checks the outgoing generation config. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01PPgg6GMvTUcvZaEXu9JfQZ --- tee_gateway/llm_backend.py | 12 ++++++++++-- tee_gateway/test/test_tee_core.py | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tee_gateway/llm_backend.py b/tee_gateway/llm_backend.py index 77bd534..6ea591f 100644 --- a/tee_gateway/llm_backend.py +++ b/tee_gateway/llm_backend.py @@ -251,14 +251,22 @@ def get_chat_model_cached( response_modalities=[Modality.TEXT, Modality.IMAGE], ) - return ChatGoogleGenerativeAI( + # Unlike the other langchain- packages, langchain-google-genai + # types `temperature` as a plain float (default 0.7) and rejects None at + # construction. Build without it, then clear it: the field is not + # re-validated on assignment, and a None temperature is dropped from the + # outgoing GenerationConfig, so the request carries no temperature. + google_llm = ChatGoogleGenerativeAI( model=api_name, google_api_key=config.google_api_key, - temperature=effective_temp, + **({} if effective_temp is None else {"temperature": effective_temp}), max_output_tokens=max_tokens, thinking_budget=cfg.thinking_budget, include_thoughts=False if cfg.thinking_budget is not None else None, ) + if effective_temp is None: + google_llm.temperature = None # type: ignore[assignment] + return google_llm elif provider == "openai": if not config.openai_api_key: diff --git a/tee_gateway/test/test_tee_core.py b/tee_gateway/test/test_tee_core.py index 6cf95f4..7745116 100644 --- a/tee_gateway/test/test_tee_core.py +++ b/tee_gateway/test/test_tee_core.py @@ -1017,6 +1017,14 @@ def test_opus_omits_temperature(self): model = get_chat_model_cached("claude-opus-5", 0.0, 1024) self.assertIsNone(model.temperature) + def test_gemini_4_argon_omits_temperature(self): + """langchain-google-genai rejects temperature=None at construction, so + the Google path has to clear it afterwards — and it must then be absent + from the generation config actually sent.""" + model = get_chat_model_cached("gemini-4-argon", 0.0, 1024) + self.assertIsNone(model.temperature) + self.assertIsNone(model._prepare_params(stop=None).temperature) + def test_temperature_supporting_model_keeps_it(self): model = get_chat_model_cached("gpt-4.1", 0.0, 1024) self.assertEqual(model.temperature, 0.0)