haystack-experimental 0.14.3__py3-none-any.whl → 0.15.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. haystack_experimental/chat_message_stores/__init__.py +1 -1
  2. haystack_experimental/chat_message_stores/in_memory.py +176 -31
  3. haystack_experimental/chat_message_stores/types.py +33 -21
  4. haystack_experimental/components/agents/agent.py +147 -44
  5. haystack_experimental/components/agents/human_in_the_loop/strategies.py +220 -3
  6. haystack_experimental/components/agents/human_in_the_loop/types.py +36 -1
  7. haystack_experimental/components/embedders/types/protocol.py +2 -2
  8. haystack_experimental/components/preprocessors/embedding_based_document_splitter.py +16 -16
  9. haystack_experimental/components/retrievers/__init__.py +1 -3
  10. haystack_experimental/components/retrievers/chat_message_retriever.py +57 -26
  11. haystack_experimental/components/writers/__init__.py +1 -1
  12. haystack_experimental/components/writers/chat_message_writer.py +25 -22
  13. {haystack_experimental-0.14.3.dist-info → haystack_experimental-0.15.0.dist-info}/METADATA +24 -31
  14. {haystack_experimental-0.14.3.dist-info → haystack_experimental-0.15.0.dist-info}/RECORD +17 -24
  15. {haystack_experimental-0.14.3.dist-info → haystack_experimental-0.15.0.dist-info}/WHEEL +1 -1
  16. haystack_experimental/components/query/__init__.py +0 -18
  17. haystack_experimental/components/query/query_expander.py +0 -294
  18. haystack_experimental/components/retrievers/multi_query_embedding_retriever.py +0 -173
  19. haystack_experimental/components/retrievers/multi_query_text_retriever.py +0 -150
  20. haystack_experimental/super_components/__init__.py +0 -3
  21. haystack_experimental/super_components/indexers/__init__.py +0 -11
  22. haystack_experimental/super_components/indexers/sentence_transformers_document_indexer.py +0 -199
  23. {haystack_experimental-0.14.3.dist-info → haystack_experimental-0.15.0.dist-info}/licenses/LICENSE +0 -0
  24. {haystack_experimental-0.14.3.dist-info → haystack_experimental-0.15.0.dist-info}/licenses/LICENSE-MIT.txt +0 -0
@@ -63,7 +63,12 @@ class ConfirmationPolicy(Protocol):
63
63
 
64
64
  class ConfirmationStrategy(Protocol):
65
65
  def run(
66
- self, tool_name: str, tool_description: str, tool_params: dict[str, Any], tool_call_id: Optional[str] = None
66
+ self,
67
+ tool_name: str,
68
+ tool_description: str,
69
+ tool_params: dict[str, Any],
70
+ tool_call_id: Optional[str] = None,
71
+ **kwargs: Optional[dict[str, Any]],
67
72
  ) -> ToolExecutionDecision:
68
73
  """
69
74
  Run the confirmation strategy for a given tool and its parameters.
@@ -73,6 +78,36 @@ class ConfirmationStrategy(Protocol):
73
78
  :param tool_params: The parameters to be passed to the tool.
74
79
  :param tool_call_id: Optional unique identifier for the tool call. This can be used to track and correlate
75
80
  the decision with a specific tool invocation.
81
+ :param kwargs: Additional keyword arguments. Implementations may accept `confirmation_strategy_context`
82
+ for passing request-scoped resources (e.g., WebSocket connections, async queues) in web/server
83
+ environments.
84
+
85
+ :returns:
86
+ The result of the confirmation strategy (e.g., tool output, rejection message, etc.).
87
+ """
88
+ ...
89
+
90
+ async def run_async(
91
+ self,
92
+ tool_name: str,
93
+ tool_description: str,
94
+ tool_params: dict[str, Any],
95
+ tool_call_id: Optional[str] = None,
96
+ **kwargs: Optional[dict[str, Any]],
97
+ ) -> ToolExecutionDecision:
98
+ """
99
+ Async version of run. Run the confirmation strategy for a given tool and its parameters.
100
+
101
+ Default implementation calls the sync run() method. Override for true async behavior.
102
+
103
+ :param tool_name: The name of the tool to be executed.
104
+ :param tool_description: The description of the tool.
105
+ :param tool_params: The parameters to be passed to the tool.
106
+ :param tool_call_id: Optional unique identifier for the tool call. This can be used to track and correlate
107
+ the decision with a specific tool invocation.
108
+ :param kwargs: Additional keyword arguments. Implementations may accept `confirmation_strategy_context`
109
+ for passing request-scoped resources (e.g., WebSocket connections, async queues) in web/server
110
+ environments.
76
111
 
77
112
  :returns:
78
113
  The result of the confirmation strategy (e.g., tool output, rejection message, etc.).
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Any, Dict, List, Protocol
5
+ from typing import Any, Protocol
6
6
 
7
7
  from haystack import Document
8
8
 
@@ -15,7 +15,7 @@ class DocumentEmbedder(Protocol):
15
15
  Protocol for Document Embedders.
16
16
  """
