agents / patterns

More retrieval patterns

Scoped filters, two-stage retrieval, CASE-routed verification, and pinned snapshots, all ordinary SQL over the same search functions.

infino explain patterns

One call, one result

  • One SQL statement retrieves, filters, joins, aggregates, and returns the finished table.
  • A count, group by, or window function runs over the full candidate set, not a client-side loop over the rows sent to the model.
  • Hybrid retrieval hands back the rows a single retriever drops: the exact error code and the paraphrase of it, fused into one ranking.

cat scoped.sql

The query defines the cohort: this tenant, this quarter, these priorities. The filters execute inside retrieval rather than in model instructions.

scoped.sql
SELECT   _id, subject, score
FROM     hybrid_search('tickets', 'body', 'disk full on ingest',
                       'embedding', :q, 500)
WHERE    tenant_id = :tenant                        -- enforced
  AND    created_at >= date_trunc('quarter', now())
  AND    priority IN ('p0', 'p1')
ORDER BY score DESC LIMIT 20;

-- → exactly this cohort, nothing outside it

cat two-stage.sql

Two retrieval granularities, one statement. A table of document-summary embeddings picks the right documents; a chunk-level search picks the right passages inside them; the join ranks on both.

two-stage.sql
-- stage one: which documents are about this, by their summary embedding
WITH docs AS (
  SELECT _id AS doc_id, score AS doc_score
  FROM   vector_search('doc_summaries', 'embedding', :q, 50)
)
-- stage two: the best passages, but only inside those documents
SELECT   c._id, c.doc_id, c.text,
         round(0.4 * d.doc_score + 0.6 * c.score, 4) AS blended
FROM     vector_search('chunks', 'embedding', :q, 500) c
JOIN     docs d ON d.doc_id = c.doc_id              -- two searches, one join
ORDER BY blended DESC
LIMIT    10;

-- → whole-document context and passage precision, in one pass

The full query surface →

cat verify.sql

A CASE expression can send only the borderline score band to an LLM for verification. The application supplies both thresholds.

verify.sql
SELECT   _id, subject, score,
         CASE
           WHEN score >= :trust_threshold THEN 'trust'
           WHEN score >= :check_threshold THEN 'llm_check'
           ELSE 'drop'                            -- never reaches the context window
         END AS action
FROM     hybrid_search('tickets', 'body', :question,
                       'embedding', :q, 200)
WHERE    created_at > now() - interval '90 days'
ORDER BY score DESC;

-- → only rows between the two thresholds require a model check

The routing thresholds live in the query, so they are versioned, reviewed, and tuned like the rest of your SQL.

infino explain disagreement

Debug the retriever before it ships

  • Join bm25_search against vector_search on _id and the rows on only one side are what a single retriever would have silently missed.
  • Run it per query class in CI: when the "meaning only" bucket grows, your embeddings and your vocabulary are drifting apart, and you find out from a query.

The disagreement query →

infino explain snapshots

One consistent read, even while writes land

  • Every query runs on one pinned snapshot, so a count and the rows behind it always come from the same version of the table, even while writes land concurrently.
  • A retained snapshot lets you rerun yesterday’s query against yesterday’s data when the result changes.

cat FAQ.md

Why put filters and joins in the query instead of the agent?

Because the constraints run inside the engine instead of being reasoned about in text. A WHERE clause on tenant, time, or status runs on the retrieval pass itself, and the aggregate is computed over every hit, not the ten rows a context window can hold.

Where do the embeddings come from?

Infino can embed text on ingest using the model selected for the table. You can also send vectors from your own model. Keyword search and SQL need no embeddings.

Can a query combine document-level and chunk-level retrieval?

Yes, in one statement. Search a table of document-summary embeddings to pick candidate documents, join the result to a chunk-level search of the same corpus, and rank on both scores. Each search function returns a relation, so the join is ordinary SQL.

Can a query decide which rows need an LLM check?

Yes. A CASE expression over retrieval scores labels each row as trust, check, or drop. The application supplies the thresholds, and the routing logic is versioned with the rest of the SQL.

What happens if writes land while a query is running?

Every query runs on one pinned snapshot. The rows it reads and the count it computes come from the same version of the table, even while writes land concurrently.