JMFTS
JMFTS is a retrieval appliance. It combines matryoshka embeddings, ColBERT-style late interaction, and BM25 into one hybrid search over PostgreSQL with pgvector.
Three read paths over one tree, fused by rank A document tree at the top left: a root marked parent id null with three children typed transcript, wiki colon arxiv and tau colon conversation, and one grandchild typed tau colon message. A dashed bracket encloses the tau conversation subtree and is labelled parent id, subtree scope. To the right, a panel headed POST slash search slash hybrid lists the request body — parent id, weights of vector 0.60 against bm25 0.40, usetype, limit, rerank and rerank method — and a short line ties its parent id field back to the bracketed subtree. An arrow runs from the tree down into a stack of three hatched, doubled-outline slabs that is the whole store: documents with its 768-dimension embed vector on an HNSW index, search term postings with search term stats, and token embeddings with embed 256 on an IVFFlat index. Legs leave the first two slabs into boxes labelled vector and bm25, and both land on one red bar. The bar is annotated weight over sixty plus rank and marked fused by rank, no similarity survives. A single arrow leaves the bar into a box labelled hybrid, one ranking. Below that the flow forks into an optional second stage: maxsim, fed both by the ranking above and by a long leg from the token embeddings slab, and cross encoder, fed only from above because it reads no table. Both merge into a SearchResponse box holding results, total and latency ms. jmfts one tree, many usetypes parent_id: null transcript wiki:arxiv tau:conversation tau:message parent_id subtree scope POST /search/hybrid { "parent_id": "<subtree root>", "weights": {"vector": 0.60, "bm25": 0.40}, "usetype": "transcript", "limit": 20, "rerank": true, "rerank_method": "cross_encoder" } the tree is one table documents 768-dim embed · HNSW search_term_postings + search_term_stats token_embeddings embed_256 · IVFFlat postgres + pgvector JMFTS_TOKEN_EMBED_DIMS [256] populated · 384/512 reserved vector cosine similarity bm25 k1 1.2 · b 0.75 weight/(60+rank) fused by rank no similarity survives hybrid one ranking ?rerank=true maxsim reuses token_embeddings no model to load cross_encoder JMFTS_RERANKER_MODEL reads no table SearchResponse results[] · total · latency_ms One documents table holds the corpus as a tree, so scoping a search is naming a parent rather than standing up a second index. Three read paths come off that one store: the 768-dim document vector, the BM25 postings, and the per-token vectors late interaction needs. Hybrid fuses the first two, and it fuses them by rank — each leg contributes weight/(60+rank), so what comes back is an ordering, not a similarity, and a relevant query and a nonsense one measured the same five scores. Threshold on vector instead. Late interaction arrives as the optional second stage, where the two rerank methods differ by prerequisite rather than by quality: maxsim reads tokens you already stored, cross_encoder loads a model and reads no table.
Where to start
The four categories below are a crosswalk, not a sequence. Pick the
cell you are actually in.
Acquisition
Application
Action
Action × Acquisition
A guided build that teaches the concepts as you go. Start at the quickstart and keep going.
Action × Application
Recipes for one specific job, for someone who already knows the basics and wants the steps without the narration.
Cognition
Cognition × Acquisition
How the system is deployed and operated, and why it is shaped that way. Read this before you run it in anger.
Cognition × Application
API surface, config, schemas, invariants. Built for search and lookup, not for reading start to finish.