17
17
 
18
- def run(self, documents: List[Document]) -> Dict[str, Any]:
18
+ def run(self, documents: list[Document]) -> dict[str, Any]:
19
19
  """
20
20
  Generate embeddings for the input documents.
21
21
 
@@ -3,7 +3,7 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  from copy import deepcopy
6
- from typing import Any, Dict, List, Optional
6
+ from typing import Any, Optional
7
7
 
8
8
  import numpy as np
9
9
  from haystack import Document, component, logging
@@ -136,8 +136,8 @@ class EmbeddingBasedDocumentSplitter:
136
136
  self.document_embedder.warm_up()
137
137
  self._is_warmed_up = True
138
138
 
139
- @component.output_types(documents=List[Document])
140
- def run(self, documents: List[Document]) -> Dict[str, List[Document]]:
139
+ @component.output_types(documents=list[Document])
140
+ def run(self, documents: list[Document]) -> dict[str, list[Document]]:
141
141
  """
142
142
  Split documents based on embedding similarity.
143
143
 
@@ -162,7 +162,7 @@ class EmbeddingBasedDocumentSplitter:
162
162
  if not isinstance(documents, list) or (documents and not isinstance(documents[0], Document)):
163
163
  raise TypeError("EmbeddingBasedDocumentSplitter expects a List of Documents as input.")
164
164
 
165
- split_docs: List[Document] = []
165
+ split_docs: list[Document] = []
166
166
  for doc in documents:
167
167
  if doc.content is None:
