Skip to content

fix: guard FallbackChatGenerator.warm_up() against repeated initialization - #11977

Closed
rautaditya2606 wants to merge 1 commit into
deepset-ai:mainfrom
rautaditya2606:fix/fallback-chat-generator-warm-up-lifecycle
Closed

fix: guard FallbackChatGenerator.warm_up() against repeated initialization#11977
rautaditya2606 wants to merge 1 commit into
deepset-ai:mainfrom
rautaditya2606:fix/fallback-chat-generator-warm-up-lifecycle

Conversation

@rautaditya2606

@rautaditya2606 rautaditya2606 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Related Issues

Fixes #11976


Proposed Changes

  • Add self._warmed_up = False to FallbackChatGenerator.__init__.
  • Guard warm_up() with if not self._warmed_up: ... self._warmed_up = True so wrapped generators are initialized at most once, matching the lifecycle semantics of other Haystack components.
  • Apply the same guard to warm_up_async().
  • Add two regression tests:
    • test_warm_up_only_called_once_across_multiple_run_calls
    • test_warm_up_async_only_called_once_across_multiple_run_async_calls
  • Add a release note.

How did you test it?

hatch run test:unit test/components/generators/chat/test_fallback.py

All 32 tests passed.


Notes for the reviewer

This PR fixes a lifecycle contract inconsistency in FallbackChatGenerator.

run() and run_async() currently invoke warm_up() on every execution. Unlike other Haystack components that perform one-time lazy initialization, FallbackChatGenerator repeatedly delegates warm_up() to its wrapped generators. This means a custom generator with non-idempotent initialization logic may be reinitialized every time it is used through FallbackChatGenerator.

This change introduces a _warmed_up guard, consistent with the pattern already used by components such as Agent and other generators. Wrapped generators are now warmed up at most once, while preserving existing behavior for generators whose warm_up() implementations are already idempotent.


Checklist

  • Read contributors guidelines and code of conduct
  • Updated related issue
  • Added unit tests
  • Used conventional commit type in PR title
  • Documented code
  • Added release note
  • Run pre-commit hooks and fixed any issues

Copilot AI review requested due to automatic review settings July 13, 2026 08:24
@rautaditya2606
rautaditya2606 requested a review from a team as a code owner July 13, 2026 08:24
@rautaditya2606
rautaditya2606 requested review from sjrl and removed request for a team July 13, 2026 08:24
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

@rautaditya2606 is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

@sjrl

sjrl commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

See comment here #11976 (comment)

@sjrl sjrl closed this Jul 13, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes repeated initialization in FallbackChatGenerator by guarding warm_up() / warm_up_async() so wrapped generators aren’t warmed up on every run() / run_async() call.

Changes:

  • Add a _warmed_up flag to make warm_up() idempotent.
  • Apply the same guard to warm_up_async().
  • Add regression tests ensuring warm-up is only delegated once across multiple runs, plus a release note.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
haystack/components/generators/chat/fallback.py Adds _warmed_up guard to prevent repeated warm-up on every run.
test/components/generators/chat/test_fallback.py Adds sync + async regression tests for “warm up only once across multiple runs”.
releasenotes/notes/fix-fallback-warm-up-lifecycle-da9d4b4af6a25872.yaml Documents the lifecycle semantic fix in release notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 98 to +106
async def warm_up_async(self) -> None:
"""Warm up all underlying chat generators on the serving event loop."""
for gen in self.chat_generators:
if hasattr(gen, "warm_up_async"):
await gen.warm_up_async()
elif hasattr(gen, "warm_up"):
gen.warm_up()
"""Warm up all underlying chat generators on the serving event loop (called at most once)."""
if not self._warmed_up:
for gen in self.chat_generators:
if hasattr(gen, "warm_up_async"):
await gen.warm_up_async()
elif hasattr(gen, "warm_up"):
gen.warm_up()
self._warmed_up = True
Comment on lines 62 to +63
self.chat_generators = list(chat_generators)
self._warmed_up = False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FallbackChatGenerator repeatedly calls warm_up() on every run() invocation

3 participants