Anchor

Provenance-first RAG that refuses to hallucinate.

## What it does Anchor is a RAG library that refuses to answer when it has no source to stand on. Every query runs a cosine-similarity search; if nothing clears the configured floor, it returns `{ answer: null, reason: "no_match" }` instead of guessing. Retrieval and storage sit on Postgres with pgvector. Ingestion is an idempotent upsert keyed on a content hash, so re-running the same documents doesn't duplicate rows. ## Why this approach Most RAG demos quietly paper over the no-source case and let the model improvise. In real estate that improvisation is a legal problem, not a UX wrinkle. So the floor is a config value you set per index, not a heuristic the model talks itself out of. The trade-off is that a too-high floor makes Anchor look ignorant on questions it could half-answer, and tuning that number is on you. ## How it's built A thin TypeScript layer over pgvector: embed the query, run a similarity search, compare the top hit against the floor, and either return the chunks or return the refusal. Ingestion hashes each chunk's content and upserts on that hash. A small Next.js playground lets you watch the retrieval decision for a given query. ## Known limitations - One cosine threshold per index. There's no per-query re-ranking or hybrid keyword pass. - The embedding model is locked per index. Switching models means a full re-embed. - Re-indexing on a schema change is a script you run by hand, not a migration. - The floor is a blunt instrument: it can't tell "no source" from "source exists but embeds poorly." ## Where it runs - GitHub: github.com/ykstorm/anchor - Demo: anchor-iota-ten.vercel.app/playground