Skip to content

Commit 1298864

Browse files
Merge branch 'main' into fix/static-methods-Astra
2 parents 5df33f0 + 6e62cfa commit 1298864

10 files changed

Lines changed: 292 additions & 41 deletions

File tree

integrations/amazon_bedrock/src/haystack_integrations/components/generators/amazon_bedrock/chat/utils.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -585,13 +585,15 @@ def _convert_event_to_streaming_chunk(
585585
reasoning_content = delta["reasoningContent"]
586586
if "redactedContent" in reasoning_content:
587587
reasoning_content["redacted_content"] = reasoning_content.pop("redactedContent")
588+
reasoning_text = reasoning_content.get("text", "")
588589
streaming_chunk = StreamingChunk(
589590
content="",
590591
index=block_idx,
591-
meta={
592-
**base_meta,
593-
"reasoning_contents": [{"index": block_idx, "reasoning_content": reasoning_content}],
594-
},
592+
reasoning=ReasoningContent(
593+
reasoning_text=reasoning_text,
594+
extra={"reasoning_contents": [{"index": block_idx, "reasoning_content": reasoning_content}]},
595+
),
596+
meta=base_meta,
595597
)
596598

597599
elif "messageStop" in event:
@@ -642,7 +644,10 @@ def _process_reasoning_contents(chunks: list[StreamingChunk]) -> ReasoningConten
642644
reasoning_signature = None
643645
redacted_content = None
644646
for chunk in chunks:
645-
reasoning_contents = chunk.meta.get("reasoning_contents", [])
647+
if chunk.reasoning and chunk.reasoning.extra:
648+
reasoning_contents = chunk.reasoning.extra.get("reasoning_contents", [])
649+
else:
650+
reasoning_contents = []
646651

647652
for reasoning_content in reasoning_contents:
648653
content_block_index = reasoning_content["index"]

integrations/amazon_bedrock/tests/test_chat_generator_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,12 @@ def test_callback(chunk: StreamingChunk):
12691269
]
12701270
assert replies == expected_messages
12711271

1272+
# Verify streaming chunks carry reasoning in the reasoning field, not in meta
1273+
reasoning_chunks = [c for c in streaming_chunks if c.reasoning is not None]
1274+
assert len(reasoning_chunks) > 0
1275+
for chunk in reasoning_chunks:
1276+
assert "reasoning_contents" not in chunk.meta
1277+
12721278
def test_process_streaming_response_with_one_tool_call_with_redacted_thinking(self, mock_boto3_session):
12731279
model = "arn:aws:bedrock:us-east-1::inference-profile/us.anthropic.claude-sonnet-3-7-20250219-v1:0"
12741280
type_ = (

integrations/cohere/src/haystack_integrations/components/generators/cohere/chat/chat_generator.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
)
2525
from haystack.utils import Secret, deserialize_secrets_inplace
2626
from haystack.utils.callable_serialization import deserialize_callable, serialize_callable
27+
from httpx import AsyncClient as AsyncHTTPXClient
28+
from httpx import AsyncHTTPTransport, HTTPTransport
29+
from httpx import Client as HTTPXClient
2730

2831
from cohere import AsyncClientV2, ChatResponse, ClientV2, StreamedChatResponseV2
2932

