Description
Is your feature request related to a problem? Please describe.
Currently, the component registry in Haystack only stores the complete module path of components. When users create init files to re-export components with shorter paths (a common Python pattern), the registry isn't updated. This forces users to always use the complete path during serialization and deserialization.
For example, if a user has:
# haystack/components/retrievers/memory.py
@component
class MemoryRetriever:
And __init__
file:
# haystack/components/__init__.py
from .retrievers.memory import MemoryRetriever
They still need to use haystack.components.retrievers.memory.MemoryRetriever
in serialized pipelines instead of the shorter haystack.components.MemoryRetriever
as it wont work.
Describe the solution you'd like
Enhance the component registry to track both original paths and re-exported paths (aliases). Below is one possible solution.
Dynamic Registry Update During Import: Update the registry when components are re-exported through init files. We could modify the _component
decorator to track both the original and re-exported paths. A quick implementation suggest by cursor for reference:
class _Component:
def __init__(self):
# Map of original path -> list of alias paths
self.registry = {}
self.alias_registry = {} # alias -> original path
def _component(self, cls: Any):
logger.debug("Registering {component} as a component", component=cls)
if not hasattr(cls, "run"):
raise ComponentError(f"{cls.__name__} must have a 'run()' method. See the docs for more information.")
# Create the new class with metaclass as before
new_cls = new_class(cls.__name__, cls.__bases__, {"metaclass": ComponentMeta}, copy_class_namespace)
# Get both the original path and current import path
original_path = f"{cls.__module__}.{cls.__name__}"
current_path = f"{new_cls.__module__}.{new_cls.__name__}"
# Register both paths
if original_path not in self.registry:
self.registry[original_path] = new_cls
# Add alias if this is a re-export
if current_path != original_path:
self.alias_registry[current_path] = original_path
logger.debug(
"Added alias {alias} for component {original}",
alias=current_path,
original=original_path
)
return new_cls
Alternate Solutions
We could maintain a separate index by class name to help with resolution.