168
168
  raise ValueError(
@@ -178,7 +178,7 @@ class EmbeddingBasedDocumentSplitter:
178
178
 
179
179
  return {"documents": split_docs}
180
180
 
181
- def _split_document(self, doc: Document) -> List[Document]:
181
+ def _split_document(self, doc: Document) -> list[Document]:
182
182
  """
183
183
  Split a single document based on embedding similarity.
184
184
  """
@@ -194,7 +194,7 @@ class EmbeddingBasedDocumentSplitter:
194
194
  # Create Document objects from the final splits
195
195
  return EmbeddingBasedDocumentSplitter._create_documents_from_splits(splits=final_splits, original_doc=doc)
196
196
 
197
- def _split_text(self, text: str) -> List[str]:
197
+ def _split_text(self, text: str) -> list[str]:
198
198
  """
199
199
  Split a text into smaller chunks based on embedding similarity.
200
200
  """
@@ -221,7 +221,7 @@ class EmbeddingBasedDocumentSplitter:
221
221
 
222
222
  return sub_splits
223
223
 
224
- def _group_sentences(self, sentences: List[str]) -> List[str]:
224
+ def _group_sentences(self, sentences: list[str]) -> list[str]:
225
225
  """
226
226
  Group sentences into groups of sentences_per_group.
227
227
  """
@@ -235,7 +235,7 @@ class EmbeddingBasedDocumentSplitter:
235
235
 
236
236
  return groups
237
237
 
238
- def _calculate_embeddings(self, sentence_groups: List[str]) -> List[List[float]]:
238
+ def _calculate_embeddings(self, sentence_groups: list[str]) -> list[list[float]]:
239
239
  """
240
240
  Calculate embeddings for each sentence group using the DocumentEmbedder.
241
241
  """
@@ -246,7 +246,7 @@ class EmbeddingBasedDocumentSplitter:
246
246
  embeddings = [doc.embedding for doc in embedded_docs]
247
247
  return embeddings
248
248
 
249
- def _find_split_points(self, embeddings: List[List[float]]) -> List[int]:
249
+ def _find_split_points(self, embeddings: list[list[float]]) -> list[int]:
250
250
  """
251
251
  Find split points based on cosine distances between sequential embeddings.
252
252
  """
@@ -273,7 +273,7 @@ class EmbeddingBasedDocumentSplitter:
273
273
  return split_points
274
274
 
275
275
  @staticmethod
276
- def _cosine_distance(embedding1: List[float], embedding2: List[float]) -> float:
276
+ def _cosine_distance(embedding1: list[float], embedding2: list[float]) -> float:
277
277
  """
278
278
  Calculate cosine distance between two embeddings.
279
279
  """
@@ -291,7 +291,7 @@ class EmbeddingBasedDocumentSplitter:
291
291
  return 1.0 - cosine_sim
292
292
 
293
293
  @staticmethod
294
- def _create_splits_from_points(sentence_groups: List[str], split_points: List[int]) -> List[str]:
294
+ def _create_splits_from_points(sentence_groups: list[str], split_points: list[int]) -> list[str]:
295
295
  """
296
296
  Create splits based on split points.
297
297
  """
@@ -315,7 +315,7 @@ class EmbeddingBasedDocumentSplitter:
315
315
 
316
316
  return splits
317
317
 
318
- def _merge_small_splits(self, splits: List[str]) -> List[str]:
318
+ def _merge_small_splits(self, splits: list[str]) -> list[str]:
319
319
  """
320
320
  Merge splits that are below min_length.
321
321
  """
@@ -341,7 +341,7 @@ class EmbeddingBasedDocumentSplitter:
341
341
 
342
342
  return merged
343
343
 
344
- def _split_large_splits(self, splits: List[str]) -> List[str]:
344
+ def _split_large_splits(self, splits: list[str]) -> list[str]:
345
345
  """
346
346
  Recursively split splits that are above max_length.
347
347
 
@@ -375,7 +375,7 @@ class EmbeddingBasedDocumentSplitter:
375
375
  return final_splits
376
376
 
377
377
  @staticmethod
378
- def _create_documents_from_splits(splits: List[str], original_doc: Document) -> List[Document]:
378
+ def _create_documents_from_splits(splits: list[str], original_doc: Document) -> list[Document]:
379
379
  """
380
380
  Create Document objects from splits.
381
381
  """
@@ -405,7 +405,7 @@ class EmbeddingBasedDocumentSplitter:
405
405
 
406
406
  return documents
407
407
 
408
- def to_dict(self) -> Dict[str, Any]:
408
+ def to_dict(self) -> dict[str, Any]:
409
409
  """
410
410
  Serializes the component to a dictionary.
411
411
  """
@@ -422,7 +422,7 @@ class EmbeddingBasedDocumentSplitter:
422
422
  )
423
423
 
424
424
  @classmethod
425
- def from_dict(cls, data: Dict[str, Any]) -> "EmbeddingBasedDocumentSplitter":
425
+ def from_dict(cls, data: dict[str, Any]) -> "EmbeddingBasedDocumentSplitter":
426
426
  """
427
427
  Deserializes the component from a dictionary.
428
428
  """
@@ -3,7 +3,5 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  from haystack_experimental.components.retrievers.chat_message_retriever import ChatMessageRetriever
6
- from haystack_experimental.components.retrievers.multi_query_embedding_retriever import MultiQueryEmbeddingRetriever
7
- from haystack_experimental.components.retrievers.multi_query_text_retriever import MultiQueryTextRetriever
8
6
 
9
- _all_ = ["ChatMessageRetriever", "MultiQueryTextRetriever", "MultiQueryEmbeddingRetriever"]
7
+ _all_ = ["ChatMessageRetriever"]
@@ -2,11 +2,11 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Any, Dict, List, Optional
5
+ from typing import Any, Optional
6
6
 
7
7
  from haystack import DeserializationError, component, default_from_dict, default_to_dict, logging
8
8
  from haystack.core.serialization import import_class_by_name
9
- from haystack.dataclasses import ChatMessage
9
+ from haystack.dataclasses import ChatMessage, ChatRole
10
10
 
11
11
  from haystack_experimental.chat_message_stores.types import ChatMessageStore
12
12
 
@@ -30,41 +30,40 @@ class ChatMessageRetriever:
30
30
  ]
31
31
 
32
32
  message_store = InMemoryChatMessageStore()
33
- message_store.write_messages(messages)
33
+ message_store.write_messages(chat_history_id="user_456_session_123", messages=messages)
34
34
  retriever = ChatMessageRetriever(message_store)
35
35
 
36
- result = retriever.run()
36
+ result = retriever.run(chat_history_id="user_456_session_123")
37
37
 
38
38
  print(result["messages"])
39
39
  ```
40
40
  """
41
41
 
42
- def __init__(self, message_store: ChatMessageStore, last_k: int = 10):
42
+ def __init__(self, chat_message_store: ChatMessageStore, last_k: Optional[int] = 10):
43
43
  """
44
44
  Create the ChatMessageRetriever component.
45
45
 
46
- :param message_store:
46
+ :param chat_message_store:
47
47
  An instance of a ChatMessageStore.
48
48
  :param last_k:
49
49
  The number of last messages to retrieve. Defaults to 10 messages if not specified.
50
50
  """
51
- self.message_store = message_store
52
- if last_k <= 0:
53
- raise ValueError(f"last_k must be greater than 0. Currently, the last_k is {last_k}")
51
+ self.chat_message_store = chat_message_store
52
+ if last_k and last_k <= 0:
53
+ raise ValueError(f"last_k must be greater than 0. Currently, last_k is {last_k}")
54
54
  self.last_k = last_k
55
55
 
56
- def to_dict(self) -> Dict[str, Any]:
56
+ def to_dict(self) -> dict[str, Any]:
57
57
  """
58
58
  Serializes the component to a dictionary.
59
59
 
60
60
  :returns:
61
61
  Dictionary with serialized data.
62
62
  """
63
- message_store = self.message_store.to_dict()
64
- return default_to_dict(self, message_store=message_store, last_k=self.last_k)
63
+ return default_to_dict(self, chat_message_store=self.chat_message_store.to_dict(), last_k=self.last_k)
65
64
 
66
65
  @classmethod
67
- def from_dict(cls, data: Dict[str, Any]) -> "ChatMessageRetriever":
66
+ def from_dict(cls, data: dict[str, Any]) -> "ChatMessageRetriever":
68
67
  """
69
68
  Deserializes the component from a dictionary.
70
69
 
@@ -74,35 +73,67 @@ class ChatMessageRetriever:
74
73
  The deserialized component.
75
74
  """
76
75
  init_params = data.get("init_parameters", {})
77
- if "message_store" not in init_params:
78
- raise DeserializationError("Missing 'message_store' in serialization data")
79
- if "type" not in init_params["message_store"]:
76
+ if "chat_message_store" not in init_params:
77
+ raise DeserializationError("Missing 'chat_message_store' in serialization data")
78
+ if "type" not in init_params["chat_message_store"]:
80
79
  raise DeserializationError("Missing 'type' in message store's serialization data")
81
80
 
82
- message_store_data = init_params["message_store"]
81
+ message_store_data = init_params["chat_message_store"]
83
82
  try:
84
83
  message_store_class = import_class_by_name(message_store_data["type"])
85
84
  except ImportError as e:
86
85
  raise DeserializationError(f"Class '{message_store_data['type']}' not correctly imported") from e
86
+ if not hasattr(message_store_class, "from_dict"):
87
+ raise DeserializationError(f"{message_store_class} does not have from_dict method implemented.")
88
+ init_params["chat_message_store"] = message_store_class.from_dict(message_store_data)
87
89
 
88
- data["init_parameters"]["message_store"] = default_from_dict(message_store_class, message_store_data)
89
90
  return default_from_dict(cls, data)
90
91
 
91
- @component.output_types(messages=List[ChatMessage])
92
- def run(self, last_k: Optional[int] = None) -> Dict[str, List[ChatMessage]]:
92
+ @component.output_types(messages=list[ChatMessage])
93
+ def run(
94
+ self,
95
+ chat_history_id: str,
96
+ *,
97
+ last_k: Optional[int] = None,
98
+ current_messages: Optional[list[ChatMessage]] = None,
99
+ ) -> dict[str, list[ChatMessage]]:
93
100
  """
94
101
  Run the ChatMessageRetriever
95
102
 
103
+ :param chat_history_id:
104
+ A unique identifier for the chat session or conversation whose messages should be retrieved.
105
+ Each `chat_history_id` corresponds to a distinct chat history stored in the underlying ChatMessageStore.
106
+ For example, use a session ID or conversation ID to isolate messages from different chat sessions.
96
107
  :param last_k: The number of last messages to retrieve. This parameter takes precedence over the last_k
97
108
  parameter passed to the ChatMessageRetriever constructor. If unspecified, the last_k parameter passed
98
109
  to the constructor will be used.
110
+ :param current_messages:
111
+ A list of incoming chat messages to combine with the retrieved messages. System messages from this list
112
+ are prepended before the retrieved history, while all other messages (e.g., user messages) are appended
113
+ after. This is useful for including new conversational context alongside stored history so the output
114
+ can be directly used as input to a ChatGenerator or an Agent. If not provided, only the stored messages
115
+ will be returned.
116
+
99
117
  :returns:
100
- - `messages` - The retrieved chat messages.
101
- :raises ValueError: If last_k is not None and is less than 1
118
+ A dictionary with the following key:
119
+ - `messages` - The retrieved chat messages combined with any provided current messages.
120
+ :raises ValueError: If last_k is not None and is less than 0.
102
121
  """
103
- if last_k is not None and last_k <= 0:
104
- raise ValueError("last_k must be greater than 0")
122
+ if last_k is not None and last_k < 0:
123
+ raise ValueError("last_k must be 0 or greater")
124
+
125
+ resolved_last_k = last_k or self.last_k
126
+ if resolved_last_k == 0:
127
+ return {"messages": current_messages or []}
128
+
129
+ retrieved_messages = self.chat_message_store.retrieve_messages(
130
+ chat_history_id=chat_history_id, last_k=last_k or self.last_k
131
+ )
105
132
 
106
- last_k = last_k or self.last_k
133
+ if not current_messages:
134
+ return {"messages": retrieved_messages}
107
135
 
108
- return {"messages": self.message_store.retrieve()[-last_k:]}
136
+ # We maintain the order: system messages first, then stored messages, then new user messages
137
+ system_messages = [msg for msg in current_messages if msg.is_from(ChatRole.SYSTEM)]
138
+ other_messages = [msg for msg in current_messages if not msg.is_from(ChatRole.SYSTEM)]
139
+ return {"messages": system_messages + retrieved_messages + other_messages}
@@ -4,4 +4,4 @@
4
4
 
5
5
  from haystack_experimental.components.writers.chat_message_writer import ChatMessageWriter
6
6
 
7
- _all_ = ["ChatMessageWriter"]
7
+ __all__ = ["ChatMessageWriter"]
@@ -2,16 +2,14 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Any, Dict, List
5
+ from typing import Any
6
6
 
7
- from haystack import DeserializationError, component, default_from_dict, default_to_dict, logging
7
+ from haystack import DeserializationError, component, default_from_dict, default_to_dict
8
8
  from haystack.core.serialization import import_class_by_name
9
9
  from haystack.dataclasses import ChatMessage
10
10
 
11
11
  from haystack_experimental.chat_message_stores.types import ChatMessageStore
12
12
 
13
- logger = logging.getLogger(__name__)
14
-
15
13
 
16
14
  @component
17
15
  class ChatMessageWriter:
@@ -30,30 +28,30 @@ class ChatMessageWriter:
30
28
  ]
