Skip to content

Commit 9e26e17

Browse files
committed
Merge upstream/main into docs/ocr-v2-defaults
Resolve multimodal-extraction.md conflicts: keep chart pdfium-path callout from main and PR OCR v2 deployment breakdown.
2 parents 3132459 + 230e328 commit 9e26e17

153 files changed

Lines changed: 10735 additions & 9939 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/reusable-pypi-publish.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ jobs:
8484
DIST_FILES=(./dist/nemo_retriever/dist/*.whl ./dist/nemo_retriever/dist/*.tar.gz)
8585
echo "After legacy glob: count=${#DIST_FILES[@]} files=${DIST_FILES[*]:-<none>}"
8686
87-
# Flat layout (older upload-artifact glob uploads): ./dist/*
87+
# Flat layout (upload-artifact strips to the common parent, so wheels
88+
# often land directly under ./dist/): ./dist/*
8889
if [ "${#DIST_FILES[@]}" -eq 0 ]; then
8990
DIST_FILES=(./dist/*.whl ./dist/*.tar.gz)
9091
echo "After flat glob: count=${#DIST_FILES[@]} files=${DIST_FILES[*]:-<none>}"

Dockerfile

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# syntax=docker/dockerfile:1.3
55
#
66
# Build from repo root: docker build -f Dockerfile -t nemo-retriever .
7+
# Service (NIM-forwarding): docker build -f Dockerfile --target service -t nemo-retriever-service .
8+
# Service + in-pod HF: docker build -f Dockerfile --target service-gpu -t nemo-retriever-service-gpu .
79
# Runtime ffmpeg/ffprobe install for service image: docker run -e INSTALL_FFMPEG=true nemo-retriever-service
810
# Run: docker run nemo-retriever (shell with venv active)
911
# Run with dev mount: docker run -v $(pwd):/workspace -it nemo-retriever (code changes reflect without rebuild)
@@ -116,6 +118,22 @@ RUN --mount=type=cache,target=/root/.cache/pip \
116118
. /opt/retriever_runtime/bin/activate \
117119
&& uv pip install -e "./nemo_retriever[service]"
118120

121+
# GPU service install: in-pod Hugging Face models + multimedia (ASR, SVG).
122+
# Build target: service-gpu
123+
FROM base AS install-service-gpu
124+
125+
WORKDIR /workspace
126+
127+
ENV PYTHONUNBUFFERED=1
128+
ENV VIRTUAL_ENV=/opt/retriever_runtime
129+
ENV PATH=/opt/retriever_runtime/bin:$PATH
130+
131+
SHELL ["/bin/bash", "-c"]
132+
RUN --mount=type=cache,target=/root/.cache/pip \
133+
--mount=type=cache,target=/root/.cache/uv \
134+
. /opt/retriever_runtime/bin/activate \
135+
&& uv pip install -e "./nemo_retriever[service,local,multimedia]"
136+
119137
# Default: run in-process pipeline (help if no args)
120138
CMD ["/bin/bash"]
121139

@@ -167,3 +185,45 @@ USER nemo
167185
ENTRYPOINT ["/usr/local/bin/retriever-service-entrypoint"]
168186

169187
CMD ["retriever", "service", "start", "--config", "/etc/nemo-retriever/retriever-service.yaml"]
188+
189+
# ---------------------------------------------------------------------------
190+
# GPU service profile: FastAPI ingest service with in-pod Hugging Face models.
191+
#
192+
# Build: docker build -f Dockerfile --target service-gpu \
193+
# -t nemo-retriever-service-gpu .
194+
#
195+
# Run (requires --gpus all and local_models.enabled in config):
196+
# docker run --rm --gpus all -p 7670:7670 \
197+
# -v /host/retriever-service.yaml:/etc/nemo-retriever/retriever-service.yaml:ro \
198+
# nemo-retriever-service-gpu
199+
# ---------------------------------------------------------------------------
200+
FROM install-service-gpu AS service-gpu
201+
202+
ENV NEMO_RETRIEVER_SERVICE_CONFIG=/etc/nemo-retriever/retriever-service.yaml
203+
204+
ENV PATH=/opt/retriever_runtime/bin:$PATH
205+
206+
COPY docker/scripts/retriever_service_entrypoint.sh /usr/local/bin/retriever-service-entrypoint
207+
COPY docker/scripts/retriever_install_ffmpeg.sh /usr/local/sbin/retriever-install-ffmpeg
208+
209+
RUN chmod a+rx /usr/local/bin/uv /usr/local/bin/uvx /usr/local/bin/retriever-service-entrypoint \
210+
/usr/local/sbin/retriever-install-ffmpeg \
211+
&& chmod -R a+rX /opt/uv \
212+
&& groupadd -r -g 1000 nemo && useradd -r -u 1000 -g nemo -d /workspace -s /sbin/nologin nemo \
213+
&& printf '%s\n' \
214+
'nemo ALL=(root) NOPASSWD: /usr/local/sbin/retriever-install-ffmpeg' \
215+
> /etc/sudoers.d/nemo-ffmpeg \
216+
&& chmod 0440 /etc/sudoers.d/nemo-ffmpeg \
217+
&& visudo -cf /etc/sudoers.d/nemo-ffmpeg \
218+
&& mkdir -p /etc/nemo-retriever /var/lib/nemo-retriever \
219+
&& cp /workspace/nemo_retriever/src/nemo_retriever/service/retriever-service.yaml \
220+
"${NEMO_RETRIEVER_SERVICE_CONFIG}" \
221+
&& chown -R nemo:nemo /workspace /etc/nemo-retriever /var/lib/nemo-retriever /opt/retriever_runtime
222+
223+
EXPOSE 7670
224+
225+
USER nemo
226+
227+
ENTRYPOINT ["/usr/local/bin/retriever-service-entrypoint"]
228+
229+
CMD ["retriever", "service", "start", "--config", "/etc/nemo-retriever/retriever-service.yaml"]

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ For small-scale workloads, such as workloads of fewer than 100 PDFs, you can use
3636
After [following the quickstart installation steps](nemo_retriever), you can start ingesting content like with the following snippet:
3737
```python
3838
from nemo_retriever import create_ingestor
39-
from nemo_retriever.io import to_markdown, to_markdown_by_page
39+
from nemo_retriever.common.io import to_markdown, to_markdown_by_page
4040
from pathlib import Path
4141

42-
documents = [str(Path("../data/multimodal_test.pdf"))]
42+
documents = [str(Path("data/multimodal_test.pdf"))]
4343
ingestor = create_ingestor(run_mode="batch")
4444

4545
# ingestion tasks are chainable and defined lazily
@@ -93,7 +93,7 @@ dict_keys([1, 2, 3])
9393
To query for relevant snippets of the ingested content, and use them with an LLM to generate answers, use the following code.
9494

9595
```python
96-
from nemo_retriever.retriever import Retriever
96+
from nemo_retriever.graph.retriever import Retriever
9797
from openai import OpenAI
9898
import os
9999

docs/docs/extraction/audio-video.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ Instead of running the pipeline locally, you can call Parakeet through [build.nv
100100

101101
2. Run inference from Python with the hosted gRPC endpoint and credentials from that page (the example below uses the default hosted gRPC hostname; confirm values in the **Get API Key** flow for your deployment). Pass hosted endpoint, function ID, and API key through `ASRParams` (`audio_endpoints`, `function_id`, `auth_token`).
102102

103+
For parameter details, refer to the [Python API guide](nemo-retriever-api-reference.md).
104+
103105
```python
104106
from nemo_retriever import create_ingestor
105107
from nemo_retriever.common.params.models import ASRParams

docs/docs/extraction/concepts.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,40 @@
22

33
These terms appear throughout NeMo Retriever Library documentation.
44

5-
## Job
5+
## Job { #job }
66

7-
An **ingestion job** is a unit of work you run on input content (documents, audio, video, and other supported types). You submit jobs through the **ingestor Python API** (for example `Ingestor` task chains such as `.extract(...)`) or the **`retriever ingest` CLI**—not by posting a standalone JSON job document. Default tasks target strong recall; customize behavior with task keyword arguments (including chunking and splitting on `.extract()`) or custom UDF-style operations ([NeMo Retriever graph](https://github.com/NVIDIA/NeMo-Retriever/tree/main/nemo_retriever/src/nemo_retriever/graph#nemo-retriever-graph)). Results are structured metadata and annotations (Ray Dataset, pandas `DataFrame`, or similar).
7+
An **ingestion job** is a unit of work you run on input content (documents, audio, video, and other supported types). You submit jobs through the **ingestor Python API** (for example `Ingestor` task chains such as `.extract(...)`) or the **`retriever ingest` CLI**—not by posting a standalone JSON job document. Default tasks target strong recall; customize behavior with task keyword arguments (including chunking and splitting on `.extract()`) or custom UDF-style operations. For UDFs and other extension paths, refer to [Customize & extend](customize-extend.md). Results are structured metadata and annotations (Ray Dataset, pandas `DataFrame`, or similar).
88

9-
## Pipeline and tasks
9+
## Pipeline and tasks { #pipeline-and-tasks }
1010

11-
NeMo Retriever Library does **not** run one static pipeline on every document. You configure **tasks** such as parsing, chunking, embedding, storage, and filtering per job. Related topics: [Extending/Customizing NeMo Retriever Library with custom code](https://github.com/NVIDIA/NeMo-Retriever/tree/main/nemo_retriever/src/nemo_retriever/graph#nemo-retriever-graph).
11+
NeMo Retriever Library does **not** run one static pipeline on every document. You configure **tasks** such as parsing, chunking, embedding, storage, and filtering per job. For UDFs, custom graph stages, and other extension paths, refer to [Customize & extend](customize-extend.md).
1212

13-
## Extraction metadata
13+
## Extraction metadata { #extraction-metadata }
1414

1515
Output is a **Ray Dataset** (Ray Data) or **pandas** `DataFrame` listing extracted objects (text regions, tables, images, and so on), processing notes, and timing or trace data. Field-level detail is in the [metadata reference](content-metadata.md).
1616

17-
## Embeddings and retrieval
17+
## Embeddings and retrieval { #embeddings-and-retrieval }
1818

19-
Optionally, the library can compute **embeddings** for extracted content and store vectors in [LanceDB](https://lancedb.com/) for downstream semantic search in your application. For upload and retrieval APIs, see [Vector databases](vdbs.md). For multimodal (VLM) embedding options, see [Multimodal embeddings (VLM)](embedding.md).
19+
Optionally, the library can compute **embeddings** for extracted content and store vectors in [LanceDB](https://lancedb.com/) for downstream semantic search in your application. For upload and retrieval APIs, refer to [Vector databases](vdbs.md). For multimodal (VLM) embedding options, refer to [Multimodal embeddings (VLM)](embedding.md).
2020

2121
## Chunking { #chunking }
2222

2323
Chunking is built into the `.extract()` task and depends on **content type**:
2424

2525
- **PDF, DOCX, and PPTX** — Text is grouped using built-in **page** boundaries (one chunk per page where the format has pages).
26-
- **Plain text (`.txt`) and HTML** — Formats without natural page breaks are split into segments of **1024 tokens** by default, using the [Llama 3.2 1B tokenizer](https://huggingface.co/meta-llama/Llama-3.2-1B) so chunk boundaries stay aligned with the default embedding tokenizer. The NeMo Retriever container image bundles this tokenizer, so default text chunking does not require a Hugging Face access token. See [Token-based splitting](#token-based-splitting) and [Environment variables](environment-config.md) for overrides and other runtimes.
27-
- **Audio and video** — Media is split into **segments** for decoding and ASR using ffmpeg-based rules (configurable **size**, **time**, or **frame** split modes in the media chunking stage). With the Parakeet ASR path, you can optionally emit **sentence-like segments** using `extract_audio_params={"segment_audio": True}`; see [Speech and audio extraction](audio-video.md#speech-and-audio-extraction).
26+
- **Plain text (`.txt`) and HTML** — Formats without natural page breaks are split into segments of **1024 tokens** by default, using the [Llama 3.2 1B tokenizer](https://huggingface.co/meta-llama/Llama-3.2-1B) so chunk boundaries stay aligned with the default embedding tokenizer. The NeMo Retriever container image bundles this tokenizer, so default text chunking does not require a Hugging Face access token. Refer to [Token-based splitting](#token-based-splitting) and [Environment variables](environment-config.md) for overrides and other runtimes.
27+
- **Audio and video** — Media is split into **segments** for decoding and ASR using ffmpeg-based rules (configurable **size**, **time**, or **frame** split modes in the media chunking stage). With the Parakeet ASR path, you can optionally emit **sentence-like segments** using `extract_audio_params={"segment_audio": True}`; refer to [Speech and audio extraction](audio-video.md#speech-and-audio-extraction).
2828

29-
For PDF parallelism before Ray processing (large files), see [PDF pre-splitting for parallel ingest](nemo-retriever-api-reference.md#pdf-pre-splitting-for-parallel-ingest).
29+
For PDF parallelism before Ray processing (large files), refer to [PDF pre-splitting for parallel ingest](nemo-retriever-api-reference.md#pdf-pre-splitting-for-parallel-ingest).
3030

3131
### Token-based splitting { #token-based-splitting }
3232

33-
Token-based splitting uses the Llama 3.2 1B tokenizer (default `meta-llama/Llama-3.2-1B`) with configurable `max_tokens` and `overlap_tokens` when you add an explicit `.split(...)` stage or when the pipeline applies the default text segmentation for unstructured text. In the shipped NeMo Retriever container, tokenizer assets are included locally, so you do not need `HF_ACCESS_TOKEN` for this default path. If your runtime loads the tokenizer from the Hugging Face Hub instead (for example, some library-only installs), set `HF_ACCESS_TOKEN` or pass `hf_access_token` in task params when the Hub requires it. Details appear in the [Python API guide](nemo-retriever-api-reference.md).
33+
Token-based splitting uses the Llama 3.2 1B tokenizer (default `meta-llama/Llama-3.2-1B`) with configurable `max_tokens` and `overlap_tokens` when you add an explicit `.split(...)` stage or when the pipeline applies the default text segmentation for unstructured text. In the shipped NeMo Retriever container, tokenizer assets are included locally, so you do not need `HF_ACCESS_TOKEN` for this default path. If your runtime loads the tokenizer from the Hugging Face Hub instead (for example, some library-only installs), set `HF_ACCESS_TOKEN` or pass `hf_access_token` in task params when the Hub requires it. For parameter details, refer to the [Python API guide](nemo-retriever-api-reference.md).
3434

35-
## Deployment modes
35+
## Deployment modes { #deployment-modes }
3636

37-
- **Library mode** — Run without the full container stack where appropriate; see [Deployment options](deployment-options.md).
38-
- **Kubernetes / Helm (self-hosted)**See [Deploy (Helm chart)](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/helm/README.md) and [deployment options](deployment-options.md) for running the full microservices pipeline on your infrastructure.
37+
- **Library mode** — Run without the full container stack where appropriate; refer to [Deployment options](deployment-options.md).
38+
- **Kubernetes / Helm (self-hosted)**Refer to [Deploy (Helm chart)](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/helm/README.md) and [deployment options](deployment-options.md) for running the full microservices pipeline on your infrastructure.
3939
- **Notebooks**[Jupyter examples](starter-kits.md) for experimentation and RAG demos.
4040

4141
For a concise comparison, refer to [Deployment options](deployment-options.md).
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Customize & extend
2+
3+
NeMo Retriever Library ships with defaults tuned for strong recall on common document types. When those defaults are not enough, you can extend the library at several levels—from task keyword arguments on the fluent ingestor API through custom graph operators and vector-database adapters.
4+
5+
Use this page to choose an extension path and find the detailed guides in the repository.
6+
7+
The following table maps common needs to the right section:
8+
9+
| If you need to… | Start here |
10+
|-----------------|------------|
11+
| Tune extraction, chunking, embedding, or upload without new code | [Start with task configuration](#start-with-task-configuration) |
12+
| Add a small Python transformation between pipeline stages | [User-defined functions (UDFs)](#user-defined-functions-udfs) |
13+
| Build or reuse operators stage-by-stage | [Custom graph pipelines](#custom-graph-pipelines) |
14+
| Store vectors in a backend other than LanceDB | [Custom vector databases](#custom-vector-databases) |
15+
16+
## On this page { #on-this-page }
17+
18+
- [Start with task configuration](#start-with-task-configuration)
19+
- [User-defined functions (UDFs)](#user-defined-functions-udfs)
20+
- [Custom graph pipelines](#custom-graph-pipelines)
21+
- [Custom vector databases](#custom-vector-databases)
22+
- [Related Topics](#related-topics)
23+
24+
## Start with task configuration { #start-with-task-configuration }
25+
26+
Most customization does not require new code. Chain tasks on `create_ingestor(...)` and pass keyword arguments to control extraction, chunking, embedding, and storage—for example `extract_method`, chunking and splitting options on `.extract()`, `embed_modality` on `.embed()`, and `vdb_op` / `vdb_kwargs` on `.vdb_upload()`.
27+
28+
For parameter details, refer to the [Python API guide](nemo-retriever-api-reference.md). For chunking behavior and pipeline concepts, refer to [Concepts](concepts.md).
29+
30+
## User-defined functions (UDFs) { #user-defined-functions-udfs }
31+
32+
A **user-defined function (UDF)** wraps your Python logic as a first-class pipeline stage. In the graph model, `UDFOperator` turns a plain callable into an operator you can chain with built-in stages—for example to normalize HTML, apply a custom split, or call an external service between extract and embed steps.
33+
34+
Use UDFs when you need a small, self-contained transformation that is not covered by task keyword arguments.
35+
36+
### Repository guides
37+
38+
- [NeMo Retriever graph README — `UDFOperator`](https://github.com/NVIDIA/NeMo-Retriever/tree/main/nemo_retriever/src/nemo_retriever/graph#using-udfoperator) — API, lifecycle, and when to use `UDFOperator` versus a custom operator class
39+
- [NimClient and custom NIM endpoints](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/developer_docs/nimclient.md#nimclient-and-custom-nim-endpoints) — call custom or self-hosted NIM microservices from UDF stages
40+
41+
## Custom graph pipelines { #custom-graph-pipelines }
42+
43+
When you need to compose pipelines stage-by-stage, reuse operators across workflows, or run the same graph in-process or with Ray Data, use the **graph execution model** instead of (or alongside) the fluent `GraphIngestor` API.
44+
45+
The graph package provides `AbstractOperator`, executors (`InprocessExecutor`, `RayDataExecutor`), and operator chaining with `>>`. Built-in ingestion operators live under `nemo_retriever.operators`; you can add your own operators or UDF stages anywhere in the chain.
46+
47+
For the full guide—including custom operator classes, executors, and graph shape constraints—refer to the [NeMo Retriever graph README](https://github.com/NVIDIA/NeMo-Retriever/tree/main/nemo_retriever/src/nemo_retriever/graph#nemo-retriever-graph).
48+
49+
## Custom vector databases { #custom-vector-databases }
50+
51+
The supported user path for vector storage is **[LanceDB](vdbs.md)** (`vdb_op="lancedb"`). That page covers upload, semantic retrieval, metadata filtering, and LanceDB deployment characteristics.
52+
53+
To integrate a different vector store, implement the [`VDB`](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/src/nemo_retriever/common/vdb/adt_vdb.py) interface and wire it through graph [`IngestVdbOperator`](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/src/nemo_retriever/operators/vdb.py) / [`RetrieveVdbOperator`](https://github.com/NVIDIA/NeMo-Retriever/blob/main/nemo_retriever/src/nemo_retriever/operators/vdb.py). NVIDIA validates the first-party LanceDB operator; you are responsible for testing and maintaining other backends.
54+
55+
### Repository guides
56+
57+
- [Vector DB package (source)](https://github.com/NVIDIA/NeMo-Retriever/tree/main/nemo_retriever/src/nemo_retriever/common/vdb)`VDB` abstract base and LanceDB reference implementation
58+
59+
Partner and blueprint integrations (Elasticsearch, Pinecone, Teradata, and others) are summarized on [Vector databases — Vector database partners](vdbs.md#vector-database-partners).
60+
61+
## Related Topics { #related-topics }
62+
63+
- [Concepts — Pipeline and tasks](concepts.md#pipeline-and-tasks)
64+
- [Vector databases](vdbs.md)
65+
- [Multimodal embeddings (VLM)](embedding.md)
66+
- [Python API guide](nemo-retriever-api-reference.md)

0 commit comments

Comments
 (0)