Skip to content

Commit 51c1390

Browse files
authored
chore: use class methods to create ChatMessage (#8581)
* use class methods to build messages * fix failing format
1 parent 473f7be commit 51c1390

File tree

5 files changed

+62
-95
lines changed

5 files changed

+62
-95
lines changed

Diff for: haystack/core/pipeline/base.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ def from_dict(
183183
"Component was deserialized with the following data:"
184184
f"{str(component_data)}."
185185
"Possible reasons include malformed serialized data, mismatch between the serialized component "
186-
"and the loaded one (due to a breaking change, see https://github.com/deepset-ai/haystack/releases), etc."
186+
"and the loaded one (due to a breaking change, see "
187+
"https://github.com/deepset-ai/haystack/releases), etc."
187188
)
188189
raise DeserializationError(msg) from error
189190
pipe.add_component(name=name, instance=instance)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
enhancements:
3+
- |
4+
Across Haystack codebase, we have replaced the use of `ChatMessage` dataclass constructor with specific
5+
class methods (`ChatMessage.from_user`, `ChatMessage.from_assistant`, etc.).

Diff for: test/components/builders/test_answer_builder.py

+45-87
Original file line numberDiff line numberDiff line change
@@ -164,77 +164,54 @@ def test_run_with_reference_pattern_set_at_runtime(self):
164164

165165
def test_run_with_chat_message_replies_without_pattern(self):
166166
component = AnswerBuilder()
167-
replies = [
168-
ChatMessage(
169-
content="Answer: AnswerString",
170-
role=ChatRole.ASSISTANT,
171-
name=None,
172-
meta={
173-
"model": "gpt-4o-mini",
174-
"index": 0,
175-
"finish_reason": "stop",
176-
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
177-
},
178-
)
179-
]
180-
output = component.run(query="test query", replies=replies, meta=[{}])
181-
answers = output["answers"]
182-
assert len(answers) == 1
183-
assert answers[0].data == "Answer: AnswerString"
184-
assert answers[0].meta == {
167+
168+
message_meta = {
185169
"model": "gpt-4o-mini",
186170
"index": 0,
187171
"finish_reason": "stop",
188172
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
189173
}
174+
replies = [ChatMessage.from_assistant("Answer: AnswerString", meta=message_meta)]
175+
176+
output = component.run(query="test query", replies=replies, meta=[{}])
177+
answers = output["answers"]
178+
assert len(answers) == 1
179+
assert answers[0].data == "Answer: AnswerString"
180+
assert answers[0].meta == message_meta
190181
assert answers[0].query == "test query"
191182
assert answers[0].documents == []
192183
assert isinstance(answers[0], GeneratedAnswer)
193184

194185
def test_run_with_chat_message_replies_with_pattern(self):
195186
component = AnswerBuilder(pattern=r"Answer: (.*)")
196-
replies = [
197-
ChatMessage(
198-
content="Answer: AnswerString",
199-
role=ChatRole.ASSISTANT,
200-
name=None,
201-
meta={
202-
"model": "gpt-4o-mini",
203-
"index": 0,
204-
"finish_reason": "stop",
205-
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
206-
},
207-
)
208-
]
209-
output = component.run(query="test query", replies=replies, meta=[{}])
210-
answers = output["answers"]
211-
assert len(answers) == 1
212-
assert answers[0].data == "AnswerString"
213-
assert answers[0].meta == {
187+
188+
message_meta = {
214189
"model": "gpt-4o-mini",
215190
"index": 0,
216191
"finish_reason": "stop",
217192
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
218193
}
194+
replies = [ChatMessage.from_assistant("Answer: AnswerString", meta=message_meta)]
195+
196+
output = component.run(query="test query", replies=replies, meta=[{}])
197+
answers = output["answers"]
198+
assert len(answers) == 1
199+
assert answers[0].data == "AnswerString"
200+
assert answers[0].meta == message_meta
219201
assert answers[0].query == "test query"
220202
assert answers[0].documents == []
221203
assert isinstance(answers[0], GeneratedAnswer)
222204

223205
def test_run_with_chat_message_replies_with_documents(self):
224206
component = AnswerBuilder(reference_pattern="\\[(\\d+)\\]")
225-
replies = [
226-
ChatMessage(
227-
content="Answer: AnswerString[2]",
228-
role=ChatRole.ASSISTANT,
229-
name=None,
230-
meta={
231-
"model": "gpt-4o-mini",
232-
"index": 0,
233-
"finish_reason": "stop",
234-
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
235-
},
236-
)
237-
]
207+
message_meta = {
208+
"model": "gpt-4o-mini",
209+
"index": 0,
210+
"finish_reason": "stop",
211+
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
212+
}
213+
replies = [ChatMessage.from_assistant("Answer: AnswerString[2]", meta=message_meta)]
214+
238215
output = component.run(
239216
query="test query",
240217
replies=replies,
@@ -244,60 +221,40 @@ def test_run_with_chat_message_replies_with_documents(self):
244221
answers = output["answers"]
245222
assert len(answers) == 1
246223
assert answers[0].data == "Answer: AnswerString[2]"
247-
assert answers[0].meta == {
248-
"model": "gpt-4o-mini",
249-
"index": 0,
250-
"finish_reason": "stop",
251-
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
252-
}
224+
assert answers[0].meta == message_meta
253225
assert answers[0].query == "test query"
254226
assert len(answers[0].documents) == 1
255227
assert answers[0].documents[0].content == "test doc 2"
256228

257229
def test_run_with_chat_message_replies_with_pattern_set_at_runtime(self):
258230
component = AnswerBuilder(pattern="unused pattern")
259-
replies = [
260-
ChatMessage(
261-
content="Answer: AnswerString",
262-
role=ChatRole.ASSISTANT,
263-
name=None,
264-
meta={
265-
"model": "gpt-4o-mini",
266-
"index": 0,
267-
"finish_reason": "stop",
268-
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
269-
},
270-
)
271-
]
272-
output = component.run(query="test query", replies=replies, meta=[{}], pattern=r"Answer: (.*)")
273-
answers = output["answers"]
274-
assert len(answers) == 1
275-
assert answers[0].data == "AnswerString"
276-
assert answers[0].meta == {
231+
message_meta = {
277232
"model": "gpt-4o-mini",
278233
"index": 0,
279234
"finish_reason": "stop",
280235
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
281236
}
237+
replies = [ChatMessage.from_assistant("Answer: AnswerString", meta=message_meta)]
238+
239+
output = component.run(query="test query", replies=replies, meta=[{}], pattern=r"Answer: (.*)")
240+
answers = output["answers"]
241+
assert len(answers) == 1
242+
assert answers[0].data == "AnswerString"
243+
assert answers[0].meta == message_meta
282244
assert answers[0].query == "test query"
283245
assert answers[0].documents == []
284246
assert isinstance(answers[0], GeneratedAnswer)
285247

286248
def test_run_with_chat_message_replies_with_meta_set_at_run_time(self):
287249
component = AnswerBuilder()
288-
replies = [
289-
ChatMessage(
290-
content="AnswerString",
291-
role=ChatRole.ASSISTANT,
292-
name=None,
293-
meta={
294-
"model": "gpt-4o-mini",
295-
"index": 0,
296-
"finish_reason": "stop",
297-
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
298-
},
299-
)
300-
]
250+
message_meta = {
251+
"model": "gpt-4o-mini",
252+
"index": 0,
253+
"finish_reason": "stop",
254+
"usage": {"prompt_tokens": 32, "completion_tokens": 153, "total_tokens": 185},
255+
}
256+
replies = [ChatMessage.from_assistant("AnswerString", meta=message_meta)]
257+
301258
output = component.run(query="test query", replies=replies, meta=[{"test": "meta"}])
302259
answers = output["answers"]
303260
assert len(answers) == 1
@@ -315,8 +272,9 @@ def test_run_with_chat_message_replies_with_meta_set_at_run_time(self):
315272

316273
def test_run_with_chat_message_no_meta_with_meta_set_at_run_time(self):
317274
component = AnswerBuilder()
318-
replies = [ChatMessage(content="AnswerString", role=ChatRole.ASSISTANT, name=None, meta={})]
275+
replies = [ChatMessage.from_assistant("AnswerString")]
319276
output = component.run(query="test query", replies=replies, meta=[{"test": "meta"}])
277+
320278
answers = output["answers"]
321279
assert len(answers) == 1
322280
assert answers[0].data == "AnswerString"

Diff for: test/components/builders/test_chat_prompt_builder.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,14 @@ def test_run_with_meta(self):
210210
Test that the ChatPromptBuilder correctly handles meta data.
211211
It should render the message and copy the meta data from the original message.
212212
"""
213-
m = ChatMessage(content="This is a {{ variable }}", role=ChatRole.USER, name=None, meta={"test": "test"})
213+
m = ChatMessage.from_user("This is a {{ variable }}")
214+
m.meta["meta_field"] = "meta_value"
214215
builder = ChatPromptBuilder(template=[m])
215216
res = builder.run(variable="test")
216-
res_msg = ChatMessage(content="This is a test", role=ChatRole.USER, name=None, meta={"test": "test"})
217-
assert res == {"prompt": [res_msg]}
217+
218+
expected_msg = ChatMessage.from_user("This is a test")
219+
expected_msg.meta["meta_field"] = "meta_value"
220+
assert res == {"prompt": [expected_msg]}
218221

219222
def test_run_with_invalid_template(self):
220223
builder = ChatPromptBuilder()

Diff for: test/dataclasses/test_chat_message.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@ def test_to_dict():
9696

9797

9898
def test_from_dict():
99-
assert ChatMessage.from_dict(data={"content": "text", "role": "user", "name": None}) == ChatMessage(
100-
content="text", role=ChatRole("user"), name=None, meta={}
99+
assert ChatMessage.from_dict(data={"content": "text", "role": "user", "name": None}) == ChatMessage.from_user(
100+
"text"
101101
)
102102

103103

104104
def test_from_dict_with_meta():
105105
assert ChatMessage.from_dict(
106-
data={"content": "text", "role": "user", "name": None, "meta": {"something": "something"}}
107-
) == ChatMessage(content="text", role=ChatRole("user"), name=None, meta={"something": "something"})
106+
data={"content": "text", "role": "assistant", "name": None, "meta": {"something": "something"}}
107+
) == ChatMessage.from_assistant("text", meta={"something": "something"})

0 commit comments

Comments
 (0)