nvidia-haystack 1.3.0__tar.gz → 2.0.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.
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/CHANGELOG.md +64 -12
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/PKG-INFO +3 -3
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/examples/chat_generator_with_structured_outputs.py +1 -1
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/pydoc/config_docusaurus.yml +0 -1
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/pyproject.toml +2 -2
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/embedders/nvidia/document_embedder.py +10 -8
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/embedders/nvidia/text_embedder.py +10 -8
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/generators/nvidia/__init__.py +1 -2
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/generators/nvidia/chat/chat_generator.py +1 -1
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/rankers/nvidia/ranker.py +36 -30
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/utils/nvidia/models.py +20 -3
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/utils/nvidia/nim_backend.py +6 -62
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_base_url.py +5 -6
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_document_embedder.py +45 -10
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_nim_backend.py +9 -74
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_nvidia_chat_generator.py +67 -94
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_ranker.py +124 -90
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_text_embedder.py +45 -9
- nvidia_haystack-1.3.0/src/haystack_integrations/components/generators/nvidia/generator.py +0 -199
- nvidia_haystack-1.3.0/tests/test_generator.py +0 -302
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/.gitignore +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/LICENSE.txt +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/README.md +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/embedders/nvidia/__init__.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/embedders/nvidia/truncate.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/embedders/py.typed +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/generators/nvidia/chat/__init__.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/generators/py.typed +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/rankers/nvidia/__init__.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/rankers/nvidia/truncate.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/components/rankers/py.typed +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/utils/nvidia/__init__.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/utils/nvidia/client.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/utils/nvidia/utils.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/utils/py.typed +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/__init__.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/conftest.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_embedding_truncate_mode.py +0 -0
- {nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/tests/test_utils.py +0 -0
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [integrations/nvidia-v1.4.0] - 2026-08-11
|
|
4
|
+
|
|
5
|
+
### 🐛 Bug Fixes
|
|
6
|
+
|
|
7
|
+
- NvidiaRanker reordered the top_k fallback to happen after validation (#3749)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## [integrations/nvidia-v1.3.0] - 2026-08-04
|
|
11
|
+
|
|
12
|
+
### 🐛 Bug Fixes
|
|
13
|
+
|
|
14
|
+
- Support Haystack 3.0's lazy OpenAI client initialization in OpenAI-inheriting generators (#3536)
|
|
15
|
+
- Fix new issues raised by ruff 0.16.0 (#3670)
|
|
16
|
+
- Fix Nvidia NimBackend type error (#3719)
|
|
17
|
+
- NvidiaRanker missing /ranking path for local NIM deployments (#3483)
|
|
18
|
+
|
|
19
|
+
### 🧪 Testing
|
|
20
|
+
|
|
21
|
+
- Trust test modules under Haystack 3.0's deserialization allowlist (#3537)
|
|
22
|
+
|
|
23
|
+
### 🧹 Chores
|
|
24
|
+
|
|
25
|
+
- Improve consistency of integrations folder structure (#3430)
|
|
26
|
+
|
|
27
|
+
|
|
3
28
|
## [integrations/nvidia-v1.2.0] - 2026-06-05
|
|
4
29
|
|
|
5
30
|
### 🧹 Chores
|
|
@@ -167,9 +192,14 @@
|
|
|
167
192
|
|
|
168
193
|
### 🚀 Features
|
|
169
194
|
|
|
170
|
-
- Improvements to NvidiaRanker and adding user input timeout (#1193)
|
|
171
195
|
- Add model `nvidia/llama-3.2-nv-rerankqa-1b-v2` to `_MODEL_ENDPOINT_MAP` (#1260)
|
|
172
196
|
|
|
197
|
+
## [integrations/nvidia-v0.1.2] - 2024-11-25
|
|
198
|
+
|
|
199
|
+
### 🚀 Features
|
|
200
|
+
|
|
201
|
+
- Improvements to NvidiaRanker and adding user input timeout (#1193)
|
|
202
|
+
|
|
173
203
|
### 🧹 Chores
|
|
174
204
|
|
|
175
205
|
- Fix linting/isort (#1215)
|
|
@@ -186,18 +216,34 @@
|
|
|
186
216
|
|
|
187
217
|
### 🚀 Features
|
|
188
218
|
|
|
189
|
-
- Update default embedding model to nvidia/nv-embedqa-e5-v5 (#1015)
|
|
190
|
-
- Add NVIDIA NIM ranker support (#1023)
|
|
191
219
|
- Raise error when attempting to embed empty documents/strings with Nvidia embedders (#1118)
|
|
192
220
|
|
|
193
221
|
### 🐛 Bug Fixes
|
|
194
222
|
|
|
195
|
-
- Lints in `nvidia-haystack` (#993)
|
|
196
223
|
- Missing Nvidia embedding truncate mode (#1043)
|
|
197
224
|
|
|
198
|
-
###
|
|
225
|
+
### ⚙️ CI
|
|
199
226
|
|
|
200
|
-
-
|
|
227
|
+
- Adopt uv as installer (#1142)
|
|
228
|
+
|
|
229
|
+
### 🧹 Chores
|
|
230
|
+
|
|
231
|
+
- Update ruff linting scripts and settings (#1105)
|
|
232
|
+
|
|
233
|
+
### 🌀 Miscellaneous
|
|
234
|
+
|
|
235
|
+
- Feat: add nvidia/llama-3.2-nv-rerankqa-1b-v1 to set of known ranking models (#1183)
|
|
236
|
+
|
|
237
|
+
## [integrations/nvidia-v0.0.5] - 2024-08-28
|
|
238
|
+
|
|
239
|
+
### 🚀 Features
|
|
240
|
+
|
|
241
|
+
- Update default embedding model to nvidia/nv-embedqa-e5-v5 (#1015)
|
|
242
|
+
- Add NVIDIA NIM ranker support (#1023)
|
|
243
|
+
|
|
244
|
+
### 🐛 Bug Fixes
|
|
245
|
+
|
|
246
|
+
- Lints in `nvidia-haystack` (#993)
|
|
201
247
|
|
|
202
248
|
### 📚 Documentation
|
|
203
249
|
|
|
@@ -207,25 +253,31 @@
|
|
|
207
253
|
|
|
208
254
|
- Do not retry tests in `hatch run test` command (#954)
|
|
209
255
|
|
|
256
|
+
### 🌀 Miscellaneous
|
|
257
|
+
|
|
258
|
+
- Raise warning for base_url ../embeddings .../completions .../rankings (#922)
|
|
259
|
+
- Update NvidiaGenerator docstrings (#966)
|
|
260
|
+
- Add default model for NVIDIA HayStack local NIM endpoints (#915)
|
|
261
|
+
|
|
262
|
+
## [integrations/nvidia-v0.0.4] - 2024-07-24
|
|
263
|
+
|
|
264
|
+
### 🚜 Refactor
|
|
265
|
+
|
|
266
|
+
- Remove deprecated Nvidia Cloud Functions backend and related code. (#803)
|
|
267
|
+
|
|
210
268
|
### ⚙️ CI
|
|
211
269
|
|
|
212
270
|
- Retry tests to reduce flakyness (#836)
|
|
213
|
-
- Adopt uv as installer (#1142)
|
|
214
271
|
|
|
215
272
|
### 🧹 Chores
|
|
216
273
|
|
|
217
274
|
- Update ruff invocation to include check parameter (#853)
|
|
218
|
-
- Update ruff linting scripts and settings (#1105)
|
|
219
275
|
|
|
220
276
|
### 🌀 Miscellaneous
|
|
221
277
|
|
|
222
278
|
- Fix: make hosted nim default (#734)
|
|
223
279
|
- Fix: align tests and docs on NVIDIA_API_KEY (instead of NVIDIA_CATALOG_API_KEY) (#731)
|
|
224
280
|
- Ci: install `pytest-rerunfailures` where needed; add retry config to `test-cov` script (#845)
|
|
225
|
-
- Raise warning for base_url ../embeddings .../completions .../rankings (#922)
|
|
226
|
-
- Update NvidiaGenerator docstrings (#966)
|
|
227
|
-
- Add default model for NVIDIA HayStack local NIM endpoints (#915)
|
|
228
|
-
- Feat: add nvidia/llama-3.2-nv-rerankqa-1b-v1 to set of known ranking models (#1183)
|
|
229
281
|
|
|
230
282
|
## [integrations/nvidia-v0.0.3] - 2024-05-22
|
|
231
283
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: nvidia-haystack
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/nvidia#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/nvidia
|
|
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
18
18
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
19
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
|
-
Requires-Dist: haystack-ai>=
|
|
21
|
+
Requires-Dist: haystack-ai>=3.0.0
|
|
22
22
|
Requires-Dist: requests>=2.25.0
|
|
23
23
|
Requires-Dist: tqdm>=4.21.0
|
|
24
24
|
Description-Content-Type: text/markdown
|
{nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/examples/chat_generator_with_structured_outputs.py
RENAMED
|
@@ -27,7 +27,7 @@ chat_messages = [
|
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
component = NvidiaChatGenerator(
|
|
30
|
-
model="
|
|
30
|
+
model="nvidia/nemotron-3.5-lightning-30b-a3b",
|
|
31
31
|
generation_kwargs={"extra_body": {"nvext": {"guided_json": json_schema}}},
|
|
32
32
|
)
|
|
33
33
|
results = component.run(chat_messages)
|
|
@@ -3,7 +3,6 @@ loaders:
|
|
|
3
3
|
- haystack_integrations.components.embedders.nvidia.document_embedder
|
|
4
4
|
- haystack_integrations.components.embedders.nvidia.text_embedder
|
|
5
5
|
- haystack_integrations.components.embedders.nvidia.truncate
|
|
6
|
-
- haystack_integrations.components.generators.nvidia.generator
|
|
7
6
|
- haystack_integrations.components.generators.nvidia.chat.chat_generator
|
|
8
7
|
- haystack_integrations.components.rankers.nvidia.ranker
|
|
9
8
|
- haystack_integrations.components.rankers.nvidia.truncate
|
|
@@ -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>=
|
|
26
|
+
dependencies = ["haystack-ai>=3.0.0", "requests>=2.25.0", "tqdm>=4.21.0"]
|
|
27
27
|
|
|
28
28
|
[project.urls]
|
|
29
29
|
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/nvidia#readme"
|
|
@@ -168,4 +168,4 @@ addopts = "--strict-markers"
|
|
|
168
168
|
markers = [
|
|
169
169
|
"integration: integration tests",
|
|
170
170
|
]
|
|
171
|
-
log_cli = true
|
|
171
|
+
log_cli = true
|
|
@@ -28,7 +28,7 @@ class NvidiaDocumentEmbedder:
|
|
|
28
28
|
|
|
29
29
|
doc = Document(content="I love pizza!")
|
|
30
30
|
|
|
31
|
-
text_embedder = NvidiaDocumentEmbedder(model="nvidia/
|
|
31
|
+
text_embedder = NvidiaDocumentEmbedder(model="nvidia/nemotron-3-embed-1b", api_url="https://integrate.api.nvidia.com/v1")
|
|
32
32
|
# Components warm up automatically on first run.
|
|
33
33
|
|
|
34
34
|
result = document_embedder.run([doc])
|
|
@@ -97,8 +97,7 @@ class NvidiaDocumentEmbedder:
|
|
|
97
97
|
truncate = EmbeddingTruncateMode.from_str(truncate)
|
|
98
98
|
self.truncate = truncate
|
|
99
99
|
|
|
100
|
-
self.backend:
|
|
101
|
-
self._initialized = False
|
|
100
|
+
self.backend: NimBackend | None = None
|
|
102
101
|
|
|
103
102
|
if timeout is None:
|
|
104
103
|
timeout = float(os.environ.get("NVIDIA_TIMEOUT", "60.0"))
|
|
@@ -134,7 +133,7 @@ class NvidiaDocumentEmbedder:
|
|
|
134
133
|
"""
|
|
135
134
|
Initializes the component.
|
|
136
135
|
"""
|
|
137
|
-
if self.
|
|
136
|
+
if self.backend is not None:
|
|
138
137
|
return
|
|
139
138
|
|
|
140
139
|
model_kwargs = {"input_type": "passage"}
|
|
@@ -152,11 +151,15 @@ class NvidiaDocumentEmbedder:
|
|
|
152
151
|
if not self.model and self.backend.model:
|
|
153
152
|
self.model = self.backend.model
|
|
154
153
|
|
|
155
|
-
self._initialized = True
|
|
156
|
-
|
|
157
154
|
if not self.model:
|
|
158
155
|
self.default_model()
|
|
159
156
|
|
|
157
|
+
def close(self) -> None:
|
|
158
|
+
"""Close the backend and release its resources."""
|
|
159
|
+
if self.backend is not None:
|
|
160
|
+
self.backend.close()
|
|
161
|
+
self.backend = None
|
|
162
|
+
|
|
160
163
|
def to_dict(self) -> dict[str, Any]:
|
|
161
164
|
"""
|
|
162
165
|
Serializes the component to a dictionary.
|
|
@@ -250,8 +253,7 @@ class NvidiaDocumentEmbedder:
|
|
|
250
253
|
:raises TypeError:
|
|
251
254
|
If the input is not a list of Documents.
|
|
252
255
|
"""
|
|
253
|
-
|
|
254
|
-
self.warm_up()
|
|
256
|
+
self.warm_up()
|
|
255
257
|
|
|
256
258
|
if not isinstance(documents, list) or (documents and not isinstance(documents[0], Document)):
|
|
257
259
|
msg = (
|
|
@@ -29,7 +29,7 @@ class NvidiaTextEmbedder:
|
|
|
29
29
|
|
|
30
30
|
text_to_embed = "I love pizza!"
|
|
31
31
|
|
|
32
|
-
text_embedder = NvidiaTextEmbedder(model="nvidia/
|
|
32
|
+
text_embedder = NvidiaTextEmbedder(model="nvidia/nemotron-3-embed-1b", api_url="https://integrate.api.nvidia.com/v1")
|
|
33
33
|
# Components warm up automatically on first run.
|
|
34
34
|
|
|
35
35
|
print(text_embedder.run(text_to_embed))
|
|
@@ -80,8 +80,7 @@ class NvidiaTextEmbedder:
|
|
|
80
80
|
truncate = EmbeddingTruncateMode.from_str(truncate)
|
|
81
81
|
self.truncate = truncate
|
|
82
82
|
|
|
83
|
-
self.backend:
|
|
84
|
-
self._initialized = False
|
|
83
|
+
self.backend: NimBackend | None = None
|
|
85
84
|
|
|
86
85
|
if timeout is None:
|
|
87
86
|
timeout = float(os.environ.get("NVIDIA_TIMEOUT", "60.0"))
|
|
@@ -123,7 +122,7 @@ class NvidiaTextEmbedder:
|
|
|
123
122
|
"""
|
|
124
123
|
Initializes the component.
|
|
125
124
|
"""
|
|
126
|
-
if self.
|
|
125
|
+
if self.backend is not None:
|
|
127
126
|
return
|
|
128
127
|
|
|
129
128
|
model_kwargs = {"input_type": "query"}
|
|
@@ -138,14 +137,18 @@ class NvidiaTextEmbedder:
|
|
|
138
137
|
timeout=self.timeout,
|
|
139
138
|
client=Client.NVIDIA_TEXT_EMBEDDER,
|
|
140
139
|
)
|
|
141
|
-
self._initialized = True
|
|
142
|
-
|
|
143
140
|
if not self.model:
|
|
144
141
|
if self.backend.model:
|
|
145
142
|
self.model = self.backend.model
|
|
146
143
|
else:
|
|
147
144
|
self.default_model()
|
|
148
145
|
|
|
146
|
+
def close(self) -> None:
|
|
147
|
+
"""Close the backend and release its resources."""
|
|
148
|
+
if self.backend is not None:
|
|
149
|
+
self.backend.close()
|
|
150
|
+
self.backend = None
|
|
151
|
+
|
|
149
152
|
def to_dict(self) -> dict[str, Any]:
|
|
150
153
|
"""
|
|
151
154
|
Serializes the component to a dictionary.
|
|
@@ -202,8 +205,7 @@ class NvidiaTextEmbedder:
|
|
|
202
205
|
:raises ValueError:
|
|
203
206
|
If the input string is empty.
|
|
204
207
|
"""
|
|
205
|
-
|
|
206
|
-
self.warm_up()
|
|
208
|
+
self.warm_up()
|
|
207
209
|
|
|
208
210
|
if not isinstance(text, str):
|
|
209
211
|
msg = (
|
|
@@ -53,7 +53,7 @@ class NvidiaChatGenerator(OpenAIChatGenerator):
|
|
|
53
53
|
self,
|
|
54
54
|
*,
|
|
55
55
|
api_key: Secret = Secret.from_env_var("NVIDIA_API_KEY"),
|
|
56
|
-
model: str = "
|
|
56
|
+
model: str = "nvidia/nemotron-3.5-lightning-30b-a3b",
|
|
57
57
|
streaming_callback: StreamingCallbackT | None = None,
|
|
58
58
|
api_base_url: str | None = os.getenv("NVIDIA_API_URL", DEFAULT_API_URL),
|
|
59
59
|
generation_kwargs: dict[str, Any] | None = None,
|
|
@@ -3,18 +3,15 @@
|
|
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
import warnings
|
|
7
6
|
from dataclasses import replace
|
|
8
7
|
from typing import Any
|
|
9
8
|
|
|
10
|
-
from haystack import Document, component, default_from_dict, default_to_dict
|
|
9
|
+
from haystack import Document, component, default_from_dict, default_to_dict
|
|
11
10
|
from haystack.utils import Secret, deserialize_secrets_inplace
|
|
12
11
|
|
|
13
12
|
from haystack_integrations.components.rankers.nvidia.truncate import RankerTruncateMode
|
|
14
13
|
from haystack_integrations.utils.nvidia import DEFAULT_API_URL, Client, NimBackend, is_hosted, url_validation
|
|
15
14
|
|
|
16
|
-
logger = logging.getLogger(__name__)
|
|
17
|
-
|
|
18
15
|
|
|
19
16
|
@component
|
|
20
17
|
class NvidiaRanker:
|
|
@@ -28,7 +25,7 @@ class NvidiaRanker:
|
|
|
28
25
|
from haystack.utils import Secret
|
|
29
26
|
|
|
30
27
|
ranker = NvidiaRanker(
|
|
31
|
-
model="nvidia/
|
|
28
|
+
model="nvidia/llama-nemotron-rerank-vl-1b-v2",
|
|
32
29
|
api_key=Secret.from_env_var("NVIDIA_API_KEY"),
|
|
33
30
|
)
|
|
34
31
|
# Components warm up automatically on first run.
|
|
@@ -84,6 +81,8 @@ class NvidiaRanker:
|
|
|
84
81
|
:param timeout:
|
|
85
82
|
Timeout for request calls, if not set it is inferred from the `NVIDIA_TIMEOUT` environment variable
|
|
86
83
|
or set to 60 by default.
|
|
84
|
+
|
|
85
|
+
:raises ValueError: If `top_k` is not > 0.
|
|
87
86
|
"""
|
|
88
87
|
if model is not None and not isinstance(model, str):
|
|
89
88
|
msg = "Ranker expects the `model` parameter to be a string."
|
|
@@ -96,6 +95,9 @@ class NvidiaRanker:
|
|
|
96
95
|
if not isinstance(top_k, int):
|
|
97
96
|
msg = "Ranker expects the `top_k` parameter to be an integer."
|
|
98
97
|
raise TypeError(msg)
|
|
98
|
+
if top_k <= 0:
|
|
99
|
+
msg = f"top_k must be > 0, but got {top_k}"
|
|
100
|
+
raise ValueError(msg)
|
|
99
101
|
|
|
100
102
|
# todo: detect default in non-hosted case (when api_url is provided)
|
|
101
103
|
self.truncate = truncate
|
|
@@ -106,8 +108,7 @@ class NvidiaRanker:
|
|
|
106
108
|
# - assume we won't call backend.models()
|
|
107
109
|
self.api_url = url_validation(api_url)
|
|
108
110
|
self.top_k = top_k
|
|
109
|
-
self.
|
|
110
|
-
self.backend: Any | None = None
|
|
111
|
+
self.backend: NimBackend | None = None
|
|
111
112
|
self.is_hosted = is_hosted(api_url)
|
|
112
113
|
|
|
113
114
|
self.query_prefix = query_prefix
|
|
@@ -162,23 +163,29 @@ class NvidiaRanker:
|
|
|
162
163
|
|
|
163
164
|
:raises ValueError: If the API key is required for hosted NVIDIA NIMs.
|
|
164
165
|
"""
|
|
165
|
-
if not
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
self.
|
|
166
|
+
if self.backend is not None:
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
model_kwargs: dict[str, Any] = {}
|
|
170
|
+
if self.truncate is not None:
|
|
171
|
+
model_kwargs.update(truncate=str(self.truncate))
|
|
172
|
+
self.backend = NimBackend(
|
|
173
|
+
model=self.model,
|
|
174
|
+
model_type="ranking",
|
|
175
|
+
api_url=self.api_url,
|
|
176
|
+
api_key=self.api_key,
|
|
177
|
+
model_kwargs=model_kwargs,
|
|
178
|
+
timeout=self.timeout,
|
|
179
|
+
client=Client.NVIDIA_RANKER,
|
|
180
|
+
)
|
|
181
|
+
if not self.is_hosted and not self.model and self.backend.model:
|
|
182
|
+
self.model = self.backend.model
|
|
183
|
+
|
|
184
|
+
def close(self) -> None:
|
|
185
|
+
"""Close the backend and release its resources."""
|
|
186
|
+
if self.backend is not None:
|
|
187
|
+
self.backend.close()
|
|
188
|
+
self.backend = None
|
|
182
189
|
|
|
183
190
|
def _prepare_documents_to_embed(self, documents: list[Document]) -> list[str]:
|
|
184
191
|
document_texts = []
|
|
@@ -202,11 +209,11 @@ class NvidiaRanker:
|
|
|
202
209
|
:param top_k: The number of documents to return.
|
|
203
210
|
|
|
204
211
|
:raises TypeError: If the arguments are of the wrong type.
|
|
212
|
+
:raises ValueError: If `top_k` is not > 0.
|
|
205
213
|
|
|
206
214
|
:returns: A dictionary containing the ranked documents.
|
|
207
215
|
"""
|
|
208
|
-
|
|
209
|
-
self.warm_up()
|
|
216
|
+
self.warm_up()
|
|
210
217
|
|
|
211
218
|
if not isinstance(query, str):
|
|
212
219
|
msg = "NvidiaRanker expects the `query` parameter to be a string."
|
|
@@ -224,11 +231,10 @@ class NvidiaRanker:
|
|
|
224
231
|
if len(documents) == 0:
|
|
225
232
|
return {"documents": []}
|
|
226
233
|
|
|
234
|
+
if top_k is not None and top_k <= 0:
|
|
235
|
+
msg = f"top_k must be > 0, but got {top_k}"
|
|
236
|
+
raise ValueError(msg)
|
|
227
237
|
top_k = top_k if top_k is not None else self.top_k
|
|
228
|
-
if top_k < 1:
|
|
229
|
-
logger.warning("top_k should be at least 1, returning nothing")
|
|
230
|
-
warnings.warn("top_k should be at least 1, returning nothing", stacklevel=2)
|
|
231
|
-
return {"documents": []}
|
|
232
238
|
|
|
233
239
|
assert self.backend is not None
|
|
234
240
|
|
{nvidia_haystack-1.3.0 → nvidia_haystack-2.0.0}/src/haystack_integrations/utils/nvidia/models.py
RENAMED
|
@@ -308,6 +308,13 @@ CHAT_MODEL_TABLE = {
|
|
|
308
308
|
supports_tools=True,
|
|
309
309
|
supports_structured_output=True,
|
|
310
310
|
),
|
|
311
|
+
"nvidia/nemotron-3.5-lightning-30b-a3b": Model(
|
|
312
|
+
id="nvidia/nemotron-3.5-lightning-30b-a3b",
|
|
313
|
+
model_type="chat",
|
|
314
|
+
client=Client.NVIDIA_GENERATOR,
|
|
315
|
+
supports_tools=True,
|
|
316
|
+
supports_structured_output=True,
|
|
317
|
+
),
|
|
311
318
|
"meta/llama-3.1-405b-instruct": Model(
|
|
312
319
|
id="meta/llama-3.1-405b-instruct",
|
|
313
320
|
model_type="chat",
|
|
@@ -430,6 +437,10 @@ EMBEDDING_MODEL_TABLE = {
|
|
|
430
437
|
id="nvidia/nv-embedqa-mistral-7b-v2",
|
|
431
438
|
model_type="embedding",
|
|
432
439
|
),
|
|
440
|
+
"nvidia/nemotron-3-embed-1b": Model(
|
|
441
|
+
id="nvidia/nemotron-3-embed-1b",
|
|
442
|
+
model_type="embedding",
|
|
443
|
+
),
|
|
433
444
|
"nvidia/nv-embedqa-e5-v5": Model(
|
|
434
445
|
id="nvidia/nv-embedqa-e5-v5",
|
|
435
446
|
model_type="embedding",
|
|
@@ -452,6 +463,12 @@ EMBEDDING_MODEL_TABLE = {
|
|
|
452
463
|
),
|
|
453
464
|
}
|
|
454
465
|
RANKING_MODEL_TABLE = {
|
|
466
|
+
"nvidia/llama-nemotron-rerank-vl-1b-v2": Model(
|
|
467
|
+
id="nvidia/llama-nemotron-rerank-vl-1b-v2",
|
|
468
|
+
model_type="ranking",
|
|
469
|
+
client=Client.NVIDIA_RANKER,
|
|
470
|
+
endpoint="https://ai.api.nvidia.com/v1/retrieval/nvidia/llama-nemotron-rerank-vl-1b-v2/reranking",
|
|
471
|
+
),
|
|
455
472
|
"nv-rerank-qa-mistral-4b:1": Model(
|
|
456
473
|
id="nv-rerank-qa-mistral-4b:1",
|
|
457
474
|
model_type="ranking",
|
|
@@ -480,9 +497,9 @@ RANKING_MODEL_TABLE = {
|
|
|
480
497
|
}
|
|
481
498
|
|
|
482
499
|
DEFAULT_MODELS = {
|
|
483
|
-
"embedding": "nvidia/
|
|
484
|
-
"ranking": "
|
|
485
|
-
"chat": "
|
|
500
|
+
"embedding": "nvidia/nemotron-3-embed-1b",
|
|
501
|
+
"ranking": "nvidia/llama-nemotron-rerank-vl-1b-v2",
|
|
502
|
+
"chat": "nvidia/nemotron-3.5-lightning-30b-a3b",
|
|
486
503
|
}
|
|
487
504
|
|
|
488
505
|
|
|
@@ -38,9 +38,6 @@ class NimBackend:
|
|
|
38
38
|
if api_key:
|
|
39
39
|
headers["authorization"] = f"Bearer {api_key.resolve_value()}"
|
|
40
40
|
|
|
41
|
-
self.session = requests.Session()
|
|
42
|
-
self.session.headers.update(headers)
|
|
43
|
-
|
|
44
41
|
self.api_url = api_url
|
|
45
42
|
# Hosted ranking models are assigned a per-model endpoint that already includes the
|
|
46
43
|
# full path (e.g. ".../nv-rerankqa-mistral-4b-v3/reranking"), unlike other hosted
|
|
@@ -79,6 +76,12 @@ class NimBackend:
|
|
|
79
76
|
if timeout is None:
|
|
80
77
|
timeout = float(os.environ.get("NVIDIA_TIMEOUT", REQUEST_TIMEOUT))
|
|
81
78
|
self.timeout = timeout
|
|
79
|
+
self.session = requests.Session()
|
|
80
|
+
self.session.headers.update(headers)
|
|
81
|
+
|
|
82
|
+
def close(self) -> None:
|
|
83
|
+
"""Close the HTTP session owned by this backend."""
|
|
84
|
+
self.session.close()
|
|
82
85
|
|
|
83
86
|
def embed(self, texts: list[str]) -> tuple[list[list[float]], dict[str, Any]]:
|
|
84
87
|
"""Compute embeddings for a list of texts via the NIM API."""
|
|
@@ -111,65 +114,6 @@ class NimBackend:
|
|
|
111
114
|
|
|
112
115
|
return embeddings, {"usage": data["usage"]}
|
|
113
116
|
|
|
114
|
-
def generate(self, prompt: str) -> tuple[list[str], list[dict[str, Any]]]:
|
|
115
|
-
"""Generate text completions for a prompt via the NIM API."""
|
|
116
|
-
# We're using the chat completion endpoint as the NIM API doesn't support
|
|
117
|
-
# the /completions endpoint. So both the non-chat and chat generator will use this.
|
|
118
|
-
# This is the same for local containers and the cloud API.
|
|
119
|
-
url = f"{self.api_url}/chat/completions"
|
|
120
|
-
|
|
121
|
-
try:
|
|
122
|
-
res = self.session.post(
|
|
123
|
-
url,
|
|
124
|
-
json={
|
|
125
|
-
"model": self.model,
|
|
126
|
-
"messages": [
|
|
127
|
-
{
|
|
128
|
-
"role": "user",
|
|
129
|
-
"content": prompt,
|
|
130
|
-
},
|
|
131
|
-
],
|
|
132
|
-
**self.model_kwargs,
|
|
133
|
-
},
|
|
134
|
-
timeout=self.timeout,
|
|
135
|
-
)
|
|
136
|
-
res.raise_for_status()
|
|
137
|
-
except requests.HTTPError as e:
|
|
138
|
-
response_text = e.response.text.strip() if e.response is not None else ""
|
|
139
|
-
error_details = f": {response_text}" if response_text else ""
|
|
140
|
-
logger.error(
|
|
141
|
-
"Error when calling NIM chat completion endpoint{error}",
|
|
142
|
-
error=error_details,
|
|
143
|
-
)
|
|
144
|
-
msg = f"Failed to query chat completion endpoint{error_details}"
|
|
145
|
-
raise ValueError(msg) from e
|
|
146
|
-
|
|
147
|
-
completions = res.json()
|
|
148
|
-
choices = completions["choices"]
|
|
149
|
-
# Sort the choices by index, we don't know whether they're out of order or not
|
|
150
|
-
choices.sort(key=lambda c: c["index"])
|
|
151
|
-
replies = []
|
|
152
|
-
meta = []
|
|
153
|
-
for choice in choices:
|
|
154
|
-
message = choice["message"]
|
|
155
|
-
replies.append(message["content"])
|
|
156
|
-
choice_meta = {
|
|
157
|
-
"role": message["role"],
|
|
158
|
-
"usage": {
|
|
159
|
-
"prompt_tokens": completions["usage"]["prompt_tokens"],
|
|
160
|
-
"total_tokens": completions["usage"]["total_tokens"],
|
|
161
|
-
},
|
|
162
|
-
}
|
|
163
|
-
# These fields could be null, the others will always be present
|
|
164
|
-
if "finish_reason" in choice:
|
|
165
|
-
choice_meta["finish_reason"] = choice["finish_reason"]
|
|
166
|
-
if "completion_tokens" in completions["usage"]:
|
|
167
|
-
choice_meta["usage"]["completion_tokens"] = completions["usage"]["completion_tokens"]
|
|
168
|
-
|
|
169
|
-
meta.append(choice_meta)
|
|
170
|
-
|
|
171
|
-
return replies, meta
|
|
172
|
-
|
|
173
117
|
def models(self) -> list[Model]:
|
|
174
118
|
"""Retrieve available models from the NIM API."""
|
|
175
119
|
url = f"{self.api_url}/models"
|
|
@@ -7,7 +7,6 @@ from typing import Any
|
|
|
7
7
|
import pytest
|
|
8
8
|
|
|
9
9
|
from haystack_integrations.components.embedders.nvidia import NvidiaDocumentEmbedder, NvidiaTextEmbedder
|
|
10
|
-
from haystack_integrations.components.generators.nvidia import NvidiaGenerator
|
|
11
10
|
from haystack_integrations.components.rankers.nvidia import NvidiaRanker
|
|
12
11
|
|
|
13
12
|
|
|
@@ -23,7 +22,7 @@ from haystack_integrations.components.rankers.nvidia import NvidiaRanker
|
|
|
23
22
|
)
|
|
24
23
|
@pytest.mark.parametrize(
|
|
25
24
|
"component",
|
|
26
|
-
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker
|
|
25
|
+
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker],
|
|
27
26
|
)
|
|
28
27
|
def test_base_url_invalid_not_hosted(base_url: str, component) -> None:
|
|
29
28
|
with pytest.warns(UserWarning) as msg:
|
|
@@ -34,7 +33,7 @@ def test_base_url_invalid_not_hosted(base_url: str, component) -> None:
|
|
|
34
33
|
|
|
35
34
|
@pytest.mark.parametrize(
|
|
36
35
|
"component",
|
|
37
|
-
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker
|
|
36
|
+
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker],
|
|
38
37
|
)
|
|
39
38
|
def test_create_without_base_url(component: type, monkeypatch) -> None:
|
|
40
39
|
monkeypatch.setenv("NVIDIA_API_KEY", "valid_api_key")
|
|
@@ -45,7 +44,7 @@ def test_create_without_base_url(component: type, monkeypatch) -> None:
|
|
|
45
44
|
|
|
46
45
|
@pytest.mark.parametrize(
|
|
47
46
|
"component",
|
|
48
|
-
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker
|
|
47
|
+
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker],
|
|
49
48
|
)
|
|
50
49
|
def test_base_url_priority(component: type) -> None:
|
|
51
50
|
param_url = "https://PARAM/v1"
|
|
@@ -59,7 +58,7 @@ def test_base_url_priority(component: type) -> None:
|
|
|
59
58
|
|
|
60
59
|
@pytest.mark.parametrize(
|
|
61
60
|
"component",
|
|
62
|
-
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker
|
|
61
|
+
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker],
|
|
63
62
|
)
|
|
64
63
|
@pytest.mark.parametrize(
|
|
65
64
|
"api_url",
|
|
@@ -78,7 +77,7 @@ def test_param_api_url_negative(component: type, api_url: str) -> None:
|
|
|
78
77
|
|
|
79
78
|
@pytest.mark.parametrize(
|
|
80
79
|
"component",
|
|
81
|
-
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker
|
|
80
|
+
[NvidiaDocumentEmbedder, NvidiaTextEmbedder, NvidiaRanker],
|
|
82
81
|
)
|
|
83
82
|
@pytest.mark.parametrize(
|
|
84
83
|
"api_url",
|