Open
Description
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
- Have you had a look at our new FAQ page?
System:
- OS:
- GPU/CPU:
- Haystack version (commit or version number):
- DocumentStore:
- Reader:
- Retriever: