mirror of
https://github.com/deepset-ai/haystack.git
synced 2026-01-04 11:07:52 +00:00
fix: serialization of nested ChatMessage in GeneratedAnswerdataclass (#9497)
* Fix serialization * small fix * fix the erros * Fix tests * PR comments
This commit is contained in:
parent
12665ade14
commit
1d6a9f652a
@ -6,7 +6,7 @@ from dataclasses import asdict, dataclass, field
|
||||
from typing import Any, Dict, List, Optional, Protocol, runtime_checkable
|
||||
|
||||
from haystack.core.serialization import default_from_dict, default_to_dict
|
||||
from haystack.dataclasses.document import Document
|
||||
from haystack.dataclasses import ChatMessage, Document
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
@ -99,7 +99,16 @@ class GeneratedAnswer:
|
||||
Serialized dictionary representation of the object.
|
||||
"""
|
||||
documents = [doc.to_dict(flatten=False) for doc in self.documents]
|
||||
return default_to_dict(self, data=self.data, query=self.query, documents=documents, meta=self.meta)
|
||||
|
||||
# Serialize ChatMessage objects to dicts
|
||||
meta = self.meta
|
||||
all_messages = meta.get("all_messages")
|
||||
|
||||
# all_messages is either a list of ChatMessage objects or a list of strings
|
||||
if all_messages and isinstance(all_messages[0], ChatMessage):
|
||||
meta = {**meta, "all_messages": [msg.to_dict() for msg in all_messages]}
|
||||
|
||||
return default_to_dict(self, data=self.data, query=self.query, documents=documents, meta=meta)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "GeneratedAnswer":
|
||||
@ -113,7 +122,13 @@ class GeneratedAnswer:
|
||||
Deserialized object.
|
||||
"""
|
||||
init_params = data.get("init_parameters", {})
|
||||
|
||||
if (documents := init_params.get("documents")) is not None:
|
||||
data["init_parameters"]["documents"] = [Document.from_dict(d) for d in documents]
|
||||
init_params["documents"] = [Document.from_dict(d) for d in documents]
|
||||
|
||||
meta = init_params.get("meta", {})
|
||||
if (all_messages := meta.get("all_messages")) is not None and isinstance(all_messages[0], dict):
|
||||
meta["all_messages"] = [ChatMessage.from_dict(m) for m in all_messages]
|
||||
init_params["meta"] = meta
|
||||
|
||||
return default_from_dict(cls, data)
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
---
|
||||
fixes:
|
||||
- Fix serialization of `GeneratedAnswer` when `ChatMessage` objects are nested in `meta`.
|
||||
@ -52,6 +52,7 @@ class TestAnswerBuilder:
|
||||
assert answers[0].data == "reply1"
|
||||
_check_metadata_excluding_all_messages(answers[0].meta, {"test": "meta"})
|
||||
assert "all_messages" in answers[0].meta
|
||||
assert answers[0].meta["all_messages"] == ["reply1"]
|
||||
assert answers[0].query == "query"
|
||||
assert answers[0].documents == []
|
||||
assert isinstance(answers[0], GeneratedAnswer)
|
||||
@ -254,6 +255,9 @@ class TestAnswerBuilder:
|
||||
assert answers[0].query == "test query"
|
||||
assert len(answers[0].documents) == 1
|
||||
assert answers[0].documents[0].content == "test doc 2"
|
||||
assert answers[0].meta["all_messages"] == [
|
||||
ChatMessage.from_assistant("Answer: AnswerString[2]", meta=message_meta)
|
||||
]
|
||||
|
||||
def test_run_with_chat_message_replies_with_pattern_set_at_runtime(self):
|
||||
component = AnswerBuilder(pattern="unused pattern")
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from haystack.dataclasses.answer import Answer, ExtractedAnswer, GeneratedAnswer
|
||||
from haystack.dataclasses.document import Document
|
||||
from haystack.dataclasses import Document, ChatMessage
|
||||
|
||||
|
||||
class TestExtractedAnswer:
|
||||
@ -133,13 +133,40 @@ class TestGeneratedAnswer:
|
||||
assert isinstance(answer, Answer)
|
||||
|
||||
def test_to_dict(self):
|
||||
answer = GeneratedAnswer(data="42", query="What is the answer?", documents=[])
|
||||
assert answer.to_dict() == {
|
||||
"type": "haystack.dataclasses.answer.GeneratedAnswer",
|
||||
"init_parameters": {"data": "42", "query": "What is the answer?", "documents": [], "meta": {}},
|
||||
}
|
||||
|
||||
def test_to_dict_with_meta(self):
|
||||
answer = GeneratedAnswer(
|
||||
data="42",
|
||||
query="What is the answer?",
|
||||
documents=[],
|
||||
meta={"meta_key": "meta_value", "all_messages": ["What is the answer?"]},
|
||||
)
|
||||
assert answer.to_dict() == {
|
||||
"type": "haystack.dataclasses.answer.GeneratedAnswer",
|
||||
"init_parameters": {
|
||||
"data": "42",
|
||||
"query": "What is the answer?",
|
||||
"documents": [],
|
||||
"meta": {"meta_key": "meta_value", "all_messages": ["What is the answer?"]},
|
||||
},
|
||||
}
|
||||
|
||||
def test_to_dict_with_chat_message_in_meta(self):
|
||||
documents = [
|
||||
Document(id="1", content="The answer is 42."),
|
||||
Document(id="2", content="I believe the answer is 42."),
|
||||
Document(id="3", content="42 is definitely the answer."),
|
||||
]
|
||||
answer = GeneratedAnswer(
|
||||
data="42", query="What is the answer?", documents=documents, meta={"meta_key": "meta_value"}
|
||||
data="42",
|
||||
query="What is the answer?",
|
||||
documents=documents,
|
||||
meta={"meta_key": "meta_value", "all_messages": [ChatMessage.from_user("What is the answer?")]},
|
||||
)
|
||||
assert answer.to_dict() == {
|
||||
"type": "haystack.dataclasses.answer.GeneratedAnswer",
|
||||
@ -147,11 +174,44 @@ class TestGeneratedAnswer:
|
||||
"data": "42",
|
||||
"query": "What is the answer?",
|
||||
"documents": [d.to_dict(flatten=False) for d in documents],
|
||||
"meta": {"meta_key": "meta_value"},
|
||||
"meta": {
|
||||
"meta_key": "meta_value",
|
||||
"all_messages": [ChatMessage.from_user("What is the answer?").to_dict()],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def test_from_dict(self):
|
||||
answer = GeneratedAnswer.from_dict(
|
||||
{
|
||||
"type": "haystack.dataclasses.answer.GeneratedAnswer",
|
||||
"init_parameters": {"data": "42", "query": "What is the answer?", "documents": [], "meta": {}},
|
||||
}
|
||||
)
|
||||
assert answer.data == "42"
|
||||
assert answer.query == "What is the answer?"
|
||||
assert answer.documents == []
|
||||
assert answer.meta == {}
|
||||
|
||||
def test_from_dict_with_meta(self):
|
||||
answer = GeneratedAnswer.from_dict(
|
||||
{
|
||||
"type": "haystack.dataclasses.answer.GeneratedAnswer",
|
||||
"init_parameters": {
|
||||
"data": "42",
|
||||
"query": "What is the answer?",
|
||||
"documents": [],
|
||||
"meta": {"meta_key": "meta_value", "all_messages": ["What is the answer?"]},
|
||||
},
|
||||
}
|
||||
)
|
||||
assert answer.data == "42"
|
||||
assert answer.query == "What is the answer?"
|
||||
assert answer.documents == []
|
||||
assert answer.meta["meta_key"] == "meta_value"
|
||||
assert answer.meta["all_messages"] == ["What is the answer?"]
|
||||
|
||||
def test_from_dict_with_chat_message_in_meta(self):
|
||||
answer = GeneratedAnswer.from_dict(
|
||||
{
|
||||
"type": "haystack.dataclasses.answer.GeneratedAnswer",
|
||||
@ -163,7 +223,10 @@ class TestGeneratedAnswer:
|
||||
{"id": "2", "content": "I believe the answer is 42."},
|
||||
{"id": "3", "content": "42 is definitely the answer."},
|
||||
],
|
||||
"meta": {"meta_key": "meta_value"},
|
||||
"meta": {
|
||||
"meta_key": "meta_value",
|
||||
"all_messages": [ChatMessage.from_user("What is the answer?").to_dict()],
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -174,4 +237,5 @@ class TestGeneratedAnswer:
|
||||
Document(id="2", content="I believe the answer is 42."),
|
||||
Document(id="3", content="42 is definitely the answer."),
|
||||
]
|
||||
assert answer.meta == {"meta_key": "meta_value"}
|
||||
assert answer.meta["meta_key"] == "meta_value"
|
||||
assert answer.meta["all_messages"] == [ChatMessage.from_user("What is the answer?")]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user