Text-to-SQL

"Just ask your database in English." Text-to-SQL makes it real — and it's a masterclass in LLM + guardrails engineering.

▶ Watch this reel

What you'll learn

  1. How it works
  2. Schema linking & semantic layer
  3. SQL safety
  4. Validation & self-correction

Remember this

Pipeline

1. Question (ambiguous NL) 2. Schema linking — prune to relevant tables/columns 3. Generation — schema + annotations + examples 4. Validate → execute read-only → verify result

Schema linking & semantic layer

SQL safety

Validation & self-correction

Code: Text-to-SQL, the full guarded pipeline

SEMANTIC_LAYER = """
churned: no transaction in 90 days
mrr: recurring revenue from subscriptions only
region: customer's billing country
"""

async def ask_db(question: str) -> str:
    # 1 · schema linking: embed question → match table/column descriptions
    schema = link_schema(question, catalog)          # ~5 relevant tables

    for attempt in range(3):
        # 2 · generate with meaning + examples
        sql = llm(GEN_PROMPT, schema=schema,
                  semantics=SEMANTIC_LAYER,
                  examples=gold_pairs_for(question))
        try:
            rows = safe_execute(sql, readonly_conn)   # fenced (slide 4)
        except (SqlRejected, DbError) as e:
            history.append((sql, str(e)))             # actionable error → retry
            continue
        if not rows or not plausible(question, rows):
            history.append((sql, "result empty/implausible"))
            continue
        return render_answer(question, rows, sql)      # answer + SQL shown

    return "I couldn't answer that reliably — can you clarify the timeframe or metric?"