Enrich support tickets with AI text functions
Use this cookbook when you have text columns in a local table and want to add AI summaries, labels, extraction, redaction, or translations in SQL.
Prerequisites
- Build and load the extension.
- Configure a completion provider with session settings or a
TYPE duckdb_aisecret. Hosted providers read their key from the environment, for exampleOPENAI_API_KEY. See the provider guides. - Create the sample
support_ticketstable.
Every function on this page sends one request per non-NULL row.
Summarize each ticket
Combine the columns that give the model enough context:
SELECT
ticket_id,
ai_summarize(subject || chr(10) || body) AS ticket_summary
FROM support_tickets;
Result: one ticket_summary VARCHAR per ticket.
Summarize by customer
Use the aggregate form when several rows belong to the same account:
SELECT
customer_id,
ai_summarize_agg(subject || ': ' || body ORDER BY created_at) AS summary
FROM support_tickets
GROUP BY customer_id;
Result: one summary VARCHAR per customer.
Classify tickets
Keep labels short and mutually exclusive:
SELECT
ticket_id,
ai_classify(
subject || chr(10) || body,
'billing, performance, integration, documentation, other'
) AS category
FROM support_tickets;
Result: category VARCHAR, always one of the listed labels.
Filter rows with a natural-language predicate
Use ai_filter when keyword logic would be too brittle. Send only the columns
the model needs: internal_note contains an email address, so it stays out of
the prompt until it has been redacted.
SELECT *
FROM support_tickets
WHERE ai_filter(
subject || chr(10) || body,
'mentions urgent production impact or needs engineering follow-up'
);
Answer several questions in one call
The classify and filter steps above each send one request per row. With a
decision-model provider (typesafe, cloudflare, perplexity, ollama 0.35
or later, or systemone), one ai_decide call answers both questions and
returns a confidence for the label and a probability for the yes/no question.
You then choose the thresholds in SQL. See
route rows by decision confidence. If you only have a
chat provider, keep ai_classify and ai_filter.
Extract compact JSON
Use ai_extract for lightweight structured values that can stay in a JSON text
column:
SELECT
ticket_id,
ai_extract(
body,
'Return compact JSON with product_area, customer_request, and urgency'
) AS extracted_json
FROM support_tickets;
Result: extracted_json VARCHAR. The function does not check the JSON against a
schema.
Use ai_extract_record
to get one typed STRUCT per row instead. See
typed records from model output.
Redact internal notes
Redact notes before sharing operational context outside the team:
SELECT
ticket_id,
ai_redact(internal_note) AS redacted_internal_note
FROM support_tickets;
Translate customer text
Translate only the rows that need it:
SELECT
ticket_id,
language,
ai_translate(subject || ': ' || body, 'English') AS english_text
FROM support_tickets
WHERE language <> 'en';
Inspect usage
After running provider calls, inspect recent usage events:
SELECT function_name, provider, model, prompt_tokens, completion_tokens, total_tokens, elapsed_ms
FROM ai_usage()
ORDER BY event_id DESC
LIMIT 10;
ai_usage() keeps the latest 1,024 events for the current DuckDB instance. See
usage and cost monitoring to keep them longer.