haystack-experimental 0.13.0__py3-none-any.whl → 0.14.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.
Files changed (24) hide show
  1. haystack_experimental/components/agents/__init__.py +16 -0
  2. haystack_experimental/components/agents/agent.py +634 -0
  3. haystack_experimental/components/agents/human_in_the_loop/__init__.py +35 -0
  4. haystack_experimental/components/agents/human_in_the_loop/breakpoint.py +63 -0
  5. haystack_experimental/components/agents/human_in_the_loop/dataclasses.py +72 -0
  6. haystack_experimental/components/agents/human_in_the_loop/errors.py +28 -0
  7. haystack_experimental/components/agents/human_in_the_loop/policies.py +78 -0
  8. haystack_experimental/components/agents/human_in_the_loop/strategies.py +455 -0
  9. haystack_experimental/components/agents/human_in_the_loop/types.py +89 -0
  10. haystack_experimental/components/agents/human_in_the_loop/user_interfaces.py +209 -0
  11. haystack_experimental/components/preprocessors/embedding_based_document_splitter.py +18 -6
  12. haystack_experimental/components/preprocessors/md_header_level_inferrer.py +146 -0
  13. haystack_experimental/components/summarizers/__init__.py +7 -0
  14. haystack_experimental/components/summarizers/llm_summarizer.py +317 -0
  15. haystack_experimental/core/__init__.py +3 -0
  16. haystack_experimental/core/pipeline/__init__.py +3 -0
  17. haystack_experimental/core/pipeline/breakpoint.py +174 -0
  18. haystack_experimental/dataclasses/__init__.py +3 -0
  19. haystack_experimental/dataclasses/breakpoints.py +53 -0
  20. {haystack_experimental-0.13.0.dist-info → haystack_experimental-0.14.0.dist-info}/METADATA +29 -14
  21. {haystack_experimental-0.13.0.dist-info → haystack_experimental-0.14.0.dist-info}/RECORD +24 -6
  22. {haystack_experimental-0.13.0.dist-info → haystack_experimental-0.14.0.dist-info}/WHEEL +0 -0
  23. {haystack_experimental-0.13.0.dist-info → haystack_experimental-0.14.0.dist-info}/licenses/LICENSE +0 -0
  24. {haystack_experimental-0.13.0.dist-info → haystack_experimental-0.14.0.dist-info}/licenses/LICENSE-MIT.txt +0 -0
