Snowflake Cortex AISQL, BigQuery's AI.GENERATE family, and Databricks ai_query() put an LLM behind a SQL function: classify a ticket, translate a review, summarize a note — no Python service, no data movement, no new infrastructure.
Tier: Core · Workflow area: Unstructured data processing
That convenience is also the trap: a function you can call in one line can burn a real budget across a hundred-million-row backfill, and a misclassification rate you never measured becomes a permanent feature of the table. This playbook is the disciplined version: sample-audit first, cost-model second, backfill last.
Reach for an external API pipeline instead when you need a custom Pydantic-grade schema contract, multi-step prompting, or a model the warehouse doesn't offer.
Prototype on 100 rows, not the table. Every warehouse AI function bills per row/token — develop on a sample:
-- Snowflake Cortex example: multilabel ticket classification
SELECT
ticket_id,
ticket_text,
AI_CLASSIFY(
ticket_text,
['billing', 'bug', 'feature_request', 'account_access', 'other']
) AS category
FROM support.tickets
LIMIT 100;
Expected output: a category column with labels drawn only from your list. The closed label list is your allowed-values guardrail — never use a free-generation function where a classify function exists.
Sample-audit the misclassification rate before scaling. Export 200 stratified rows (make sure rare labels are represented), have a human label them, and compute per-label precision/recall:
CREATE TABLE tmp.audit_sample AS
SELECT * FROM classified_sample
QUALIFY ROW_NUMBER() OVER (PARTITION BY category ORDER BY RANDOM()) <= 40;
If overall accuracy is below the bar (agree it with consumers first — 90% is a common floor for routing use cases), iterate: rename ambiguous labels, add label descriptions, or split "other" into real categories. Label wording is your prompt here.
Build the cost model per million rows. Run the function on a known row count, read the warehouse's usage/credit view, and extrapolate:
-- Snowflake: credits consumed by AI functions
SELECT * FROM SNOWFLAKE.ACCOUNT_USAGE.CORTEX_FUNCTIONS_USAGE_HISTORY
ORDER BY start_time DESC LIMIT 10;
Produce a one-line answer: "AI_CLASSIFY on avg-300-token tickets ≈ $X per 1M rows." Compare against the external-API alternative (tokens × batch pricing) — warehouse-native usually wins on simplicity, not always on unit cost.
Gate the backfill. Wrap the classification in a pipeline (dbt model or task) that enforces the validation-gate pattern even in SQL: label must be in the allowed set (defensive check even though the function promises it), null/failure rows routed to a review table, and a low-confidence band if the function returns scores:
INSERT INTO staging.ticket_categories
SELECT ticket_id, category, classified_at
FROM classified
WHERE category IN ('billing','bug','feature_request','account_access','other');
INSERT INTO review.ticket_categories_failed
SELECT * FROM classified
WHERE category IS NULL
OR category NOT IN ('billing','bug','feature_request','account_access','other');
Backfill incrementally with a cap. Chunk by date or ID range, with a hard stop after each chunk to check spend and label distribution. Never fire a single UPDATE over the full history.
Monitor label drift. Schedule a daily check on the label distribution of new rows; a sudden jump in one label usually means upstream text changed (new ticket form, new language) — not that users suddenly love billing.
Write results to a separate enrichment table keyed by row ID instead of mutating the source table. Re-running with a better label set becomes a swap, not a migration, and the raw table stays reproducible.
AI_COMPLETE-style functions returning open text create an unbounded label set; use the classify/filter-shaped functions with a closed list.AI_CLASSIFY, AI_FILTER, AI_COMPLETE; usage visible in account-usage views for the cost model.AI.GENERATE family / AI.GENERATE_TABLE for schema-shaped output; sandbox tier works for practice.Warehouse-native AI functions are often the easiest option to clear with a client, because data never leaves their warehouse's security boundary — but confirm rather than assume: some clients' agreements with their warehouse vendor exclude AI features, and some regions route AI function calls to endpoints in other geographies. Get the client's platform team to confirm which AI functions are enabled and where inference runs. Run everything under a client-owned role with a dedicated warehouse/reservation so AI spend is separately meterable, present the cost model and audit results before requesting backfill approval, and leave behind the drift monitor plus the review-table process so the enrichment stays owned after you roll off.