ai-sql-cookbook
seekdb exposes model calls as SQL functions. The hard part is never the idea - it is the placeholder rules, the JSON typing, and the error that only shows up against a live endpoint. This skill makes both halves mechanical: generate statements that are already correct, then lint anything hand-written.
When to use it
- "I have a
bodycolumn, how do I search it semantically?" -> recipes 5-7. - "Which of these 50 support articles is most relevant?" -> recipes 8-9.
- "Pull the order id and amount out of this email and give me JSON." -> recipe 1.
- An existing AI-function statement fails with
OB_INVALID_ARGUMENT,OB_NOT_SUPPORTED, or error 5083 -> run the linter first, it names the cause.
Workflow
-
Generate. Pick a recipe and call the builder instead of writing literals by hand:
python3 scripts/build_sql.py --prompt "Extract {0} from: {1}. Reply with JSON only." "the order id and amount" body python3 scripts/build_sql.py --embed my_embed_model body 1024 python3 scripts/build_sql.py --rerank my_rerank_model "refund policy" '["a","b"]' textQuoting,
CAST(... AS JSON)for JSON arguments, and the optional dimension are handled. -
Lint. Any statement that was written or edited by hand goes through:
python3 scripts/build_sql.py --lint my_query.sqlEach finding carries a stable code (
AI_PROMPT_PLACEHOLDER_OUT_OF_RANGE,AI_EMBED_DIMENSION_FLOAT,AI_RERANK_DOCS_STRING, ...) with the line number and the error the server raises. Exit status is 1 when anything is found, so it can gate a migration script. -
Wire the endpoint. AI functions need a model and an endpoint before they can run. The exact DDL shape is in
references/functions.md; the builder emits it too:from build_sql import endpoint_ddl endpoint_ddl("my_embed_ep", "my_embed_model", "https://api.example.com/v1/embeddings", "openai", "sk-...") -
Run, then check the shape, not just the exit code.
AI_PROMPTreturns a JSON object ({"template":..., "args":[...]});AI_EMBEDreturns a JSON array of numbers whose length equals the requested dimension;AI_RERANKreturns a JSON array ordered by relevance. ANULLon any required argument propagates toNULL, it does not raise.
Placeholder rules worth memorising
AI_PROMPT uses zero-based {n} placeholders into the argument list that follows the
template:
| Template | Arguments | Result |
|---|---|---|
| Compare {0} with {0} | latency | Compare latency with latency - repeats expand |
| Answer {0} | (none) | the call fails with OB_INVALID_ARGUMENT |
| Answer {3} | 2 arguments | the call fails with OB_INVALID_ARGUMENT |
Arguments may be strings, JSON values, or TEXT/LONGTEXT columns. A NULL argument is
rejected, so guard row scans with WHERE col IS NOT NULL. The template itself must be a
string - a JSON or numeric template is rejected before evaluation.
Rules this skill follows
- Offline only: no network calls, no database connection, no model keys. It produces SQL and diagnoses SQL; the user runs it.
- Generated statements never interpolate a value into the template string. They pass it as an argument, which is what keeps injection out of prompt text.
- Column references accepted by the builders are validated against
[A-Za-z_][A-Za-z0-9_]*, so a table name cannot smuggle a statement separator into generated SQL. - The linter only reports what maps to a real server error; it does not invent style rules.
Scan to join WeChat group