31
29
  message_store = InMemoryChatMessageStore()
32
30
  writer = ChatMessageWriter(message_store)
33
- writer.run(messages)
31
+ writer.run(chat_history_id="user_456_session_123", messages=messages)
34
32
  ```
35
33
  """
36
34
 
37
- def __init__(self, message_store: ChatMessageStore):
35
+ def __init__(self, chat_message_store: ChatMessageStore) -> None:
38
36
  """
39
37
  Create a ChatMessageWriter component.
40
38
 
41
- :param message_store:
39
+ :param chat_message_store:
42
40
  The ChatMessageStore where the chat messages are to be written.
43
41
  """
44
- self.message_store = message_store
42
+ self.chat_message_store = chat_message_store
45
43
 
46
- def to_dict(self) -> Dict[str, Any]:
44
+ def to_dict(self) -> dict[str, Any]:
47
45
  """
48
46
  Serializes the component to a dictionary.
49
47
 
50
48
  :returns:
51
49
  Dictionary with serialized data.
52
50
  """
53
- return default_to_dict(self, message_store=self.message_store.to_dict())
51
+ return default_to_dict(self, chat_message_store=self.chat_message_store.to_dict())
54
52
 
55
53
  @classmethod
56
- def from_dict(cls, data: Dict[str, Any]) -> "ChatMessageWriter":
54
+ def from_dict(cls, data: dict[str, Any]) -> "ChatMessageWriter":
57
55
  """
58
56
  Deserializes the component from a dictionary.
59
57
 
@@ -66,31 +64,36 @@ class ChatMessageWriter:
66
64
  If the message store is not properly specified in the serialization data or its type cannot be imported.
67
65
  """
68
66
  init_params = data.get("init_parameters", {})
69
- if "message_store" not in init_params:
70
- raise DeserializationError("Missing 'message_store' in serialization data")
71
- if "type" not in init_params["message_store"]:
67
+ if "chat_message_store" not in init_params:
68
+ raise DeserializationError("Missing 'chat_message_store' in serialization data")
69
+ if "type" not in init_params["chat_message_store"]:
72
70
  raise DeserializationError("Missing 'type' in message store's serialization data")
73
- message_store_data = init_params["message_store"]
71
+
72
+ message_store_data = init_params["chat_message_store"]
74
73
  try:
75
74
  message_store_class = import_class_by_name(message_store_data["type"])
76
75
  except ImportError as e:
77
76
  raise DeserializationError(f"Class '{message_store_data['type']}' not correctly imported") from e
78
- data["init_parameters"]["message_store"] = default_from_dict(message_store_class, message_store_data)
77
+ if not hasattr(message_store_class, "from_dict"):
78
+ raise DeserializationError(f"{message_store_class} does not have from_dict method implemented.")
79
+ init_params["chat_message_store"] = message_store_class.from_dict(message_store_data)
80
+
79
81
  return default_from_dict(cls, data)
80
82
 
81
83
  @component.output_types(messages_written=int)
82
- def run(self, messages: List[ChatMessage]) -> Dict[str, int]:
84
+ def run(self, chat_history_id: str, messages: list[ChatMessage]) -> dict[str, int]:
83
85
  """
84
86
  Run the ChatMessageWriter on the given input data.
85
87
 
88
+ :param chat_history_id:
89
+ A unique identifier for the chat session or conversation whose messages should be retrieved.
90
+ Each `chat_history_id` corresponds to a distinct chat history stored in the underlying ChatMessageStore.
91
+ For example, use a session ID or conversation ID to isolate messages from different chat sessions.
86
92
  :param messages:
87
93
  A list of chat messages to write to the store.
94
+
88
95
  :returns:
89
96
  - `messages_written`: Number of messages written to the ChatMessageStore.
90
-
91
- :raises ValueError:
92
- If the specified message store is not found.
93
97
  """
94
-
95
- messages_written = self.message_store.write_messages(messages=messages)
98
+ messages_written = self.chat_message_store.write_messages(chat_history_id=chat_history_id, messages=messages)
96
99
  return {"messages_written": messages_written}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haystack-experimental
3
- Version: 0.14.3
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 | Expected End Date | Dependencies | Cookbook | Discussion |
75
- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|-------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
76
- | [`InMemoryChatMessageStore`][1] | Memory Store | December 2024 | 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] |
77
- | [`ChatMessageRetriever`][2] | Memory Component | December 2024 | 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] |
78
- | [`ChatMessageWriter`][3] | Memory Component | December 2024 | 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
- | [`QueryExpander`][5] | Query Expansion Component | October 2025 | None | None | [Discuss][6] |
80
- | [`EmbeddingBasedDocumentSplitter`][8] | EmbeddingBasedDocumentSplitter | August 2025 | None | None | [Discuss][7] |
81
- | [`MultiQueryEmbeddingRetriever`][13] | MultiQueryEmbeddingRetriever | November 2025 | None | None | [Discuss][11] |
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
- [11]: https://github.com/deepset-ai/haystack-experimental/discussions/363
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 | Type | Final release |
116
- |----------------------------------------------------------------------------------------|------------------------------------------|---------------|
117
- | `ChatMessage` refactoring; `Tool` class; tool support in ChatGenerators; `ToolInvoker` | Tool Calling support | 0.4.0 |
118
- | `AsyncPipeline`; `Pipeline` bug fixes and refactoring | AsyncPipeline execution | 0.7.0 |
119
- | `LLMMetadataExtractor` | Metadata extraction with LLM | 0.7.0 |
120
- | `Auto-Merging Retriever` & `HierarchicalDocumentSplitter` | Document Splitting & Retrieval Technique | 0.8.0 |
121
- | `Agent` | Simplify Agent development | 0.8.0 |
122
- | `SuperComponent` | Simplify Pipeline development | 0.8.0 |
123
- | `Pipeline` | Pipeline breakpoints for debugging | 0.12.0 |
124
- | `ImageContent`; Image Converters; multimodal support in `OpenAIChatGenerator` and `AmazonBedrockChatGenerator`; `ChatPromptBuilder` refactoring; `SentenceTransformersDocumentImageEmbedder`; `LLMDocumentContentExtractor`; new `Routers` | Multimodality | 0.12.0 |
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