cohere-haystack 9.5.0__tar.gz → 10.0.1__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.
Files changed (37) hide show
  1. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/CHANGELOG.md +51 -13
  2. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/PKG-INFO +3 -3
  3. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/pydoc/config_docusaurus.yml +0 -1
  4. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/pyproject.toml +1 -1
  5. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/embedders/cohere/document_embedder.py +28 -12
  6. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/embedders/cohere/document_image_embedder.py +26 -12
  7. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/embedders/cohere/text_embedder.py +25 -12
  8. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/embedders/cohere/utils.py +26 -17
  9. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/generators/cohere/__init__.py +1 -2
  10. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/generators/cohere/chat/chat_generator.py +34 -15
  11. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/rankers/cohere/ranker.py +20 -6
  12. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_chat_generator.py +118 -45
  13. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_document_embedder.py +75 -1
  14. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_document_image_embedder.py +51 -7
  15. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_ranker.py +35 -21
  16. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_text_embedder.py +47 -1
  17. cohere_haystack-9.5.0/src/haystack_integrations/components/generators/cohere/generator.py +0 -140
  18. cohere_haystack-9.5.0/tests/test_generator.py +0 -159
  19. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/.gitignore +0 -0
  20. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/LICENSE.txt +0 -0
  21. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/README.md +0 -0
  22. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/examples/cohere_embedding.py +0 -0
  23. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/examples/cohere_generation.py +0 -0
  24. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/examples/cohere_ranker.py +0 -0
  25. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/embedders/cohere/__init__.py +0 -0
  26. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/embedders/cohere/embedding_types.py +0 -0
  27. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/embedders/py.typed +0 -0
  28. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/generators/cohere/chat/__init__.py +0 -0
  29. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/generators/py.typed +0 -0
  30. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/rankers/cohere/__init__.py +0 -0
  31. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/src/haystack_integrations/components/rankers/py.typed +0 -0
  32. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/__init__.py +0 -0
  33. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/conftest.py +0 -0
  34. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_chat_generator_async.py +0 -0
  35. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_chat_generator_chunks.py +0 -0
  36. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_files/apple.jpg +0 -0
  37. {cohere_haystack-9.5.0 → cohere_haystack-10.0.1}/tests/test_files/sample_pdf_1.pdf +0 -0
@@ -1,6 +1,30 @@
1
1
  # Changelog
2
2
 