@@ -502,6 +505,9 @@ def __init__(
502505
api_base_url: str | None = None,
503506
generation_kwargs: dict[str, Any] | None = None,
504507
tools: ToolsType | None = None,
508+
*,
509+
timeout: float | None = None,
510+
max_retries: int | None = None,
505511
**kwargs: Any,
506512
):
507513
"""
@@ -526,6 +532,13 @@ def __init__(
526532
mean less random generations.
527533
:param tools: A list of Tool and/or Toolset objects, or a single Toolset that the model can use.
528534
Each tool should have a unique name.
535+
:param timeout:
536+
Timeout for Cohere client calls. If not set, it defaults to the default set by the Cohere client.
537+
:param max_retries:
538+
Maximum number of retries to attempt for failed requests. If not set, it defaults to the default set by
539+
the Cohere client.
540+
:param kwargs:
541+
Additional generation parameters. These are merged into `generation_kwargs` for backward compatibility.
529542
530543
"""
531544
_check_duplicate_tool_names(flatten_tools_or_toolsets(tools))
@@ -534,23 +547,32 @@ def __init__(
534547
api_base_url = "https://api.cohere.com"
535548
if generation_kwargs is None:
536549
generation_kwargs = {}
550+
if kwargs:
551+
generation_kwargs = {**generation_kwargs, **kwargs}
537552
self.api_key = api_key
538553
self.model = model
539554
self.streaming_callback = streaming_callback
540555
self.api_base_url = api_base_url
541556
self.generation_kwargs = generation_kwargs
542557
self.tools = tools
543-
self.model_parameters = kwargs
544-
self.client = ClientV2(
545-
api_key=self.api_key.resolve_value(),
546-
base_url=self.api_base_url,
547-
client_name="haystack",
548-
)
549-
self.async_client = AsyncClientV2(
550-
api_key=self.api_key.resolve_value(),
551-
base_url=self.api_base_url,
552-
client_name="haystack",
553-
)
558+
self.timeout = timeout
559+
self.max_retries = max_retries
560+
561+
client_kwargs: dict[str, Any] = {
562+
"api_key": self.api_key.resolve_value(),
563+
"base_url": self.api_base_url,
564+
"client_name": "haystack",
565+
}
566+
if timeout is not None:
567+
client_kwargs["timeout"] = timeout
568+
if max_retries is not None:
569+
sync_httpx_client = HTTPXClient(transport=HTTPTransport(retries=max_retries))
570+
async_httpx_client = AsyncHTTPXClient(transport=AsyncHTTPTransport(retries=max_retries))
571+
self.client = ClientV2(**client_kwargs, httpx_client=sync_httpx_client)
572+
self.async_client = AsyncClientV2(**client_kwargs, httpx_client=async_httpx_client)
573+
else:
574+
self.client = ClientV2(**client_kwargs)
575+
self.async_client = AsyncClientV2(**client_kwargs)
554576

555577
def _get_telemetry_data(self) -> dict[str, Any]:
556578
"""
@@ -574,6 +596,8 @@ def to_dict(self) -> dict[str, Any]:
574596
api_key=self.api_key.to_dict(),
575597
generation_kwargs=self.generation_kwargs,
576598
tools=serialize_tools_or_toolset(self.tools),
599+
timeout=self.timeout,
600+
max_retries=self.max_retries,
577601
)
578602

579603
@classmethod

integrations/cohere/tests/test_chat_generator.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ def test_init_default(self, monkeypatch):
157157
assert component.streaming_callback is None
158158
assert component.api_base_url == "https://api.cohere.com"
159159
assert not component.generation_kwargs
160+
assert component.timeout is None
161+
assert component.max_retries is None
160162

161163
def test_init_fail_wo_api_key(self, monkeypatch):
162164
monkeypatch.delenv("COHERE_API_KEY", raising=False)
@@ -174,6 +176,8 @@ def test_init_with_parameters(self):
174176
"max_tokens": 10,
175177
"some_test_param": "test-params",
176178
},
179+
timeout=30.0,
180+
max_retries=5,
177181
)
178182
assert component.api_key == Secret.from_token("test-api-key")
179183
assert component.model == "command-nightly"
@@ -183,6 +187,8 @@ def test_init_with_parameters(self):
183187
"max_tokens": 10,
184188
"some_test_param": "test-params",
185189
}
190+
assert component.timeout == 30.0
191+
assert component.max_retries == 5
186192

187193
def test_to_dict_default(self, monkeypatch):
188194
monkeypatch.setenv("COHERE_API_KEY", "test-api-key")
@@ -201,6 +207,8 @@ def test_to_dict_default(self, monkeypatch):
201207
"api_base_url": "https://api.cohere.com",
202208
"generation_kwargs": {},
203209
"tools": None,
210+
"timeout": None,
211+
"max_retries": None,
204212
},
205213
}
206214

@@ -234,6 +242,8 @@ def test_to_dict_with_parameters(self, monkeypatch):
234242
"some_test_param": "test-params",
235243
},
236244
"tools": None,
245+
"timeout": None,
246+
"max_retries": None,
237247
},
238248
}
239249

@@ -255,6 +265,8 @@ def test_from_dict(self, monkeypatch):
255265
"max_tokens": 10,
256266
"some_test_param": "test-params",
257267
},
268+
"timeout": None,
269+
"max_retries": None,
258270
},
259271
}
260272
component = CohereChatGenerator.from_dict(data)
@@ -265,6 +277,8 @@ def test_from_dict(self, monkeypatch):
265277
"max_tokens": 10,
266278
"some_test_param": "test-params",
267279
}
280+
assert component.timeout is None
281+
assert component.max_retries is None
268282

269283
def test_from_dict_fail_wo_env_var(self, monkeypatch):
270284
monkeypatch.delenv("COHERE_API_KEY", raising=False)
@@ -284,6 +298,8 @@ def test_from_dict_fail_wo_env_var(self, monkeypatch):
284298
"max_tokens": 10,
285299
"some_test_param": "test-params",
286300
},
301+
"timeout": None,
302+
"max_retries": None,
287303
},
288304
}
289305
with pytest.raises(ValueError):
@@ -327,6 +343,8 @@ def test_serde_in_pipeline(self, monkeypatch):
327343
"streaming_callback": "haystack.components.generators.utils.print_streaming_chunk",
328344
"api_base_url": "https://api.cohere.com",
329345
"generation_kwargs": {"temperature": 0.7},
346+
"timeout": None,
347+
"max_retries": None,
330348
"tools": [
331349
{
332350
"type": "haystack.tools.tool.Tool",

integrations/cohere/tests/test_generator.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_init_default(self, monkeypatch):
2222
assert component.model == "command-a-03-2025"
2323
assert component.streaming_callback is None
2424
assert component.api_base_url == COHERE_API_URL
25-
assert component.model_parameters == {}
25+
assert component.generation_kwargs == {}
2626

2727
def test_init_with_parameters(self):
2828
callback = lambda x: x # noqa: E731
@@ -38,7 +38,7 @@ def test_init_with_parameters(self):
3838
assert component.model == "command-light"
3939
assert component.streaming_callback == callback
4040
assert component.api_base_url == "test-base-url"
41-
assert component.model_parameters == {"max_tokens": 10, "some_test_param": "test-params"}
41+
assert component.generation_kwargs == {"max_tokens": 10, "some_test_param": "test-params"}
4242

4343
def test_to_dict_default(self, monkeypatch):
4444
monkeypatch.setenv("COHERE_API_KEY", "test-api-key")
@@ -53,6 +53,8 @@ def test_to_dict_default(self, monkeypatch):
5353
"api_base_url": COHERE_API_URL,
5454
"generation_kwargs": {},
5555
"tools": None,
56+
"timeout": None,
57+
"max_retries": None,
5658
},
5759
}
5860

@@ -75,8 +77,10 @@ def test_to_dict_with_parameters(self, monkeypatch):
7577
"api_base_url": "test-base-url",
7678
"api_key": {"env_vars": ["ENV_VAR"], "strict": False, "type": "env_var"},
7779
"streaming_callback": "haystack.components.generators.utils.print_streaming_chunk",
78-
"generation_kwargs": {},
80+
"generation_kwargs": {"max_tokens": 10, "some_test_param": "test-params"},
7981
"tools": None,
82+
"timeout": None,
83+
"max_retries": None,
8084
},
8185
}
8286

@@ -100,7 +104,7 @@ def test_from_dict(self, monkeypatch):
100104
assert component.model == "command-a-03-2025"
101105
assert component.streaming_callback == print_streaming_chunk
102106
assert component.api_base_url == "test-base-url"
103-
assert component.model_parameters == {"max_tokens": 10, "some_test_param": "test-params"}
107+
assert component.generation_kwargs == {"max_tokens": 10, "some_test_param": "test-params"}
104108

105109
@pytest.mark.skipif(
106110
not os.environ.get("COHERE_API_KEY", None) and not os.environ.get("CO_API_KEY", None),

integrations/ollama/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog
22

3+
## [integrations/ollama-v6.2.0] - 2026-03-09
4+
5+
### 🚀 Features
6+
7+
- *(ollama)* Add max_retries to chat generator (#2899)
8+
9+
### 🧹 Chores
10+
11+
- Remove unused allow-direct-references (#2866)
12+
13+
314
## [integrations/ollama-v6.1.0] - 2026-02-19
415

516
### 🚀 Features

integrations/ollama/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ classifiers = [
2626
"Programming Language :: Python :: Implementation :: CPython",
2727
"Programming Language :: Python :: Implementation :: PyPy",
2828
]
29-
dependencies = ["haystack-ai>=2.22.0", "ollama>=0.5.0", "pydantic"]
29+
dependencies = ["haystack-ai>=2.22.0", "ollama>=0.5.0", "pydantic", "tenacity>=8.2.3"]
3030

3131
[project.urls]
3232
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/ollama#readme"

0 commit comments

Comments
 (0)