@@ -0,0 +1,35 @@
1
+ # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import sys
6
+ from typing import TYPE_CHECKING
7
+
8
+ from lazy_imports import LazyImporter
9
+
10
+ _import_structure = {
11
+ "dataclasses": ["ConfirmationUIResult", "ToolExecutionDecision"],
12
+ "errors": ["HITLBreakpointException"],
13
+ "policies": ["AlwaysAskPolicy", "NeverAskPolicy", "AskOncePolicy"],
14
+ "strategies": ["BlockingConfirmationStrategy", "BreakpointConfirmationStrategy"],
15
+ "types": ["ConfirmationPolicy", "ConfirmationUI", "ConfirmationStrategy"],
16
+ "user_interfaces": ["RichConsoleUI", "SimpleConsoleUI"],
17
+ }
18
+
19
+ if TYPE_CHECKING:
20
+ from .dataclasses import ConfirmationUIResult as ConfirmationUIResult
21
+ from .dataclasses import ToolExecutionDecision as ToolExecutionDecision
22
+ from .errors import HITLBreakpointException as HITLBreakpointException
23
+ from .policies import AlwaysAskPolicy as AlwaysAskPolicy
24
+ from .policies import AskOncePolicy as AskOncePolicy
25
+ from .policies import NeverAskPolicy as NeverAskPolicy
26
+ from .strategies import BlockingConfirmationStrategy as BlockingConfirmationStrategy
27
+ from .strategies import BreakpointConfirmationStrategy as BreakpointConfirmationStrategy
28
+ from .types import ConfirmationPolicy as ConfirmationPolicy
29
+ from .types import ConfirmationStrategy as ConfirmationStrategy
30
+ from .types import ConfirmationUI as ConfirmationUI
31
+ from .user_interfaces import RichConsoleUI as RichConsoleUI
32
+ from .user_interfaces import SimpleConsoleUI as SimpleConsoleUI
33
+
34
+ else:
35
+ sys.modules[__name__] = LazyImporter(name=__name__, module_file=__file__, import_structure=_import_structure)
@@ -0,0 +1,63 @@
1
+ # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from haystack.dataclasses.breakpoints import AgentSnapshot, ToolBreakpoint
6
+ from haystack.utils import _deserialize_value_with_schema
7
+
8
+ from haystack_experimental.components.agents.human_in_the_loop.strategies import _prepare_tool_args
9
+
10
+
11
+ def get_tool_calls_and_descriptions_from_snapshot(
12
+ agent_snapshot: AgentSnapshot, breakpoint_tool_only: bool = True
13
+ ) -> tuple[list[dict], dict[str, str]]:
14
+ """
15
+ Extract tool calls and tool descriptions from an AgentSnapshot.
16
+
17
+ By default, only the tool call that caused the breakpoint is processed and its arguments are reconstructed.
18
+ This is useful for scenarios where you want to present the relevant tool call and its description
19
+ to a human for confirmation before execution.
20
+
21
+ :param agent_snapshot: The AgentSnapshot from which to extract tool calls and descriptions.
22
+ :param breakpoint_tool_only: If True, only the tool call that caused the breakpoint is returned. If False, all tool
23
+ calls are returned.
24
+ :returns:
25
+ A tuple containing a list of tool call dictionaries and a dictionary of tool descriptions
26
+ """
27
+ break_point = agent_snapshot.break_point.break_point
28
+ if not isinstance(break_point, ToolBreakpoint):
29
+ raise ValueError("The provided AgentSnapshot does not contain a ToolBreakpoint.")
30
+
31
+ tool_caused_break_point = break_point.tool_name
32
+
33
+ # Deserialize the tool invoker inputs from the snapshot
34
+ tool_invoker_inputs = _deserialize_value_with_schema(agent_snapshot.component_inputs["tool_invoker"])
35
+ tool_call_messages = tool_invoker_inputs["messages"]
36
+ state = tool_invoker_inputs["state"]
37
+ tool_name_to_tool = {t.name: t for t in tool_invoker_inputs["tools"]}
38
+
39
+ tool_calls = []
40
+ for msg in tool_call_messages:
41
+ if msg.tool_calls:
42
+ tool_calls.extend(msg.tool_calls)
43
+ serialized_tcs = [tc.to_dict() for tc in tool_calls]
44
+
45
+ # Reconstruct the final arguments for each tool call
46
+ tool_descriptions = {}
47
+ updated_tool_calls = []
48
+ for tc in serialized_tcs:
49
+ # Only process the tool that caused the breakpoint if breakpoint_tool_only is True
50
+ if breakpoint_tool_only and tc["tool_name"] != tool_caused_break_point:
51
+ continue
52
+
53
+ final_args = _prepare_tool_args(
54
+ tool=tool_name_to_tool[tc["tool_name"]],
55
+ tool_call_arguments=tc["arguments"],
56
+ state=state,
57
+ streaming_callback=tool_invoker_inputs.get("streaming_callback", None),
58
+ enable_streaming_passthrough=tool_invoker_inputs.get("enable_streaming_passthrough", False),
59
+ )
60
+ updated_tool_calls.append({**tc, "arguments": final_args})
61
+ tool_descriptions[tc["tool_name"]] = tool_name_to_tool[tc["tool_name"]].description
62
+
63
+ return updated_tool_calls, tool_descriptions
@@ -0,0 +1,72 @@
1
+ # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from dataclasses import asdict, dataclass
6
+ from typing import Any, Optional
7
+
8
+
9
+ @dataclass
10
+ class ConfirmationUIResult:
11
+ """
12
+ Result of the confirmation UI interaction.
13
+
14
+ :param action:
15
+ The action taken by the user such as "confirm", "reject", or "modify".
16
+ This action type is not enforced to allow for custom actions to be implemented.
17
+ :param feedback:
18
+ Optional feedback message from the user. For example, if the user rejects the tool execution,
19
+ they might provide a reason for the rejection.
20
+ :param new_tool_params:
21
+ Optional set of new parameters for the tool. For example, if the user chooses to modify the tool parameters,
22
+ they can provide a new set of parameters here.
23
+ """
24
+
25
+ action: str # "confirm", "reject", "modify"
26
+ feedback: Optional[str] = None
27
+ new_tool_params: Optional[dict[str, Any]] = None
28
+
29
+
30
+ @dataclass
31
+ class ToolExecutionDecision:
32
+ """
33
+ Decision made regarding tool execution.
34
+
35
+ :param tool_name:
36
+ The name of the tool to be executed.
37
+ :param execute:
38
+ A boolean indicating whether to execute the tool with the provided parameters.
39
+ :param tool_call_id:
40
+ Optional unique identifier for the tool call. This can be used to track and correlate the decision with a
41
+ specific tool invocation.
42
+ :param feedback:
43
+ Optional feedback message.
44
+ For example, if the tool execution is rejected, this can contain the reason. Or if the tool parameters were
45
+ modified, this can contain the modification details.
46
+ :param final_tool_params:
47
+ Optional final parameters for the tool if execution is confirmed or modified.
48
+ """
49
+
50
+ tool_name: str
51
+ execute: bool
52
+ tool_call_id: Optional[str] = None
53
+ feedback: Optional[str] = None
54
+ final_tool_params: Optional[dict[str, Any]] = None
55
+
56
+ def to_dict(self) -> dict[str, Any]:
57
+ """
58
+ Convert the ToolExecutionDecision to a dictionary representation.
59
+
60
+ :return: A dictionary containing the tool execution decision details.
61
+ """
62
+ return asdict(self)
63
+
64
+ @classmethod
65
+ def from_dict(cls, data: dict[str, Any]) -> "ToolExecutionDecision":
66
+ """
67
+ Populate the ToolExecutionDecision from a dictionary representation.
68
+
69
+ :param data: A dictionary containing the tool execution decision details.
70
+ :return: An instance of ToolExecutionDecision.
71
+ """
72
+ return cls(**data)
@@ -0,0 +1,28 @@
1
+ # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from typing import Optional
6
+
7
+
8
+ class HITLBreakpointException(Exception):
9
+ """
10
+ Exception raised when a tool execution is paused by a ConfirmationStrategy (e.g. BreakpointConfirmationStrategy).
11
+ """
12
+
13
+ def __init__(
14
+ self, message: str, tool_name: str, snapshot_file_path: str, tool_call_id: Optional[str] = None
15
+ ) -> None:
16
+ """
17
+ Initialize the HITLBreakpointException.
18
+
19
+ :param message: The exception message.
20
+ :param tool_name: The name of the tool whose execution is paused.
21
+ :param snapshot_file_path: The file path to the saved pipeline snapshot.
22
+ :param tool_call_id: Optional unique identifier for the tool call. This can be used to track and correlate
23
+ the decision with a specific tool invocation.
24
+ """
25
+ super().__init__(message)
26
+ self.tool_name = tool_name
27
+ self.snapshot_file_path = snapshot_file_path
28
+ self.tool_call_id = tool_call_id
@@ -0,0 +1,78 @@
1
+ # SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from typing import Any
6
+
7
+ from haystack_experimental.components.agents.human_in_the_loop.dataclasses import ConfirmationUIResult
8
+ from haystack_experimental.components.agents.human_in_the_loop.types import ConfirmationPolicy
9
+
10
+
11
+ class AlwaysAskPolicy(ConfirmationPolicy):
12
+ """Always ask for confirmation."""
13
+
14
+ def should_ask(self, tool_name: str, tool_description: str, tool_params: dict[str, Any]) -> bool:
15
+ """
16
+ Always ask for confirmation before executing the tool.
17
+
18
+ :param tool_name: The name of the tool to be executed.
19
+ :param tool_description: The description of the tool.
20
+ :param tool_params: The parameters to be passed to the tool.
21
+ :returns: Always returns True, indicating confirmation is needed.
22
+ """
23
+ return True
24
+
25
+
26
+ class NeverAskPolicy(ConfirmationPolicy):
27
+ """Never ask for confirmation."""
28
+
29
+ def should_ask(self, tool_name: str, tool_description: str, tool_params: dict[str, Any]) -> bool:
30
+ """
31
+ Never ask for confirmation, always proceed with tool execution.
32
+
33
+ :param tool_name: The name of the tool to be executed.
34
+ :param tool_description: The description of the tool.
35
+ :param tool_params: The parameters to be passed to the tool.
36
+ :returns: Always returns False, indicating no confirmation is needed.
37
+ """
38
+ return False
39
+
40
+
41
+ class AskOncePolicy(ConfirmationPolicy):
42
+ """Ask only once per tool with specific parameters."""
43
+
44
+ def __init__(self):
45
+ self._asked_tools = {}
46
+
47
+ def should_ask(self, tool_name: str, tool_description: str, tool_params: dict[str, Any]) -> bool:
48
+ """
49
+ Ask for confirmation only once per tool with specific parameters.
50
+
51
+ :param tool_name: The name of the tool to be executed.
52
+ :param tool_description: The description of the tool.
53
+ :param tool_params: The parameters to be passed to the tool.
54
+ :returns: True if confirmation is needed, False if already asked with the same parameters.
55
+ """
56
+ # Don't ask again if we've already asked for this tool with the same parameters
57
+ return not (tool_name in self._asked_tools and self._asked_tools[tool_name] == tool_params)
58
+
59
+ def update_after_confirmation(
60
+ self,
61
+ tool_name: str,
62
+ tool_description: str,
63
+ tool_params: dict[str, Any],
64
+ confirmation_result: ConfirmationUIResult,
65
+ ) -> None:
66
+ """
67
+ Store the tool and parameters if the action was "confirm" to avoid asking again.
68
+
69
+ This method updates the internal state to remember that the user has already confirmed the execution of the
70
+ tool with the given parameters.
71
+
72
+ :param tool_name: The name of the tool that was executed.
73
+ :param tool_description: The description of the tool.
74
+ :param tool_params: The parameters that were passed to the tool.
75
+ :param confirmation_result: The result from the confirmation UI.
76
+ """
77
+ if confirmation_result.action == "confirm":
78
+ self._asked_tools[tool_name] = tool_params