Solved: pgvector ≤2000-dim index limit with NeMo embeddings — use dimensions=1536 on llama-3.2-nv-embedqa-1b-v2

Context
While productionizing a RAG chatbot at SecuAI (Postgres + pgvector), our embedding vectors would not index with ANN.

Environment

  • Vector DB: PostgreSQL 16 + pgvector (HNSW / cosine)

  • API: NVIDIA NIM (OpenAI-compatible endpoint)

  • Models tried:

    • nvidia/llama-3.2-nemoretriever-300m-embed-v2 (2048D, fixed)

    • sentence-transformers/all-MiniLM-L6-v2 (384D)

    • Final: nvidia/llama-3.2-nv-embedqa-1b-v2 at 1536D (configurable)

Symptom
ERROR: column cannot have more than 2000 dimensions for ivfflat index
(also blocks HNSW with classic vector type when > 2000D)

Root cause
pgvector ANN indexes require ≤ 2000 dimensions for vector. The 300M retriever emits 2048D and (today) doesn’t support dynamic dimensions.

Fix
Switch to nvidia/llama-3.2-nv-embedqa-1b-v2 and request 1536D at inference.

Embed calls (OpenAI-compatible)

from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["NVIDIA_API_KEY"],
    base_url="https://integrate.api.nvidia.com/v1"
)

# Index time (documents/chunks)
idx = client.embeddings.create(
    model="nvidia/llama-3.2-nv-embedqa-1b-v2",
    input=["<doc chunk 1>", "<doc chunk 2>"],
    encoding_format="float",
    extra_body={"input_type": "passage", "truncate": "NONE", "dimensions": 1536}
)

# Query time
qry = client.embeddings.create(
    model="nvidia/llama-3.2-nv-embedqa-1b-v2",
    input=["What is SoD risk F005 in SAP?"],
    encoding_format="float",
    extra_body={"input_type": "query", "truncate": "NONE", "dimensions": 1536}
)

assert all(len(d.embedding) == 1536 for d in idx.data)
assert len(qry.data[0].embedding) == 1536

pgvector DDL

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE docs (
  id          bigserial PRIMARY KEY,
  source      text,
  chunk_id    int,
  text        text NOT NULL,
  embedding   vector(1536) NOT NULL,
  model_ver   text NOT NULL DEFAULT 'nv-embedqa-1b-v2/1536',
  created_at  timestamptz DEFAULT now()
);

CREATE INDEX docs_embedding_hnsw
  ON docs USING hnsw (embedding vector_cosine_ops);

Retrieval

-- $1: 1536-D query vector
SELECT id, source, chunk_id, text,
       1 - (embedding <#> $1) AS cosine_sim
FROM docs
ORDER BY embedding <#> $1
LIMIT 40;  -- then rerank to top 6–8

Results

  • ANN indexing works (no 2000D error)

  • Lower latency vs flat scan

  • Better relevance using input_type="passage" at index time, input_type="query" at query time

  • Optional reranker (e.g., llama-3.2-nv-rerankqa-1b-v2) improved precision without noticeable latency