realZachi/pg-jev
Ask your Postgres tables questions in plain language. A PostgreSQL extension powered by TypeSafe's Jev.
pg-jev — plain-language queries inside PostgreSQL
pg-jev is a PostgreSQL extension that lets you filter, rank, and classify rows in your tables using natural-language conditions, powered by an AI model called Jev (from TypeSafe). Instead of writing WHERE age > 40 AND country = 'France', you can write WHERE jev(people, 'the name is European').
What it does
It adds SQL functions that judge each row against a condition you write in plain English:
jev(row, 'condition')— returns true/false, usable inWHEREclausesjev_prob(row, 'condition')— returns a probability 0–1 that the row matchesjev_choice(row, 'question', options)— picks the most likely option from a list (e.g., which team should handle a ticket)jev_score(row, 'question', levels)— ranks a row on an ordered scale (e.g., how luxurious is this product)
Because these are ordinary SQL functions, they compose with everything else: joins, GROUP BY, ORDER BY, LIMIT, and other WHERE predicates.
How it works
- When you call
jev()on a table, the extension starts read-ahead: it streams the table in physical order, batching rows. - Rows are packed 20 per API request into a single shared state, with one yes/no question per row. The model evaluates all 20 questions in parallel, which amortizes the per-request overhead (~175 tokens per row in batches of 20 vs ~435 for a single row).
- Multiple requests run concurrently over persistent HTTPS connections. A
LIMITstops the read-ahead as soon as enough rows are answered, and cheaper predicates in the sameWHERErun first so rejected rows are never sent to the API. - Answers are cached per row content and question for the session, so re-running a query or sorting by probability is nearly free the second time.
Measured on a 2,000-row table: first run ≈ 3.5 s and ≈ $0.012 in API cost; second run ≈ 50 ms (cached); LIMIT 3 on a new condition ≈ 0.6 s.
Key design choices
- No index, no embeddings, no vector column — it's a full scan by design; every row the executor asks about goes to the API.
- Batch size of 20 is a deliberate accuracy trade-off: against ground-truth tests, batches of 1–20 rows were 100% correct, but batches of 40 dropped to 92–98% and batches of 80 to 77–94%.
- Calibrated probabilities, not generated text — the model returns a probability for each row, so ambiguous cases land near 0.5 and you can tune a threshold.
- Local-server support —
jev.api_urlcan point at a local Jev-compatible server, so rows never leave your network and there's no per-row billing.
Installation & requirements
Requires PostgreSQL 14–17 with plpython3u, a superuser, and a TypeSafe API key. Managed hosts that withhold superuser or plpython3u (Supabase, Neon, RDS) can't run it. Install via PGXN, from source, Docker, or an AI-agent skill that automates setup.
Caveats
- Row contents are sent to a third-party API (unless you run a local server) — don't use it on data you can't share.
- The answer cache lives per backend session and can grow with unique row/question pairs;
jev_cache_clear()resets it. plpython3uis an untrusted language, so functions run with the server's OS privileges.- Spend guards exist (
jev.max_rows_per_statement,jev.max_chars_per_statement) for shared deployments.
Bottom line
pg-jev is a practical, well-engineered bridge between natural language and SQL — useful when you want to filter or rank data by meaning (sentiment, category, tone) rather than by exact values, and you're willing to pay a small per-row API cost and accept a full scan.
Related
- Project
- Project
- Project
- Project
- Project