pg-jev
PostgreSQL extension for semantic questions over table rows.
# jev — ask your Postgres tables questions in plain language
[](https://github.com/realZachi/pg-jev/actions/workflows/ci.yml)
[](https://pgxn.org/dist/jev/)
[](LICENSE)
[](https://pgjev.com)
Write the condition the way you would say it. Postgres does the rest.
`jev` lets you filter, rank and classify rows with plain-language conditions. Every row is judged by
[TypeSafe's Jev](https://docs.typesafe.ai), a System One model that returns calibrated probabilities
instead of generated text. No index, no embeddings, no vector column.
Website: [pgjev.com](https://pgjev.com)
```sql
CREATE EXTENSION jev CASCADE;
SELECT * FROM people WHERE jev(people, 'the name is European');
SELECT subject, jev_prob(tickets, 'the customer is angry') AS p
FROM tickets ORDER BY p DESC LIMIT 20;
SELECT jev_choice(tickets, 'which team should handle this?',
ARRAY['billing', 'technical', 'security', 'sales']) AS team, count(*)
FROM tickets GROUP BY 1;
SELECT name, jev_score(products, 'how luxurious is this product?',
ARRAY['budget', 'mid-range', 'premium', 'luxury']) AS luxury
FROM products ORDER BY luxury DESC;
```
`jev()` is an ordinary boolean function, so it composes with everything else in SQL: `AND age > 40`,
joins, `GROUP BY`, `LIMIT`, `ORDER BY jev_prob(...)`.
## How it works
1. `jev(table, 'condition')` receives the row as a composite value. The first call for a table + condition starts a
read-ahead that streams the table in physical order (TID range scans; `OFFSET` pages for views), so memory stays
constant whatever the table size.
2. Rows are packed `jev.batch_size` (20) per request into one shared *state*
(`{"condition": ..., "rows": [...]}`) with one yes/no [Noul](https://docs.typesafe.ai/primitives/noul)
question per row. Je