diff --git a/.github/workflows/nrl-docs-nvidia-publish.yml b/.github/workflows/nrl-docs-nvidia-publish.yml index c06bf69da8..12134ecb59 100644 --- a/.github/workflows/nrl-docs-nvidia-publish.yml +++ b/.github/workflows/nrl-docs-nvidia-publish.yml @@ -11,17 +11,17 @@ # Variables (optional): DOCS_AWS_REGION, NRL_DOCS_PUBLISH_VERSION, DOCS_RELEASE_EMAILS # # S3 layout written under developer/docs/nemo/retriever/: -# index.html, versions.json, latest/, / (e.g. 26.5.0/) +# index.html, versions.json, latest/, / (e.g. 26.8.0/) # # Manual publish only (workflow_dispatch). Do not re-enable push/tag auto-publish -# while docs.nvidia.com 26.5.0 / latest are frozen to the 26.05 release docs. +# while docs.nvidia.com 26.8.0 / latest are frozen to the 26.08 release docs. # # Operator steps when ready to publish: -# 1. Merge doc changes to the 26.05 branch (content source for the build). +# 1. Merge doc changes to the 26.08 branch (content source for the build). # 2. Keep docs/publish/versions.json on main accurate (version picker + latest alias). # 3. Actions → "NRL documentation — docs.nvidia.com publish" → Run workflow: # dry-run: false -# docs-version-override: 26.5.0 (or leave empty to use NRL_DOCS_PUBLISH_VERSION / default) +# docs-version-override: 26.8.0 (or leave empty to use NRL_DOCS_PUBLISH_VERSION / default) # publish-as-latest: true only when intentionally refreshing latest/ # Backports: publish-as-latest: false; do not move the "latest" alias in versions.json. name: NRL documentation — docs.nvidia.com publish @@ -35,7 +35,7 @@ on: type: boolean default: true docs-version-override: - description: Version folder to publish (e.g. 26.5.0). Empty uses NRL_DOCS_PUBLISH_VERSION, or 26.5.0. + description: Version folder to publish (e.g. 26.8.0). Empty uses NRL_DOCS_PUBLISH_VERSION, or 26.8.0. required: false type: string default: "" @@ -93,7 +93,7 @@ jobs: VERSION="${NRL_DOCS_PUBLISH_VERSION_VAR}" fi if [[ -z "${VERSION}" ]]; then - VERSION="26.5.0" + VERSION="26.8.0" fi echo "docs_version=${VERSION}" >> "$GITHUB_OUTPUT" echo "site_url=${{ env.DOCS_SITE_URL_BASE }}/${VERSION}/" >> "$GITHUB_OUTPUT" @@ -116,16 +116,16 @@ jobs: needs: resolve runs-on: ubuntu-latest steps: - # Publish the doc pages from the 26.05 release branch, not main. main keeps + # Publish the doc pages from the 26.08 release branch, not main. main keeps # moving toward the next release, so its docs must not be published under the - # 26.5.0 label. mkdocs.yml, requirements.txt, and docs/docs/** come from 26.05. - - name: Checkout 26.05 docs content + # 26.8.0 label. mkdocs.yml, requirements.txt, and docs/docs/** come from 26.08. + - name: Checkout 26.08 docs content uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - ref: "26.05" + ref: "26.08" # versions.json (the version picker + "latest" alias) is canonical on main and - # does not exist on 26.05, so fetch just that file from main into a side path. + # does not exist on 26.08, so fetch just that file from main into a side path. - name: Checkout version-picker metadata from main uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: diff --git a/.github/workflows/perform-release.yml b/.github/workflows/perform-release.yml index 3460b466cb..66182a29af 100644 --- a/.github/workflows/perform-release.yml +++ b/.github/workflows/perform-release.yml @@ -5,12 +5,12 @@ on: workflow_dispatch: inputs: source-branch: - description: 'Git ref to build from (e.g. `26.05`). When empty, RC versions like `26.05-RC8` build from `26.05`; otherwise uses the branch selected in "Run workflow".' + description: 'Git ref to build from (e.g. `26.08`). When empty, prerelease versions build from `26.08`; otherwise uses the branch selected in "Run workflow".' required: false type: string default: '' version: - description: 'Release version for artifacts and git tag (e.g. `26.05-RC8`). Does not need to exist before the run.' + description: 'Release version for artifacts and git tag (e.g. `26.08`). Does not need to exist before the run.' required: false type: string default: '' diff --git a/.github/workflows/release-helm.yml b/.github/workflows/release-helm.yml index a2201d8271..1751f0f149 100644 --- a/.github/workflows/release-helm.yml +++ b/.github/workflows/release-helm.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: version: - description: 'Chart version (e.g. 26.5.0)' + description: 'Chart version (e.g. 26.8.0)' required: true type: string source-ref: diff --git a/Dockerfile b/Dockerfile index 4c0165f630..6b7a412423 100644 --- a/Dockerfile +++ b/Dockerfile @@ -170,7 +170,7 @@ FROM install AS service # Optional release metadata for OpenAPI ``info.version`` and package version helpers. # Release builds should pass matching values, for example: -# --build-arg RETRIEVER_VERSION=26.08-RC4 --build-arg RETRIEVER_RELEASE_TYPE=release +# --build-arg RETRIEVER_VERSION=26.08 --build-arg RETRIEVER_RELEASE_TYPE=release ARG RETRIEVER_VERSION= ARG RETRIEVER_RELEASE_TYPE=dev ENV RETRIEVER_VERSION=${RETRIEVER_VERSION} diff --git a/README.md b/README.md index 6fe8b82e74..ae0469efea 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ SPDX-License-Identifier: Apache-2.0 **Important: The default branch is main, which tracks active development and may be ahead of the latest supported release.** -For the latest supported release, use the [26.05 branch](https://github.com/NVIDIA/NeMo-Retriever/tree/26.05) (GA PyPI and Helm chart version `26.5.0`). The previous stable line is [26.03](https://github.com/NVIDIA/NeMo-Retriever/tree/26.03). +For the latest supported release, use the [26.08 branch](https://github.com/NVIDIA/NeMo-Retriever/tree/26.08) (GA PyPI and Helm chart version `26.8.0`). The previous stable line is [26.03](https://github.com/NVIDIA/NeMo-Retriever/tree/26.03). See the corresponding [NeMo Retriever Library documentation](https://docs.nvidia.com/nemo/retriever/latest/extraction/overview/). diff --git a/docs/docs/extraction/releasenotes.md b/docs/docs/extraction/releasenotes.md index a493354435..5bc5ec629f 100644 --- a/docs/docs/extraction/releasenotes.md +++ b/docs/docs/extraction/releasenotes.md @@ -4,17 +4,17 @@ This documentation contains the release notes for [NeMo Retriever Library](overv ## 26.08 Release Notes (26.8.0) { #release-2608 } -NVIDIA® NeMo Retriever Library version 26.08 adds a shared text-generation task API, configurable large language model (LLM) settings, grounded answer-generation model paths, agentic retrieval, and updated Helm NIM defaults. It continues the 26.05 graph ingest, multimodal extraction, and Helm-first deployment foundation. +NVIDIA® NeMo Retriever Library version 26.08 adds a shared text-generation task API, configurable large language model (LLM) settings, grounded answer-generation model paths, agentic retrieval, and updated Helm NIM defaults. It builds on the graph ingest, multimodal extraction, and Helm-first deployment foundation. To upgrade the Helm charts for this release, refer to the [NeMo Retriever Library Helm Charts](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/helm/README.md). -The following sections summarize user-visible changes introduced in 26.08. Capabilities first documented in 26.05 that remain current are listed under [Continuing from 26.05](#continuing-from-2605). +The following sections summarize user-visible changes introduced in 26.08 and foundational capabilities that remain current. ### Upgrade notes { #upgrade-notes } -- Nemotron OCR v2 is now the default OCR engine for local Hugging Face, hosted CPU actors, and Helm NIM deployments. 26.05 kept Helm on OCR v1. The Helm default image is `nvcr.io/nim/nvidia/nemotron-ocr-v2:2.0.1`. +- Nemotron OCR v2 is now the default OCR engine for local Hugging Face, hosted CPU actors, and Helm NIM deployments. The previous release kept Helm on OCR v1. The Helm default image is `nvcr.io/nim/nvidia/nemotron-ocr-v2:2.0.1`. - Helm replaces separate page-elements and table-structure NIMs with the combined `nemotron-object-detection:2.0.1` image. Development Compose uses the same combined object-detection image and OCR v2, but still defaults to `2.0.0` tags unless you override `NIM_*_TAG`. -- Helm default VL embed and VL rerank NIM images bump to `2.3.0`. 26.05 used `1.12.0` and `1.11.0`. Development Compose still defaults to `1.12.0` and `1.11.0` unless you override `NIM_EMBED_TAG` and `NIM_RERANK_TAG`. +- Helm default VL embed and VL rerank NIM images bump to `2.3.0`. The previous release used `1.12.0` and `1.11.0`. Development Compose still defaults to `1.12.0` and `1.11.0` unless you override `NIM_EMBED_TAG` and `NIM_RERANK_TAG`. - Default VLM image captioning is Nemotron 3 Nano Omni for local and hosted paths. Chart-classified PDF regions remain on the layout and OCR path. - Hosted Nemotron Parse and self-hosted Nemotron Parse use distinct HTTP contracts. Select the matching client path for your endpoint. - macOS Intel (x86_64) is no longer supported for package installs. Use Apple Silicon (arm64) macOS, Windows x64, or Linux. Refer to [Packaging and platform](#packaging-and-platform). @@ -22,7 +22,7 @@ The following sections summarize user-visible changes introduced in 26.08. Capab - Self-hosted Parakeet on Helm requires both `nimOperator.audio.enabled=true` and `serviceConfig.nimEndpoints.audioGrpcEndpoint=audio:50051`. Enabling the audio NIM alone does not wire the service ASR endpoint. - Changing a Helm NIM image repository or tag on an existing release cannot patch `NIMCache` `spec.source.ngc.modelPuller`. Delete the `NIMCache` and its PVC, then upgrade. The affected NIM is unavailable while the operator re-caches weights. Refer to [Changing a NIM image repository or tag](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/helm/README.md#changing-nim-image-repository-or-tag). - A document whose VectorDB write is not acknowledged now fails instead of reporting `completed` with a positive row count. Earlier builds failed only collection-managed writes and logged a legacy fixed-table failure as a warning. The worker acknowledgement timeout is configurable through `serviceConfig.vectordb.writeTimeoutSeconds` (rendered as `vectordb.write_timeout_s`) and defaults to 300 seconds. Refer to [Ingest fails with a VectorDB write error](troubleshoot.md#vectordb-write-not-acknowledged). -- Retriever Service OpenAPI `info.version` no longer reports a stale `26.5.0` value. The service reports the package version, and Helm sets `RETRIEVER_SERVICE_VERSION` from the running service image tag so `/openapi.json` matches the deployed release. +- Retriever Service OpenAPI `info.version` no longer reports a stale package-version value. The service reports the package version, and Helm sets `RETRIEVER_SERVICE_VERSION` from the running service image tag so `/openapi.json` matches the deployed release. ### Text generation and LLM configuration { #text-generation-and-llm-configuration } @@ -109,7 +109,7 @@ The following sections summarize user-visible changes introduced in 26.08. Capab ### Packaging and platform { #packaging-and-platform } - Public nightlies are published to PyPI while local install extras remain stable. -- Ray is raised to `>=2.56.1` for CVE remediation. 26.05 used `>=2.49.0`. Ray no longer publishes wheels for macOS Intel (x86_64), so `pip` and `uv` installs fail on Intel Macs, including in-process library mode. Apple Silicon (arm64) macOS remains supported for slim remote or NIM-only installs, alongside Windows x64. +- Ray is raised to `>=2.56.1` for CVE remediation. The previous release used `>=2.49.0`. Ray no longer publishes wheels for macOS Intel (x86_64), so `pip` and `uv` installs fail on Intel Macs, including in-process library mode. Apple Silicon (arm64) macOS remains supported for slim remote or NIM-only installs, alongside Windows x64. ### Helm chart { #helm-chart } @@ -121,9 +121,9 @@ The following sections summarize user-visible changes introduced in 26.08. Capab - Published [One-shot text generation](nemo-retriever-api-reference.md#one-shot-text-generation) for `TextGenerationTask`, `GenericGenerationOperator`, `SummarizationOperator`, and `TextGenerationParams`. - Clarified Super-49B and Omni answer-generation paths on this page and in [Answer generation](prerequisites-support-matrix.md#answer-generation). For Helm enablement and slot overrides, refer to [Answer generation (operator-managed LLM)](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/helm/README.md#answer-generation-llm). -### Continuing from 26.05 { #continuing-from-2605 } +### Current foundational capabilities { #current-foundational-capabilities } -The following capabilities shipped in 26.05 and remain current in 26.08. They are not new 26.08 highlights. For the original 26.05 wording, refer to the [26.05 Release Notes](https://docs.nvidia.com/nemo/retriever/26.5.0/extraction/releasenotes-nv-ingest/). +The following foundational capabilities remain current. They are not new 26.08 highlights. - Text splitting for graph and library ingest uses `.extract(split_config=...)` instead of standalone `.split()` on the graph ingest path. The service ingestor API can still expose `.split()` separately. - Direct `Retriever(...)` construction uses `vdb_kwargs`, `embed_kwargs`, and `rerank` instead of flat `lancedb_uri`, `lancedb_table`, `embedder`, `embedding_endpoint`, `local_query_embed_backend`, and `reranker` arguments. @@ -150,7 +150,6 @@ The following capabilities shipped in 26.05 and remain current in 26.08. They ar ## Release Notes for Previous Versions { #previous-versions } -- [26.05](https://docs.nvidia.com/nemo/retriever/26.5.0/extraction/releasenotes-nv-ingest/) (GA on docs.nvidia.com at time of 26.08 RC) - [26.03](https://docs.nvidia.com/nemo/retriever/26.3.0/extraction/releasenotes-nv-ingest/) - [26.1.2](https://archive.docs.nvidia.com/nemo/retriever/26.1.2/extraction/releasenotes-nv-ingest/) - [26.1.1](https://archive.docs.nvidia.com/nemo/retriever/26.1.1/extraction/releasenotes-nv-ingest/) diff --git a/docs/publish/versions.json b/docs/publish/versions.json index 1135650ef6..e66f30c35b 100644 --- a/docs/publish/versions.json +++ b/docs/publish/versions.json @@ -1,7 +1,7 @@ [ { - "version": "26.5.0", - "title": "26.5.0", + "version": "26.8.0", + "title": "26.8.0", "aliases": ["latest"] }, { diff --git a/nemo_retriever/README.md b/nemo_retriever/README.md index 685effa08b..9ddf077b7b 100644 --- a/nemo_retriever/README.md +++ b/nemo_retriever/README.md @@ -55,7 +55,7 @@ try prerelease/nightly Nemotron packages from PyPI within the same supported major-version windows, opt in with `--pre`: ```bash -uv pip install --pre "nemo-retriever[local]==26.08-RC1" +uv pip install --pre "nemo-retriever[local]==26.08" ``` **Remote NIM (no local GPU)** diff --git a/nemo_retriever/docker.md b/nemo_retriever/docker.md index dc6cee0265..4badb8c47c 100644 --- a/nemo_retriever/docker.md +++ b/nemo_retriever/docker.md @@ -20,9 +20,9 @@ For a release-tagged image whose OpenAPI document should report a specific versi docker build \ -f Dockerfile \ --target service \ - --build-arg RETRIEVER_VERSION=26.08-RC4 \ + --build-arg RETRIEVER_VERSION=26.08 \ --build-arg RETRIEVER_RELEASE_TYPE=release \ - -t nemo-retriever-service:26.08-RC4 \ + -t nemo-retriever-service:26.08 \ . ``` diff --git a/nemo_retriever/harness/examples/managed-helm-nrl-26.05.yaml b/nemo_retriever/harness/examples/managed-helm-nrl-26.08.yaml similarity index 89% rename from nemo_retriever/harness/examples/managed-helm-nrl-26.05.yaml rename to nemo_retriever/harness/examples/managed-helm-nrl-26.08.yaml index 3d45207745..a33d7d20d3 100644 --- a/nemo_retriever/harness/examples/managed-helm-nrl-26.05.yaml +++ b/nemo_retriever/harness/examples/managed-helm-nrl-26.08.yaml @@ -1,4 +1,4 @@ -# Historical managed NRL Helm service configuration for the 26.05 perf sweep. +# Historical managed NRL Helm service configuration for the 26.08 perf sweep. # # This body preserves the retired nested harness schema for release reference; # it is not accepted by the current managed-Helm runner. For current runs, use @@ -11,9 +11,9 @@ # - ngc-api: opaque secret with the NGC API key entries required by the NIM operator # Keep credentials out of this file and out of command history. -# Use the official 26.5.0 NGC chart. The chart defaults to the matching -# nvcr.io/nvidia/nemo-microservices/nrl-service:26.5.0 service image. -x-nrl-chart-version: &nrl_chart_version "26.5.0" +# Use the official 26.8.0 NGC chart. The chart defaults to the matching +# nvcr.io/nvidia/nemo-microservices/nrl-service:26.8.0 service image. +x-nrl-chart-version: &nrl_chart_version "26.8.0" active: dataset: bo767 diff --git a/nemo_retriever/helm/Chart.yaml b/nemo_retriever/helm/Chart.yaml index 8f377aac81..d5843cec0c 100644 --- a/nemo_retriever/helm/Chart.yaml +++ b/nemo_retriever/helm/Chart.yaml @@ -18,8 +18,8 @@ description: | work and status history. type: application -version: "26.5.0" -appVersion: "26.5.0" +version: "26.8.0" +appVersion: "26.8.0" kubeVersion: ">=1.25.0-0" home: https://github.com/NVIDIA/NeMo-Retriever sources: diff --git a/nemo_retriever/helm/README.md b/nemo_retriever/helm/README.md index fa38b44cca..f192b99eac 100644 --- a/nemo_retriever/helm/README.md +++ b/nemo_retriever/helm/README.md @@ -324,7 +324,7 @@ If `helm install` already succeeded and NIM pods stay `Pending` on The chart defaults to the image published to NGC: ``` -nvcr.io/nvidia/nemo-microservices/nrl-service:26.5.0 +nvcr.io/nvidia/nemo-microservices/nrl-service:26.8.0 ``` Pulling from `nvcr.io` requires an NGC pull secret — either set @@ -567,7 +567,7 @@ short list of knobs you'll touch first. | Path | Default | Notes | |-------------------------------|------------------------------------|-------| | `service.image.repository` | `nvcr.io/nvidia/nemo-microservices/nrl-service` | NGC image; override to pin a different build or use a local registry. | -| `service.image.tag` | `26.5.0` | Also injected as `RETRIEVER_SERVICE_VERSION` so `/openapi.json` `info.version` matches the running image tag. | +| `service.image.tag` | `26.8.0` | Also injected as `RETRIEVER_SERVICE_VERSION` so `/openapi.json` `info.version` matches the running image tag. | | `service.replicas` | `1` | Keep at 1 because standalone job and scheduler state are process-local. | | `service.installFfmpeg` | `false` | Install `ffmpeg`/`ffprobe` at container startup by setting `INSTALL_FFMPEG=true`. Requires network egress, writable root filesystem, and sudo/setuid allowed. Not for air-gapped clusters — use a custom image instead. | diff --git a/nemo_retriever/helm/values.yaml b/nemo_retriever/helm/values.yaml index c678578e71..36eb7d5979 100644 --- a/nemo_retriever/helm/values.yaml +++ b/nemo_retriever/helm/values.yaml @@ -71,7 +71,7 @@ service: # docker build -f Dockerfile --target service \ # -t /nemo-retriever-service: . repository: nvcr.io/nvidia/nemo-microservices/nrl-service - tag: "26.5.0" + tag: "26.8.0" pullPolicy: IfNotPresent # Optional image for in-pod Hugging Face models (service-gpu Docker target). @@ -1041,7 +1041,7 @@ nimOperator: # --------------------------------------------------------------------------- # Two enablement tiers, matching the docs' "core vs optional" contract # (see docs/extraction/deployment-options.md "Core NIMs for the default - # extraction pipeline (26.05)"): + # extraction pipeline (26.08)"): # # Core (enabled: true by default, auto-wired into the service config): # - page_elements @@ -1065,11 +1065,11 @@ nimOperator: # * `nimOperator..enabled: true` — per-NIM toggle below. # # The optional NIMs sit behind their per-NIM toggles to honor the - # "optional and disabled by default" contract in 26.05 — turning them + # "optional and disabled by default" contract in 26.08 — turning them # on alongside the core stack at install time would silently pull tens # of gigabytes of model weights (Omni 30B ≈ 62 GiB BF16) and consume # an additional dedicated GPU per NIM with no opt-in from the operator. - # See helm/README.md "Recommended minimal install (26.05)" for the + # See helm/README.md "Recommended minimal install (26.08)" for the # opt-in flags and "Image tag conventions" for what the # ``1.7.0-variant`` Parse and ``2.0.4-variant`` Omni tags mean. # --------------------------------------------------------------------------- @@ -1390,7 +1390,7 @@ nimOperator: # Llama Nemotron rerank VL 1B v2 — multimodal reranking NIM. # - # Disabled by default per the 26.05 "optional and disabled by default" + # Disabled by default per the 26.08 "optional and disabled by default" # contract (see docs/extraction/deployment-options.md L21 and # docs/extraction/prerequisites-support-matrix.md L92 / L128). Opt in # only when the retrieval pipeline calls a reranker — enabling this NIM @@ -1402,7 +1402,7 @@ nimOperator: # `serviceConfig.nimEndpoints.rerankInvokeUrl` / # `rerankModelName` when pointing at an external ranking endpoint. # - # IMPORTANT — VL vs text-only: 26.05 documents the **VL** reranker + # IMPORTANT — VL vs text-only: 26.08 documents the **VL** reranker # (``llama-nemotron-rerank-vl-1b-v2``) as the supported NIM so the # ingest pipeline can score image + text passages together. The # text-only ``llama-nemotron-rerank-1b-v2`` is a different SKU that @@ -1454,14 +1454,14 @@ nimOperator: # Nemotron Parse v1.2. Optional structured document parser. # - # Disabled by default per the 26.05 "optional and disabled by default" + # Disabled by default per the 26.08 "optional and disabled by default" # contract (see docs/extraction/deployment-options.md). Opt in only when # the pipeline runs `extract_method="nemotron_parse"`; enabling this # NIM consumes one GPU and ~3.5 GiB of GPU memory at runtime, plus # ~16 GB of on-disk NIM model cache (see prerequisites-support-matrix). # # The default image tag (`1.7.0-variant`) is the Nemotron Parse v1.2 - # NIM SKU shipped alongside the 26.05 release; the `-variant` suffix + # NIM SKU shipped alongside the 26.08 release; the `-variant` suffix # marks it as the build that ships with the per-GPU TensorRT engine # variants required by NIM Operator profile reconciliation, matching # `nemotron-3-nano-omni-30b-a3b-reasoning:2.0.4-variant` and the row @@ -1515,7 +1515,7 @@ nimOperator: # Nemotron 3 Nano Omni 30B A3B Reasoning. Multimodal reasoning VLM # used by the image-captioning stage. # - # Disabled by default per the 26.05 "optional and disabled by default" + # Disabled by default per the 26.08 "optional and disabled by default" # contract (see docs/extraction/deployment-options.md). This is the # canonical caption NIM — once enabled the chart auto-wires # `nim_endpoints.caption_invoke_url` + `caption_model_name` into the @@ -1528,7 +1528,7 @@ nimOperator: # nimservice` if necessary). # # The default image tag (`2.0.4-variant`) is the Omni NIM SKU shipped - # alongside the 26.05 release; the `-variant` suffix marks it as the + # alongside the 26.08 release; the `-variant` suffix marks it as the # build that ships with the per-GPU TensorRT engine variants required # by NIM Operator profile reconciliation, matching the row for the # Omni caption NIM in diff --git a/nemo_retriever/src/nemo_retriever/service/client.py b/nemo_retriever/src/nemo_retriever/service/client.py index 86d84698d3..95666ef095 100644 --- a/nemo_retriever/src/nemo_retriever/service/client.py +++ b/nemo_retriever/src/nemo_retriever/service/client.py @@ -139,7 +139,7 @@ class RetrieverServiceCompatibilityError(RuntimeError): nrl-service is older than this SDK build. Raising a dedicated error type lets callers surface a single, actionable message instead of the previous silent "no document_complete event" - failure mode that 26.05-RC2 customers reported. + failure mode that 26.08 customers reported. """ @@ -168,9 +168,9 @@ def _compat_error_message( "This signals an SDK/service version mismatch: this Python " "SDK targets the job-scoped ingest API " "(POST /v1/ingest/job + POST /v1/ingest/job/{job_id}/document " - "+ GET /v1/ingest/job/{job_id}/events) introduced in 26.05, " + "+ GET /v1/ingest/job/{job_id}/events) introduced in 26.08, " "but the deployed nrl-service does not advertise that route. " - "Upgrade the chart/image to a 26.05+ build, or downgrade the " + "Upgrade the chart/image to a 26.08+ build, or downgrade the " "Python SDK to match the deployed service version. Server " f"response body: {body_clip}" ) @@ -643,7 +643,7 @@ async def _create_job( # A 404/410 here means the deployed service does not advertise # the job-scoped ingest API. Surface a dedicated compatibility # error instead of a generic HTTPStatusError so callers see one - # actionable message — see the 26.05-RC2 release-integration + # actionable message — see the 26.08 release-integration # regression report. if _is_api_mismatch_status(resp.status_code): raise RetrieverServiceCompatibilityError( diff --git a/nemo_retriever/src/nemo_retriever/service/retriever-service-nvidia-endpoints.yaml b/nemo_retriever/src/nemo_retriever/service/retriever-service-nvidia-endpoints.yaml new file mode 100644 index 0000000000..1b5ccc263e --- /dev/null +++ b/nemo_retriever/src/nemo_retriever/service/retriever-service-nvidia-endpoints.yaml @@ -0,0 +1,254 @@ +# Retriever Service Mode — NVIDIA Inference API MCP profile +# +# Discovery precedence: +# 1. Explicit --config /path/to/retriever-service.yaml +# 2. ./retriever-service.yaml (current working directory) +# 3. Bundled default shipped with the nemo-retriever package +# +# Every value below can also be overridden from the CLI: +# retriever service start --port 9000 --log-level DEBUG +# +# NVIDIA Inference API profile. Export NVIDIA_API_KEY before startup; +# load_config expands ${NVIDIA_API_KEY} in this file. This profile keeps the +# MCP transport mounted at /mcp and delegates extraction, embedding, and +# reranking to NVIDIA-hosted endpoints. + +# Runtime role: standalone | gateway | realtime | batch +# standalone — single pod with both worker pools (default) +# gateway — proxy that routes uploads to realtime/batch worker pods +# realtime — worker pod running only the realtime pool +# batch — worker pod running only the batch pool +mode: standalone + +server: + host: "0.0.0.0" + port: 7670 + +logging: + level: "INFO" + file: "retriever-service.log" + format: "%(asctime)s | %(levelname)s | %(name)s | %(message)s" + +# Remote NIM microservice endpoints. When set, the pipeline calls these +# HTTP endpoints instead of loading GPU models locally. +# +# Multiple endpoints per model: Provide a comma-separated list of URLs +# to spread load across replicas. +nim_endpoints: + page_elements_invoke_url: https://inference-api.nvidia.com/v1/ocr/nvidia/nvidia/nemotron-page-elements-v3/v1/page-elements + table_structure_invoke_url: null + ocr_invoke_url: https://inference-api.nvidia.com/v1/ocr/nvidia/nvidia/nemotron-ocr-v2-multilingual/v1/ocr + # Remote Nemotron Parse chat-completions endpoint and model. Both are + # server-owned; service clients select method="nemotron_parse" but cannot + # redirect the endpoint or change the deployed model. + nemotron_parse_invoke_url: null + nemotron_parse_model: null + embed_invoke_url: https://inference-api.nvidia.com/v1/embeddings + # Model name for the remote embed NIM (server-owned; must match the SKU). + embed_model_name: nvidia/nvidia/llama-nemotron-embed-vl-1b-v2 + # Optional LiteLLM provider prefix prepended to embed_model_name for + # proxies that require provider/model IDs. + embed_model_provider_prefix: null + # Optional remote reranker used by POST /v1/query with rerank=true. The + # endpoint can be an in-cluster NIM, a vLLM server, or another compatible + # ranking API. This service config does not deploy or manage that endpoint. + rerank_invoke_url: https://inference-api.nvidia.com/v1/rerank + # Optional server-owned model ID sent to the reranking endpoint. + rerank_model_name: nvidia/nvidia/llama-nemotron-rerank-vl-1b-v2 + # gRPC endpoint for the Parakeet ASR NIM (e.g. parakeet-nim:50051). + # When set, audio/video pipelines use remote ASR instead of loading + # the local Parakeet model (which requires torch + GPU). + audio_grpc_endpoint: null + # Remote VLM endpoint for the ``caption`` stage. When set, clients + # may submit caption_params overrides (prompt, system_prompt, + # batch_size, …). The endpoint URL, API key, and model name itself + # stay server-owned regardless of pipeline_overrides.mode. + caption_invoke_url: null + caption_model_name: null + api_key: "${NVIDIA_API_KEY}" + +# In-pod Hugging Face models (alternative to remote NIMs above). +# Requires nemo-retriever[local] (+ multimedia for audio) and GPU resources. +# NIM URLs always win when both are set for the same stage. +local_models: + enabled: false + hf_cache_dir: null + device: null + warmup_on_startup: false + max_tasks_per_child: null + # Each process-pool worker loads the full HF stack into GPU memory. + max_process_pool_workers: 1 + extract: + enabled: true + use_table_structure: true + ocr_version: v2 + ocr_lang: null + embed: + enabled: true + model_name: nvidia/llama-nemotron-embed-vl-1b-v2 + local_ingest_embed_backend: hf + gpu_memory_utilization: 0.45 + asr: + enabled: true + # Query-time reranking is loaded lazily in the main service process when a + # client sends ``rerank: true``. It is independent of ``local_models.enabled`` + # because it does not run in the ingestion process pools. Leave this disabled + # when using a remote/NIM reranker configured under ``nim_endpoints``. + rerank: + enabled: false + model_name: nvidia/llama-nemotron-rerank-1b-v2 + backend: vllm + gpu_memory_utilization: 0.5 + max_length: 512 + batch_size: 32 + +# Remote LLM endpoint used by POST /v1/answer. Helm auto-wires these +# fields when the Super-49B NIM is enabled. +llm: + enabled: false + model: "openai/nvidia/llama-3.3-nemotron-super-49b-v1.5" + api_base: null + api_key: null + temperature: 0.0 + top_p: null + max_tokens: 512 + extra_params: {} + num_retries: 3 + timeout: 180.0 + rag_system_prompt: null + rag_system_prompt_prefix: null + reasoning_enabled: true + +# Agentic (ReAct) retrieval exposed through POST /v1/query with agentic=true. +# The agentic_query MCP tool is registered when mcp.query_methods is agentic or all +# and agentic.enabled is true. Service mode requires a remote OpenAI-compatible +# invoke_url and llm_model when enabled. +agentic: + enabled: false + llm_model: null + invoke_url: null + reasoning_effort: high + backend_top_k: 20 + react_max_steps: 50 + text_truncation: 0 + temperature: 0.0 + request_timeout_s: 1800.0 + +# Pipeline worker pools. Workers are abstract dispatchers — sizing +# depends on whether they do local GPU work or fan out to remote NIMs. +# For CPU-only NIM-forwarding nodes, higher worker counts are fine. +# For in-pod HF models, local_models.max_process_pool_workers caps these. +pipeline: + realtime_workers: 8 + realtime_queue_size: 2048 + batch_workers: 16 + batch_queue_size: 4096 + +# Split-mode gateway pull scheduler. The gateway owns queue metadata and +# atomically spools upload bodies; worker execution slots long-poll it. +work_queue: + gateway_url: "http://nemo-retriever-gateway:7670" + spool_directory: "/tmp/nemo-retriever-work" + spool_limit_bytes: 21474836480 + claim_timeout_s: 30.0 + lease_ttl_s: 60.0 + heartbeat_interval_s: 20.0 + max_delivery_attempts: 3 + max_active_leases_realtime: 8 + max_active_leases_batch: 48 + +# Dedicated LanceDB pod used by standalone/gateway modes for /v1/query. +# Workers POST embedding rows to vectordb_url; the gateway proxies queries. +# Start that process with the same NVIDIA endpoint, for example: +# python -m nemo_retriever.service.vectordb_app \ +# --embed-endpoint https://inference-api.nvidia.com/v1/embeddings \ +# --embed-model nvidia/nvidia/llama-nemotron-embed-vl-1b-v2 \ +# --embed-api-key "" +vectordb: + enabled: true + lancedb_uri: "/data/vectordb" + table_name: "nemo_retriever" + embed_model: "nvidia/nvidia/llama-nemotron-embed-vl-1b-v2" + embed_model_provider_prefix: null + # /v1/query auto-detects retrieval from the table's own indexes: a table with + # both a vector column and an FTS/BM25 index runs hybrid, a vector-only table + # runs dense. The FTS index must be built at ingestion time; the service never + # mutates the table at query time. + vectordb_url: "http://nemo-retriever-vectordb:7671" + +resources: + max_memory_mb: null + max_cpu_cores: null + gpu_devices: [] + +# Gateway backend URLs (only used when mode: gateway). +# Defaults point at the Kubernetes Services created by the Helm chart +# when topology.mode is "split". +gateway: + realtime_url: "http://nemo-retriever-realtime:7670" + batch_url: "http://nemo-retriever-batch:7670" + timeout_s: 300.0 + max_connections: 100 + +# Optional bearer-token authentication. When api_token is set, every +# request must carry "Authorization: Bearer ". +auth: + api_token: null + header_name: "Authorization" + bypass_paths: + - "/v1/health" + - "/docs" + - "/openapi.json" + - "/redoc" + +# FastMCP agent integration. When enabled, retriever service start mounts +# the MCP HTTP transport at /mcp. The same tools are available over stdio +# through `retriever service mcp-stdio`. +mcp: + enabled: true + path: "/mcp" + # Defaults to loopback on server.port when null. + base_url: null + enable_write_tools: true + # Which retrieval tools to register: classic | agentic | all. + # Agentic tools are omitted when agentic.enabled is false. + query_methods: classic + max_concurrency: 8 + request_timeout_s: 60.0 + ingest_timeout_s: 1800.0 + poll_interval_s: 2.0 + +# Controls whether (and how widely) client-supplied PipelineSpec +# overrides are honored on a per-request basis. +# +# reject — every client override is rejected; YAML-only config. +# allow_list — only audited "shape" keys may be overridden +# (chunk sizes, batch sizes, output flags, …). +# Endpoint URLs and API keys are ALWAYS denied. +# allow_all — every key passes except the endpoint/api_key denylist. +# Convenient in dev clusters; UNSAFE in multi-tenant prod. +# +# The extra_*_keys lists let operators widen the allow_list with +# additional params keys without dropping to allow_all. +# +# The sinks: subsection gates client-driven egress (store / webhook / +# vdb_upload). Each list is empty by default which DISABLES that sink +# in service mode; populate them with URI schemes or URL prefixes to +# enable. Use "*" as a single wildcard entry to bypass enforcement +# (dev clusters only — never in multi-tenant production). +pipeline_overrides: + mode: allow_list + extra_extract_keys: [] + extra_embed_keys: [] + extra_dedup_keys: [] + extra_split_keys: [] + extra_store_keys: [] + extra_webhook_keys: [] + extra_vdb_upload_keys: [] + # extra_caption_keys only has effect when nim_endpoints.caption_invoke_url + # is set above — without an endpoint, the caption stage is rejected entirely. + extra_caption_keys: [] + sinks: + storage_uri_schemes: [] # e.g. ["s3://", "gs://", "azure://"] + webhook_url_prefixes: [] # e.g. ["https://hooks.example.com/"] + vdb_uri_schemes: [] # e.g. ["s3://", "gs://"] diff --git a/nemo_retriever/src/nemo_retriever/service/routers/ingest.py b/nemo_retriever/src/nemo_retriever/service/routers/ingest.py index 6ae535e87c..4cc2e4d6bc 100644 --- a/nemo_retriever/src/nemo_retriever/service/routers/ingest.py +++ b/nemo_retriever/src/nemo_retriever/service/routers/ingest.py @@ -2192,7 +2192,7 @@ async def job_callback(request: Request) -> JSONResponse: # ------------------------------------------------------------------ -_LEGACY_REMOVED_VERSION = "26.05" +_LEGACY_REMOVED_VERSION = "26.08" _LEGACY_INGEST_DETAIL = ( "POST /v1/ingest was removed in retriever-service " @@ -2223,7 +2223,7 @@ async def _legacy_ingest_upload_removed() -> None: Older SDK builds (pre-v2 client) upload through ``POST /v1/ingest``. Without this stub FastAPI returns a body-less 404 and the SDK surfaces "no documents completed" with no indication of why — the - customer-visible regression captured in the 26.05-RC2 release notes. + customer-visible regression captured in the 26.08 release notes. """ raise HTTPException(status_code=410, detail=_LEGACY_INGEST_DETAIL) diff --git a/nemo_retriever/tests/test_helm_caption_endpoint.py b/nemo_retriever/tests/test_helm_caption_endpoint.py index 9bfcffb7d4..31ec807986 100644 --- a/nemo_retriever/tests/test_helm_caption_endpoint.py +++ b/nemo_retriever/tests/test_helm_caption_endpoint.py @@ -4,7 +4,7 @@ """Regression tests for the Omni 30B caption-endpoint auto-wiring. -In 26.05 RC2 the chart could deploy the Nemotron 3 Nano Omni VLM as a +In 26.08 the chart could deploy the Nemotron 3 Nano Omni VLM as a NIMService, but the retriever-service ConfigMap rendered no ``caption_invoke_url`` / ``caption_model_name``. The downstream service deriving ``caption_enabled`` from diff --git a/nemo_retriever/tests/test_helm_nimcache_model_profile.py b/nemo_retriever/tests/test_helm_nimcache_model_profile.py index 70f7c69a08..c284d115d4 100644 --- a/nemo_retriever/tests/test_helm_nimcache_model_profile.py +++ b/nemo_retriever/tests/test_helm_nimcache_model_profile.py @@ -6,7 +6,7 @@ The NIM Operator's NIMCache CRD supports an optional ``spec.source.ngc.model`` block that restricts which model profiles a -cache job downloads (by GPU SKU or by profile UUID). Through 26.05 RC2 +cache job downloads (by GPU SKU or by profile UUID). Through 26.08 the chart's NIMCache templates omitted the field entirely and ``values.yaml`` exposed no corresponding knob — even ``--set nimOperator..gpus[0].ids[0]=26B5`` could not move the @@ -135,7 +135,7 @@ def _iter_nimcache_docs(rendered: str) -> list[dict]: class NimCacheModelProfileTests(TestCase): - """26.05 contract: every NIMCache exposes spec.source.ngc.model.""" + """26.08 contract: every NIMCache exposes spec.source.ngc.model.""" # ------------------------------------------------------------------ # values.yaml — source-level invariants diff --git a/nemo_retriever/tests/test_helm_optional_nims_disabled_by_default.py b/nemo_retriever/tests/test_helm_optional_nims_disabled_by_default.py index 3345d447a2..efe1f8e34b 100644 --- a/nemo_retriever/tests/test_helm_optional_nims_disabled_by_default.py +++ b/nemo_retriever/tests/test_helm_optional_nims_disabled_by_default.py @@ -2,12 +2,12 @@ # All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Regression tests for the 26.05 "optional and disabled by default" contract. +"""Regression tests for the 26.08 "optional and disabled by default" contract. -The 26.05 docs at ``docs/extraction/deployment-options.md`` mark the +The 26.08 docs at ``docs/extraction/deployment-options.md`` mark the **VL reranker** (``llama-nemotron-rerank-vl-1b-v2``), **Nemotron Parse**, and the **Nemotron 3 Nano Omni 30B** caption NIM as optional and not -auto-wired into the retriever-service. Through 26.05 RC2 the Helm +auto-wired into the retriever-service. Through 26.08 the Helm chart did the opposite — all three NIMs were ``enabled: true`` in ``values.yaml`` — so a plain ``helm install`` (matching the documented quick-start) silently pulled tens of GiB of model weights and claimed a @@ -30,7 +30,7 @@ ``--set nimOperator..enabled=true`` workflow keeps working. * The README and ``values.yaml`` document the ``1.7.0-variant`` tag used by Parse + Omni so air-gapped mirror pipelines and - reproducibility audits can map it to the 26.05 release. + reproducibility audits can map it to the 26.08 release. The integration tests shell out to ``helm template`` when ``helm`` is on ``$PATH``; otherwise they skip cleanly. @@ -68,7 +68,7 @@ _PARSE_SERVICE_NAME = "name: nemotron-parse" _OMNI_SERVICE_NAME = "name: nemotron-3-nano-omni-30b-a3b-reasoning" -# Image tags the chart pins for Parse and Omni in 26.05. Documenting it on +# Image tags the chart pins for Parse and Omni in 26.08. Documenting it on # both ends (values.yaml comments + README) keeps air-gapped mirror # pipelines pointed at the right NGC tag. _PARSE_VARIANT_TAG = "1.7.0-variant" @@ -76,7 +76,7 @@ # Repositories the rerank NIM may be pinned to. The chart MUST point at # the VL SKU — the text-only SKU silently degrades multimodal -# reranking, which is the bug surfaced in the 26.05 report. +# reranking, which is the bug surfaced in the 26.08 report. _RERANK_VL_REPOSITORY = "nvcr.io/nim/nvidia/llama-nemotron-rerank-vl-1b-v2" _RERANK_TEXT_REPOSITORY = "nvcr.io/nim/nvidia/llama-nemotron-rerank-1b-v2" @@ -146,7 +146,7 @@ def _assert_helm_ok(self: TestCase, proc: subprocess.CompletedProcess[str]) -> N class OptionalNimsDefaultDisabledTests(TestCase): - """26.05 contract: Parse and Omni are off until the user opts in.""" + """26.08 contract: Parse and Omni are off until the user opts in.""" # ------------------------------------------------------------------ # values.yaml — source-level invariants @@ -193,7 +193,7 @@ def test_values_omni_enabled_defaults_to_false(self) -> None: def test_values_rerankqa_enabled_defaults_to_false(self) -> None: """``nimOperator.rerankqa.enabled`` must default to ``false``. - Through 26.05 RC2 this defaulted to ``true``, so a plain + Through 26.08 this defaulted to ``true``, so a plain ``helm install`` provisioned an extra ≈ 3.1 GiB GPU NIM with no opt-in. The docs explicitly mark the VL reranker as optional and disabled by default (``docs/extraction/deployment-options.md`` @@ -215,7 +215,7 @@ def test_values_rerankqa_image_is_vl_sku(self) -> None: ``docs/extraction/prerequisites-support-matrix.md`` L92 / L128 documents ``llama-nemotron-rerank-vl-1b-v2`` as the supported - reranker NIM for 26.05. Through RC2 the chart shipped the + reranker NIM for 26.08. Through RC2 the chart shipped the text-only ``llama-nemotron-rerank-1b-v2`` — that SKU silently degrades multimodal reranking and is not the documented POR. """ @@ -235,7 +235,7 @@ def test_values_rerankqa_image_is_vl_sku(self) -> None: values, "values.yaml must not pin the text-only rerank SKU " f"`{_RERANK_TEXT_REPOSITORY}` — that silently degrades " - "multimodal reranking and contradicts the 26.05 docs. Use " + "multimodal reranking and contradicts the 26.08 docs. Use " "the VL build instead.", ) @@ -298,7 +298,7 @@ def test_readme_per_nim_table_reflects_new_defaults(self) -> None: self.assertRegex( readme, rf"`{path}`.*\|\s*`false`", - f"README per-NIM defaults table must show `{path}` defaulting " "to `false` after the 26.05 fix.", + f"README per-NIM defaults table must show `{path}` defaulting " "to `false` after the 26.08 fix.", ) def test_readme_image_table_pins_vl_rerank_sku(self) -> None: @@ -400,7 +400,7 @@ def test_readme_minimal_install_no_longer_disables_parse_or_omni(self) -> None: window, "Minimal-install recipe must not set " "`nimOperator.rerankqa.enabled=false` — that's the default " - "in 26.05 now and listing it implies the chart still " + "in 26.08 now and listing it implies the chart still " "provisions the VL reranker on a plain install.", ) @@ -429,14 +429,14 @@ def test_helm_template_default_render_omits_parse_and_omni(self) -> None: proc.stdout, "Default helm template render must not contain a " "`name: nemotron-parse` resource — Parse is optional and " - "disabled by default in 26.05.", + "disabled by default in 26.08.", ) self.assertNotIn( _OMNI_SERVICE_NAME, proc.stdout, "Default helm template render must not contain a " "`name: nemotron-3-nano-omni-30b-a3b-reasoning` resource — " - "Omni 30B is optional and disabled by default in 26.05.", + "Omni 30B is optional and disabled by default in 26.08.", ) # Caption auto-wiring must stay off too, otherwise the service # would call a non-existent NIM Service. @@ -464,7 +464,7 @@ def test_helm_template_default_render_omits_rerankqa(self) -> None: proc.stdout, "Default helm template render must not contain a " f"`{name}` resource — the VL reranker is optional and " - "disabled by default in 26.05 (the text-only SKU must " + "disabled by default in 26.08 (the text-only SKU must " "never appear at all).", ) @@ -546,7 +546,7 @@ def test_helm_template_rerankqa_opt_in_renders_vl_nimservice(self) -> None: f"{_RERANK_TEXT_REPOSITORY}:", proc.stdout, "Rendered manifest must not reference the text-only rerank " - "repository — that is the bug the 26.05 fix exists to " + "repository — that is the bug the 26.08 fix exists to " "prevent.", ) self.assertIn( diff --git a/nemo_retriever/tests/test_helm_rerank_endpoint.py b/nemo_retriever/tests/test_helm_rerank_endpoint.py index e0b00797d1..c5b9fe567e 100644 --- a/nemo_retriever/tests/test_helm_rerank_endpoint.py +++ b/nemo_retriever/tests/test_helm_rerank_endpoint.py @@ -4,7 +4,7 @@ """Regression tests for VL reranker endpoint auto-wiring. -In 26.08 RC2 the chart could deploy the VL reranker as a NIMService and +In 26.08 the chart could deploy the VL reranker as a NIMService and accept ``serviceConfig.nimEndpoints.rerankInvokeUrl`` / ``rerankModelName``, but ``templates/configmap.yaml`` never rendered ``nim_endpoints.rerank_invoke_url`` / ``rerank_model_name``. Split-mode diff --git a/nemo_retriever/tests/test_helm_service_openapi_version.py b/nemo_retriever/tests/test_helm_service_openapi_version.py index 386afcb295..190e419160 100644 --- a/nemo_retriever/tests/test_helm_service_openapi_version.py +++ b/nemo_retriever/tests/test_helm_service_openapi_version.py @@ -68,7 +68,7 @@ def test_standalone_injects_image_tag_as_service_version(self) -> None: "--set", "topology.mode=standalone", "--set", - "service.image.tag=26.08-RC4", + "service.image.tag=26.08", ) ) self.assertEqual( @@ -79,7 +79,7 @@ def test_standalone_injects_image_tag_as_service_version(self) -> None: docs = list(yaml.safe_load_all(proc.stdout)) containers = _nemo_retriever_containers(docs) self.assertEqual(len(containers), 1) - self.assertEqual(_env_value(containers[0], "RETRIEVER_SERVICE_VERSION"), "26.08-RC4") + self.assertEqual(_env_value(containers[0], "RETRIEVER_SERVICE_VERSION"), "26.08") def test_split_injects_image_tag_on_gateway_and_workers(self) -> None: proc = _helm_template( @@ -87,7 +87,7 @@ def test_split_injects_image_tag_on_gateway_and_workers(self) -> None: "--set", "topology.mode=split", "--set", - "service.image.tag=26.08-RC4", + "service.image.tag=26.08", ) ) self.assertEqual( @@ -99,7 +99,7 @@ def test_split_injects_image_tag_on_gateway_and_workers(self) -> None: containers = _nemo_retriever_containers(docs) self.assertGreaterEqual(len(containers), 2) for container in containers: - self.assertEqual(_env_value(container, "RETRIEVER_SERVICE_VERSION"), "26.08-RC4") + self.assertEqual(_env_value(container, "RETRIEVER_SERVICE_VERSION"), "26.08") if __name__ == "__main__": diff --git a/nemo_retriever/tests/test_pipeline_image_caption_concurrency.py b/nemo_retriever/tests/test_pipeline_image_caption_concurrency.py index 836704e114..303683efb6 100644 --- a/nemo_retriever/tests/test_pipeline_image_caption_concurrency.py +++ b/nemo_retriever/tests/test_pipeline_image_caption_concurrency.py @@ -4,7 +4,7 @@ """Regression tests pinning the ``image_caption`` stage's concurrency. -Customer-reported head-of-line block (26.05): +Customer-reported head-of-line block (26.08): Client A ingests a small text-only PDF (``--task=extract:{...}``, no caption work). On its own A finishes in ~0.45 s. diff --git a/nemo_retriever/tests/test_service_client_compat.py b/nemo_retriever/tests/test_service_client_compat.py index def7f057c0..2a02674592 100644 --- a/nemo_retriever/tests/test_service_client_compat.py +++ b/nemo_retriever/tests/test_service_client_compat.py @@ -4,7 +4,7 @@ """Regression tests for SDK/service version-mismatch handling. -These tests pin the customer-facing failure mode reported in 26.05-RC2: +These tests pin the customer-facing failure mode reported in 26.08: a Python SDK wheel whose ``RetrieverServiceClient`` targets the new job-scoped ingest API (``POST /v1/ingest/job`` + ``POST /v1/ingest/job/{job_id}/document`` + @@ -140,7 +140,7 @@ def test_compat_error_message_clips_long_body() -> None: def test_create_job_raises_compat_error_for_404_and_410(status: int) -> None: """The very first SDK call ⇒ clear compat error, not silent empty result. - Reproduces the 26.05-RC2 customer scenario: ``POST /v1/ingest/job`` + Reproduces the 26.08 customer scenario: ``POST /v1/ingest/job`` on a service image that does not advertise that route. Before this fix the client surfaced a generic ``httpx.HTTPStatusError`` (which callers often catch+log+continue), so the documented service-mode @@ -154,7 +154,7 @@ def _handler(request: httpx.Request) -> httpx.Response: if status == 410: return httpx.Response( 410, - json={"detail": "POST /v1/ingest was removed in 26.05"}, + json={"detail": "POST /v1/ingest was removed in 26.08"}, ) return httpx.Response(404) @@ -402,7 +402,7 @@ def test_upload_one_410_surfaces_replacement_routes(tmp_path: Path) -> None: def _handler(request: httpx.Request) -> httpx.Response: return httpx.Response( 410, - json={"detail": "POST /v1/ingest was removed in 26.05"}, + json={"detail": "POST /v1/ingest was removed in 26.08"}, ) rc = RetrieverServiceClient(base_url="http://nrl:7670") diff --git a/nemo_retriever/tests/test_service_ingestor_compat.py b/nemo_retriever/tests/test_service_ingestor_compat.py index 8c9cbf7896..8fde48bb4c 100644 --- a/nemo_retriever/tests/test_service_ingestor_compat.py +++ b/nemo_retriever/tests/test_service_ingestor_compat.py @@ -2,11 +2,11 @@ # All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""End-to-end regression test for the 26.05-RC2 version-mismatch bug. +"""End-to-end regression test for the 26.08 version-mismatch bug. The customer-reported failure mode: - The published 26.05-RC2 Python SDK calls legacy ``/v1/ingest`` / + The published 26.08 Python SDK calls legacy ``/v1/ingest`` / ``/v1/ingest/events`` routes against an nrl-service image that expects the newer job-scoped API. The documented service-mode flow appears to run but returns an empty result with no successful @@ -72,7 +72,7 @@ def _factory(*args, **kwargs): def test_service_ingestor_ingest_surfaces_compat_error_on_404(monkeypatch: pytest.MonkeyPatch, tmp_path) -> None: """Customer entry point: ``ServiceIngestor.ingest()`` must raise, not return empty. - This pins the exact end-to-end behavior that 26.05-RC2 customers + This pins the exact end-to-end behavior that 26.08 customers expected. Before the fix the documented flow produced an empty :class:`ServiceIngestResult` with ``len(result) == 0`` and no actionable error. After the fix: @@ -112,7 +112,7 @@ def _handler(request: httpx.Request) -> httpx.Response: def test_service_ingestor_ingest_surfaces_compat_error_on_410(monkeypatch: pytest.MonkeyPatch, tmp_path) -> None: """An explicit ``410 Gone`` from a new service raises the same error. - The mirror-image case: the SDK is the older 26.05-RC2 build, but + The mirror-image case: the SDK is the older 26.08 build, but the deployed service ships the 410 stub that explains the legacy route is gone. Our new SDK targets the new route, so the 410 is delivered to the new client too — and it must still produce the @@ -124,7 +124,7 @@ def _handler(request: httpx.Request) -> httpx.Response: return httpx.Response( 410, json={ - "detail": ("POST /v1/ingest was removed in retriever-service 26.05"), + "detail": ("POST /v1/ingest was removed in retriever-service 26.08"), }, ) diff --git a/nemo_retriever/tests/test_service_openapi_version.py b/nemo_retriever/tests/test_service_openapi_version.py index 7690bc42ce..2177093b13 100644 --- a/nemo_retriever/tests/test_service_openapi_version.py +++ b/nemo_retriever/tests/test_service_openapi_version.py @@ -21,17 +21,17 @@ def test_openapi_version_matches_service_api_version() -> None: schema = client.get("/openapi.json").json() assert schema["info"]["version"] == get_service_api_version() - assert schema["info"]["version"] != "26.5.0" + assert schema["info"]["version"] != "26.8.0" def test_openapi_version_respects_service_version_override( monkeypatch: pytest.MonkeyPatch, ) -> None: - monkeypatch.setenv("RETRIEVER_SERVICE_VERSION", "26.08-RC4") + monkeypatch.setenv("RETRIEVER_SERVICE_VERSION", "26.08") app = create_app(ServiceConfig(mode="gateway")) with TestClient(app) as client: schema = client.get("/openapi.json").json() - assert schema["info"]["version"] == "26.08-RC4" - assert get_service_api_version() == "26.08-RC4" + assert schema["info"]["version"] == "26.08" + assert get_service_api_version() == "26.08" diff --git a/nemo_retriever/tests/test_service_sse.py b/nemo_retriever/tests/test_service_sse.py index 1e017f7afd..2742c4e83c 100644 --- a/nemo_retriever/tests/test_service_sse.py +++ b/nemo_retriever/tests/test_service_sse.py @@ -124,7 +124,7 @@ def test_legacy_ingest_upload_route_returns_410_with_migration_body( Older SDK builds upload through this path. Without an explicit handler FastAPI returns a body-less 404 and the SDK surfaces an empty result — the customer-facing regression captured in the - 26.05-RC2 release-integration report. The 410 body must name the + 26.08 release-integration report. The 410 body must name the replacement pair (``/v1/ingest/job`` + ``/v1/ingest/job/{job_id}/document``). """ # Body is intentionally empty — the route should reject the request