You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Search-side automatic embedding for vector search (@embed counterpart) #1277
@embed computes vectors automatically on the write side, but there is no search-side counterpart: querying an HNSW index requires the caller to produce the vector themselves (models.embed(text, { inputType: 'query' })) before calling search. Raised by @dawsontoth while reviewing the 5.1 models docs: HarperFast/documentation#523 (comment: HarperFast/documentation#523 (comment)).
Sketch
Accept query text directly on the vector search descriptor and embed it with the attribute's configured @embed model before the index search, e.g.:
Document.search({sort: {attribute: 'embedding',text: 'what is harper?'},});
The attribute's @embed(model: …) declaration already names the right model; the search side would use it with inputType: 'query' (the write-side hook uses 'document'), which matters for models with asymmetric document/query prefixes (e.g. nomic-embed-text).
Same shape would apply to threshold conditions ({ attribute, comparator: 'le', value, text }).
For attributes indexed HNSW without @embed, there is no model to infer — either reject, or accept an explicit model key on the descriptor.
Open questions: REST/operations-API exposure (the QUERY body path carries the descriptor through; search_by_conditions mapping would need the text key preserved), and whether embedding latency belongs inside the search call or should stay an explicit caller step for hot paths.
Related: #510 (models API), #1235 (5.1 GA readiness — listed there as a post-GA follow-up), HarperFast/documentation#523 (docs that surfaced the gap).
Reinforcing this from the retrieval side — building the RAPTOR summary-tree work (#1244 Thread B, reference component HarperFast/summary-tree) the search-side gap showed up as a papercut on every query: the retrieval resource has to models.embed(queryText, { inputType: 'query' }) itself before each search, so the app re-implements what @embed already does on the write side.
Two datapoints for the sketch above:
The inputType: 'query' asymmetry is load-bearing, not cosmetic. The corpus was embedded with nomic-embed-text (search_document: prefix) and queries need the search_query: prefix; getting this wrong quietly degrades recall. The proposed design (search side uses the attribute's @embed model with inputType: 'query') handles exactly this — worth keeping as a hard requirement, not a nice-to-have.
On the "latency inside the search call vs. explicit caller step" open question: for this class of app (RAG retrieval) the embed-then-search round trip is already the critical path, so folding it into the search call is the ergonomic win and doesn't change the latency profile. An escape hatch (pass a pre-computed vector to skip embedding) covers the hot-path case.
Net: a concrete second consumer for this beyond the docs-review origin. The declarative form (sort: { attribute: 'embedding', text: '…' }) would remove a whole boilerplate step from every vector-search app.
Activity
kriszyp commentedon Jul 13, 2026
Reinforcing this from the retrieval side — building the RAPTOR summary-tree work (#1244 Thread B, reference component HarperFast/summary-tree) the search-side gap showed up as a papercut on every query: the retrieval resource has to
models.embed(queryText, { inputType: 'query' })itself before eachsearch, so the app re-implements what@embedalready does on the write side.Two datapoints for the sketch above:
inputType: 'query'asymmetry is load-bearing, not cosmetic. The corpus was embedded with nomic-embed-text (search_document:prefix) and queries need thesearch_query:prefix; getting this wrong quietly degrades recall. The proposed design (search side uses the attribute's@embedmodel withinputType: 'query') handles exactly this — worth keeping as a hard requirement, not a nice-to-have.Net: a concrete second consumer for this beyond the docs-review origin. The declarative form (
sort: { attribute: 'embedding', text: '…' }) would remove a whole boilerplate step from every vector-search app.— Claude (Opus 4.8)