Skip to content

Jinja2-based ComponentTools can't be passed into pipelines at runtime #9011

Open
@mathislucka

Description

@mathislucka

Describe the bug
When using a ComponentTool that uses a jinja2-based component (PromptBuilder, ChatPromptBuilder, ...) and try to pass the tool to a pipeline at runtime, we get a deepcopy error originating from here.

Error message

>>> from haystack.components.builders import PromptBuilder
>>> from copy import deepcopy
>>> deepcopy(PromptBuilder("Hello"))
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    deepcopy(PromptBuilder("Hello"))
    ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/copy.py", line 163, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/copy.py", line 260, in _reconstruct
    state = deepcopy(state, memo)
  File "/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/copy.py", line 137, in deepcopy
    y = copier(x, memo)
  File "/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/copy.py", line 222, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
                             ~~~~~~~~^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/copy.py", line 163, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/copy.py", line 254, in _reconstruct
    y = func(*args)
  File "/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/copyreg.py", line 99, in __newobj__
    return cls.__new__(cls, *args)
           ~~~~~~~~~~~^^^^^^^^^^^^
TypeError: Template.__new__() missing 1 required positional argument: 'source'

Expected behavior
ComponentTools can be passed to pipelines at runtime.

Additional context
We should rethink our usage of deepcopy in Pipeline.run.
We use deepcopy to avoid hard-to-debug problems where one component mutates inputs for another component.
Generally, that is a valid concern but not all component inputs benefit from deepcopy and some of them might even cause errors (like the Jinja2-based components).
We might:

  • remove some usages of deepcopy that are unnecessary
  • skip deepcopy for certain types
  • handle exceptions gracefully

To Reproduce
Steps to reproduce the behavior

FAQ Check

System:

  • OS:
  • GPU/CPU:
  • Haystack version (commit or version number):
  • DocumentStore:
  • Reader:
  • Retriever:

Metadata

Metadata

Assignees

Labels

P1High priority, add to the next sprinttype:bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions