From 3beb320639d18010c3cae46f67d649b06cf04070 Mon Sep 17 00:00:00 2001 From: Alex Castillo Date: Sun, 30 Aug 2026 22:44:31 -0400 Subject: [PATCH 1/2] fix: serialize timeout and max_retries in OpenAIImageGenerator.to_dict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both are stored on the instance and feed _client_kwargs(), but to_dict dropped them, so a saved pipeline reloaded with the OPENAI_TIMEOUT/OPENAI_MAX_RETRIES fallbacks (30s, 5) instead of the configured values. OpenAIChatGenerator, OpenAITextEmbedder and OpenAIDocumentEmbedder already serialize both — the embedders since #9421, which fixed this same defect for them. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01PqBhR4HokMA14K9nLLQDTh --- .../generators/openai_image_generator.py | 2 ++ ...ize-timeout-max-retries-4b1d0e77a9c62f31.yaml | 8 ++++++++ .../generators/test_openai_image_generator.py | 16 ++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml diff --git a/haystack/components/generators/openai_image_generator.py b/haystack/components/generators/openai_image_generator.py index 1dc47dc79c0..867ce3385c0 100644 --- a/haystack/components/generators/openai_image_generator.py +++ b/haystack/components/generators/openai_image_generator.py @@ -238,6 +238,8 @@ def to_dict(self) -> dict[str, Any]: api_key=self.api_key, api_base_url=self.api_base_url, organization=self.organization, + timeout=self.timeout, + max_retries=self.max_retries, http_client_kwargs=self.http_client_kwargs, ) diff --git a/releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml b/releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml new file mode 100644 index 00000000000..fa7ae0a4a19 --- /dev/null +++ b/releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Add the init parameters `timeout` and `max_retries` to the `to_dict` method of + `OpenAIImageGenerator`. They were dropped on serialization, so a pipeline saved and + reloaded silently fell back to the `OPENAI_TIMEOUT`/`OPENAI_MAX_RETRIES` defaults + instead of the configured values. This matches `OpenAIChatGenerator`, + `OpenAITextEmbedder` and `OpenAIDocumentEmbedder`, which already serialize both. diff --git a/test/components/generators/test_openai_image_generator.py b/test/components/generators/test_openai_image_generator.py index 2c9998a446f..fbb317c2f12 100644 --- a/test/components/generators/test_openai_image_generator.py +++ b/test/components/generators/test_openai_image_generator.py @@ -88,6 +88,8 @@ def test_to_dict(self) -> None: "api_key": {"type": "env_var", "env_vars": ["OPENAI_API_KEY"], "strict": True}, "api_base_url": None, "organization": None, + "timeout": None, + "max_retries": None, "http_client_kwargs": None, }, } @@ -114,6 +116,8 @@ def test_to_dict_with_params(self) -> None: "api_key": {"type": "env_var", "env_vars": ["EXAMPLE_API_KEY"], "strict": True}, "api_base_url": "https://api.openai.com", "organization": "test-org", + "timeout": 60, + "max_retries": 10, "http_client_kwargs": {"proxy": "http://localhost:8080"}, }, } @@ -138,6 +142,18 @@ def test_from_dict(self) -> None: assert generator.api_key.to_dict() == {"type": "env_var", "env_vars": ["OPENAI_API_KEY"], "strict": True} assert generator.http_client_kwargs is None + def test_to_dict_from_dict_roundtrip_preserves_client_settings(self, monkeypatch: pytest.MonkeyPatch) -> None: + """`timeout` and `max_retries` decide the client the component builds, so a pipeline + that survives a save/load round trip must keep them. Without them in `to_dict` they + silently revert to the `OPENAI_TIMEOUT`/`OPENAI_MAX_RETRIES` fallbacks (30s, 5).""" + monkeypatch.setenv("OPENAI_API_KEY", "test-api-key") + generator = OpenAIImageGenerator(timeout=120.0, max_retries=10) + restored = OpenAIImageGenerator.from_dict(generator.to_dict()) + assert restored.timeout == 120.0 + assert restored.max_retries == 10 + assert restored._client_kwargs()["timeout"] == 120.0 + assert restored._client_kwargs()["max_retries"] == 10 + def test_from_dict_default_params(self) -> None: data = { "type": "haystack.components.generators.openai_image_generator.OpenAIImageGenerator", From b1c7440f90b4cd50ce692e8bf89fec002eed1263 Mon Sep 17 00:00:00 2001 From: Alex Castillo Date: Sun, 30 Aug 2026 22:55:53 -0400 Subject: [PATCH 2/2] docs: use double backticks in the release note for reST --- ...serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml b/releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml index fa7ae0a4a19..0e336c82f02 100644 --- a/releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml +++ b/releasenotes/notes/openai-image-generator-serialize-timeout-max-retries-4b1d0e77a9c62f31.yaml @@ -1,8 +1,8 @@ --- fixes: - | - Add the init parameters `timeout` and `max_retries` to the `to_dict` method of - `OpenAIImageGenerator`. They were dropped on serialization, so a pipeline saved and - reloaded silently fell back to the `OPENAI_TIMEOUT`/`OPENAI_MAX_RETRIES` defaults - instead of the configured values. This matches `OpenAIChatGenerator`, - `OpenAITextEmbedder` and `OpenAIDocumentEmbedder`, which already serialize both. + Add the init parameters ``timeout`` and ``max_retries`` to the ``to_dict`` method of + ``OpenAIImageGenerator``. They were dropped on serialization, so a pipeline saved and + reloaded silently fell back to the ``OPENAI_TIMEOUT``/``OPENAI_MAX_RETRIES`` defaults + instead of the configured values. This matches ``OpenAIChatGenerator``, + ``OpenAITextEmbedder`` and ``OpenAIDocumentEmbedder``, which already serialize both.