Skip to content

Commit b85c8e3

Browse files
feat: adding deserialize_component_inplace() (#9459)
* adding tests * adding release notes * deserialize_chatgenerator_inplace uses deserialize_component_inplace * removing tests
1 parent 25c8d7e commit b85c8e3

File tree

3 files changed

+38
-19
lines changed

3 files changed

+38
-19
lines changed

haystack/utils/deserialization.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,40 @@ def deserialize_chatgenerator_inplace(data: Dict[str, Any], key: str = "chat_gen
4848
:param key:
4949
The key in the dictionary where the ChatGenerator is stored.
5050
51+
:raises DeserializationError:
52+
If the key is missing in the serialized data, the value is not a dictionary,
53+
the type key is missing, the class cannot be imported, or the class lacks a 'from_dict' method.
54+
"""
55+
deserialize_component_inplace(data, key=key)
56+
57+
58+
def deserialize_component_inplace(data: Dict[str, Any], key: str = "chat_generator") -> None:
59+
"""
60+
Deserialize a Component in a dictionary inplace.
61+
62+
:param data:
63+
The dictionary with the serialized data.
64+
:param key:
65+
The key in the dictionary where the Component is stored. Default is "chat_generator".
66+
5167
:raises DeserializationError:
5268
If the key is missing in the serialized data, the value is not a dictionary,
5369
the type key is missing, the class cannot be imported, or the class lacks a 'from_dict' method.
5470
"""
5571
if key not in data:
5672
raise DeserializationError(f"Missing '{key}' in serialization data")
5773

58-
serialized_chat_generator = data[key]
74+
serialized_component = data[key]
5975

60-
if not isinstance(serialized_chat_generator, dict):
76+
if not isinstance(serialized_component, dict):
6177
raise DeserializationError(f"The value of '{key}' is not a dictionary")
6278

63-
if "type" not in serialized_chat_generator:
79+
if "type" not in serialized_component:
6480
raise DeserializationError(f"Missing 'type' in {key} serialization data")
6581

6682
try:
67-
chat_generator_class = import_class_by_name(serialized_chat_generator["type"])
83+
component_class = import_class_by_name(serialized_component["type"])
6884
except ImportError as e:
69-
raise DeserializationError(f"Class '{serialized_chat_generator['type']}' not correctly imported") from e
85+
raise DeserializationError(f"Class '{serialized_component['type']}' not correctly imported") from e
7086

71-
data[key] = component_from_dict(cls=chat_generator_class, data=serialized_chat_generator, name="chat_generator")
87+
data[key] = component_from_dict(cls=component_class, data=serialized_component, name=key)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
enhancements:
3+
- |
4+
Added a new `deserialize_component_inplace` function to handle generic component deserialization that works with any component type.

test/utils/test_deserialization.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from haystack.document_stores.in_memory.document_store import InMemoryDocumentStore
99
from haystack.utils.deserialization import (
1010
deserialize_document_store_in_init_params_inplace,
11-
deserialize_chatgenerator_inplace,
11+
deserialize_component_inplace,
1212
)
1313
from haystack.core.errors import DeserializationError
1414
from haystack.components.generators.chat.openai import OpenAIChatGenerator
@@ -97,38 +97,37 @@ def test_invalid_class_import(self):
9797
deserialize_document_store_in_init_params_inplace(data)
9898

9999

100-
class TestDeserializeChatGeneratorInplace:
101-
def test_deserialize_chatgenerator_inplace(self, monkeypatch):
100+
class TestDeserializeComponentInplace:
101+
def test_deserialize_component_inplace(self, monkeypatch):
102102
monkeypatch.setenv("OPENAI_API_KEY", "test-api-key")
103103
chat_generator = OpenAIChatGenerator()
104104
data = {"chat_generator": chat_generator.to_dict()}
105-
106-
deserialize_chatgenerator_inplace(data)
105+
deserialize_component_inplace(data)
107106
assert isinstance(data["chat_generator"], OpenAIChatGenerator)
108107
assert data["chat_generator"].to_dict() == chat_generator.to_dict()
109108

110-
def test_missing_chat_generator_key(self):
109+
def test_missing_key(self):
111110
data = {"some_key": "some_value"}
112111
with pytest.raises(DeserializationError):
113-
deserialize_chatgenerator_inplace(data)
112+
deserialize_component_inplace(data)
114113

115-
def test_chat_generator_is_not_a_dict(self):
114+
def test_component_is_not_a_dict(self):
116115
data = {"chat_generator": "not_a_dict"}
117116
with pytest.raises(DeserializationError):
118-
deserialize_chatgenerator_inplace(data)
117+
deserialize_component_inplace(data)
119118

120119
def test_type_key_missing(self):
121120
data = {"chat_generator": {"some_key": "some_value"}}
122121
with pytest.raises(DeserializationError):
123-
deserialize_chatgenerator_inplace(data)
122+
deserialize_component_inplace(data)
124123

125124
def test_class_not_correctly_imported(self):
126125
data = {"chat_generator": {"type": "invalid.module.InvalidClass"}}
127126
with pytest.raises(DeserializationError):
128-
deserialize_chatgenerator_inplace(data)
127+
deserialize_component_inplace(data)
129128

130-
def test_chat_generator_no_from_dict_method(self):
129+
def test_component_no_from_dict_method(self):
131130
chat_generator = ChatGeneratorWithoutFromDict()
132131
data = {"chat_generator": chat_generator.to_dict()}
133-
deserialize_chatgenerator_inplace(data)
132+
deserialize_component_inplace(data)
134133
assert isinstance(data["chat_generator"], ChatGeneratorWithoutFromDict)

0 commit comments

Comments
 (0)