haystack-experimental 0.14.2__py3-none-any.whl → 0.15.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- haystack_experimental/chat_message_stores/__init__.py +1 -1
- haystack_experimental/chat_message_stores/in_memory.py +176 -31
- haystack_experimental/chat_message_stores/types.py +33 -21
- haystack_experimental/components/agents/agent.py +184 -35
- haystack_experimental/components/agents/human_in_the_loop/strategies.py +220 -3
- haystack_experimental/components/agents/human_in_the_loop/types.py +36 -1
- haystack_experimental/components/embedders/types/protocol.py +2 -2
- haystack_experimental/components/preprocessors/__init__.py +2 -0
- haystack_experimental/components/preprocessors/embedding_based_document_splitter.py +16 -16
- haystack_experimental/components/preprocessors/md_header_level_inferrer.py +2 -2
- haystack_experimental/components/retrievers/__init__.py +1 -3
- haystack_experimental/components/retrievers/chat_message_retriever.py +57 -26
- haystack_experimental/components/writers/__init__.py +1 -1
- haystack_experimental/components/writers/chat_message_writer.py +25 -22
- haystack_experimental/core/pipeline/breakpoint.py +5 -3
- {haystack_experimental-0.14.2.dist-info → haystack_experimental-0.15.0.dist-info}/METADATA +24 -31
- {haystack_experimental-0.14.2.dist-info → haystack_experimental-0.15.0.dist-info}/RECORD +20 -27
- {haystack_experimental-0.14.2.dist-info → haystack_experimental-0.15.0.dist-info}/WHEEL +1 -1
- haystack_experimental/components/query/__init__.py +0 -18
- haystack_experimental/components/query/query_expander.py +0 -299
- haystack_experimental/components/retrievers/multi_query_embedding_retriever.py +0 -180
- haystack_experimental/components/retrievers/multi_query_text_retriever.py +0 -158
- haystack_experimental/super_components/__init__.py +0 -3
- haystack_experimental/super_components/indexers/__init__.py +0 -11
- haystack_experimental/super_components/indexers/sentence_transformers_document_indexer.py +0 -199
- {haystack_experimental-0.14.2.dist-info → haystack_experimental-0.15.0.dist-info}/licenses/LICENSE +0 -0
- {haystack_experimental-0.14.2.dist-info → haystack_experimental-0.15.0.dist-info}/licenses/LICENSE-MIT.txt +0 -0
|
@@ -22,11 +22,11 @@ import haystack_experimental.core.pipeline.breakpoint as exp_breakpoint
|
|
|
22
22
|
hs_breakpoint._create_agent_snapshot = exp_breakpoint._create_agent_snapshot
|
|
23
23
|
hs_breakpoint._create_pipeline_snapshot_from_tool_invoker = exp_breakpoint._create_pipeline_snapshot_from_tool_invoker # type: ignore[assignment]
|
|
24
24
|
|
|
25
|
-
from haystack import logging
|
|
25
|
+
from haystack import DeserializationError, logging
|
|
26
26
|
from haystack.components.agents.agent import Agent as HaystackAgent
|
|
27
27
|
from haystack.components.agents.agent import _ExecutionContext as Haystack_ExecutionContext
|
|
28
28
|
from haystack.components.agents.agent import _schema_from_dict
|
|
29
|
-
from haystack.components.agents.state import replace_values
|
|
29
|
+
from haystack.components.agents.state import replace_values, State
|
|
30
30
|
from haystack.components.generators.chat.types import ChatGenerator
|
|
31
31
|
from haystack.core.errors import PipelineRuntimeError
|
|
32
32
|
from haystack.core.pipeline import AsyncPipeline, Pipeline
|
|
@@ -36,19 +36,25 @@ from haystack.core.pipeline.breakpoint import (
|
|
|
36
36
|
)
|
|
37
37
|
from haystack.core.pipeline.utils import _deepcopy_with_exceptions
|
|
38
38
|
from haystack.core.serialization import default_from_dict, import_class_by_name
|
|
39
|
-
from haystack.dataclasses import ChatMessage
|
|
39
|
+
from haystack.dataclasses import ChatMessage, ChatRole
|
|
40
40
|
from haystack.dataclasses.breakpoints import AgentBreakpoint, ToolBreakpoint
|
|
41
|
-
from haystack.dataclasses.streaming_chunk import StreamingCallbackT
|
|
41
|
+
from haystack.dataclasses.streaming_chunk import StreamingCallbackT, select_streaming_callback
|
|
42
42
|
from haystack.tools import ToolsType, deserialize_tools_or_toolset_inplace
|
|
43
43
|
from haystack.utils.callable_serialization import deserialize_callable
|
|
44
44
|
from haystack.utils.deserialization import deserialize_chatgenerator_inplace
|
|
45
45
|
|
|
46
|
+
from haystack_experimental.chat_message_stores.types import ChatMessageStore
|
|
46
47
|
from haystack_experimental.components.agents.human_in_the_loop import (
|
|
47
48
|
ConfirmationStrategy,
|
|
48
49
|
ToolExecutionDecision,
|
|
49
50
|
HITLBreakpointException,
|
|
50
51
|
)
|
|
51
|
-
from haystack_experimental.components.agents.human_in_the_loop.strategies import
|
|
52
|
+
from haystack_experimental.components.agents.human_in_the_loop.strategies import (
|
|
53
|
+
_process_confirmation_strategies,
|
|
54
|
+
_process_confirmation_strategies_async,
|
|
55
|
+
)
|
|
56
|
+
from haystack_experimental.components.retrievers import ChatMessageRetriever
|
|
57
|
+
from haystack_experimental.components.writers import ChatMessageWriter
|
|
52
58
|
|
|
53
59
|
logger = logging.getLogger(__name__)
|
|
54
60
|
|
|
@@ -62,9 +68,15 @@ class _ExecutionContext(Haystack_ExecutionContext):
|
|
|
62
68
|
|
|
63
69
|
:param tool_execution_decisions: Optional list of ToolExecutionDecision objects to use instead of prompting
|
|
64
70
|
the user. This is useful when restarting from a snapshot where tool execution decisions were already made.
|
|
71
|
+
:param confirmation_strategy_context: Optional dictionary for passing request-scoped resources
|
|
72
|
+
to confirmation strategies. In web/server environments, this enables passing per-request
|
|
73
|
+
objects (e.g., WebSocket connections, async queues, or pub/sub clients) that strategies can use for
|
|
74
|
+
non-blocking user interaction. This is passed directly to strategies via the `confirmation_strategy_context`
|
|
75
|
+
parameter in their `run()` and `run_async()` methods.
|
|
65
76
|
"""
|
|
66
77
|
|
|
67
78
|
tool_execution_decisions: Optional[list[ToolExecutionDecision]] = None
|
|
79
|
+
confirmation_strategy_context: Optional[dict[str, Any]] = None
|
|
68
80
|
|
|
69
81
|
|
|
70
82
|
class Agent(HaystackAgent):
|
|
@@ -131,6 +143,7 @@ class Agent(HaystackAgent):
|
|
|
131
143
|
raise_on_tool_invocation_failure: bool = False,
|
|
132
144
|
confirmation_strategies: Optional[dict[str, ConfirmationStrategy]] = None,
|
|
133
145
|
tool_invoker_kwargs: Optional[dict[str, Any]] = None,
|
|
146
|
+
chat_message_store: Optional[ChatMessageStore] = None,
|
|
134
147
|
) -> None:
|
|
135
148
|
"""
|
|
136
149
|
Initialize the agent component.
|
|
@@ -164,6 +177,13 @@ class Agent(HaystackAgent):
|
|
|
164
177
|
tool_invoker_kwargs=tool_invoker_kwargs,
|
|
165
178
|
)
|
|
166
179
|
self._confirmation_strategies = confirmation_strategies or {}
|
|
180
|
+
self._chat_message_store = chat_message_store
|
|
181
|
+
self._chat_message_retriever = (
|
|
182
|
+
ChatMessageRetriever(chat_message_store=chat_message_store) if chat_message_store else None
|
|
183
|
+
)
|
|
184
|
+
self._chat_message_writer = (
|
|
185
|
+
ChatMessageWriter(chat_message_store=chat_message_store) if chat_message_store else None
|
|
186
|
+
)
|
|
167
187
|
|
|
168
188
|
def _initialize_fresh_execution(
|
|
169
189
|
self,
|
|
@@ -172,7 +192,10 @@ class Agent(HaystackAgent):
|
|
|
172
192
|
requires_async: bool,
|
|
173
193
|
*,
|
|
174
194
|
system_prompt: Optional[str] = None,
|
|
195
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
175
196
|
tools: Optional[Union[ToolsType, list[str]]] = None,
|
|
197
|
+
confirmation_strategy_context: Optional[dict[str, Any]] = None,
|
|
198
|
+
chat_message_store_kwargs: Optional[dict[str, Any]] = None,
|
|
176
199
|
**kwargs: dict[str, Any],
|
|
177
200
|
) -> _ExecutionContext:
|
|
178
201
|
"""
|
|
@@ -184,27 +207,56 @@ class Agent(HaystackAgent):
|
|
|
184
207
|
:param system_prompt: System prompt for the agent. If provided, it overrides the default system prompt.
|
|
185
208
|
:param tools: Optional list of Tool objects, a Toolset, or list of tool names to use for this run.
|
|
186
209
|
When passing tool names, tools are selected from the Agent's originally configured tools.
|
|
210
|
+
:param confirmation_strategy_context: Optional dictionary for passing request-scoped resources
|
|
211
|
+
to confirmation strategies.
|
|
212
|
+
:param chat_message_store_kwargs: Optional dictionary of keyword arguments to pass to the ChatMessageStore.
|
|
187
213
|
:param kwargs: Additional data to pass to the State used by the Agent.
|
|
188
214
|
"""
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
215
|
+
system_prompt = system_prompt or self.system_prompt
|
|
216
|
+
if system_prompt is not None:
|
|
217
|
+
messages = [ChatMessage.from_system(system_prompt)] + messages
|
|
218
|
+
|
|
219
|
+
# NOTE: difference with parent method to add chat message retrieval
|
|
220
|
+
if self._chat_message_retriever:
|
|
221
|
+
retriever_kwargs = _select_kwargs(self._chat_message_retriever, chat_message_store_kwargs or {})
|
|
222
|
+
if "chat_history_id" in retriever_kwargs:
|
|
223
|
+
messages = self._chat_message_retriever.run(
|
|
224
|
+
current_messages=messages,
|
|
225
|
+
**retriever_kwargs,
|
|
226
|
+
)["messages"]
|
|
227
|
+
|
|
228
|
+
if all(m.is_from(ChatRole.SYSTEM) for m in messages):
|
|
229
|
+
logger.warning("All messages provided to the Agent component are system messages. This is not recommended.")
|
|
230
|
+
|
|
231
|
+
state = State(schema=self.state_schema, data=kwargs)
|
|
232
|
+
state.set("messages", messages)
|
|
233
|
+
|
|
234
|
+
streaming_callback = select_streaming_callback( # type: ignore[call-overload]
|
|
235
|
+
init_callback=self.streaming_callback, runtime_callback=streaming_callback, requires_async=requires_async
|
|
196
236
|
)
|
|
197
|
-
|
|
237
|
+
|
|
238
|
+
selected_tools = self._select_tools(tools)
|
|
239
|
+
tool_invoker_inputs: dict[str, Any] = {"tools": selected_tools}
|
|
240
|
+
generator_inputs: dict[str, Any] = {"tools": selected_tools}
|
|
241
|
+
if streaming_callback is not None:
|
|
242
|
+
tool_invoker_inputs["streaming_callback"] = streaming_callback
|
|
243
|
+
generator_inputs["streaming_callback"] = streaming_callback
|
|
244
|
+
if generation_kwargs is not None:
|
|
245
|
+
generator_inputs["generation_kwargs"] = generation_kwargs
|
|
246
|
+
|
|
247
|
+
# NOTE: difference with parent method to add this to tool_invoker_inputs
|
|
198
248
|
if self._tool_invoker:
|
|
199
|
-
|
|
249
|
+
tool_invoker_inputs["enable_streaming_callback_passthrough"] = (
|
|
200
250
|
self._tool_invoker.enable_streaming_callback_passthrough
|
|
201
251
|
)
|
|
202
|
-
|
|
252
|
+
|
|
253
|
+
# NOTE: difference is to use the extended _ExecutionContext with confirmation_strategy_context
|
|
203
254
|
return _ExecutionContext(
|
|
204
|
-
state=
|
|
205
|
-
component_visits=
|
|
206
|
-
chat_generator_inputs=
|
|
207
|
-
tool_invoker_inputs=
|
|
255
|
+
state=state,
|
|
256
|
+
component_visits=dict.fromkeys(["chat_generator", "tool_invoker"], 0),
|
|
257
|
+
chat_generator_inputs=generator_inputs,
|
|
258
|
+
tool_invoker_inputs=tool_invoker_inputs,
|
|
259
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
208
260
|
)
|
|
209
261
|
|
|
210
262
|
def _initialize_from_snapshot( # type: ignore[override]
|
|
@@ -213,7 +265,9 @@ class Agent(HaystackAgent):
|
|
|
213
265
|
streaming_callback: Optional[StreamingCallbackT],
|
|
214
266
|
requires_async: bool,
|
|
215
267
|
*,
|
|
268
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
216
269
|
tools: Optional[Union[ToolsType, list[str]]] = None,
|
|
270
|
+
confirmation_strategy_context: Optional[dict[str, Any]] = None,
|
|
217
271
|
) -> _ExecutionContext:
|
|
218
272
|
"""
|
|
219
273
|
Initialize execution context from an AgentSnapshot.
|
|
@@ -221,18 +275,35 @@ class Agent(HaystackAgent):
|
|
|
221
275
|
:param snapshot: An AgentSnapshot containing the state of a previously saved agent execution.
|
|
222
276
|
:param streaming_callback: Optional callback for streaming responses.
|
|
223
277
|
:param requires_async: Whether the agent run requires asynchronous execution.
|
|
278
|
+
:param generation_kwargs: Additional keyword arguments for chat generator. These parameters will
|
|
279
|
+
override the parameters passed during component initialization.
|
|
224
280
|
:param tools: Optional list of Tool objects, a Toolset, or list of tool names to use for this run.
|
|
225
281
|
When passing tool names, tools are selected from the Agent's originally configured tools.
|
|
282
|
+
:param confirmation_strategy_context: Optional dictionary for passing request-scoped resources
|
|
283
|
+
to confirmation strategies.
|
|
226
284
|
"""
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
285
|
+
# The PR https://github.com/deepset-ai/haystack/pull/9616 added the generation_kwargs parameter to
|
|
286
|
+
# _initialize_from_snapshot. This change has been released in Haystack 2.20.0.
|
|
287
|
+
# To maintain compatibility with Haystack 2.19 we check the number of parameters and call accordingly.
|
|
288
|
+
if inspect.signature(super(Agent, self)._initialize_from_snapshot).parameters.get("generation_kwargs"):
|
|
289
|
+
exe_context = super(Agent, self)._initialize_from_snapshot( # type: ignore[call-arg]
|
|
290
|
+
snapshot=snapshot,
|
|
291
|
+
streaming_callback=streaming_callback,
|
|
292
|
+
requires_async=requires_async,
|
|
293
|
+
generation_kwargs=generation_kwargs,
|
|
294
|
+
tools=tools,
|
|
295
|
+
)
|
|
296
|
+
else:
|
|
297
|
+
exe_context = super(Agent, self)._initialize_from_snapshot(
|
|
298
|
+
snapshot=snapshot, streaming_callback=streaming_callback, requires_async=requires_async, tools=tools
|
|
299
|
+
)
|
|
230
300
|
# NOTE: 1st difference with parent method to add this to tool_invoker_inputs
|
|
231
301
|
if self._tool_invoker:
|
|
232
302
|
exe_context.tool_invoker_inputs["enable_streaming_callback_passthrough"] = (
|
|
233
303
|
self._tool_invoker.enable_streaming_callback_passthrough
|
|
234
304
|
)
|
|
235
|
-
# NOTE: 2nd difference is to use the extended _ExecutionContext
|
|
305
|
+
# NOTE: 2nd difference is to use the extended _ExecutionContext
|
|
306
|
+
# and add tool_execution_decisions + confirmation_strategy_context
|
|
236
307
|
return _ExecutionContext(
|
|
237
308
|
state=exe_context.state,
|
|
238
309
|
component_visits=exe_context.component_visits,
|
|
@@ -241,17 +312,21 @@ class Agent(HaystackAgent):
|
|
|
241
312
|
counter=exe_context.counter,
|
|
242
313
|
skip_chat_generator=exe_context.skip_chat_generator,
|
|
243
314
|
tool_execution_decisions=snapshot.tool_execution_decisions,
|
|
315
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
244
316
|
)
|
|
245
317
|
|
|
246
|
-
def run( # noqa: PLR0915
|
|
318
|
+
def run( # type: ignore[override] # noqa: PLR0915
|
|
247
319
|
self,
|
|
248
320
|
messages: list[ChatMessage],
|
|
249
321
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
250
322
|
*,
|
|
323
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
251
324
|
break_point: Optional[AgentBreakpoint] = None,
|
|
252
|
-
snapshot: Optional[AgentSnapshot] = None,
|
|
325
|
+
snapshot: Optional[AgentSnapshot] = None,
|
|
253
326
|
system_prompt: Optional[str] = None,
|
|
254
327
|
tools: Optional[Union[ToolsType, list[str]]] = None,
|
|
328
|
+
confirmation_strategy_context: Optional[dict[str, Any]] = None,
|
|
329
|
+
chat_message_store_kwargs: Optional[dict[str, Any]] = None,
|
|
255
330
|
**kwargs: Any,
|
|
256
331
|
) -> dict[str, Any]:
|
|
257
332
|
"""
|
|
@@ -260,6 +335,8 @@ class Agent(HaystackAgent):
|
|
|
260
335
|
:param messages: List of Haystack ChatMessage objects to process.
|
|
261
336
|
:param streaming_callback: A callback that will be invoked when a response is streamed from the LLM.
|
|
262
337
|
The same callback can be configured to emit tool results when a tool is called.
|
|
338
|
+
:param generation_kwargs: Additional keyword arguments for LLM. These parameters will
|
|
339
|
+
override the parameters passed during component initialization.
|
|
263
340
|
:param break_point: An AgentBreakpoint, can be a Breakpoint for the "chat_generator" or a ToolBreakpoint
|
|
264
341
|
for "tool_invoker".
|
|
265
342
|
:param snapshot: A dictionary containing a snapshot of a previously saved agent execution. The snapshot contains
|
|
@@ -267,6 +344,12 @@ class Agent(HaystackAgent):
|
|
|
267
344
|
:param system_prompt: System prompt for the agent. If provided, it overrides the default system prompt.
|
|
268
345
|
:param tools: Optional list of Tool objects, a Toolset, or list of tool names to use for this run.
|
|
269
346
|
When passing tool names, tools are selected from the Agent's originally configured tools.
|
|
347
|
+
:param confirmation_strategy_context: Optional dictionary for passing request-scoped resources
|
|
348
|
+
to confirmation strategies. Useful in web/server environments to provide per-request
|
|
349
|
+
objects (e.g., WebSocket connections, async queues, Redis pub/sub clients) that strategies
|
|
350
|
+
can use for non-blocking user interaction.
|
|
351
|
+
:param chat_message_store_kwargs: Optional dictionary of keyword arguments to pass to the ChatMessageStore.
|
|
352
|
+
For example, it can include the `chat_history_id` and `last_k` parameters for retrieving chat history.
|
|
270
353
|
:param kwargs: Additional data to pass to the State schema used by the Agent.
|
|
271
354
|
The keys must match the schema defined in the Agent's `state_schema`.
|
|
272
355
|
:returns:
|
|
@@ -290,13 +373,18 @@ class Agent(HaystackAgent):
|
|
|
290
373
|
# _runtime_checks. This change will be released in Haystack 2.20.0.
|
|
291
374
|
# To maintain compatibility with Haystack 2.19 we check the number of parameters and call accordingly.
|
|
292
375
|
if len(inspect.signature(self._runtime_checks).parameters) == 2:
|
|
293
|
-
self._runtime_checks(break_point, snapshot)
|
|
376
|
+
self._runtime_checks(break_point, snapshot) # type: ignore[call-arg] # pylint: disable=too-many-function-args
|
|
294
377
|
else:
|
|
295
378
|
self._runtime_checks(break_point) # type: ignore[call-arg] # pylint: disable=no-value-for-parameter
|
|
296
379
|
|
|
297
380
|
if snapshot:
|
|
298
381
|
exe_context = self._initialize_from_snapshot(
|
|
299
|
-
snapshot=snapshot,
|
|
382
|
+
snapshot=snapshot,
|
|
383
|
+
streaming_callback=streaming_callback,
|
|
384
|
+
requires_async=False,
|
|
385
|
+
generation_kwargs=generation_kwargs,
|
|
386
|
+
tools=tools,
|
|
387
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
300
388
|
)
|
|
301
389
|
else:
|
|
302
390
|
exe_context = self._initialize_fresh_execution(
|
|
@@ -304,7 +392,10 @@ class Agent(HaystackAgent):
|
|
|
304
392
|
streaming_callback=streaming_callback,
|
|
305
393
|
requires_async=False,
|
|
306
394
|
system_prompt=system_prompt,
|
|
395
|
+
generation_kwargs=generation_kwargs,
|
|
307
396
|
tools=tools,
|
|
397
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
398
|
+
chat_message_store_kwargs=chat_message_store_kwargs,
|
|
308
399
|
**kwargs,
|
|
309
400
|
)
|
|
310
401
|
|
|
@@ -431,17 +522,27 @@ class Agent(HaystackAgent):
|
|
|
431
522
|
result = {**exe_context.state.data}
|
|
432
523
|
if msgs := result.get("messages"):
|
|
433
524
|
result["last_message"] = msgs[-1]
|
|
525
|
+
|
|
526
|
+
# Write messages to ChatMessageStore if configured
|
|
527
|
+
if self._chat_message_writer:
|
|
528
|
+
writer_kwargs = _select_kwargs(self._chat_message_writer, chat_message_store_kwargs or {})
|
|
529
|
+
if "chat_history_id" in writer_kwargs:
|
|
530
|
+
self._chat_message_writer.run(messages=result["messages"], **writer_kwargs)
|
|
531
|
+
|
|
434
532
|
return result
|
|
435
533
|
|
|
436
|
-
async def run_async(
|
|
534
|
+
async def run_async( # type: ignore[override]
|
|
437
535
|
self,
|
|
438
536
|
messages: list[ChatMessage],
|
|
439
537
|
streaming_callback: Optional[StreamingCallbackT] = None,
|
|
440
538
|
*,
|
|
539
|
+
generation_kwargs: Optional[dict[str, Any]] = None,
|
|
441
540
|
break_point: Optional[AgentBreakpoint] = None,
|
|
442
|
-
snapshot: Optional[AgentSnapshot] = None,
|
|
541
|
+
snapshot: Optional[AgentSnapshot] = None,
|
|
443
542
|
system_prompt: Optional[str] = None,
|
|
444
543
|
tools: Optional[Union[ToolsType, list[str]]] = None,
|
|
544
|
+
confirmation_strategy_context: Optional[dict[str, Any]] = None,
|
|
545
|
+
chat_message_store_kwargs: Optional[dict[str, Any]] = None,
|
|
445
546
|
**kwargs: Any,
|
|
446
547
|
) -> dict[str, Any]:
|
|
447
548
|
"""
|
|
@@ -454,12 +555,20 @@ class Agent(HaystackAgent):
|
|
|
454
555
|
:param messages: List of Haystack ChatMessage objects to process.
|
|
455
556
|
:param streaming_callback: An asynchronous callback that will be invoked when a response is streamed from the
|
|
456
557
|
LLM. The same callback can be configured to emit tool results when a tool is called.
|
|
558
|
+
:param generation_kwargs: Additional keyword arguments for LLM. These parameters will
|
|
559
|
+
override the parameters passed during component initialization.
|
|
457
560
|
:param break_point: An AgentBreakpoint, can be a Breakpoint for the "chat_generator" or a ToolBreakpoint
|
|
458
561
|
for "tool_invoker".
|
|
459
562
|
:param snapshot: A dictionary containing a snapshot of a previously saved agent execution. The snapshot contains
|
|
460
563
|
the relevant information to restart the Agent execution from where it left off.
|
|
461
564
|
:param system_prompt: System prompt for the agent. If provided, it overrides the default system prompt.
|
|
462
565
|
:param tools: Optional list of Tool objects, a Toolset, or list of tool names to use for this run.
|
|
566
|
+
:param confirmation_strategy_context: Optional dictionary for passing request-scoped resources
|
|
567
|
+
to confirmation strategies. Useful in web/server environments to provide per-request
|
|
568
|
+
objects (e.g., WebSocket connections, async queues, Redis pub/sub clients) that strategies
|
|
569
|
+
can use for non-blocking user interaction.
|
|
570
|
+
:param chat_message_store_kwargs: Optional dictionary of keyword arguments to pass to the ChatMessageStore.
|
|
571
|
+
For example, it can include the `chat_history_id` and `last_k` parameters for retrieving chat history.
|
|
463
572
|
:param kwargs: Additional data to pass to the State schema used by the Agent.
|
|
464
573
|
The keys must match the schema defined in the Agent's `state_schema`.
|
|
465
574
|
:returns:
|
|
@@ -483,13 +592,18 @@ class Agent(HaystackAgent):
|
|
|
483
592
|
# _runtime_checks. This change will be released in Haystack 2.20.0.
|
|
484
593
|
# To maintain compatibility with Haystack 2.19 we check the number of parameters and call accordingly.
|
|
485
594
|
if len(inspect.signature(self._runtime_checks).parameters) == 2:
|
|
486
|
-
self._runtime_checks(break_point, snapshot)
|
|
595
|
+
self._runtime_checks(break_point, snapshot) # type: ignore[call-arg] # pylint: disable=too-many-function-args
|
|
487
596
|
else:
|
|
488
597
|
self._runtime_checks(break_point) # type: ignore[call-arg] # pylint: disable=no-value-for-parameter
|
|
489
598
|
|
|
490
599
|
if snapshot:
|
|
491
600
|
exe_context = self._initialize_from_snapshot(
|
|
492
|
-
snapshot=snapshot,
|
|
601
|
+
snapshot=snapshot,
|
|
602
|
+
streaming_callback=streaming_callback,
|
|
603
|
+
requires_async=True,
|
|
604
|
+
generation_kwargs=generation_kwargs,
|
|
605
|
+
tools=tools,
|
|
606
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
493
607
|
)
|
|
494
608
|
else:
|
|
495
609
|
exe_context = self._initialize_fresh_execution(
|
|
@@ -497,7 +611,10 @@ class Agent(HaystackAgent):
|
|
|
497
611
|
streaming_callback=streaming_callback,
|
|
498
612
|
requires_async=True,
|
|
499
613
|
system_prompt=system_prompt,
|
|
614
|
+
generation_kwargs=generation_kwargs,
|
|
500
615
|
tools=tools,
|
|
616
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
617
|
+
chat_message_store_kwargs=chat_message_store_kwargs,
|
|
501
618
|
**kwargs,
|
|
502
619
|
)
|
|
503
620
|
|
|
@@ -535,8 +652,8 @@ class Agent(HaystackAgent):
|
|
|
535
652
|
|
|
536
653
|
# Apply confirmation strategies and update State and messages sent to ToolInvoker
|
|
537
654
|
try:
|
|
538
|
-
# Run confirmation strategies to get updated tool call messages and modified chat history
|
|
539
|
-
modified_tool_call_messages, new_chat_history =
|
|
655
|
+
# Run confirmation strategies to get updated tool call messages and modified chat history (async)
|
|
656
|
+
modified_tool_call_messages, new_chat_history = await _process_confirmation_strategies_async(
|
|
540
657
|
confirmation_strategies=self._confirmation_strategies,
|
|
541
658
|
messages_with_tool_calls=llm_messages,
|
|
542
659
|
execution_context=exe_context,
|
|
@@ -600,6 +717,13 @@ class Agent(HaystackAgent):
|
|
|
600
717
|
result = {**exe_context.state.data}
|
|
601
718
|
if msgs := result.get("messages"):
|
|
602
719
|
result["last_message"] = msgs[-1]
|
|
720
|
+
|
|
721
|
+
# Write messages to ChatMessageStore if configured
|
|
722
|
+
if self._chat_message_writer:
|
|
723
|
+
writer_kwargs = _select_kwargs(self._chat_message_writer, chat_message_store_kwargs or {})
|
|
724
|
+
if "chat_history_id" in writer_kwargs:
|
|
725
|
+
self._chat_message_writer.run(messages=result["messages"], **writer_kwargs)
|
|
726
|
+
|
|
603
727
|
return result
|
|
604
728
|
|
|
605
729
|
def to_dict(self) -> dict[str, Any]:
|
|
@@ -614,6 +738,9 @@ class Agent(HaystackAgent):
|
|
|
614
738
|
if self._confirmation_strategies
|
|
615
739
|
else None
|
|
616
740
|
)
|
|
741
|
+
data["init_parameters"]["chat_message_store"] = (
|
|
742
|
+
self._chat_message_store.to_dict() if self._chat_message_store is not None else None
|
|
743
|
+
)
|
|
617
744
|
return data
|
|
618
745
|
|
|
619
746
|
@classmethod
|
|
@@ -638,9 +765,31 @@ class Agent(HaystackAgent):
|
|
|
638
765
|
|
|
639
766
|
if "confirmation_strategies" in init_params and init_params["confirmation_strategies"] is not None:
|
|
640
767
|
for name, strategy_dict in init_params["confirmation_strategies"].items():
|
|
641
|
-
|
|
768
|
+
try:
|
|
769
|
+
strategy_class = import_class_by_name(strategy_dict["type"])
|
|
770
|
+
except ImportError as e:
|
|
771
|
+
raise DeserializationError(f"Class '{strategy_dict['type']}' not correctly imported") from e
|
|
642
772
|
if not hasattr(strategy_class, "from_dict"):
|
|
643
|
-
raise
|
|
773
|
+
raise DeserializationError(f"{strategy_class} does not have from_dict method implemented.")
|
|
644
774
|
init_params["confirmation_strategies"][name] = strategy_class.from_dict(strategy_dict)
|
|
645
775
|
|
|
776
|
+
if "chat_message_store" in init_params and init_params["chat_message_store"] is not None:
|
|
777
|
+
cms_data = init_params["chat_message_store"]
|
|
778
|
+
try:
|
|
779
|
+
cms_class = import_class_by_name(cms_data["type"])
|
|
780
|
+
except ImportError as e:
|
|
781
|
+
raise DeserializationError(f"Class '{cms_data['type']}' not correctly imported") from e
|
|
782
|
+
if not hasattr(cms_class, "from_dict"):
|
|
783
|
+
raise DeserializationError(f"{cms_class} does not have from_dict method implemented.")
|
|
784
|
+
init_params["chat_message_store"] = cms_class.from_dict(cms_data)
|
|
785
|
+
|
|
646
786
|
return default_from_dict(cls, data)
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
def _select_kwargs(obj: Any, source: dict) -> dict[str, Any]:
|
|
790
|
+
"""
|
|
791
|
+
Select only those key-value pairs from source dict that are valid parameters for obj.run() method.
|
|
792
|
+
"""
|
|
793
|
+
sig = inspect.signature(obj.run)
|
|
794
|
+
allowed = set(sig.parameters.keys())
|
|
795
|
+
return {k: v for k, v in source.items() if k in allowed}
|