3
- ## [unreleased]
3
+ ## [integrations/cohere-v10.0.0] - 2026-09-04
4
+
5
+ ### 🚜 Refactor
6
+
7
+ - [**breaking**] Cohere - create clients in warm up methods (#3911)
8
+
9
+ ### ⚙️ CI
10
+
11
+ - Improve changelog generation; fix existing changelogs (#3883)
12
+
13
+ ### 🧹 Chores
14
+
15
+ - Clarify how generation_kwargs passed in run are handled (#3805)
16
+ - [**breaking**] Remove deprecated `CohereGenerator` (use `CohereChatGenerator` instead) (#3885)
17
+
18
+
19
+ ## [integrations/cohere-v9.5.0] - 2026-08-11
20
+
21
+ ### 🐛 Bug Fixes
22
+
23
+ - Fix new issues raised by ruff 0.16.0 (#3670)
24
+ - CohereRanker reordered the top_k fallback to happen after validation (#3747)
25
+
26
+
27
+ ## [integrations/cohere-v9.4.1] - 2026-07-22
4
28
 
5
29
 
6
30
  ## [integrations/cohere-v9.4.0] - 2026-07-22
@@ -111,7 +135,7 @@
111
135
  - [**breaking**] Cohere - drop Python 3.9 and use X|Y typing (#2696)
112
136
 
113
137
 
114
- ## [integrations/cohere-v6.3.0] - 2025-11-26
138
+ ## [integrations/cohere-v6.2.0] - 2025-11-26
115
139
 
116
140
  ### ⚙️ CI
117
141
 
@@ -320,8 +344,6 @@
320
344
 
321
345
  ### 🚀 Features
322
346
 
323
- - Update Anthropic/Cohere for tools use (#790)
324
- - Update Cohere default LLMs, add examples and update unit tests (#838)
325
347
  - Cohere LLM - adjust token counting meta to match OpenAI format (#1086)
326
348
 
327
349
  ### 🐛 Bug Fixes
@@ -332,10 +354,6 @@
332
354
 
333
355
  - Do not retry tests in `hatch run test` command (#954)
334
356
 
335
- ### ⚙️ CI
336
-
337
- - Retry tests to reduce flakyness (#836)
338
-
339
357
  ### 🧹 Chores
340
358
 
341
359
  - Update ruff invocation to include check parameter (#853)
@@ -346,6 +364,24 @@
346
364
  - Update CohereChatGenerator docstrings (#958)
347
365
  - Update CohereGenerator docstrings (#960)
348
366
 
367
+ ## [integrations/cohere-v1.1.3] - 2024-06-21
368
+
369
+ ### 🚀 Features
370
+
371
+ - Update Cohere default LLMs, add examples and update unit tests (#838)
372
+
373
+ ### ⚙️ CI
374
+
375
+ - Retry tests to reduce flakyness (#836)
376
+
377
+
378
+ ## [integrations/cohere-v1.1.2] - 2024-06-18
379
+
380
+ ### 🚀 Features
381
+
382
+ - Update Anthropic/Cohere for tools use (#790)
383
+
384
+
349
385
  ## [integrations/cohere-v1.1.1] - 2024-06-12
350
386
 
351
387
  ### 🌀 Miscellaneous
@@ -418,11 +454,6 @@
418
454
 
419
455
  ## [integrations/cohere-v0.4.0] - 2024-02-12
420
456
 
421
- ### 🐛 Bug Fixes
422
-
423
- - Fix Cohere tests (#337)
424
- - Cohere inconsistent embeddings and documents lengths (#284)
425
-
426
457
  ### 🚜 Refactor
427
458
 
428
459
  - [**breaking**] Use `Secret` for API keys in Cohere components (#386)
@@ -431,6 +462,13 @@
431
462
 
432
463
  - Fix failing `TestCohereChatGenerator.test_from_dict_fail_wo_env_var` test (#393)
433
464
 
465
+ ## [integrations/cohere-v0.3.1] - 2024-02-08
466
+
467
+ ### 🐛 Bug Fixes
468
+
469
+ - Fix Cohere tests (#337)
470
+ - Cohere inconsistent embeddings and documents lengths (#284)
471
+
434
472
  ### 🌀 Miscellaneous
435
473
 
436
474
  - Cohere: generate api docs (#321)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: cohere-haystack
3
- Version: 9.5.0
3
+ Version: 10.0.1
4
4
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/cohere#readme
5
5
  Project-URL: Issues, https://github.com/deepset-ai/haystack-core-integrations/issues
6
6
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/cohere
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
19
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
20
20
  Requires-Python: >=3.10
21
21
  Requires-Dist: cohere>=5.17.0
22
- Requires-Dist: haystack-ai>=2.30.0
22
+ Requires-Dist: haystack-ai>=3.0.0
23
23
  Requires-Dist: pydantic>=2.12.0
24
24
  Description-Content-Type: text/markdown
25
25
 
@@ -4,7 +4,6 @@ loaders:
4
4
  - haystack_integrations.components.embedders.cohere.document_image_embedder
5
5
  - haystack_integrations.components.embedders.cohere.text_embedder
6
6
  - haystack_integrations.components.embedders.cohere.utils
7
- - haystack_integrations.components.generators.cohere.generator
8
7
  - haystack_integrations.components.generators.cohere.chat.chat_generator
9
8
  - haystack_integrations.components.rankers.cohere.ranker
10
9
  search_path: [../src]
@@ -23,7 +23,7 @@ classifiers = [
23
23
  "Programming Language :: Python :: Implementation :: CPython",
24
24
  "Programming Language :: Python :: Implementation :: PyPy",
25
25
  ]
26
- dependencies = ["haystack-ai>=2.30.0", "cohere>=5.17.0", "pydantic>=2.12.0"]
26
+ dependencies = ["haystack-ai>=3.0.0", "cohere>=5.17.0", "pydantic>=2.12.0"]
27
27
 
28
28
  [project.urls]
29
29
  Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/cohere#readme"
@@ -95,18 +95,28 @@ class CohereDocumentEmbedder:
95
95
  self.embedding_separator = embedding_separator
96
96
  self.embedding_type = embedding_type or EmbeddingTypes.FLOAT
97
97
 
98
- self._client = ClientV2(
99
- api_key=self.api_key.resolve_value(),
100
- base_url=self.api_base_url,
101
- timeout=self.timeout,
102
- client_name="haystack",
103
- )
104
- self._async_client = AsyncClientV2(
105
- api_key=self.api_key.resolve_value(),
106
- base_url=self.api_base_url,
107
- timeout=self.timeout,
108
- client_name="haystack",
109
- )
98
+ self._client: ClientV2 | None = None
99
+ self._async_client: AsyncClientV2 | None = None
100
+
101
+ def warm_up(self) -> None:
102
+ """Create the synchronous Cohere client."""
103
+ if self._client is None:
104
+ self._client = ClientV2(
105
+ api_key=self.api_key.resolve_value(),
106
+ base_url=self.api_base_url,
107
+ timeout=self.timeout,
108
+ client_name="haystack",
109
+ )
110
+
111
+ async def warm_up_async(self) -> None:
112
+ """Create the asynchronous Cohere client."""
113
+ if self._async_client is None:
114
+ self._async_client = AsyncClientV2(
115
+ api_key=self.api_key.resolve_value(),
116
+ base_url=self.api_base_url,
117
+ timeout=self.timeout,
118
+ client_name="haystack",
119
+ )
110
120
 
111
121
  def to_dict(self) -> dict[str, Any]:
112
122
  """
@@ -191,6 +201,8 @@ class CohereDocumentEmbedder:
191
201
  if not documents:
192
202
  return {"documents": [], "meta": {}}
193
203
 
204
+ self.warm_up()
205
+ assert self._client is not None
194
206
  texts_to_embed = self._prepare_texts_to_embed(documents)
195
207
 
196
208
  all_embeddings, metadata = get_response(
@@ -227,6 +239,8 @@ class CohereDocumentEmbedder:
227
239
  if not documents:
228
240
  return {"documents": [], "meta": {}}
229
241
 
242
+ await self.warm_up_async()
243
+ assert self._async_client is not None
230
244
  texts_to_embed = self._prepare_texts_to_embed(documents)
231
245
 
232
246
  all_embeddings, metadata = await get_async_response(
@@ -235,6 +249,8 @@ class CohereDocumentEmbedder:
235
249
  model_name=self.model,
236
250
  input_type=self.input_type,
237
251
  truncate=self.truncate,
252
+ batch_size=self.batch_size,
253
+ progress_bar=self.progress_bar,
238
254
  embedding_type=self.embedding_type,
239
255
  )
240
256
 
@@ -128,18 +128,28 @@ class CohereDocumentImageEmbedder:
128
128
  self._api_base_url = api_base_url
129
129
  self._timeout = timeout
130
130
 
131
- self._client = ClientV2(
132
- api_key=self._api_key.resolve_value(),
133
- base_url=self._api_base_url,
134
- timeout=self._timeout,
135
- client_name="haystack",
136
- )
137
- self._async_client = AsyncClientV2(
138
- api_key=self._api_key.resolve_value(),
139
- base_url=self._api_base_url,
140
- timeout=self._timeout,
141
- client_name="haystack",
142
- )
131
+ self._client: ClientV2 | None = None
132
+ self._async_client: AsyncClientV2 | None = None
133
+
134
+ def warm_up(self) -> None:
135
+ """Create the synchronous Cohere client."""
136
+ if self._client is None:
137
+ self._client = ClientV2(
138
+ api_key=self._api_key.resolve_value(),
139
+ base_url=self._api_base_url,
140
+ timeout=self._timeout,
141
+ client_name="haystack",
142
+ )
143
+
144
+ async def warm_up_async(self) -> None:
145
+ """Create the asynchronous Cohere client."""
146
+ if self._async_client is None:
147
+ self._async_client = AsyncClientV2(
148
+ api_key=self._api_key.resolve_value(),
149
+ base_url=self._api_base_url,
150
+ timeout=self._timeout,
151
+ client_name="haystack",
152
+ )
143
153
 
144
154
  def to_dict(self) -> dict[str, Any]:
145
155
  """
@@ -264,6 +274,8 @@ class CohereDocumentImageEmbedder:
264
274
  - `documents`: Documents with embeddings.
265
275
  """
266
276
 
277
+ self.warm_up()
278
+ assert self._client is not None
267
279
  images_to_embed = self._extract_images_to_embed(documents)
268
280
 
269
281
  embeddings = []
@@ -312,6 +324,8 @@ class CohereDocumentImageEmbedder:
312
324
  - `documents`: Documents with embeddings.
313
325
  """
314
326
 
327
+ await self.warm_up_async()
328
+ assert self._async_client is not None
315
329
  images_to_embed = self._extract_images_to_embed(documents)
316
330
 
317
331
  embeddings = []
@@ -78,19 +78,28 @@ class CohereTextEmbedder:
78
78
  self.timeout = timeout
79
79
  self.embedding_type = embedding_type or EmbeddingTypes.FLOAT
80
80
 
81
- self._client = ClientV2(
82
- api_key=self.api_key.resolve_value(),
83
- base_url=self.api_base_url,
84
- timeout=self.timeout,
85
- client_name="haystack",
86
- )
81
+ self._client: ClientV2 | None = None
82
+ self._async_client: AsyncClientV2 | None = None
83
+
84
+ def warm_up(self) -> None:
85
+ """Create the synchronous Cohere client."""
86
+ if self._client is None:
87
+ self._client = ClientV2(
88
+ api_key=self.api_key.resolve_value(),
89
+ base_url=self.api_base_url,
90
+ timeout=self.timeout,
91
+ client_name="haystack",
92
+ )
87
93
 
88
- self._async_client = AsyncClientV2(
89
- api_key=self.api_key.resolve_value(),
90
- base_url=self.api_base_url,
91
- timeout=self.timeout,
92
- client_name="haystack",
93
- )
94
+ async def warm_up_async(self) -> None:
95
+ """Create the asynchronous Cohere client."""
96
+ if self._async_client is None:
97
+ self._async_client = AsyncClientV2(
98
+ api_key=self.api_key.resolve_value(),
99
+ base_url=self.api_base_url,
100
+ timeout=self.timeout,
101
+ client_name="haystack",
102
+ )
94
103
 
95
104
  def _validate_input(self, text: str) -> None:
96
105
  if not isinstance(text, str):
@@ -155,6 +164,8 @@ class CohereTextEmbedder:
155
164
  If the input is not a string.
156
165
  """
157
166
  self._validate_input(text=text)
167
+ self.warm_up()
168
+ assert self._client is not None
158
169
 
159
170
  embedding, metadata = get_response(
160
171
  cohere_client=self._client,
@@ -187,6 +198,8 @@ class CohereTextEmbedder:
187
198
  If the input is not a string.
188
199
  """
189
200
  self._validate_input(text=text)
201
+ await self.warm_up_async()
202
+ assert self._async_client is not None
190
203
 
191
204
  embedding, metadata = await get_async_response(
192
205
  cohere_async_client=self._async_client,
@@ -16,6 +16,8 @@ async def get_async_response(
16
16
  model_name: str,
17
17
  input_type: str,
18
18
  truncate: str,
19
+ batch_size: int = 32,
20
+ progress_bar: bool = False,
19
21
  embedding_type: EmbeddingTypes | None = None,
20
22
  ) -> tuple[list[list[float]], dict[str, Any]]:
21
23
  """
@@ -27,6 +29,9 @@ async def get_async_response(
27
29
  :param input_type: one of "classification", "clustering", "search_document", "search_query".
28
30
  The type of input text provided to embed.
29
31
  :param truncate: one of "NONE", "START", "END". How the API handles text longer than the maximum token length.
32
+ :param batch_size: the batch size to use. The Cohere embed endpoint caps the number of texts per call, so the
33
+ texts are sent in batches just like the synchronous path.
34
+ :param progress_bar: if `True`, show a progress bar
30
35
  :param embedding_type: the type of embeddings to return. Defaults to float embeddings.
31
36
 
32
37
  :returns: A tuple of the embeddings and metadata.
@@ -35,24 +40,28 @@ async def get_async_response(
35
40
  """
36
41
  all_embeddings: list[list[float]] = []
37
42
  metadata: dict[str, Any] = {}
38
-
39
43
  embedding_type = embedding_type or EmbeddingTypes.FLOAT
40
- response = await cohere_async_client.embed(
41
- texts=texts,
42
- model=model_name,
43
- input_type=input_type,
44
- truncate=truncate,
45
- embedding_types=[embedding_type.value],
46
- )
47
- if response.meta is not None:
48
- metadata = response.meta.model_dump()
49
- for emb_tuple in response.embeddings:
50
- # emb_tuple[0] is a str denoting the embedding type (e.g. "float", "int8", etc.)
51
- if emb_tuple[1] is not None:
52
- # ok we have embeddings for this type, let's take all
53
- # the embeddings (a list of embeddings) and break the loop
54
- all_embeddings.extend(emb_tuple[1])
55
- break
44
+
45
+ for i in tqdm(
46
+ range(0, len(texts), batch_size),
47
+ disable=not progress_bar,
48
+ desc="Calculating embeddings",
49
+ ):
50
+ batch = texts[i : i + batch_size]
51
+ response = await cohere_async_client.embed(
52
+ texts=batch,
53
+ model=model_name,
54
+ input_type=input_type,
55
+ truncate=truncate,
56
+ embedding_types=[embedding_type.value],
57
+ )
58
+ for emb_tuple in response.embeddings:
59
+ # emb_tuple[0] is a str denoting the embedding type (e.g. "float", "int8", etc.)
60
+ if emb_tuple[1] is not None:
61
+ # ok we have embeddings for this type, let's take all the embeddings (a list of embeddings)
62
+ all_embeddings.extend(emb_tuple[1])
63
+ if response.meta is not None:
64
+ metadata = response.meta.model_dump()
56
65
 
57
66
  return all_embeddings, metadata
58
67
 
@@ -2,6 +2,5 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  from .chat.chat_generator import CohereChatGenerator
5
- from .generator import CohereGenerator
6
5
 
7
- __all__ = ["CohereChatGenerator", "CohereGenerator"]
6
+ __all__ = ["CohereChatGenerator"]
@@ -579,22 +579,35 @@ class CohereChatGenerator:
579
579
  self.timeout = timeout
580
580
  self.max_retries = max_retries
581
581
 
582
+ self.client: ClientV2 | None = None
583
+ self.async_client: AsyncClientV2 | None = None
584
+
585
+ def _client_kwargs(self, *, async_client: bool) -> dict[str, Any]:
586
+ """Build the keyword arguments used to create a Cohere client."""
582
587
  client_kwargs: dict[str, Any] = {
583
588
  "api_key": self.api_key.resolve_value(),
584
589
  "base_url": self.api_base_url,
585
590
  "client_name": "haystack",
586
591
  }
587
- if timeout is not None:
588
- client_kwargs["timeout"] = timeout
589
-
590
- sync_kwargs = {**client_kwargs}
591
- async_kwargs = {**client_kwargs}
592
- if max_retries is not None:
593
- sync_kwargs["httpx_client"] = HTTPXClient(transport=HTTPTransport(retries=max_retries))
594
- async_kwargs["httpx_client"] = AsyncHTTPXClient(transport=AsyncHTTPTransport(retries=max_retries))
595
-
596
- self.client = ClientV2(**sync_kwargs)
597
- self.async_client = AsyncClientV2(**async_kwargs)
592
+ if self.timeout is not None:
593
+ client_kwargs["timeout"] = self.timeout
594
+
595
+ if self.max_retries is not None:
596
+ if async_client:
597
+ client_kwargs["httpx_client"] = AsyncHTTPXClient(transport=AsyncHTTPTransport(retries=self.max_retries))
598
+ else:
599
+ client_kwargs["httpx_client"] = HTTPXClient(transport=HTTPTransport(retries=self.max_retries))
600
+ return client_kwargs
601
+
602
+ def warm_up(self) -> None:
603
+ """Create the synchronous Cohere client."""
604
+ if self.client is None:
605
+ self.client = ClientV2(**self._client_kwargs(async_client=False))
606
+
607
+ async def warm_up_async(self) -> None:
608
+ """Create the asynchronous Cohere client."""
609
+ if self.async_client is None:
610
+ self.async_client = AsyncClientV2(**self._client_kwargs(async_client=True))
598
611
 
599
612
  def _get_telemetry_data(self) -> dict[str, Any]:
600
613
  """
@@ -652,8 +665,9 @@ class CohereChatGenerator:
652
665
 
653
666
  :param messages: list of `ChatMessage` instances representing the input messages.
654
667
  If a string is provided, it is converted to a list containing a ChatMessage with user role.
655
- :param generation_kwargs: additional keyword arguments for chat generation. These parameters will
656
- potentially override the parameters passed in the __init__ method.
668
+ :param generation_kwargs: additional keyword arguments for chat generation. These are merged per key
669
+ with the `generation_kwargs` passed at initialization: keys provided here take precedence, keys set
670
+ only at initialization are kept.
657
671
  For more details on the parameters supported by the Cohere API, refer to the
658
672
  Cohere [documentation](https://docs.cohere.com/reference/chat).
659
673
  :param tools: A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
@@ -664,6 +678,8 @@ class CohereChatGenerator:
664
678
  :returns: A dictionary with the following keys:
665
679
  - `replies`: a list of `ChatMessage` instances representing the generated responses.
666
680
  """
681
+ self.warm_up()
682
+ assert self.client is not None
667
683
  messages = _normalize_messages(messages)
668
684
 
669
685
  # update generation kwargs by merging with the generation kwargs passed to the run method
@@ -720,8 +736,9 @@ class CohereChatGenerator:
720
736
 
721
737
  :param messages: list of `ChatMessage` instances representing the input messages.
722
738
  If a string is provided, it is converted to a list containing a ChatMessage with user role.
723
- :param generation_kwargs: additional keyword arguments for chat generation. These parameters will
724
- potentially override the parameters passed in the __init__ method.
739
+ :param generation_kwargs: additional keyword arguments for chat generation. These are merged per key
740
+ with the `generation_kwargs` passed at initialization: keys provided here take precedence, keys set
741
+ only at initialization are kept.
725
742
  For more details on the parameters supported by the Cohere API, refer to the
726
743
  Cohere [documentation](https://docs.cohere.com/reference/chat).
727
744
  :param tools: A list of Tool and/or Toolset objects, or a single Toolset for which the model can prepare calls.
@@ -730,6 +747,8 @@ class CohereChatGenerator:
730
747
  :returns: A dictionary with the following keys:
731
748
  - `replies`: a list of `ChatMessage` instances representing the generated responses.
732
749
  """
750
+ await self.warm_up_async()
751
+ assert self.async_client is not None
733
752
  messages = _normalize_messages(messages)
734
753
 
735
754
  # update generation kwargs by merging with the generation kwargs passed to the run method
@@ -69,12 +69,22 @@ class CohereRanker:
69
69
  self.meta_data_separator = meta_data_separator
70
70
  self.max_tokens_per_doc = max_tokens_per_doc
71
71
 
72
- self._cohere_client = ClientV2(
73
- api_key=self.api_key.resolve_value(), base_url=self.api_base_url, client_name="haystack"
74
- )
75
- self._cohere_async_client = AsyncClientV2(
76
- api_key=self.api_key.resolve_value(), base_url=self.api_base_url, client_name="haystack"
77
- )
72
+ self._cohere_client: ClientV2 | None = None
73
+ self._cohere_async_client: AsyncClientV2 | None = None
74
+
75
+ def warm_up(self) -> None:
76
+ """Create the synchronous Cohere client."""
77
+ if self._cohere_client is None:
78
+ self._cohere_client = ClientV2(
79
+ api_key=self.api_key.resolve_value(), base_url=self.api_base_url, client_name="haystack"
80
+ )
81
+
82
+ async def warm_up_async(self) -> None:
83
+ """Create the asynchronous Cohere client."""
84
+ if self._cohere_async_client is None:
85
+ self._cohere_async_client = AsyncClientV2(
86
+ api_key=self.api_key.resolve_value(), base_url=self.api_base_url, client_name="haystack"
87
+ )
78
88
 
79
89
  def to_dict(self) -> dict[str, Any]:
80
90
  """
@@ -172,6 +182,8 @@ class CohereRanker:
172
182
 
173
183
  :raises ValueError: If `top_k` is not > 0.
174
184
  """
185
+ self.warm_up()
186
+ assert self._cohere_client is not None
175
187
  cohere_input_docs, top_k = self._prepare_cohere_input_docs(documents, top_k)
176
188
 
177
189
  response = self._cohere_client.rerank(
@@ -205,6 +217,8 @@ class CohereRanker:
205
217
 
206
218
  :raises ValueError: If `top_k` is not > 0.
207
219
  """
220
+ await self.warm_up_async()
221
+ assert self._cohere_async_client is not None
208
222
  cohere_input_docs, top_k = self._prepare_cohere_input_docs(documents, top_k)
209
223
 
210
224
  response = await self._cohere_async_client.rerank(