Skip to main content

Compare support tickets with embeddings

Use this cookbook to find semantically similar support tickets from text columns. ai_similarity embeds both inputs with the same model and returns cosine similarity.

Prerequisites​

For OpenAI, use an embedding model such as text-embedding-3-small.

Rank ticket pairs​

Compare every ticket pair and rank the closest matches:

SELECT
left_ticket.ticket_id AS left_ticket_id,
right_ticket.ticket_id AS right_ticket_id,
ai_similarity(
left_ticket.subject || chr(10) || left_ticket.body,
right_ticket.subject || chr(10) || right_ticket.body,
provider := 'openai',
model := 'text-embedding-3-small'
) AS similarity
FROM support_tickets AS left_ticket
JOIN support_tickets AS right_ticket
ON left_ticket.ticket_id < right_ticket.ticket_id
ORDER BY similarity DESC;

Compare against a target description​

Use a fixed description when you want to find rows that match a theme:

SELECT
ticket_id,
subject,
ai_similarity(
subject || chr(10) || body,
'production incident blocking an important business workflow',
provider := 'openai',
model := 'text-embedding-3-small'
) AS similarity
FROM support_tickets
ORDER BY similarity DESC;

Keep batches bounded​

Pairwise comparison grows quickly. For larger tables, filter first:

SELECT
left_ticket.ticket_id AS left_ticket_id,
right_ticket.ticket_id AS right_ticket_id,
ai_similarity(
left_ticket.subject || chr(10) || left_ticket.body,
right_ticket.subject || chr(10) || right_ticket.body,
provider := 'openai',
model := 'text-embedding-3-small'
) AS similarity
FROM support_tickets AS left_ticket
JOIN support_tickets AS right_ticket
ON left_ticket.ticket_id < right_ticket.ticket_id
WHERE left_ticket.priority = 'high'
OR right_ticket.priority = 'high'
ORDER BY similarity DESC;

For repeated large workloads, store embeddings with ai_embed and compare those vectors in a separate workflow instead of recomputing every pair.