nvidia-haystack 1.2.0__tar.gz → 1.4.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.2.0 → nvidia_haystack-1.4.0}/CHANGELOG.md +25 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/PKG-INFO +1 -1
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/pyproject.toml +1 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/rankers/nvidia/ranker.py +10 -8
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/nim_backend.py +32 -7
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/conftest.py +10 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_nim_backend.py +23 -1
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_nvidia_chat_generator.py +16 -5
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_ranker.py +46 -8
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/.gitignore +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/LICENSE.txt +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/README.md +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/examples/chat_generator_with_structured_outputs.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/pydoc/config_docusaurus.yml +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/embedders/nvidia/__init__.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/embedders/nvidia/document_embedder.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/embedders/nvidia/text_embedder.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/embedders/nvidia/truncate.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/embedders/py.typed +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/generators/nvidia/__init__.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/generators/nvidia/chat/__init__.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/generators/nvidia/chat/chat_generator.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/generators/nvidia/generator.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/generators/py.typed +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/rankers/nvidia/__init__.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/components/rankers/nvidia/truncate.py +0 -0
- {nvidia_haystack-1.2.0/src/haystack_integrations/components/rankers/nvidia → nvidia_haystack-1.4.0/src/haystack_integrations/components/rankers}/py.typed +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/__init__.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/client.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/models.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/utils.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/py.typed +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/__init__.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_base_url.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_document_embedder.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_embedding_truncate_mode.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_generator.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_text_embedder.py +0 -0
- {nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/tests/test_utils.py +0 -0
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [integrations/nvidia-v1.3.0] - 2026-08-04
|
|
4
|
+
|
|
5
|
+
### 🐛 Bug Fixes
|
|
6
|
+
|
|
7
|
+
- Support Haystack 3.0's lazy OpenAI client initialization in OpenAI-inheriting generators (#3536)
|
|
8
|
+
- Fix new issues raised by ruff 0.16.0 (#3670)
|
|
9
|
+
- Fix Nvidia NimBackend type error (#3719)
|
|
10
|
+
- NvidiaRanker missing /ranking path for local NIM deployments (#3483)
|
|
11
|
+
|
|
12
|
+
### 🧪 Testing
|
|
13
|
+
|
|
14
|
+
- Trust test modules under Haystack 3.0's deserialization allowlist (#3537)
|
|
15
|
+
|
|
16
|
+
### 🧹 Chores
|
|
17
|
+
|
|
18
|
+
- Improve consistency of integrations folder structure (#3430)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## [integrations/nvidia-v1.2.0] - 2026-06-05
|
|
22
|
+
|
|
23
|
+
### 🧹 Chores
|
|
24
|
+
|
|
25
|
+
- NVIDIA - deprecate generator (#3391)
|
|
26
|
+
|
|
27
|
+
|
|
3
28
|
## [integrations/nvidia-v1.1.1] - 2026-04-14
|
|
4
29
|
|
|
5
30
|
### 🐛 Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nvidia-haystack
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.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
|
|
@@ -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:
|
|
@@ -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
|
|
@@ -202,6 +204,7 @@ class NvidiaRanker:
|
|
|
202
204
|
:param top_k: The number of documents to return.
|
|
203
205
|
|
|
204
206
|
:raises TypeError: If the arguments are of the wrong type.
|
|
207
|
+
:raises ValueError: If `top_k` is not > 0.
|
|
205
208
|
|
|
206
209
|
:returns: A dictionary containing the ranked documents.
|
|
207
210
|
"""
|
|
@@ -224,11 +227,10 @@ class NvidiaRanker:
|
|
|
224
227
|
if len(documents) == 0:
|
|
225
228
|
return {"documents": []}
|
|
226
229
|
|
|
230
|
+
if top_k is not None and top_k <= 0:
|
|
231
|
+
msg = f"top_k must be > 0, but got {top_k}"
|
|
232
|
+
raise ValueError(msg)
|
|
227
233
|
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
234
|
|
|
233
235
|
assert self.backend is not None
|
|
234
236
|
|
|
@@ -42,6 +42,11 @@ class NimBackend:
|
|
|
42
42
|
self.session.headers.update(headers)
|
|
43
43
|
|
|
44
44
|
self.api_url = api_url
|
|
45
|
+
# Hosted ranking models are assigned a per-model endpoint that already includes the
|
|
46
|
+
# full path (e.g. ".../nv-rerankqa-mistral-4b-v3/reranking"), unlike other hosted
|
|
47
|
+
# endpoints which only override the host. `rank()` uses this to decide whether it
|
|
48
|
+
# still needs to append the `/ranking` path itself.
|
|
49
|
+
self._has_custom_ranking_endpoint = False
|
|
45
50
|
if isinstance(client, str):
|
|
46
51
|
client = Client.from_str(client)
|
|
47
52
|
validated_model: Model | None = None
|
|
@@ -64,6 +69,8 @@ class NimBackend:
|
|
|
64
69
|
# we override the endpoint to use the custom endpoint
|
|
65
70
|
self.api_url = validated_model.endpoint
|
|
66
71
|
self.model_type = validated_model.model_type
|
|
72
|
+
if validated_model.model_type == "ranking":
|
|
73
|
+
self._has_custom_ranking_endpoint = True
|
|
67
74
|
|
|
68
75
|
self.model = validated_model.id if validated_model else model
|
|
69
76
|
self.model_kwargs = model_kwargs or {}
|
|
@@ -89,8 +96,13 @@ class NimBackend:
|
|
|
89
96
|
)
|
|
90
97
|
res.raise_for_status()
|
|
91
98
|
except requests.HTTPError as e:
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
response_text = e.response.text.strip() if e.response is not None else ""
|
|
100
|
+
error_details = f": {response_text}" if response_text else ""
|
|
101
|
+
logger.error(
|
|
102
|
+
"Error when calling NIM embedding endpoint{error}",
|
|
103
|
+
error=error_details,
|
|
104
|
+
)
|
|
105
|
+
msg = f"Failed to query embedding endpoint{error_details}"
|
|
94
106
|
raise ValueError(msg) from e
|
|
95
107
|
|
|
96
108
|
data = res.json()
|
|
@@ -123,8 +135,13 @@ class NimBackend:
|
|
|
123
135
|
)
|
|
124
136
|
res.raise_for_status()
|
|
125
137
|
except requests.HTTPError as e:
|
|
126
|
-
|
|
127
|
-
|
|
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}"
|
|
128
145
|
raise ValueError(msg) from e
|
|
129
146
|
|
|
130
147
|
completions = res.json()
|
|
@@ -179,7 +196,10 @@ class NimBackend:
|
|
|
179
196
|
|
|
180
197
|
def rank(self, query_text: str, document_texts: list[str]) -> list[dict[str, Any]]:
|
|
181
198
|
"""Rank documents by relevance to a query via the NIM API."""
|
|
182
|
-
|
|
199
|
+
# Hosted ranking models already carry the full path in their custom endpoint;
|
|
200
|
+
# everything else (local NIM containers, non-ranking-table models) needs the
|
|
201
|
+
# `/ranking` suffix appended explicitly, like the other endpoints below do.
|
|
202
|
+
url = self.api_url if self._has_custom_ranking_endpoint else f"{self.api_url}/ranking"
|
|
183
203
|
|
|
184
204
|
try:
|
|
185
205
|
res = self.session.post(
|
|
@@ -194,8 +214,13 @@ class NimBackend:
|
|
|
194
214
|
)
|
|
195
215
|
res.raise_for_status()
|
|
196
216
|
except requests.HTTPError as e:
|
|
197
|
-
|
|
198
|
-
|
|
217
|
+
response_text = e.response.text.strip() if e.response is not None else ""
|
|
218
|
+
error_details = f": {response_text}" if response_text else ""
|
|
219
|
+
logger.error(
|
|
220
|
+
"Error when calling NIM ranking endpoint{error}",
|
|
221
|
+
error=error_details,
|
|
222
|
+
)
|
|
223
|
+
msg = f"Failed to query ranking endpoint{error_details}"
|
|
199
224
|
raise ValueError(msg) from e
|
|
200
225
|
|
|
201
226
|
data = res.json()
|
|
@@ -47,3 +47,13 @@ def mock_local_models(requests_mock: Mocker) -> None:
|
|
|
47
47
|
]
|
|
48
48
|
},
|
|
49
49
|
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.fixture(autouse=True)
|
|
53
|
+
def allow_deserialization_of_test_modules(monkeypatch):
|
|
54
|
+
"""
|
|
55
|
+
haystack-ai >= 3.0 refuses to deserialize classes and callables from modules outside its
|
|
56
|
+
trusted-module allowlist. Tools and callbacks defined in the test modules live outside that
|
|
57
|
+
allowlist, so trust them explicitly; haystack-ai 2.x ignores this environment variable.
|
|
58
|
+
"""
|
|
59
|
+
monkeypatch.setenv("HAYSTACK_DESERIALIZATION_ALLOWLIST", "tests,test_*")
|
|
@@ -289,6 +289,28 @@ class TestNimBackend:
|
|
|
289
289
|
timeout=60.0,
|
|
290
290
|
)
|
|
291
291
|
|
|
292
|
+
def test_rank_local_nim_appends_ranking_path(self, monkeypatch):
|
|
293
|
+
# Local/self-hosted NIM deployments have no model-specific endpoint override,
|
|
294
|
+
# so `rank()` must append the `/ranking` path itself instead of relying on
|
|
295
|
+
# `validate_hosted_model` having already baked it into `self.api_url`.
|
|
296
|
+
with patch("requests.sessions.Session.post", side_effect=mock_rank_post_response) as mock_post:
|
|
297
|
+
monkeypatch.setenv("NVIDIA_API_KEY", "fake-api-key")
|
|
298
|
+
backend = NimBackend(model="custom-rerank-model", api_url="http://localhost:8000/v1", client="NvidiaRanker")
|
|
299
|
+
query_text = "query"
|
|
300
|
+
document_texts = ["text1", "text2"]
|
|
301
|
+
backend.rank(query_text=query_text, document_texts=document_texts)
|
|
302
|
+
|
|
303
|
+
expected_url = "http://localhost:8000/v1/ranking"
|
|
304
|
+
mock_post.assert_called_once_with(
|
|
305
|
+
expected_url,
|
|
306
|
+
json={
|
|
307
|
+
"model": "custom-rerank-model",
|
|
308
|
+
"query": {"text": query_text},
|
|
309
|
+
"passages": [{"text": text} for text in document_texts],
|
|
310
|
+
},
|
|
311
|
+
timeout=60.0,
|
|
312
|
+
)
|
|
313
|
+
|
|
292
314
|
def test_rank_raises_on_http_error(self, monkeypatch):
|
|
293
315
|
error_response = requests.Response()
|
|
294
316
|
error_response.status_code = 500
|
|
@@ -298,7 +320,7 @@ class TestNimBackend:
|
|
|
298
320
|
backend = NimBackend(
|
|
299
321
|
model="nvidia/llama-3.2-nv-rerankqa-1b-v2", api_url=DEFAULT_API_URL, client="NvidiaRanker"
|
|
300
322
|
)
|
|
301
|
-
with pytest.raises(ValueError, match="Failed to
|
|
323
|
+
with pytest.raises(ValueError, match="Failed to query ranking endpoint"):
|
|
302
324
|
backend.rank(query_text="q", document_texts=["a"])
|
|
303
325
|
|
|
304
326
|
def test_rank_raises_when_rankings_missing(self, monkeypatch):
|
|
@@ -119,15 +119,23 @@ class TestNvidiaChatGenerator:
|
|
|
119
119
|
def test_init_default(self, monkeypatch):
|
|
120
120
|
monkeypatch.setenv("NVIDIA_API_KEY", "test-api-key")
|
|
121
121
|
component = NvidiaChatGenerator()
|
|
122
|
-
assert component.
|
|
122
|
+
assert component.api_key.resolve_value() == "test-api-key"
|
|
123
123
|
assert component.model == "meta/llama-3.1-8b-instruct"
|
|
124
124
|
assert component.streaming_callback is None
|
|
125
125
|
assert not component.generation_kwargs
|
|
126
126
|
|
|
127
|
+
def test_warm_up(self, monkeypatch):
|
|
128
|
+
monkeypatch.setenv("NVIDIA_API_KEY", "test-api-key")
|
|
129
|
+
component = NvidiaChatGenerator()
|
|
130
|
+
component.warm_up() # with haystack-ai >= 3.0 the client is created during warm-up
|
|
131
|
+
assert component.client.api_key == "test-api-key"
|
|
132
|
+
|
|
127
133
|
def test_init_fail_wo_api_key(self, monkeypatch):
|
|
128
134
|
monkeypatch.delenv("NVIDIA_API_KEY", raising=False)
|
|
129
135
|
with pytest.raises(ValueError, match=r"None of the .* environment variables are set"):
|
|
130
|
-
|
|
136
|
+
# haystack-ai 2.x raises at init; haystack-ai >= 3.0 raises when the client is created in warm_up
|
|
137
|
+
component = NvidiaChatGenerator()
|
|
138
|
+
component.warm_up()
|
|
131
139
|
|
|
132
140
|
def test_init_with_parameters(self):
|
|
133
141
|
component = NvidiaChatGenerator(
|
|
@@ -137,7 +145,7 @@ class TestNvidiaChatGenerator:
|
|
|
137
145
|
api_base_url="test-base-url",
|
|
138
146
|
generation_kwargs={"max_tokens": 10, "some_test_param": "test-params"},
|
|
139
147
|
)
|
|
140
|
-
assert component.
|
|
148
|
+
assert component.api_key.resolve_value() == "test-api-key"
|
|
141
149
|
assert component.model == "meta/llama-3.1-8b-instruct"
|
|
142
150
|
assert component.streaming_callback is print_streaming_chunk
|
|
143
151
|
assert component.generation_kwargs == {"max_tokens": 10, "some_test_param": "test-params"}
|
|
@@ -463,13 +471,16 @@ class TestNvidiaChatGenerator:
|
|
|
463
471
|
|
|
464
472
|
|
|
465
473
|
class TestNvidiaChatGeneratorAsync:
|
|
466
|
-
|
|
474
|
+
@pytest.mark.asyncio
|
|
475
|
+
async def test_warm_up_async(self, monkeypatch):
|
|
467
476
|
monkeypatch.setenv("NVIDIA_API_KEY", "test-api-key")
|
|
468
477
|
component = NvidiaChatGenerator()
|
|
478
|
+
if hasattr(component, "warm_up_async"):
|
|
479
|
+
# haystack-ai >= 3.0 creates the async client during async warm-up
|
|
480
|
+
await component.warm_up_async()
|
|
469
481
|
|
|
470
482
|
assert isinstance(component.async_client, AsyncOpenAI)
|
|
471
483
|
assert component.async_client.api_key == "test-api-key"
|
|
472
|
-
assert not component.generation_kwargs
|
|
473
484
|
|
|
474
485
|
@pytest.mark.asyncio
|
|
475
486
|
async def test_run_async(self, chat_messages, mock_async_chat_completion, monkeypatch): # noqa: ARG002
|
|
@@ -120,6 +120,36 @@ class TestNvidiaRanker:
|
|
|
120
120
|
assert response[0].content == documents[1].content
|
|
121
121
|
assert response[0].score == 4.2
|
|
122
122
|
|
|
123
|
+
@pytest.mark.parametrize(
|
|
124
|
+
("model", "api_url", "expected_url"),
|
|
125
|
+
[
|
|
126
|
+
(
|
|
127
|
+
_DEFAULT_MODEL,
|
|
128
|
+
None,
|
|
129
|
+
"https://ai.api.nvidia.com/v1/retrieval/nvidia/nv-rerankqa-mistral-4b-v3/reranking",
|
|
130
|
+
),
|
|
131
|
+
("custom-rerank-model", "http://localhost:8000/v1", "http://localhost:8000/v1/ranking"),
|
|
132
|
+
],
|
|
133
|
+
ids=["hosted", "local-nim"],
|
|
134
|
+
)
|
|
135
|
+
def test_ranking_url(self, requests_mock, monkeypatch, model, api_url, expected_url) -> None:
|
|
136
|
+
# Hosted models are assigned a per-model endpoint that already includes the full path,
|
|
137
|
+
# while local/self-hosted NIM deployments get no such override and need `/ranking`
|
|
138
|
+
# appended to the base URL. Registering only the exact expected URL means any other
|
|
139
|
+
# URL raises NoMockAddress instead of silently passing.
|
|
140
|
+
monkeypatch.setenv("NVIDIA_API_KEY", "fake-api-key")
|
|
141
|
+
requests_mock.post(expected_url, json={"rankings": [{"index": 0, "logit": 1.0}]}, complete_qs=True)
|
|
142
|
+
|
|
143
|
+
api_url_param = {} if api_url is None else {"api_url": api_url}
|
|
144
|
+
client = NvidiaRanker(model=model, top_k=1, **api_url_param)
|
|
145
|
+
client.warm_up()
|
|
146
|
+
|
|
147
|
+
response = client.run(query="q", documents=[Document(content="doc")])["documents"]
|
|
148
|
+
|
|
149
|
+
assert len(response) == 1
|
|
150
|
+
assert requests_mock.last_request is not None
|
|
151
|
+
assert requests_mock.last_request.url == expected_url
|
|
152
|
+
|
|
123
153
|
@pytest.mark.parametrize("truncate", [True, False, 1, 0, 1.0, "START", "BOGUS"])
|
|
124
154
|
def test_truncate_invalid(self, truncate: Any) -> None:
|
|
125
155
|
with pytest.raises(ValueError) as e:
|
|
@@ -181,6 +211,7 @@ class TestNvidiaRanker:
|
|
|
181
211
|
client = NvidiaRanker(
|
|
182
212
|
model=os.environ["NVIDIA_NIM_RANKER_MODEL"],
|
|
183
213
|
api_url=os.environ["NVIDIA_NIM_RANKER_ENDPOINT_URL"],
|
|
214
|
+
api_key=None,
|
|
184
215
|
top_k=2,
|
|
185
216
|
)
|
|
186
217
|
client.warm_up()
|
|
@@ -190,20 +221,27 @@ class TestNvidiaRanker:
|
|
|
190
221
|
assert len(response) == 2
|
|
191
222
|
assert {response[0].content, response[1].content} == {documents[0].content, documents[1].content}
|
|
192
223
|
|
|
193
|
-
|
|
224
|
+
@pytest.mark.parametrize("top_k", [0, -1])
|
|
225
|
+
def test_top_k_init_invalid(self, monkeypatch, top_k: int) -> None:
|
|
194
226
|
monkeypatch.setenv("NVIDIA_API_KEY", "fake-api-key")
|
|
227
|
+
with pytest.raises(ValueError, match=rf"top_k must be > 0, but got {top_k}"):
|
|
228
|
+
NvidiaRanker(top_k=top_k)
|
|
195
229
|
|
|
196
|
-
|
|
230
|
+
@pytest.mark.parametrize("top_k", [0, -1])
|
|
231
|
+
def test_top_k_run_invalid(self, monkeypatch, top_k: int) -> None:
|
|
232
|
+
monkeypatch.setenv("NVIDIA_API_KEY", "fake-api-key")
|
|
233
|
+
client = NvidiaRanker()
|
|
197
234
|
client.warm_up()
|
|
198
|
-
with pytest.
|
|
199
|
-
client.run("query", [Document(content="doc")])
|
|
200
|
-
assert "top_k should be at least 1" in str(record0[0].message)
|
|
235
|
+
with pytest.raises(ValueError, match=rf"top_k must be > 0, but got {top_k}"):
|
|
236
|
+
client.run("query", [Document(content="doc")], top_k=top_k)
|
|
201
237
|
|
|
202
|
-
|
|
238
|
+
def test_top_k_zero_at_run_does_not_fall_back_to_instance_top_k(self, monkeypatch) -> None:
|
|
239
|
+
# a runtime top_k=0 must raise, not silently fall back to the instance top_k
|
|
240
|
+
monkeypatch.setenv("NVIDIA_API_KEY", "fake-api-key")
|
|
241
|
+
client = NvidiaRanker(top_k=5)
|
|
203
242
|
client.warm_up()
|
|
204
|
-
with pytest.
|
|
243
|
+
with pytest.raises(ValueError, match=r"top_k must be > 0, but got 0"):
|
|
205
244
|
client.run("query", [Document(content="doc")], top_k=0)
|
|
206
|
-
assert "top_k should be at least 1" in str(record1[0].message)
|
|
207
245
|
|
|
208
246
|
def test_model_typeerror(self) -> None:
|
|
209
247
|
with pytest.raises(TypeError) as e:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/examples/chat_generator_with_structured_outputs.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/__init__.py
RENAMED
|
File without changes
|
{nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/client.py
RENAMED
|
File without changes
|
{nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/models.py
RENAMED
|
File without changes
|
{nvidia_haystack-1.2.0 → nvidia_haystack-1.4.0}/src/haystack_integrations/utils/nvidia/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|