-
Notifications
You must be signed in to change notification settings - Fork 3k
Expand file tree
/
Copy pathanswer.py
More file actions
146 lines (116 loc) · 4.63 KB
/
Copy pathanswer.py
File metadata and controls
146 lines (116 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
#
# SPDX-License-Identifier: Apache-2.0
from dataclasses import asdict, dataclass, field
from typing import Any, Optional, Protocol, runtime_checkable
from haystack.core.serialization import default_from_dict, default_to_dict
from haystack.dataclasses import ChatMessage, Document
from haystack.utils.dataclasses import _warn_on_inplace_mutation
@runtime_checkable
@dataclass
class Answer(Protocol):
data: Any
query: str
meta: dict[str, Any]
def to_dict(self) -> dict[str, Any]: # noqa: D102
...
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "Answer": # noqa: D102
...
@_warn_on_inplace_mutation
@dataclass
class ExtractedAnswer:
"""
Holds an answer extracted by an extractive Reader (query, score, text, and optional document/context).
"""
query: str
score: float
data: str | None = None
document: Document | None = None
context: str | None = None
document_offset: Optional["Span"] = None
context_offset: Optional["Span"] = None
meta: dict[str, Any] = field(default_factory=dict)
@_warn_on_inplace_mutation
@dataclass
class Span:
start: int
end: int
def to_dict(self) -> dict[str, Any]:
"""
Serialize the object to a dictionary.
:returns:
Serialized dictionary representation of the object.
"""
document = self.document.to_dict(flatten=False) if self.document is not None else None
document_offset = asdict(self.document_offset) if self.document_offset is not None else None
context_offset = asdict(self.context_offset) if self.context_offset is not None else None
return default_to_dict(
self,
data=self.data,
query=self.query,
document=document,
context=self.context,
score=self.score,
document_offset=document_offset,
context_offset=context_offset,
meta=self.meta,
)
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "ExtractedAnswer":
"""
Deserialize the object from a dictionary.
:param data:
Dictionary representation of the object.
:returns:
Deserialized object.
"""
init_params = data.get("init_parameters", {})
if (doc := init_params.get("document")) is not None:
data["init_parameters"]["document"] = Document.from_dict(doc)
if (offset := init_params.get("document_offset")) is not None:
data["init_parameters"]["document_offset"] = ExtractedAnswer.Span(**offset)
if (offset := init_params.get("context_offset")) is not None:
data["init_parameters"]["context_offset"] = ExtractedAnswer.Span(**offset)
return default_from_dict(cls, data)
@_warn_on_inplace_mutation
@dataclass
class GeneratedAnswer:
"""
Holds a generated answer from a Generator (answer text, query, referenced documents, and metadata).
"""
data: str
query: str
documents: list[Document]
meta: dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> dict[str, Any]:
"""
Serialize the object to a dictionary.
:returns:
Serialized dictionary representation of the object.
"""
documents = [doc.to_dict(flatten=False) for doc in self.documents]
# 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":
"""
Deserialize the object from a dictionary.
:param data:
Dictionary representation of the object.
:returns:
Deserialized object.
"""
init_params = data.get("init_parameters", {})
if (documents := init_params.get("documents")) is not None:
init_params["documents"] = [Document.from_dict(d) for d in documents]
meta = init_params.get("meta", {})
if (all_messages := meta.get("all_messages")) 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)