Skip to content
relay_
pipeline ]

From a fileto a footnote.

Seven stages, all in the repository. Scroll and each one lights up with what it does and the numbers it runs on. Nothing here is rounded up for effect.

  1. 01

    Ingest

    Adapters pull text from Drive and Docs, Gmail, Calendar and Sheets through Google's read-only APIs. Drive PDFs are read with pdf.js. Gmail reads only the label or dates you configure.

    sources
    drive · gmail · calendar · sheets
    access
    read-only scopes
    gmail
    opt-in scope required
  2. 02

    Chunk

    Prose is cut into pieces of about 1,000 characters with 150 characters of overlap, breaking at a paragraph if it can, then a sentence, then a word. A spreadsheet row is one chunk, with its header cells naming every value.

    size
    ~1000 chars
    overlap
    150 chars
    sheets
    1 row = 1 chunk
  3. 03

    Embed and store

    Each chunk becomes a vector with BAAI/bge-small-en-v1.5 and is written to Qdrant. Where it came from (source, title, deep link) lives in Postgres. A content hash means unchanged text is never embedded twice.

    model
    BAAI/bge-small-en-v1.5
    vector
    384 dims · cosine
    stores
    Qdrant + Postgres
  4. 04

    Retrieve and rerank

    Vector search casts a wide net and returns 12 candidates. A cross-encoder then reads the question and each candidate together and re-scores them. That is slower than vector search and far more precise, so it only sees the shortlist.

    retrieve
    12 candidates
    rerank
    BAAI/bge-reranker-v2-m3
    keep
    top 4
  5. 05

    Gate

    The best reranked score is the confidence. Under 0.02, Relay refuses. In the eval set, unrelated questions scored below 0.003 while answerable ones started near 0.05, so the line sits in a real gap.

    threshold
    0.02
    below
    refuse
    above
    answer
  6. 06

    Generate

    Groq runs openai/gpt-oss-120b over the top passages. Retrieved text goes in as untrusted data, never as instructions, and the model is told to copy identifiers exactly. A last step corrects typographic Unicode the model likes to substitute.

    model
    openai/gpt-oss-120b
    host
    Groq
    input
    top 4 passages
  7. 07

    Cite

    The answer carries numbered markers that map back to chunks. Each citation opens the retrieved passage in the app and links to the original: a Drive file, a Gmail message, a Calendar event, or the exact Sheets row.

    markers
    [1] [2] …
    opens
    the passage
    links
    the original
freshness ]

Stayingup to date.

All sync work runs as background jobs on Upstash QStash. A Postgres-backed lock per source stops a duplicate delivery from running twice, a bug this project hit for real and fixed. Push needs a public HTTPS URL, so in local development a tunnel provides one.

How each source stays fresh
SourceMechanismWhat happensWorth knowing
Drive & DocspushGoogle calls Relay's webhook, a job syncs the change listChannel lasts 24h, renewed every 6h
CalendarpushSame channel mechanism as DriveWindow is 90 days back, 180 ahead
Sheetsrides DriveChanged spreadsheets are re-read after each Drive syncRow position is the citation key, so deleting a row shifts later citations
Gmailpoll · 5 minReads messages added since the last history cursorPush via Pub/Sub is deferred until a public URL exists
measured ]

Checkedagainst realdata.

Relay ships its own eval suite, run against a real workspace and re-run whenever chunking, the gate or generation changed. It is one person's data and a small suite, so read it as a regression guard, not a benchmark.

Results from the bundled eval suite
Ground-truth questions23Answerable and should-refuse, across Drive, Gmail, Calendar and Sheets
Adversarial cases7Including an instruction hidden in an HTML comment of a forwarded email
Citation accuracy100%The expected source was among the citations on every answerable question
Correct refusals100%Out-of-scope questions were refused, none answered
Adversarial resistance100%A planted instruction’s marker never showed up in the answer
Drive keyword match63%Legitimate paraphrasing on three questions, not wrong answers. Kept in on purpose