Skip to content

Retrieve structured facts without embeddings

The Acme Deploy pricing table lives at course/source/acme-deploy/data/plans.csv. Open it before you write any retrieval code. The Pro row says included_build_minutes is 5000.

For the Query How many build minutes come with Pro?, the correct operation is an exact row lookup. Similarity search would add uncertainty to a question the data can answer directly.

Run the lookup

From course/:

uv run python - <<'PY'
from pathlib import Path
from buildrag.structured import lookup_plan

path = Path("source/acme-deploy/data/plans.csv")
plan = lookup_plan(path, "Pro")
print(plan["included_build_minutes"] if plan else "plan not found")
PY

You should see:

5000

Read course/src/buildrag/structured.py. The function loads the CSV, compares the plan name case-insensitively, and returns the matching record. There is no model call and no ranking threshold to tune.

Keep the tool narrow

A production system might move this data into PostgreSQL, but the interface can stay specific:

structured_lookup(
    name="plan",
    filters={"plan": "Pro"},
)

The application should validate name and the allowed filter fields, then run parameterized SQL or deterministic Python. Do not hand a user string to unrestricted SQL, and do not ask the model to invent a query against tables it does not understand.

The returned value still needs provenance. Keep the Source ID for data/plans.csv, the row identity, and the fields used in the Answer. When generation says "Pro includes 5,000 build minutes," the Citation should lead back to that record.

Choose methods by the shape of the question

You now have three retrieval methods:

  • glob narrows Sources by path;
  • lexical search finds and ranks words or identifiers;
  • structured lookup returns known fields and records.

None is a fallback for a failed vector search. Each one fits a different information need.

Next, we will add embeddings for the case these methods still miss: a Query and a relevant passage that mean the same thing but use different words.

Understand embeddings