title-v2.ts 2.5 KB

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