title-v2.ts89 lines · main
1import { generateText, Output } from 'ai'
2import { source } from 'common-tags'
3import { NextApiRequest, NextApiResponse } from 'next'
4import { z } from 'zod'
5
6import { getModel } from '@/lib/ai/model'
7import { DEFAULT_COMPLETION_MODEL } from '@/lib/ai/model.utils'
8import apiWrapper from '@/lib/api/apiWrapper'
9
10const titleSchema = z.object({
11 title: z
12 .string()
13 .describe(
14 'The generated title for the SQL snippet (short and concise). Omit these words: "SQL", "Postgres", "Query", "Database"'
15 ),
16 description: z.string().describe('The generated description for the SQL snippet.'),
17})
18
19async function handler(req: NextApiRequest, res: NextApiResponse) {
20 const { method } = req
21
22 switch (method) {
23 case 'POST':
24 return handlePost(req, res)
25 default:
26 res.setHeader('Allow', ['POST'])
27 res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
28 }
29}
30
31export async function handlePost(req: NextApiRequest, res: NextApiResponse) {
32 const {
33 body: { sql },
34 } = req
35
36 if (!sql) {
37 return res.status(400).json({
38 error: 'SQL query is required',
39 })
40 }
41
42 try {
43 const { modelParams, error: modelError } = await getModel({
44 provider: 'openai',
45 modelEntry: DEFAULT_COMPLETION_MODEL,
46 })
47
48 if (modelError) {
49 return res.status(500).json({ error: modelError.message })
50 }
51
52 const result = await generateText({
53 ...modelParams,
54 output: Output.object({ schema: titleSchema }),
55 prompt: source`
56 Generate a short title and summarized description for this Postgres SQL snippet:
57
58 ${sql}
59
60 The description should describe why this table was created (eg. "Table to track todos") or what the query does.
61 `,
62 })
63
64 return res.json(result.output)
65 } catch (error) {
66 if (error instanceof Error) {
67 console.error(`AI title generation failed: ${error.message}`)
68
69 // Check for context length error
70 if (error.message.includes('context_length') || error.message.includes('too long')) {
71 return res.status(400).json({
72 error:
73 'Your SQL query is too large for Briven Assistant to ingest. Try splitting it into smaller queries.',
74 })
75 }
76 } else {
77 console.log(`Unknown error: ${error}`)
78 }
79
80 return res.status(500).json({
81 error: 'There was an unknown error generating the snippet title. Please try again.',
82 })
83 }
84}
85
86const wrapper = (req: NextApiRequest, res: NextApiResponse) =>
87 apiWrapper(req, res, handler, { withAuth: true })
88
89export default wrapper