haystack-experimental 0.17.0__tar.gz → 0.19.0__tar.gz
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-0.17.0 → haystack_experimental-0.19.0}/PKG-INFO +24 -27
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/README.md +23 -25
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/agents/agent.py +75 -143
- haystack_experimental-0.19.0/haystack_experimental/components/agents/human_in_the_loop/__init__.py +22 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/agents/human_in_the_loop/breakpoint.py +1 -2
- haystack_experimental-0.19.0/haystack_experimental/components/agents/human_in_the_loop/strategies.py +128 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/dataclasses/breakpoints.py +3 -4
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/pyproject.toml +2 -2
- haystack_experimental-0.17.0/haystack_experimental/components/agents/human_in_the_loop/__init__.py +0 -35
- haystack_experimental-0.17.0/haystack_experimental/components/agents/human_in_the_loop/dataclasses.py +0 -72
- haystack_experimental-0.17.0/haystack_experimental/components/agents/human_in_the_loop/policies.py +0 -78
- haystack_experimental-0.17.0/haystack_experimental/components/agents/human_in_the_loop/strategies.py +0 -672
- haystack_experimental-0.17.0/haystack_experimental/components/agents/human_in_the_loop/types.py +0 -124
- haystack_experimental-0.17.0/haystack_experimental/components/agents/human_in_the_loop/user_interfaces.py +0 -209
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/.gitignore +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/LICENSE +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/LICENSE-MIT.txt +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/chat_message_stores/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/chat_message_stores/in_memory.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/chat_message_stores/types.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/agents/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/agents/human_in_the_loop/errors.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/embedders/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/embedders/types/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/embedders/types/protocol.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/generators/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/generators/chat/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/generators/chat/openai.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/preprocessors/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/preprocessors/md_header_level_inferrer.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/retrievers/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/retrievers/chat_message_retriever.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/retrievers/types/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/retrievers/types/protocol.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/summarizers/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/summarizers/llm_summarizer.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/writers/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/components/writers/chat_message_writer.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/core/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/core/pipeline/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/core/pipeline/breakpoint.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/dataclasses/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/memory_stores/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/memory_stores/mem0/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/memory_stores/mem0/memory_store.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/memory_stores/types/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/memory_stores/types/protocol.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/utils/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/utils/hallucination_risk_calculator/__init__.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/utils/hallucination_risk_calculator/core_math.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/utils/hallucination_risk_calculator/dataclasses.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/utils/hallucination_risk_calculator/openai_planner.py +0 -0
- {haystack_experimental-0.17.0 → haystack_experimental-0.19.0}/haystack_experimental/utils/hallucination_risk_calculator/skeletonization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: haystack-experimental
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.0
|
|
4
4
|
Summary: Experimental components and features for the Haystack LLM framework.
|
|
5
5
|
Project-URL: CI: GitHub, https://github.com/deepset-ai/haystack-experimental/actions
|
|
6
6
|
Project-URL: GitHub: issues, https://github.com/deepset-ai/haystack-experimental/issues
|
|
@@ -24,7 +24,6 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
24
24
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
25
25
|
Requires-Python: >=3.10
|
|
26
26
|
Requires-Dist: haystack-ai
|
|
27
|
-
Requires-Dist: rich
|
|
28
27
|
Description-Content-Type: text/markdown
|
|
29
28
|
|
|
30
29
|
[](https://pypi.org/project/haystack-experimental)
|
|
@@ -70,14 +69,14 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
70
69
|
|
|
71
70
|
### Active experiments
|
|
72
71
|
|
|
73
|
-
| Name
|
|
74
|
-
|
|
75
|
-
| [`OpenAIChatGenerator`][9]
|
|
76
|
-
| [`MarkdownHeaderLevelInferrer`][15]
|
|
77
|
-
| [`Agent`][17]; [
|
|
78
|
-
| [`LLMSummarizer`][24]
|
|
79
|
-
| [`InMemoryChatMessageStore`][1]; [`ChatMessageRetriever`][2]; [`ChatMessageWriter`][3]
|
|
80
|
-
| [`Mem0MemoryStore`][26]
|
|
72
|
+
| Name | Type | Expected End Date | Dependencies | Cookbook | Discussion |
|
|
73
|
+
|----------------------------------------------------------------------------------------|---------------------------------------|-------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
|
74
|
+
| [`OpenAIChatGenerator`][9] | Chat Generator Component | November 2025 | None | <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/hallucination_score_calculator.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/> | [Discuss][10] |
|
|
75
|
+
| [`MarkdownHeaderLevelInferrer`][15] | Preprocessor | January 2025 | None | None | [Discuss][16] |
|
|
76
|
+
| [`Agent`][17]; [`BreakpointConfirmationStrategy`][20]; [`HITLBreakpointException`][22] | Human in the Loop via Breakpoints | December 2025 | None | None | [Discuss][23] |
|
|
77
|
+
| [`LLMSummarizer`][24] | Document Summarizer | January 2025 | None | None | [Discuss][25] |
|
|
78
|
+
| [`InMemoryChatMessageStore`][1]; [`ChatMessageRetriever`][2]; [`ChatMessageWriter`][3] | Chat Message Store, Retriever, Writer | February 2025 | None | <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/conversational_rag_using_memory.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/> | [Discuss][4] |
|
|
79
|
+
| [`Mem0MemoryStore`][26] | MemoryStore | April 2025 | mem0ai | None | -- |
|
|
81
80
|
|
|
82
81
|
[1]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/chat_message_stores/in_memory.py
|
|
83
82
|
[2]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/chat_message_retriever.py
|
|
@@ -88,10 +87,7 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
88
87
|
[15]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/md_header_level_inferrer.py
|
|
89
88
|
[16]: https://github.com/deepset-ai/haystack-experimental/discussions/376
|
|
90
89
|
[17]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/agent.py
|
|
91
|
-
[18]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/policies.py
|
|
92
|
-
[19]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/user_interfaces.py
|
|
93
90
|
[20]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/strategies.py
|
|
94
|
-
[21]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/dataclasses.py
|
|
95
91
|
[22]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/errors.py
|
|
96
92
|
[23]: https://github.com/deepset-ai/haystack-experimental/discussions/381
|
|
97
93
|
[24]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/sumarizers/llm_summarizer.py
|
|
@@ -99,20 +95,21 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
99
95
|
[26]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/memory_stores/mem0/memory_store.py
|
|
100
96
|
|
|
101
97
|
### Adopted experiments
|
|
102
|
-
| Name | Type
|
|
103
|
-
|
|
104
|
-
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker` | Tool Calling support
|
|
105
|
-
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring | AsyncPipeline execution
|
|
106
|
-
| `LLMMetadataExtractor` | Metadata extraction with LLM
|
|
107
|
-
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter` | Document Splitting & Retrieval Technique
|
|
108
|
-
| `Agent` | Simplify Agent development
|
|
109
|
-
| `SuperComponent` | Simplify Pipeline development
|
|
110
|
-
| `Pipeline` | Pipeline breakpoints for debugging
|
|
111
|
-
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers` | Multimodality
|
|
112
|
-
| `QueryExpander` | Query Expansion Component
|
|
113
|
-
| `MultiQueryEmbeddingRetriever` | MultiQueryEmbeddingRetriever
|
|
114
|
-
| `MultiQueryTextRetriever` | MultiQueryTextRetriever
|
|
115
|
-
| `EmbeddingBasedDocumentSplitter`
|
|
98
|
+
| Name | Type | Final release |
|
|
99
|
+
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|---------------|
|
|
100
|
+
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker` | Tool Calling support | 0.4.0 |
|
|
101
|
+
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring | AsyncPipeline execution | 0.7.0 |
|
|
102
|
+
| `LLMMetadataExtractor` | Metadata extraction with LLM | 0.7.0 |
|
|
103
|
+
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter` | Document Splitting & Retrieval Technique | 0.8.0 |
|
|
104
|
+
| `Agent` | Simplify Agent development | 0.8.0 |
|
|
105
|
+
| `SuperComponent` | Simplify Pipeline development | 0.8.0 |
|
|
106
|
+
| `Pipeline` | Pipeline breakpoints for debugging | 0.12.0 |
|
|
107
|
+
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers` | Multimodality | 0.12.0 |
|
|
108
|
+
| `QueryExpander` | Query Expansion Component | 0.14.3 |
|
|
109
|
+
| `MultiQueryEmbeddingRetriever` | MultiQueryEmbeddingRetriever | 0.14.3 |
|
|
110
|
+
| `MultiQueryTextRetriever` | MultiQueryTextRetriever | 0.14.3 |
|
|
111
|
+
| `EmbeddingBasedDocumentSplitter` | Document Splitting | 0.15.2 |
|
|
112
|
+
| `Confirmation Policies`; `ConfirmationUIs`; `BlockingConfirmationStrategy`; `ConfirmationUIResult`; `ToolExecutionDecision` | Human in the Loop | 0.16.0 |
|
|
116
113
|
|
|
117
114
|
### Discontinued experiments
|
|
118
115
|
|
|
@@ -41,14 +41,14 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
41
41
|
|
|
42
42
|
### Active experiments
|
|
43
43
|
|
|
44
|
-
| Name
|
|
45
|
-
|
|
46
|
-
| [`OpenAIChatGenerator`][9]
|
|
47
|
-
| [`MarkdownHeaderLevelInferrer`][15]
|
|
48
|
-
| [`Agent`][17]; [
|
|
49
|
-
| [`LLMSummarizer`][24]
|
|
50
|
-
| [`InMemoryChatMessageStore`][1]; [`ChatMessageRetriever`][2]; [`ChatMessageWriter`][3]
|
|
51
|
-
| [`Mem0MemoryStore`][26]
|
|
44
|
+
| Name | Type | Expected End Date | Dependencies | Cookbook | Discussion |
|
|
45
|
+
|----------------------------------------------------------------------------------------|---------------------------------------|-------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
|
46
|
+
| [`OpenAIChatGenerator`][9] | Chat Generator Component | November 2025 | None | <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/hallucination_score_calculator.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/> | [Discuss][10] |
|
|
47
|
+
| [`MarkdownHeaderLevelInferrer`][15] | Preprocessor | January 2025 | None | None | [Discuss][16] |
|
|
48
|
+
| [`Agent`][17]; [`BreakpointConfirmationStrategy`][20]; [`HITLBreakpointException`][22] | Human in the Loop via Breakpoints | December 2025 | None | None | [Discuss][23] |
|
|
49
|
+
| [`LLMSummarizer`][24] | Document Summarizer | January 2025 | None | None | [Discuss][25] |
|
|
50
|
+
| [`InMemoryChatMessageStore`][1]; [`ChatMessageRetriever`][2]; [`ChatMessageWriter`][3] | Chat Message Store, Retriever, Writer | February 2025 | None | <a href="https://colab.research.google.com/github/deepset-ai/haystack-cookbook/blob/main/notebooks/conversational_rag_using_memory.ipynb" target="_parent"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/> | [Discuss][4] |
|
|
51
|
+
| [`Mem0MemoryStore`][26] | MemoryStore | April 2025 | mem0ai | None | -- |
|
|
52
52
|
|
|
53
53
|
[1]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/chat_message_stores/in_memory.py
|
|
54
54
|
[2]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/chat_message_retriever.py
|
|
@@ -59,10 +59,7 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
59
59
|
[15]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/md_header_level_inferrer.py
|
|
60
60
|
[16]: https://github.com/deepset-ai/haystack-experimental/discussions/376
|
|
61
61
|
[17]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/agent.py
|
|
62
|
-
[18]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/policies.py
|
|
63
|
-
[19]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/user_interfaces.py
|
|
64
62
|
[20]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/strategies.py
|
|
65
|
-
[21]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/dataclasses.py
|
|
66
63
|
[22]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/errors.py
|
|
67
64
|
[23]: https://github.com/deepset-ai/haystack-experimental/discussions/381
|
|
68
65
|
[24]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/sumarizers/llm_summarizer.py
|
|
@@ -70,20 +67,21 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
70
67
|
[26]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/memory_stores/mem0/memory_store.py
|
|
71
68
|
|
|
72
69
|
### Adopted experiments
|
|
73
|
-
| Name | Type
|
|
74
|
-
|
|
75
|
-
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker` | Tool Calling support
|
|
76
|
-
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring | AsyncPipeline execution
|
|
77
|
-
| `LLMMetadataExtractor` | Metadata extraction with LLM
|
|
78
|
-
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter` | Document Splitting & Retrieval Technique
|
|
79
|
-
| `Agent` | Simplify Agent development
|
|
80
|
-
| `SuperComponent` | Simplify Pipeline development
|
|
81
|
-
| `Pipeline` | Pipeline breakpoints for debugging
|
|
82
|
-
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers` | Multimodality
|
|
83
|
-
| `QueryExpander` | Query Expansion Component
|
|
84
|
-
| `MultiQueryEmbeddingRetriever` | MultiQueryEmbeddingRetriever
|
|
85
|
-
| `MultiQueryTextRetriever` | MultiQueryTextRetriever
|
|
86
|
-
| `EmbeddingBasedDocumentSplitter`
|
|
70
|
+
| Name | Type | Final release |
|
|
71
|
+
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|---------------|
|
|
72
|
+
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker` | Tool Calling support | 0.4.0 |
|
|
73
|
+
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring | AsyncPipeline execution | 0.7.0 |
|
|
74
|
+
| `LLMMetadataExtractor` | Metadata extraction with LLM | 0.7.0 |
|
|
75
|
+
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter` | Document Splitting & Retrieval Technique | 0.8.0 |
|
|
76
|
+
| `Agent` | Simplify Agent development | 0.8.0 |
|
|
77
|
+
| `SuperComponent` | Simplify Pipeline development | 0.8.0 |
|
|
78
|
+
| `Pipeline` | Pipeline breakpoints for debugging | 0.12.0 |
|
|
79
|
+
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers` | Multimodality | 0.12.0 |
|
|
80
|
+
| `QueryExpander` | Query Expansion Component | 0.14.3 |
|
|
81
|
+
| `MultiQueryEmbeddingRetriever` | MultiQueryEmbeddingRetriever | 0.14.3 |
|
|
82
|
+
| `MultiQueryTextRetriever` | MultiQueryTextRetriever | 0.14.3 |
|
|
83
|
+
| `EmbeddingBasedDocumentSplitter` | Document Splitting | 0.15.2 |
|
|
84
|
+
| `Confirmation Policies`; `ConfirmationUIs`; `BlockingConfirmationStrategy`; `ConfirmationUIResult`; `ToolExecutionDecision` | Human in the Loop | 0.16.0 |
|
|
87
85
|
|
|
88
86
|
### Discontinued experiments
|
|
89
87
|
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
# ruff: noqa: I001
|
|
7
7
|
|
|
8
8
|
import inspect
|
|
9
|
-
from dataclasses import dataclass
|
|
10
9
|
from typing import Any
|
|
11
10
|
|
|
12
11
|
# Monkey patch Haystack's AgentSnapshot with our extended version
|
|
@@ -22,11 +21,14 @@ import haystack_experimental.core.pipeline.breakpoint as exp_breakpoint
|
|
|
22
21
|
hs_breakpoint._create_agent_snapshot = exp_breakpoint._create_agent_snapshot
|
|
23
22
|
hs_breakpoint._create_pipeline_snapshot_from_tool_invoker = exp_breakpoint._create_pipeline_snapshot_from_tool_invoker # type: ignore[assignment]
|
|
24
23
|
|
|
25
|
-
from haystack import
|
|
26
|
-
from haystack.components.agents.agent import Agent as HaystackAgent
|
|
27
|
-
from haystack.
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
from haystack import component, logging
|
|
25
|
+
from haystack.components.agents.agent import Agent as HaystackAgent, _ExecutionContext, _schema_from_dict
|
|
26
|
+
from haystack.human_in_the_loop.strategies import (
|
|
27
|
+
ConfirmationStrategy,
|
|
28
|
+
_process_confirmation_strategies,
|
|
29
|
+
_process_confirmation_strategies_async,
|
|
30
|
+
)
|
|
31
|
+
from haystack.components.agents.state import replace_values
|
|
30
32
|
from haystack.components.generators.chat.types import ChatGenerator
|
|
31
33
|
from haystack.core.errors import BreakpointException, PipelineRuntimeError
|
|
32
34
|
from haystack.core.pipeline import AsyncPipeline, Pipeline
|
|
@@ -37,24 +39,16 @@ from haystack.core.pipeline.breakpoint import (
|
|
|
37
39
|
_should_trigger_tool_invoker_breakpoint,
|
|
38
40
|
)
|
|
39
41
|
from haystack.core.pipeline.utils import _deepcopy_with_exceptions
|
|
40
|
-
from haystack.core.serialization import default_from_dict
|
|
41
|
-
from haystack.dataclasses import ChatMessage
|
|
42
|
+
from haystack.core.serialization import default_from_dict
|
|
43
|
+
from haystack.dataclasses import ChatMessage
|
|
42
44
|
from haystack.dataclasses.breakpoints import AgentBreakpoint, ToolBreakpoint
|
|
43
|
-
from haystack.dataclasses.streaming_chunk import StreamingCallbackT
|
|
45
|
+
from haystack.dataclasses.streaming_chunk import StreamingCallbackT
|
|
44
46
|
from haystack.tools import ToolsType, deserialize_tools_or_toolset_inplace
|
|
45
47
|
from haystack.utils.callable_serialization import deserialize_callable
|
|
46
|
-
from haystack.utils.deserialization import
|
|
48
|
+
from haystack.utils.deserialization import deserialize_component_inplace
|
|
47
49
|
|
|
48
50
|
from haystack_experimental.chat_message_stores.types import ChatMessageStore
|
|
49
|
-
from haystack_experimental.components.agents.human_in_the_loop import
|
|
50
|
-
ConfirmationStrategy,
|
|
51
|
-
ToolExecutionDecision,
|
|
52
|
-
HITLBreakpointException,
|
|
53
|
-
)
|
|
54
|
-
from haystack_experimental.components.agents.human_in_the_loop.strategies import (
|
|
55
|
-
_process_confirmation_strategies,
|
|
56
|
-
_process_confirmation_strategies_async,
|
|
57
|
-
)
|
|
51
|
+
from haystack_experimental.components.agents.human_in_the_loop import HITLBreakpointException
|
|
58
52
|
from haystack_experimental.components.retrievers import ChatMessageRetriever
|
|
59
53
|
from haystack_experimental.components.writers import ChatMessageWriter
|
|
60
54
|
from haystack_experimental.memory_stores.types import MemoryStore
|
|
@@ -62,26 +56,7 @@ from haystack_experimental.memory_stores.types import MemoryStore
|
|
|
62
56
|
logger = logging.getLogger(__name__)
|
|
63
57
|
|
|
64
58
|
|
|
65
|
-
@
|
|
66
|
-
class _ExecutionContext(Haystack_ExecutionContext):
|
|
67
|
-
"""
|
|
68
|
-
Execution context for the Agent component
|
|
69
|
-
|
|
70
|
-
Extends Haystack's _ExecutionContext to include tool execution decisions for human-in-the-loop strategies.
|
|
71
|
-
|
|
72
|
-
:param tool_execution_decisions: Optional list of ToolExecutionDecision objects to use instead of prompting
|
|
73
|
-
the user. This is useful when restarting from a snapshot where tool execution decisions were already made.
|
|
74
|
-
:param confirmation_strategy_context: Optional dictionary for passing request-scoped resources
|
|
75
|
-
to confirmation strategies. In web/server environments, this enables passing per-request
|
|
76
|
-
objects (e.g., WebSocket connections, async queues, or pub/sub clients) that strategies can use for
|
|
77
|
-
non-blocking user interaction. This is passed directly to strategies via the `confirmation_strategy_context`
|
|
78
|
-
parameter in their `run()` and `run_async()` methods.
|
|
79
|
-
"""
|
|
80
|
-
|
|
81
|
-
tool_execution_decisions: list[ToolExecutionDecision] | None = None
|
|
82
|
-
confirmation_strategy_context: dict[str, Any] | None = None
|
|
83
|
-
|
|
84
|
-
|
|
59
|
+
@component
|
|
85
60
|
class Agent(HaystackAgent):
|
|
86
61
|
"""
|
|
87
62
|
A Haystack component that implements a tool-using agent with provider-agnostic chat model support.
|
|
@@ -182,8 +157,8 @@ class Agent(HaystackAgent):
|
|
|
182
157
|
streaming_callback=streaming_callback,
|
|
183
158
|
raise_on_tool_invocation_failure=raise_on_tool_invocation_failure,
|
|
184
159
|
tool_invoker_kwargs=tool_invoker_kwargs,
|
|
160
|
+
confirmation_strategies=confirmation_strategies,
|
|
185
161
|
)
|
|
186
|
-
self._confirmation_strategies = confirmation_strategies or {}
|
|
187
162
|
self._chat_message_store = chat_message_store
|
|
188
163
|
self._chat_message_retriever = (
|
|
189
164
|
ChatMessageRetriever(chat_message_store=chat_message_store) if chat_message_store else None
|
|
@@ -226,79 +201,57 @@ class Agent(HaystackAgent):
|
|
|
226
201
|
For example, it can include the `chat_history_id` and `last_k` parameters for retrieving chat history.
|
|
227
202
|
:param kwargs: Additional data to pass to the State used by the Agent.
|
|
228
203
|
"""
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
204
|
+
exe_context = super(Agent, self)._initialize_fresh_execution(
|
|
205
|
+
messages=messages,
|
|
206
|
+
streaming_callback=streaming_callback,
|
|
207
|
+
requires_async=requires_async,
|
|
208
|
+
system_prompt=system_prompt,
|
|
209
|
+
generation_kwargs=generation_kwargs,
|
|
210
|
+
tools=tools,
|
|
211
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
212
|
+
chat_message_store_kwargs=chat_message_store_kwargs,
|
|
213
|
+
**kwargs,
|
|
214
|
+
)
|
|
232
215
|
|
|
233
|
-
#
|
|
216
|
+
# NOTE: difference with parent method to add memory retrieval
|
|
234
217
|
if self._memory_store:
|
|
235
|
-
retrieved_memories = self._memory_store.search_memories(
|
|
236
|
-
|
|
218
|
+
retrieved_memories = self._memory_store.search_memories(
|
|
219
|
+
query=messages[-1].text, **memory_store_kwargs if memory_store_kwargs else {}
|
|
220
|
+
)
|
|
237
221
|
# we combine the memories into a single string
|
|
238
222
|
combined_memory = "\n".join(
|
|
239
223
|
f"- MEMORY #{idx + 1}: {memory.text}" for idx, memory in enumerate(retrieved_memories)
|
|
240
224
|
)
|
|
241
225
|
retrieved_memory = ChatMessage.from_system(text=combined_memory)
|
|
242
|
-
|
|
243
|
-
if retrieved_memory:
|
|
244
226
|
memory_instruction = (
|
|
245
|
-
"\n\nWhen messages start with `[MEMORY]`, treat them as long-term "
|
|
246
|
-
"
|
|
227
|
+
"\n\nWhen messages start with `[MEMORY]`, treat them as long-term context and use them to guide the "
|
|
228
|
+
"response if relevant."
|
|
247
229
|
)
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
combined_messages = messages + [updated_memory] if updated_memory else messages
|
|
257
|
-
if updated_system_prompt is not None:
|
|
258
|
-
combined_messages = [ChatMessage.from_system(updated_system_prompt)] + combined_messages
|
|
230
|
+
new_system_message = ChatMessage.from_system(text=f"{system_prompt}{memory_instruction}")
|
|
231
|
+
memory_system_message = ChatMessage.from_system(
|
|
232
|
+
text=f"Here are the relevant memories for the user's query: {retrieved_memory.text}"
|
|
233
|
+
)
|
|
234
|
+
new_chat_history = [new_system_message] + messages + [memory_system_message]
|
|
235
|
+
# We replace the messages in state with the new chat history including memories
|
|
236
|
+
exe_context.state.set("messages", new_chat_history, handler_override=replace_values)
|
|
259
237
|
|
|
260
238
|
# NOTE: difference with parent method to add chat message retrieval
|
|
261
239
|
if self._chat_message_retriever:
|
|
262
240
|
retriever_kwargs = _select_kwargs(self._chat_message_retriever, chat_message_store_kwargs or {})
|
|
263
241
|
if "chat_history_id" in retriever_kwargs:
|
|
264
|
-
|
|
265
|
-
current_messages=
|
|
242
|
+
updated_messages = self._chat_message_retriever.run(
|
|
243
|
+
current_messages=exe_context.state.get("messages", []),
|
|
266
244
|
**retriever_kwargs,
|
|
267
245
|
)["messages"]
|
|
268
|
-
|
|
246
|
+
# We replace the messages in state with the updated messages including chat history
|
|
247
|
+
exe_context.state.set("messages", updated_messages, handler_override=replace_values)
|
|
269
248
|
|
|
270
|
-
if all(m.is_from(ChatRole.SYSTEM) for m in combined_messages):
|
|
271
|
-
logger.warning("All messages provided to the Agent component are system messages. This is not recommended.")
|
|
272
|
-
|
|
273
|
-
state = State(schema=self.state_schema, data=kwargs)
|
|
274
|
-
state.set("messages", combined_messages)
|
|
275
|
-
|
|
276
|
-
streaming_callback = select_streaming_callback( # type: ignore[call-overload]
|
|
277
|
-
init_callback=self.streaming_callback, runtime_callback=streaming_callback, requires_async=requires_async
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
selected_tools = self._select_tools(tools)
|
|
281
|
-
tool_invoker_inputs: dict[str, Any] = {"tools": selected_tools}
|
|
282
|
-
generator_inputs: dict[str, Any] = {"tools": selected_tools}
|
|
283
|
-
if streaming_callback is not None:
|
|
284
|
-
tool_invoker_inputs["streaming_callback"] = streaming_callback
|
|
285
|
-
generator_inputs["streaming_callback"] = streaming_callback
|
|
286
|
-
if generation_kwargs is not None:
|
|
287
|
-
generator_inputs["generation_kwargs"] = generation_kwargs
|
|
288
|
-
|
|
289
|
-
# NOTE: difference with parent method to add this to tool_invoker_inputs
|
|
290
|
-
if self._tool_invoker:
|
|
291
|
-
tool_invoker_inputs["enable_streaming_callback_passthrough"] = (
|
|
292
|
-
self._tool_invoker.enable_streaming_callback_passthrough
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
# NOTE: difference is to use the extended _ExecutionContext with confirmation_strategy_context
|
|
296
249
|
return _ExecutionContext(
|
|
297
|
-
state=state,
|
|
298
|
-
component_visits=
|
|
299
|
-
chat_generator_inputs=
|
|
300
|
-
tool_invoker_inputs=tool_invoker_inputs,
|
|
301
|
-
confirmation_strategy_context=confirmation_strategy_context,
|
|
250
|
+
state=exe_context.state,
|
|
251
|
+
component_visits=exe_context.component_visits,
|
|
252
|
+
chat_generator_inputs=exe_context.chat_generator_inputs,
|
|
253
|
+
tool_invoker_inputs=exe_context.tool_invoker_inputs,
|
|
254
|
+
confirmation_strategy_context=exe_context.confirmation_strategy_context,
|
|
302
255
|
)
|
|
303
256
|
|
|
304
257
|
def _initialize_from_snapshot( # type: ignore[override]
|
|
@@ -324,28 +277,15 @@ class Agent(HaystackAgent):
|
|
|
324
277
|
:param confirmation_strategy_context: Optional dictionary for passing request-scoped resources
|
|
325
278
|
to confirmation strategies.
|
|
326
279
|
"""
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
tools=tools,
|
|
337
|
-
)
|
|
338
|
-
else:
|
|
339
|
-
exe_context = super(Agent, self)._initialize_from_snapshot(
|
|
340
|
-
snapshot=snapshot, streaming_callback=streaming_callback, requires_async=requires_async, tools=tools
|
|
341
|
-
)
|
|
342
|
-
# NOTE: 1st difference with parent method to add this to tool_invoker_inputs
|
|
343
|
-
if self._tool_invoker:
|
|
344
|
-
exe_context.tool_invoker_inputs["enable_streaming_callback_passthrough"] = (
|
|
345
|
-
self._tool_invoker.enable_streaming_callback_passthrough
|
|
346
|
-
)
|
|
347
|
-
# NOTE: 2nd difference is to use the extended _ExecutionContext
|
|
348
|
-
# and add tool_execution_decisions + confirmation_strategy_context
|
|
280
|
+
exe_context = super(Agent, self)._initialize_from_snapshot(
|
|
281
|
+
snapshot=snapshot,
|
|
282
|
+
streaming_callback=streaming_callback,
|
|
283
|
+
requires_async=requires_async,
|
|
284
|
+
generation_kwargs=generation_kwargs,
|
|
285
|
+
tools=tools,
|
|
286
|
+
confirmation_strategy_context=confirmation_strategy_context,
|
|
287
|
+
)
|
|
288
|
+
# NOTE: Only difference is to use pass tool_execution_decisions to _ExecutionContext
|
|
349
289
|
return _ExecutionContext(
|
|
350
290
|
state=exe_context.state,
|
|
351
291
|
component_visits=exe_context.component_visits,
|
|
@@ -353,8 +293,8 @@ class Agent(HaystackAgent):
|
|
|
353
293
|
tool_invoker_inputs=exe_context.tool_invoker_inputs,
|
|
354
294
|
counter=exe_context.counter,
|
|
355
295
|
skip_chat_generator=exe_context.skip_chat_generator,
|
|
296
|
+
confirmation_strategy_context=exe_context.confirmation_strategy_context,
|
|
356
297
|
tool_execution_decisions=snapshot.tool_execution_decisions,
|
|
357
|
-
confirmation_strategy_context=confirmation_strategy_context,
|
|
358
298
|
)
|
|
359
299
|
|
|
360
300
|
def run( # type: ignore[override] # noqa: PLR0915 PLR0912
|
|
@@ -515,8 +455,9 @@ class Agent(HaystackAgent):
|
|
|
515
455
|
resolved_break_point = break_point
|
|
516
456
|
break_point_to_pass = resolved_break_point.break_point
|
|
517
457
|
|
|
518
|
-
#
|
|
458
|
+
# NOTE: difference with parent method to add support HITLBreakpointException
|
|
519
459
|
try:
|
|
460
|
+
# Apply confirmation strategies and update State and messages sent to ToolInvoker
|
|
520
461
|
# Run confirmation strategies to get updated tool call messages and modified chat history
|
|
521
462
|
modified_tool_call_messages, new_chat_history = _process_confirmation_strategies(
|
|
522
463
|
confirmation_strategies=self._confirmation_strategies,
|
|
@@ -772,8 +713,9 @@ class Agent(HaystackAgent):
|
|
|
772
713
|
resolved_break_point = break_point
|
|
773
714
|
break_point_to_pass = resolved_break_point.break_point
|
|
774
715
|
|
|
775
|
-
#
|
|
716
|
+
# NOTE: difference with parent method to add support HITLBreakpointException
|
|
776
717
|
try:
|
|
718
|
+
# Apply confirmation strategies and update State and messages sent to ToolInvoker
|
|
777
719
|
# Run confirmation strategies to get updated tool call messages and modified chat history (async)
|
|
778
720
|
modified_tool_call_messages, new_chat_history = await _process_confirmation_strategies_async(
|
|
779
721
|
confirmation_strategies=self._confirmation_strategies,
|
|
@@ -873,14 +815,13 @@ class Agent(HaystackAgent):
|
|
|
873
815
|
:return: Dictionary with serialized data
|
|
874
816
|
"""
|
|
875
817
|
data = super(Agent, self).to_dict()
|
|
876
|
-
|
|
877
|
-
{name: strategy.to_dict() for name, strategy in self._confirmation_strategies.items()}
|
|
878
|
-
if self._confirmation_strategies
|
|
879
|
-
else None
|
|
880
|
-
)
|
|
818
|
+
# NOTE: This is different from the base Agent class to handle ChatMessageStore serialization
|
|
881
819
|
data["init_parameters"]["chat_message_store"] = (
|
|
882
820
|
self._chat_message_store.to_dict() if self._chat_message_store is not None else None
|
|
883
821
|
)
|
|
822
|
+
data["init_parameters"]["memory_store"] = (
|
|
823
|
+
self._memory_store.to_dict() if self._memory_store is not None else None
|
|
824
|
+
)
|
|
884
825
|
return data
|
|
885
826
|
|
|
886
827
|
@classmethod
|
|
@@ -893,9 +834,9 @@ class Agent(HaystackAgent):
|
|
|
893
834
|
"""
|
|
894
835
|
init_params = data.get("init_parameters", {})
|
|
895
836
|
|
|
896
|
-
|
|
837
|
+
deserialize_component_inplace(init_params, key="chat_generator")
|
|
897
838
|
|
|
898
|
-
if "state_schema"
|
|
839
|
+
if init_params.get("state_schema") is not None:
|
|
899
840
|
init_params["state_schema"] = _schema_from_dict(init_params["state_schema"])
|
|
900
841
|
|
|
901
842
|
if init_params.get("streaming_callback") is not None:
|
|
@@ -904,24 +845,15 @@ class Agent(HaystackAgent):
|
|
|
904
845
|
deserialize_tools_or_toolset_inplace(init_params, key="tools")
|
|
905
846
|
|
|
906
847
|
if "confirmation_strategies" in init_params and init_params["confirmation_strategies"] is not None:
|
|
907
|
-
for name
|
|
908
|
-
|
|
909
|
-
strategy_class = import_class_by_name(strategy_dict["type"])
|
|
910
|
-
except ImportError as e:
|
|
911
|
-
raise DeserializationError(f"Class '{strategy_dict['type']}' not correctly imported") from e
|
|
912
|
-
if not hasattr(strategy_class, "from_dict"):
|
|
913
|
-
raise DeserializationError(f"{strategy_class} does not have from_dict method implemented.")
|
|
914
|
-
init_params["confirmation_strategies"][name] = strategy_class.from_dict(strategy_dict)
|
|
848
|
+
for name in init_params["confirmation_strategies"]:
|
|
849
|
+
deserialize_component_inplace(init_params["confirmation_strategies"], key=name)
|
|
915
850
|
|
|
851
|
+
# NOTE: This is different from the base Agent class to handle ChatMessageStore deserialization
|
|
916
852
|
if "chat_message_store" in init_params and init_params["chat_message_store"] is not None:
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
raise DeserializationError(f"Class '{cms_data['type']}' not correctly imported") from e
|
|
922
|
-
if not hasattr(cms_class, "from_dict"):
|
|
923
|
-
raise DeserializationError(f"{cms_class} does not have from_dict method implemented.")
|
|
924
|
-
init_params["chat_message_store"] = cms_class.from_dict(cms_data)
|
|
853
|
+
deserialize_component_inplace(init_params, key="chat_message_store")
|
|
854
|
+
|
|
855
|
+
if "memory_store" in init_params and init_params["memory_store"] is not None:
|
|
856
|
+
deserialize_component_inplace(init_params, key="memory_store")
|
|
925
857
|
|
|
926
858
|
return default_from_dict(cls, data)
|
|
927
859
|
|
haystack_experimental-0.19.0/haystack_experimental/components/agents/human_in_the_loop/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
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": ["ToolExecutionDecision"],
|
|
12
|
+
"errors": ["HITLBreakpointException"],
|
|
13
|
+
"strategies": ["BreakpointConfirmationStrategy"],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from .dataclasses import ToolExecutionDecision as ToolExecutionDecision
|
|
18
|
+
from .errors import HITLBreakpointException as HITLBreakpointException
|
|
19
|
+
from .strategies import BreakpointConfirmationStrategy as BreakpointConfirmationStrategy
|
|
20
|
+
|
|
21
|
+
else:
|
|
22
|
+
sys.modules[__name__] = LazyImporter(name=__name__, module_file=__file__, import_structure=_import_structure)
|
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
from copy import deepcopy
|
|
6
6
|
|
|
7
7
|
from haystack.dataclasses.breakpoints import AgentSnapshot, ToolBreakpoint
|
|
8
|
+
from haystack.human_in_the_loop.strategies import _prepare_tool_args
|
|
8
9
|
from haystack.utils import _deserialize_value_with_schema
|
|
9
10
|
|
|
10
|
-
from haystack_experimental.components.agents.human_in_the_loop.strategies import _prepare_tool_args
|
|
11
|
-
|
|
12
11
|
|
|
13
12
|
def get_tool_calls_and_descriptions_from_snapshot(
|
|
14
13
|
agent_snapshot: AgentSnapshot, breakpoint_tool_only: bool = True
|