Skip to content

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

34 Commits

Folders and files

Repository files navigation

Jev recipes for Qdrant

Small, tested recipes that use Jev (TypeSafe's System One decision model, reached through OpenRouter) next to a Qdrant collection. Jev answers many yes/no and pick-one questions about a piece of text in one cheap request (about $0.00002 each, cached on disk), so each recipe is "ask Jev a batch of questions, then apply a plain function to the probabilities".

Recipe Use it to Code
Query understanding Turn a query into classes and facets, then filter or boost the search jevqu/
Rerank / prune Re-order and de-duplicate the top results of any search recipes/prune/
Semantic chunker Split documents at topic changes before embedding recipes/chunker/

The recipes share the Jev client (jevqu/jev.py) and nothing else, so you can take one without the others.

Install

uv sync --extra dev                       # core + tests
uv sync --extra chunk                     # chunker baselines and QASPER loader (chonkie, pyarrow)
uv sync --extra eval --extra notebook     # STaRK evaluation, notebooks
export OPENROUTER_API_KEY=...             # the code reads the environment, not .env

Query understanding (jevqu)

Induce a taxonomy from your collection alone (no queries or relevance labels), label every point with it, and understand each query against it.

from qdrant_client import QdrantClient
from jevqu.jev import Jev
from jevqu.api import (create_query_understanding, set_query_understanding,
                       upload_points, understand_query, query_points)

client, jev = QdrantClient(...), Jev()

tax, report = create_query_understanding(client, "products", jev, sample=2000, embed=embed)  # induce
set_query_understanding(client, "products", tax)                                             # store + index
upload_points(client, "products", new_points, jev)                                           # label on ingest
hits = query_points(client, "products", "waterproof hiking boots", jev,
                    dense=embed(["waterproof hiking boots"])[0], sparse=sparse_vec,
                    understanding="auto", limit=10)                                          # search

understanding is auto, filter, boost or off. understand_query returns the matched classes and facets without searching. The taxonomy is stored in the collection (_query_understanding).

create_query_understanding(..., llm=LLM()) (from jevqu.llm) lets a chat model write the class names and Jev validate them. It is a baseline; the default path needs no chat model.

Evaluation: scripts/build_stark_collection.py and scripts/run_eval.py (STaRK-Amazon recall-loss curve). Demos: notebooks/.

Rerank / prune

One Jev request per query reads the top 20 results and answers, per result, "is it relevant?" and "is it a near-duplicate of a higher-ranked result?". Thresholds apply afterwards, so one set of requests serves any sweep.

from recipes.prune.prune import relevance, judge, prune

rel = relevance(jev, query, texts)                      # rerank: sort the top 20 by this
rel, dup = judge(jev, query, texts)                     # or also get duplicate probabilities
ids, backfilled = prune(ids, rel, dup, rel_min=0.5, dup_max=0.5, keep=10)

Measured on WANDS (240 held-out queries): sorting the hybrid top 20 by Jev's relevance gives nDCG@10 +0.086 over hybrid and cuts irrelevant results in the top 10 from 102 to 38. It beats MiniLM-L-6 by +0.022 and bge-reranker-base by +0.039, but it is not faster than local cross-encoders. The notebook (recipes/prune/prune.ipynb) also covers variety (MMR with Jev relevance as the relevance term) and sweeps the thresholds.

Measured on NFCorpus (100 test queries, BGE-small top 50, nDCG@10 lift over BGE-small): Jev Score +0.074, Jev Choice +0.067, and Jev Iterative Choice +0.079, against +0.026 for ms-marco-MiniLM-L-6-v2 and -0.013 for bge-reranker-base. Iterative Choice sends one request per ranking position and took about five times as long as Score. See notebooks/jev_reranking_nfcorpus.ipynb, a Colab notebook; the cross-encoder rows come from a separate CPU run of the same code, as the notebook explains.

Semantic chunker

Jev reads windows of numbered sentences and judges, per gap, whether the next sentence starts a new topic. Cutting is a pure function of those probabilities, so one set of requests serves every threshold and size bound.

from recipes.chunker.chunker import sentences, gap_probs, cut, chunks

spans = sentences(text)
probs = gap_probs([text[a:b] for a, b in spans], jev)
starts = cut(probs, sizes=[b - a for a, b in spans], threshold=0.5, min_size=200, max_size=800)
pieces = chunks(text, spans, starts)                    # exact slices of `text`

Measured on the QASPER test split (407 papers, 1,297 questions written by researchers, with the answer paragraphs marked by other researchers), retrieving 5 chunks per question from Qdrant at matched mean chunk size: against fixed-size, recursive and chonkie semantic chunking, recall +0.03 to +0.06, precision 8 to 14% higher and IoU 8 to 18% higher, every 95% interval above zero. The smallest gain is against a recursive splitter that breaks on paragraph boundaries. See recipes/chunker/chunker.ipynb.

Both results are one dataset family each, so treat them as evidence, not a guarantee.

Layout

Path What
jevqu/jev.py, llm.py OpenRouter clients with on-disk cache and cost tracking
jevqu/api.py the five public query-understanding calls
jevqu/induce.py, classify.py, cascade.py taxonomy induction, point labeling, local classifier cascade
jevqu/understand.py, qquery.py query to classes/facets; filter/boost search
recipes/wands.py shared WANDS loader and hybrid index used by the recipe notebooks
recipes/chunker/qasper.py QASPER loader and character-overlap scores for the chunker benchmark
docs/ design notes and implementation plan

Tests

uv run pytest        # tests/ and recipes/; Jev is faked

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages