Evoke — Getting Started
Install Evoke (II-42/ii42) with Docker or package managers, create your first hybrid keyword-plus-semantic index, run your first ii42_query, and understand the async write path.
Getting Started with Evoke
Evoke ships as a Postgres extension named ii42. This page walks install → first index → first query → how the write path behaves in production.
Quick start: Docker (recommended)
The quickest start is the PostgreSQL 18 image. On a fresh data volume it creates the extension and enables the shared runtime:
docker pull ghcr.io/intelligent-internet/ii-42:pg18-v0.2.5
Start the container with the command from the README, then build an index and query it:
CREATE INDEX docs_semantic_idx ON docs USING ii42 (body) WITH (sae = true);
SELECT d.id, d.title,
ii42_query('docs_semantic_idx'::regclass, 'database search architecture') AS score
FROM docs AS d
ORDER BY score DESC
LIMIT 10;
BM25 is the default behavior; sae = true turns on Sparse Semantic Retrieval — the learned-sparse expansion terms that make meaning-aware matches possible. Launch semantic search only after you've confirmed keyword search behaves the way you expect; one toggle, one index.
Package installs (PG17/PG18)
Official packages for PostgreSQL 17 and 18 on Linux x86-64, with checksums, are on the v0.2.5 release page. Two notes that will save you an hour:
- Package installs load the extension through
shared_preload_librariesand require a PostgreSQL restart — don't skip the restart when the query function isn't found. - Existing databases follow a dedicated upgrade guide rather than treating Evoke like a plain extension bump.
Air-gapped installs are a design goal, not an afterthought:
The release includes a checksummed offline Docker archive built for deployments where text should not leave the server. Verify checksums at load time; treat unsigned copies of the image as a supply-chain risk, same as any model binary.Your first index: what happens on write
INSERT INTO docs (body, title) VALUES ('...long text...', 'A doc');
Three things occur, and only the first is on the critical path:
- Keyword evidence is stored and the write commits immediately. Your INSERT does not wait for the model.
- The row is queued for semantic encoding by shared background workers — every connection hands its work to the same workers instead of loading its own model copy.
- Background workers encode the row with ONNX Runtime on ordinary CPUs, then publish the expansion terms into the same inverted index, in a separate namespace from keyword terms.
This split is the difference between Evoke and an embedding pipeline: the meaning layer cannot stall your write path, and there is no separate sync job that can silently drift.
Read path: one lookup
Every ii42_query() call is a single lookup against the one index. Keyword and semantic evidence add to one score per document, and each returned row is checked against the table as it currently stands — a deleted document can't resurface from a stale copy. Index maintenance follows PostgreSQL's own rules for row visibility, crash recovery, and physical replication.
Practical query checklist:
- Exact identifiers still win. Product codes, case numbers, and error strings search as literal terms. If you only get keyword-quality results, confirm
sae = trueon the index. - Order by the returned score, not a mix — there is no second list to blend.
- Sketch how many rows you'll fetch. Evoke is a first-stage retriever; for production pipelines, feed the top ~1,000 to a reranker rather than showing the raw order to users.
Model notes
The model (~30M parameters, built on IBM's Granite-Embedding-30M-Sparse) is bundled with ONNX Runtime in the official packages and Docker image — nothing separate to download. Source builds pull it from Hugging Face. English text is what's evaluated today; test your own corpus before committing a non-English deployment.
Verify it works
Sanity checks after install:
-- 1. Does the extension load?
SELECT * FROM pg_extension WHERE extname = 'ii42';
-- 2. Did the semantic index build?
SELECT indexrelid::regclass FROM pg_index WHERE indexrelid = 'docs_semantic_idx'::regclass;
-- 3. Does semantic expansion fire? (requires docs containing paraphrase-style matches)
SELECT d.id, ii42_query('docs_semantic_idx'::regclass, 'different words, same point') AS score
FROM docs AS d ORDER BY score DESC LIMIT 5;
If step 3 returns scores comparable to a pure keyword query, sae is off or encoding workers haven't finished backfill — give the queue a moment and check logs.
Related
- Evoke overview — what it is and how it compares to pgvector stacks
- Use Cases — where this fits
- Exact vs Paraphrase Pattern — the one-index mechanism in depth
Related Articles & Guides
Evoke — Semantic Search Inside Postgres
Evoke (II-42 / ii42) is an open-source Postgres extension for learned-sparse retrieval: keyword and meaning evidence share one inverted index and one score. A 30M-parameter model runs on CPUs inside the database — no embedding pipeline, no vector index, no fusion step.
Evoke — Use Cases
Where Evoke's one-index, CPU-only, inside-Postgres retrieval fits: agent doc search, exact-code-or-plain-words lookups, air-gapped deployments, reranker handoff, async event logs, and MCP-backed knowledge retrieval — plus where it doesn't.
Evoke — The Exact-vs-Paraphrase Pattern
How Evoke scores keyword evidence and learned-sparse expansion terms in one inverted index — why exact matches keep leading, when paraphrases enter, and how to hand the result to a reranker.