haystack-experimental 0.14.3__tar.gz → 0.15.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.14.3 → haystack_experimental-0.15.0}/.gitignore +1 -1
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/PKG-INFO +24 -31
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/README.md +23 -30
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/chat_message_stores/__init__.py +1 -1
- haystack_experimental-0.15.0/haystack_experimental/chat_message_stores/in_memory.py +231 -0
- haystack_experimental-0.15.0/haystack_experimental/chat_message_stores/types.py +86 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/agent.py +147 -44
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/strategies.py +220 -3
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/types.py +36 -1
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/embedders/types/protocol.py +2 -2
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/preprocessors/embedding_based_document_splitter.py +16 -16
- haystack_experimental-0.15.0/haystack_experimental/components/retrievers/__init__.py +7 -0
- haystack_experimental-0.15.0/haystack_experimental/components/retrievers/chat_message_retriever.py +139 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/writers/__init__.py +1 -1
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/writers/chat_message_writer.py +25 -22
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/pyproject.toml +4 -10
- haystack_experimental-0.14.3/haystack_experimental/chat_message_stores/in_memory.py +0 -86
- haystack_experimental-0.14.3/haystack_experimental/chat_message_stores/types.py +0 -74
- haystack_experimental-0.14.3/haystack_experimental/components/query/__init__.py +0 -18
- haystack_experimental-0.14.3/haystack_experimental/components/query/query_expander.py +0 -294
- haystack_experimental-0.14.3/haystack_experimental/components/retrievers/__init__.py +0 -9
- haystack_experimental-0.14.3/haystack_experimental/components/retrievers/chat_message_retriever.py +0 -108
- haystack_experimental-0.14.3/haystack_experimental/components/retrievers/multi_query_embedding_retriever.py +0 -173
- haystack_experimental-0.14.3/haystack_experimental/components/retrievers/multi_query_text_retriever.py +0 -150
- haystack_experimental-0.14.3/haystack_experimental/super_components/indexers/__init__.py +0 -11
- haystack_experimental-0.14.3/haystack_experimental/super_components/indexers/sentence_transformers_document_indexer.py +0 -199
- haystack_experimental-0.14.3/haystack_experimental/utils/__init__.py +0 -3
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/LICENSE +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/LICENSE-MIT.txt +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/breakpoint.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/dataclasses.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/errors.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/policies.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/agents/human_in_the_loop/user_interfaces.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/embedders/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/embedders/types/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/generators/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/generators/chat/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/generators/chat/openai.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/preprocessors/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/preprocessors/md_header_level_inferrer.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/retrievers/types/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/retrievers/types/protocol.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/summarizers/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/components/summarizers/llm_summarizer.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/core/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/core/pipeline/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/core/pipeline/breakpoint.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/dataclasses/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/dataclasses/breakpoints.py +0 -0
- {haystack_experimental-0.14.3/haystack_experimental/super_components → haystack_experimental-0.15.0/haystack_experimental/utils}/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/utils/hallucination_risk_calculator/__init__.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/utils/hallucination_risk_calculator/core_math.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/utils/hallucination_risk_calculator/dataclasses.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.0}/haystack_experimental/utils/hallucination_risk_calculator/openai_planner.py +0 -0
- {haystack_experimental-0.14.3 → haystack_experimental-0.15.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.15.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
|
|
@@ -71,35 +71,24 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
71
71
|
|
|
72
72
|
### Active experiments
|
|
73
73
|
|
|
74
|
-
| Name | Type
|
|
75
|
-
|
|
76
|
-
| [`
|
|
77
|
-
| [`
|
|
78
|
-
| [`
|
|
79
|
-
| [`
|
|
80
|
-
| [`
|
|
81
|
-
| [`
|
|
82
|
-
| [`MultiQueryTextRetriever`][14] | MultiQueryTextRetriever | November 2025 | None | None | [Discuss][12] |
|
|
83
|
-
| [`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] |
|
|
84
|
-
| [`MarkdownHeaderLevelInferrer`][15] | Preprocessor | January 2025 | None | None | [Discuss][16] |
|
|
85
|
-
| [`Agent`][17]; [Confirmation Policies][18]; [ConfirmationUIs][19]; [ConfirmationStrategies][20]; [`ConfirmationUIResult` and `ToolExecutionDecision`][21] [HITLBreakpointException][22] | Human in the Loop | December 2025 | rich | None | [Discuss][23] |
|
|
86
|
-
| [`LLMSummarizer`][24] | Document Summarizer | January 2025 | None | None | [Discuss][25] |
|
|
74
|
+
| Name | Type | Expected End Date | Dependencies | Cookbook | Discussion |
|
|
75
|
+
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------|-------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
|
76
|
+
| [`EmbeddingBasedDocumentSplitter`][8] | EmbeddingBasedDocumentSplitter | August 2025 | None | None | [Discuss][7] |
|
|
77
|
+
| [`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] |
|
|
78
|
+
| [`MarkdownHeaderLevelInferrer`][15] | Preprocessor | January 2025 | None | None | [Discuss][16] |
|
|
79
|
+
| [`Agent`][17]; [Confirmation Policies][18]; [ConfirmationUIs][19]; [ConfirmationStrategies][20]; [`ConfirmationUIResult` and `ToolExecutionDecision`][21] [HITLBreakpointException][22] | Human in the Loop | December 2025 | rich | None | [Discuss][23] |
|
|
80
|
+
| [`LLMSummarizer`][24] | Document Summarizer | January 2025 | None | None | [Discuss][25] |
|
|
81
|
+
| [`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] |
|
|
87
82
|
|
|
88
83
|
[1]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/chat_message_stores/in_memory.py
|
|
89
84
|
[2]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/chat_message_retriever.py
|
|
90
85
|
[3]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/writers/chat_message_writer.py
|
|
91
86
|
[4]: https://github.com/deepset-ai/haystack-experimental/discussions/75
|
|
92
|
-
[5]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/query/query_expander.py
|
|
93
|
-
[6]: https://github.com/deepset-ai/haystack-experimental/discussions/346
|
|
94
87
|
[7]: https://github.com/deepset-ai/haystack-experimental/discussions/356
|
|
95
88
|
[8]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/embedding_based_document_splitter.py
|
|
96
89
|
[9]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/generators/chat/openai.py
|
|
97
90
|
[10]: https://github.com/deepset-ai/haystack-experimental/discussions/361
|
|
98
|
-
[
|
|
99
|
-
[12]: https://github.com/deepset-ai/haystack-experimental/discussions/364
|
|
100
|
-
[13]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/multi_query_embedding_retriever.py
|
|
101
|
-
[14]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/multi_query_text_retriever.py
|
|
102
|
-
[15]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/md_header_level_inferrer.py
|
|
91
|
+
[15]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/md_header_level_inferrer.py
|
|
103
92
|
[16]: https://github.com/deepset-ai/haystack-experimental/discussions/376
|
|
104
93
|
[17]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/agent.py
|
|
105
94
|
[18]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/policies.py
|
|
@@ -112,16 +101,20 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
112
101
|
[25]: https://github.com/deepset-ai/haystack-experimental/discussions/382
|
|
113
102
|
|
|
114
103
|
### Adopted experiments
|
|
115
|
-
| Name
|
|
116
|
-
|
|
117
|
-
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker`
|
|
118
|
-
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring
|
|
119
|
-
| `LLMMetadataExtractor`
|
|
120
|
-
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter`
|
|
121
|
-
| `Agent`
|
|
122
|
-
| `SuperComponent`
|
|
123
|
-
| `Pipeline`
|
|
124
|
-
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers`
|
|
104
|
+
| Name | Type | Final release |
|
|
105
|
+
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------|---------------|
|
|
106
|
+
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker` | Tool Calling support | 0.4.0 |
|
|
107
|
+
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring | AsyncPipeline execution | 0.7.0 |
|
|
108
|
+
| `LLMMetadataExtractor` | Metadata extraction with LLM | 0.7.0 |
|
|
109
|
+
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter` | Document Splitting & Retrieval Technique | 0.8.0 |
|
|
110
|
+
| `Agent` | Simplify Agent development | 0.8.0 |
|
|
111
|
+
| `SuperComponent` | Simplify Pipeline development | 0.8.0 |
|
|
112
|
+
| `Pipeline` | Pipeline breakpoints for debugging | 0.12.0 |
|
|
113
|
+
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers` | Multimodality | 0.12.0 |
|
|
114
|
+
| `QueryExpander` | Query Expansion Component | 0.14.3 |
|
|
115
|
+
| `MultiQueryEmbeddingRetriever` | MultiQueryEmbeddingRetriever | 0.14.3 |
|
|
116
|
+
| `MultiQueryTextRetriever` | MultiQueryTextRetriever | 0.14.3 |
|
|
117
|
+
|
|
125
118
|
|
|
126
119
|
### Discontinued experiments
|
|
127
120
|
|
|
@@ -41,35 +41,24 @@ 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 | Type
|
|
45
|
-
|
|
46
|
-
| [`
|
|
47
|
-
| [`
|
|
48
|
-
| [`
|
|
49
|
-
| [`
|
|
50
|
-
| [`
|
|
51
|
-
| [`
|
|
52
|
-
| [`MultiQueryTextRetriever`][14] | MultiQueryTextRetriever | November 2025 | None | None | [Discuss][12] |
|
|
53
|
-
| [`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] |
|
|
54
|
-
| [`MarkdownHeaderLevelInferrer`][15] | Preprocessor | January 2025 | None | None | [Discuss][16] |
|
|
55
|
-
| [`Agent`][17]; [Confirmation Policies][18]; [ConfirmationUIs][19]; [ConfirmationStrategies][20]; [`ConfirmationUIResult` and `ToolExecutionDecision`][21] [HITLBreakpointException][22] | Human in the Loop | December 2025 | rich | None | [Discuss][23] |
|
|
56
|
-
| [`LLMSummarizer`][24] | Document Summarizer | January 2025 | None | None | [Discuss][25] |
|
|
44
|
+
| Name | Type | Expected End Date | Dependencies | Cookbook | Discussion |
|
|
45
|
+
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------|-------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
|
46
|
+
| [`EmbeddingBasedDocumentSplitter`][8] | EmbeddingBasedDocumentSplitter | August 2025 | None | None | [Discuss][7] |
|
|
47
|
+
| [`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] |
|
|
48
|
+
| [`MarkdownHeaderLevelInferrer`][15] | Preprocessor | January 2025 | None | None | [Discuss][16] |
|
|
49
|
+
| [`Agent`][17]; [Confirmation Policies][18]; [ConfirmationUIs][19]; [ConfirmationStrategies][20]; [`ConfirmationUIResult` and `ToolExecutionDecision`][21] [HITLBreakpointException][22] | Human in the Loop | December 2025 | rich | None | [Discuss][23] |
|
|
50
|
+
| [`LLMSummarizer`][24] | Document Summarizer | January 2025 | None | None | [Discuss][25] |
|
|
51
|
+
| [`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] |
|
|
57
52
|
|
|
58
53
|
[1]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/chat_message_stores/in_memory.py
|
|
59
54
|
[2]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/chat_message_retriever.py
|
|
60
55
|
[3]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/writers/chat_message_writer.py
|
|
61
56
|
[4]: https://github.com/deepset-ai/haystack-experimental/discussions/75
|
|
62
|
-
[5]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/query/query_expander.py
|
|
63
|
-
[6]: https://github.com/deepset-ai/haystack-experimental/discussions/346
|
|
64
57
|
[7]: https://github.com/deepset-ai/haystack-experimental/discussions/356
|
|
65
58
|
[8]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/embedding_based_document_splitter.py
|
|
66
59
|
[9]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/generators/chat/openai.py
|
|
67
60
|
[10]: https://github.com/deepset-ai/haystack-experimental/discussions/361
|
|
68
|
-
[
|
|
69
|
-
[12]: https://github.com/deepset-ai/haystack-experimental/discussions/364
|
|
70
|
-
[13]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/multi_query_embedding_retriever.py
|
|
71
|
-
[14]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/retrievers/multi_query_text_retriever.py
|
|
72
|
-
[15]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/md_header_level_inferrer.py
|
|
61
|
+
[15]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/preprocessors/md_header_level_inferrer.py
|
|
73
62
|
[16]: https://github.com/deepset-ai/haystack-experimental/discussions/376
|
|
74
63
|
[17]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/agent.py
|
|
75
64
|
[18]: https://github.com/deepset-ai/haystack-experimental/blob/main/haystack_experimental/components/agents/human_in_the_loop/policies.py
|
|
@@ -82,16 +71,20 @@ that includes it. Once it reaches the end of its lifespan, the experiment will b
|
|
|
82
71
|
[25]: https://github.com/deepset-ai/haystack-experimental/discussions/382
|
|
83
72
|
|
|
84
73
|
### Adopted experiments
|
|
85
|
-
| Name
|
|
86
|
-
|
|
87
|
-
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker`
|
|
88
|
-
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring
|
|
89
|
-
| `LLMMetadataExtractor`
|
|
90
|
-
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter`
|
|
91
|
-
| `Agent`
|
|
92
|
-
| `SuperComponent`
|
|
93
|
-
| `Pipeline`
|
|
94
|
-
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers`
|
|
74
|
+
| Name | Type | Final release |
|
|
75
|
+
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------|---------------|
|
|
76
|
+
| `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker` | Tool Calling support | 0.4.0 |
|
|
77
|
+
| `AsyncPipeline`; `Pipeline` bug fixes and refactoring | AsyncPipeline execution | 0.7.0 |
|
|
78
|
+
| `LLMMetadataExtractor` | Metadata extraction with LLM | 0.7.0 |
|
|
79
|
+
| `Auto-Merging Retriever` & `HierarchicalDocumentSplitter` | Document Splitting & Retrieval Technique | 0.8.0 |
|
|
80
|
+
| `Agent` | Simplify Agent development | 0.8.0 |
|
|
81
|
+
| `SuperComponent` | Simplify Pipeline development | 0.8.0 |
|
|
82
|
+
| `Pipeline` | Pipeline breakpoints for debugging | 0.12.0 |
|
|
83
|
+
| `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers` | Multimodality | 0.12.0 |
|
|
84
|
+
| `QueryExpander` | Query Expansion Component | 0.14.3 |
|
|
85
|
+
| `MultiQueryEmbeddingRetriever` | MultiQueryEmbeddingRetriever | 0.14.3 |
|
|
86
|
+
| `MultiQueryTextRetriever` | MultiQueryTextRetriever | 0.14.3 |
|
|
87
|
+
|
|
95
88
|
|
|
96
89
|
### Discontinued experiments
|
|
97
90
|
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from dataclasses import replace
|
|
6
|
+
from typing import Any, Iterable, Optional
|
|
7
|
+
|
|
8
|
+
from haystack import default_from_dict, default_to_dict
|
|
9
|
+
from haystack.dataclasses import ChatMessage, ChatRole
|
|
10
|
+
|
|
11
|
+
# Global storage for all InMemoryDocumentStore instances, indexed by the chat history id.
|
|
12
|
+
_STORAGES: dict[str, list[ChatMessage]] = {}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class InMemoryChatMessageStore:
|
|
16
|
+
"""
|
|
17
|
+
Stores chat messages in-memory.
|
|
18
|
+
|
|
19
|
+
The `chat_history_id` parameter is used as a unique identifier for each conversation or chat session.
|
|
20
|
+
It acts as a namespace that isolates messages from different sessions. Each `chat_history_id` value corresponds to a
|
|
21
|
+
separate list of `ChatMessage` objects stored in memory.
|
|
22
|
+
|
|
23
|
+
Typical usage involves providing a unique `chat_history_id` (for example, a session ID or conversation ID)
|
|
24
|
+
whenever you write, read, or delete messages. This ensures that chat messages from different
|
|
25
|
+
conversations do not overlap.
|
|
26
|
+
|
|
27
|
+
Usage example:
|
|
28
|
+
```python
|
|
29
|
+
from haystack.dataclasses import ChatMessage
|
|
30
|
+
from haystack_experimental.chat_message_stores.in_memory import InMemoryChatMessageStore
|
|
31
|
+
|
|
32
|
+
message_store = InMemoryChatMessageStore()
|
|
33
|
+
|
|
34
|
+
messages = [
|
|
35
|
+
ChatMessage.from_assistant("Hello, how can I help you?"),
|
|
36
|
+
ChatMessage.from_user("Hi, I have a question about Python. What is a Protocol?"),
|
|
37
|
+
]
|
|
38
|
+
message_store.write_messages(chat_history_id="user_456_session_123", messages=messages)
|
|
39
|
+
retrieved_messages = message_store.retrieve_messages(chat_history_id="user_456_session_123")
|
|
40
|
+
|
|
41
|
+
print(retrieved_messages)
|
|
42
|
+
```
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, skip_system_messages: bool = True, last_k: Optional[int] = 10) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Create an InMemoryChatMessageStore.
|
|
48
|
+
|
|
49
|
+
:param skip_system_messages:
|
|
50
|
+
Whether to skip storing system messages. Defaults to True.
|
|
51
|
+
:param last_k:
|
|
52
|
+
The number of last messages to retrieve. Defaults to 10 messages if not specified.
|
|
53
|
+
"""
|
|
54
|
+
self.skip_system_messages = skip_system_messages
|
|
55
|
+
self.last_k = last_k
|
|
56
|
+
|
|
57
|
+
def to_dict(self) -> dict[str, Any]:
|
|
58
|
+
"""
|
|
59
|
+
Serializes the component to a dictionary.
|
|
60
|
+
|
|
61
|
+
:returns:
|
|
62
|
+
Dictionary with serialized data.
|
|
63
|
+
"""
|
|
64
|
+
return default_to_dict(self, skip_system_messages=self.skip_system_messages, last_k=self.last_k)
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def from_dict(cls, data: dict[str, Any]) -> "InMemoryChatMessageStore":
|
|
68
|
+
"""
|
|
69
|
+
Deserializes the component from a dictionary.
|
|
70
|
+
|
|
71
|
+
:param data:
|
|
72
|
+
The dictionary to deserialize from.
|
|
73
|
+
:returns:
|
|
74
|
+
The deserialized component.
|
|
75
|
+
"""
|
|
76
|
+
return default_from_dict(cls, data)
|
|
77
|
+
|
|
78
|
+
def count_messages(self, chat_history_id: str) -> int:
|
|
79
|
+
"""
|
|
80
|
+
Returns the number of chat messages stored in this store.
|
|
81
|
+
|
|
82
|
+
:param chat_history_id:
|
|
83
|
+
The chat history id for which to count messages.
|
|
84
|
+
|
|
85
|
+
:returns: The number of messages.
|
|
86
|
+
"""
|
|
87
|
+
return len(_STORAGES.get(chat_history_id, []))
|
|
88
|
+
|
|
89
|
+
def write_messages(self, chat_history_id: str, messages: list[ChatMessage]) -> int:
|
|
90
|
+
"""
|
|
91
|
+
Writes chat messages to the ChatMessageStore.
|
|
92
|
+
|
|
93
|
+
:param chat_history_id:
|
|
94
|
+
The chat history id under which to store the messages.
|
|
95
|
+
:param messages:
|
|
96
|
+
A list of ChatMessages to write.
|
|
97
|
+
|
|
98
|
+
:returns: The number of messages written.
|
|
99
|
+
|
|
100
|
+
:raises ValueError: If messages is not a list of ChatMessages.
|
|
101
|
+
"""
|
|
102
|
+
if not isinstance(messages, Iterable) or any(not isinstance(message, ChatMessage) for message in messages):
|
|
103
|
+
raise ValueError("Please provide a list of ChatMessages.")
|
|
104
|
+
|
|
105
|
+
# We assign an ID to messages that don't have one yet. The ID simply corresponds to the chat_history_id in the
|
|
106
|
+
# array.
|
|
107
|
+
counter = self.count_messages(chat_history_id)
|
|
108
|
+
messages_with_id = []
|
|
109
|
+
for msg in messages:
|
|
110
|
+
# Skip system messages if configured to do so
|
|
111
|
+
if self.skip_system_messages and msg.is_from(ChatRole.SYSTEM):
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
chat_message_id = msg.meta.get("chat_message_id")
|
|
115
|
+
if chat_message_id is None:
|
|
116
|
+
# We use replace to avoid mutating the original message
|
|
117
|
+
msg = replace(msg, _meta={"chat_message_id": str(counter), **msg.meta})
|
|
118
|
+
counter += 1
|
|
119
|
+
|
|
120
|
+
messages_with_id.append(msg)
|
|
121
|
+
|
|
122
|
+
# For now, we always skip messages that are already stored based on their ID.
|
|
123
|
+
existing_messages = _STORAGES.get(chat_history_id, [])
|
|
124
|
+
existing_ids = {
|
|
125
|
+
msg.meta.get("chat_message_id") for msg in existing_messages if msg.meta.get("chat_message_id") is not None
|
|
126
|
+
}
|
|
127
|
+
messages_to_write = [
|
|
128
|
+
message for message in messages_with_id if message.meta["chat_message_id"] not in existing_ids
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
for message in messages_to_write:
|
|
132
|
+
if chat_history_id not in _STORAGES:
|
|
133
|
+
_STORAGES[chat_history_id] = []
|
|
134
|
+
_STORAGES[chat_history_id].append(message)
|
|
135
|
+
|
|
136
|
+
return len(messages_to_write)
|
|
137
|
+
|
|
138
|
+
def retrieve_messages(self, chat_history_id: str, last_k: Optional[int] = None) -> list[ChatMessage]:
|
|
139
|
+
"""
|
|
140
|
+
Retrieves all stored chat messages.
|
|
141
|
+
|
|
142
|
+
:param chat_history_id:
|
|
143
|
+
The chat history id from which to retrieve messages.
|
|
144
|
+
:param last_k:
|
|
145
|
+
The number of last messages to retrieve. If unspecified, the last_k parameter passed
|
|
146
|
+
to the constructor will be used.
|
|
147
|
+
|
|
148
|
+
:returns: A list of chat messages.
|
|
149
|
+
:raises ValueError:
|
|
150
|
+
If last_k is not None and is less than 0.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
if last_k is not None and last_k < 0:
|
|
154
|
+
raise ValueError("last_k must be 0 or greater")
|
|
155
|
+
|
|
156
|
+
resolved_last_k = last_k if last_k is not None else self.last_k
|
|
157
|
+
if resolved_last_k == 0:
|
|
158
|
+
return []
|
|
159
|
+
|
|
160
|
+
messages = _STORAGES.get(chat_history_id, [])
|
|
161
|
+
if resolved_last_k is not None:
|
|
162
|
+
messages = self._get_last_k_messages(messages=messages, last_k=resolved_last_k)
|
|
163
|
+
|
|
164
|
+
return messages
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
def _get_last_k_messages(messages: list[ChatMessage], last_k: int) -> list[ChatMessage]:
|
|
168
|
+
"""
|
|
169
|
+
Get the last_k rounds of messages from the incoming list of messages.
|
|
170
|
+
|
|
171
|
+
This is done in such a way such the returned list of messages is always valid. By valid we mean it will
|
|
172
|
+
be submittable to an LLM without causing issues. For example, we want to avoid slicing the chat history in a
|
|
173
|
+
way that a ToolCall is present without its corresponding ToolOutput.
|
|
174
|
+
|
|
175
|
+
This is handled by treating ToolCalls and its corresponding ToolOutput(s) as a single unit when slicing the chat
|
|
176
|
+
history.
|
|
177
|
+
|
|
178
|
+
:param messages:
|
|
179
|
+
List of chat messages.
|
|
180
|
+
:param last_k:
|
|
181
|
+
The number of last rounds of messages to retrieve. By rounds of messages we mean pairs of
|
|
182
|
+
User -> Assistant messages. ToolCalls and ToolOutputs are considered part of the Assistant message.
|
|
183
|
+
:returns:
|
|
184
|
+
The sliced list of chat messages.
|
|
185
|
+
"""
|
|
186
|
+
rounds = []
|
|
187
|
+
current = []
|
|
188
|
+
|
|
189
|
+
for msg in messages:
|
|
190
|
+
# Treat system messages as separate rounds
|
|
191
|
+
if msg.role == "system":
|
|
192
|
+
rounds.append([msg])
|
|
193
|
+
continue
|
|
194
|
+
|
|
195
|
+
# User messages always start a new round
|
|
196
|
+
if msg.role == "user":
|
|
197
|
+
current.append(msg)
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
# Assistant messages can either end a round or continue it (in case of tool calls)
|
|
201
|
+
if msg.role == "assistant":
|
|
202
|
+
current.append(msg)
|
|
203
|
+
if msg.text and not msg.tool_calls:
|
|
204
|
+
rounds.append(current)
|
|
205
|
+
current = []
|
|
206
|
+
continue
|
|
207
|
+
|
|
208
|
+
# Append all other messages (e.g., tool outputs) to the current round
|
|
209
|
+
current.append(msg)
|
|
210
|
+
|
|
211
|
+
# Catch any remaining messages in the current round
|
|
212
|
+
if current:
|
|
213
|
+
rounds.append(current)
|
|
214
|
+
|
|
215
|
+
selected = rounds[-last_k:]
|
|
216
|
+
return [m for r in selected for m in r]
|
|
217
|
+
|
|
218
|
+
def delete_messages(self, chat_history_id: str) -> None:
|
|
219
|
+
"""
|
|
220
|
+
Deletes all stored chat messages.
|
|
221
|
+
|
|
222
|
+
:param chat_history_id:
|
|
223
|
+
The chat history id from which to delete messages.
|
|
224
|
+
"""
|
|
225
|
+
_STORAGES.pop(chat_history_id, None)
|
|
226
|
+
|
|
227
|
+
def delete_all_messages(self) -> None:
|
|
228
|
+
"""
|
|
229
|
+
Deletes all stored chat messages from all chat history ids.
|
|
230
|
+
"""
|
|
231
|
+
_STORAGES.clear()
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional, Protocol
|
|
6
|
+
|
|
7
|
+
from haystack.dataclasses import ChatMessage
|
|
8
|
+
|
|
9
|
+
# Ellipsis are needed for the type checker, it's safe to disable module-wide
|
|
10
|
+
# pylint: disable=unnecessary-ellipsis
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ChatMessageStore(Protocol):
|
|
14
|
+
"""
|
|
15
|
+
Stores ChatMessages to be used by the components of a Pipeline.
|
|
16
|
+
|
|
17
|
+
Classes implementing this protocol might store ChatMessages either in durable storage or in memory. They might
|
|
18
|
+
allow specialized components (e.g. retrievers) to perform retrieval on them, either by embedding, by keyword,
|
|
19
|
+
hybrid, and so on, depending on the backend used.
|
|
20
|
+
|
|
21
|
+
In order to write or retrieve chat messages, consider using a ChatMessageWriter or ChatMessageRetriever.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def to_dict(self) -> dict[str, Any]:
|
|
25
|
+
"""
|
|
26
|
+
Serializes this store to a dictionary.
|
|
27
|
+
|
|
28
|
+
:returns: The serialized store as a dictionary.
|
|
29
|
+
"""
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def from_dict(cls, data: dict[str, Any]) -> "ChatMessageStore":
|
|
34
|
+
"""
|
|
35
|
+
Deserializes the store from a dictionary.
|
|
36
|
+
|
|
37
|
+
:param data: The dictionary to deserialize from.
|
|
38
|
+
:returns: The deserialized store.
|
|
39
|
+
"""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
def count_messages(self, chat_history_id: str) -> int:
|
|
43
|
+
"""
|
|
44
|
+
Returns the number of chat messages stored.
|
|
45
|
+
|
|
46
|
+
:param chat_history_id: The chat history id for which to count messages.
|
|
47
|
+
|
|
48
|
+
:returns: The number of messages.
|
|
49
|
+
"""
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
def write_messages(self, chat_history_id: str, messages: list[ChatMessage]) -> int:
|
|
53
|
+
"""
|
|
54
|
+
Writes chat messages to the ChatMessageStore.
|
|
55
|
+
|
|
56
|
+
:param chat_history_id: The chat history id under which to store the messages.
|
|
57
|
+
:param messages: A list of ChatMessages to write.
|
|
58
|
+
|
|
59
|
+
:returns: The number of messages written.
|
|
60
|
+
"""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
def delete_messages(self, chat_history_id: str) -> None:
|
|
64
|
+
"""
|
|
65
|
+
Deletes all stored chat messages.
|
|
66
|
+
|
|
67
|
+
:param chat_history_id: The chat history id from which to delete all messages.
|
|
68
|
+
"""
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
def delete_all_messages(self) -> None:
|
|
72
|
+
"""
|
|
73
|
+
Deletes all stored chat messages from all indices.
|
|
74
|
+
"""
|
|
75
|
+
...
|
|
76
|
+
|
|
77
|
+
def retrieve_messages(self, chat_history_id: str, last_k: Optional[int] = None) -> list[ChatMessage]:
|
|
78
|
+
"""
|
|
79
|
+
Retrieves chat messages from the ChatMessageStore.
|
|
80
|
+
|
|
81
|
+
:param chat_history_id: The chat history id from which to retrieve messages.
|
|
82
|
+
:param last_k: The number of last messages to retrieve. If None, retrieves all messages.
|
|
83
|
+
|
|
84
|
+
:returns: A list of retrieved ChatMessages.
|
|
85
|
+
"""
|
|
86
|
+
...
|