[Перевод] Разработка SQL Expert Bot: подробный гайд по использованию Vercel AI SDK и API OpenAI

OpenAI заложила фундамент для революции в сфере искусственного интеллекта с появлением ChatGPT, открывая новую эру в области AI, которую активно используют как отдельные люди, так и бизнес-сообщества. OpenAI даже предоставила API для разработки персонализированных AI-решений, включая чат-ботов, виртуальных помощников и многого другого. Доступ к этому API можно получить через SDK, которые OpenAI выпустила для разных языков программирования, а также через оболочки, разработанные для удобства создания интерфейсов.

3c3739278b57e5257d03ef2f7a568e03.png

Компания Vercel внесла свой вклад, разработав AI SDK для создания интерактивных пользовательских интерфейсов с использованием TypeScript и JavaScript. Примечательно, что этот SDK является проектом с открытым исходным кодом и поддерживает Vercel Edge runtime.

В рамках данной статьи мы создадим SQL Expert ChatBot, применив API OpenAI и SDK от Vercel. Мы рассмотрим вопросы стриминговых ответов, настройки запросов и многое другое.

Получение API ключа

Первым шагом будет создание аккаунта на OpenAI и получение ключа для API. Сперва мы проходим регистрацию и после того, как мы выполнили вход в свой аккаунт, нам нужно перейти в раздел управления API-ключами. Здесь мы можем сгенерировать новый ключ и дать ему имя, в моем случае — vercel-ai-sdk, но вы можете выбрать другое наименование на свое усмотрение.

38afb1b49004268b411be044c2d82018.png

Предлагаю не медлить и перейти к обзору Vercel AI SDK и процессу настройки на устройстве.

Конфигурация Vercel AI SDK

Vercel AI SDK предназначен для взаимодействия с API OpenAI и обладает рядом инструментов для эффективного использования функционала OpenAI API.

Для старта мы создаем приложение на базе Next.js и подключаем необходимые зависимости: пакет ai для Vercel AI SDK и пакет openai для клиента OpenAI API:

pnpm dlx create-next-app ai-sql-expert

cd ai-sql-expert

pnpm install ai openai

Проверьте, чтобы конфигурация вашего проекта была следующей:

8aace35769d6651721d61e9c848c40da.png

Создаем файл .env в корневой директории проекта и добавим в него сгенерированный ранее OpenAI API ключ:

OPENAI_API_KEY=xxxxxxxxx

На этом настройка SDK OpenAI и Vercel AI подходит к завершению, а значит мы можем перейти к настройке API-маршрутов.

Настройка API-маршрутов

Мы организуем API-маршрут для обработки сообщений от пользователей таким образом, чтобы после отправки сообщения пользователем OpenAI API обрабатывал запрос и возвращал ответ в Next.js.

В начале создаем файл route.ts в папке api/chatиз директории src/app и пропишем в нем следующий код:

# app/api/chat/route.ts

import OpenAI from 'openai';

import { OpenAIStream, StreamingTextResponse } from 'ai';

const openai = new OpenAI({

  apiKey: process.env.OPENAI_API_KEY,

});

export const runtime = 'edge';

export async function POST(req: Request) {

  const { messages } = await req.json();

  const response = await openai.chat.completions.create({

    model: 'gpt-3.5-turbo',

    stream: true,

    messages,

  });

  const stream = OpenAIStream(response);

  return new StreamingTextResponse(stream);

}

Немного пояснений:

  1. Сперва мы предоставляем ключ API для настройки экземпляра OpenAI:

    const openai = new OpenAI({

      apiKey: process.env.OPENAI_API_KEY,

    });

  2. С помощью этой строки мы указываем Next.js использовать среду выполнения на краю (edge runtime) для обработки API-запросов:

    export const runtime = 'edge';

  3. Для извлечения данных из поля messages, , которые приходят в теле JSON-запроса мы используем POST -функцию.

  4. Далее мы применяем метод openai.chat.completions.create для отправки этих сообщений в модель gpt-3.5-turbo для дальнейшей обработки. Этот метод генерирует ответы, основываясь на введенных сообщениях.

  5. Параметр stream мы устанавливаем в значение true, поскольку это позволяет передавать ответы в формате реального времени.

  6. ППолучив ответ от OpenAI, код трансформирует его в формат удобного текстового потока с использованием функции OpenAIStream.

  7. И в завершение, функция формирует ответ, включающий в себя текстовые потоки, созданные OpenAI в качестве реакции на запросы пользователя, через класс StreamingTextResponse и отправляет его обратно:

    export async function POST(req: Request) {

      const { messages } = await req.json();

      const response = await openai.chat.completions.create({

        model: 'gpt-3.5-turbo',

        stream: true,

        messages,

      });

      const stream = OpenAIStream(response);

      return new StreamingTextResponse(stream);

    }

Теперь у нас есть API-маршрут для приема и обработки пользовательских запросов с помощью API OpenAI. Перейдем к созданию UI для нашего бота.

Разработка пользовательского интерфейса

Перед тем как приступить к работе с UI, определим константы для начальный сообщений чата, которые мы будем использовать в качестве настраиваемого промта для направления поведения разрабатываемого бота.

Создаем файл chat.constants.ts в папке constant, расположенной в директории src/app и напишем следующий код:

import { Message } from 'ai/react';

export const INITIAL_MESSAGES: Message[] = [

  {

    id: '',

    role: 'system',

    content: 'Вы эксперт по SQL и можете создать генерируемые SQL-запросы для любой проблемы.

        Убедитесь, что возвращаемый вами запрос с правильным форматированием и отступом.

        Убедитесь, что возвращаемый запрос снабжен корректным объяснением и комментариями.

        Если вы не в силах решить проблему, вы вправе запросить дополнительные сведения.

        Если пользователь не может понять запрос, вы можете объяснить запрос простыми словами.

        Если пользователь предоставляет неправильную подсказку, вы можете запросить правильную подсказку.

        `,

  },

];

Мы задаем системе руководящие принципы поведения в различных ситуациях, формулируем соответствующие модели ответов и определяем механизм их доставки.

Далее вставим следующий код в src/app/pages.tsx:

'use client';

import { useChat } from 'ai/react';

import Markdown from 'react-markdown';

import { INITIAL_MESSAGES } from './constant/chat.constants';

export default function Chat() {

  const { messages, input, handleInputChange, handleSubmit } = useChat({

    initialMessages: INITIAL_MESSAGES,

  });

  return (

    

      

        

Эксперт SQL

        

          Добро пожаловать в Эксперта SQL. Вы можете задать любые вопросы, связанные с SQL, и эксперт вам поможет.

        

      

      

        {messages

          .filter((m) => m.role !== 'system')

          .map((m) => (

            

              key={m.id}

              className="bg-gray-100 p-4 rounded flex gap-2 flex-col"

            >

              

                {m.role === 'user' ? 'Вы' : 'Эксперт'}

              

              {m.content}

            

          ))}

        

          className="flex gap-4 fixed bottom-0 w-full mb-8"

          onSubmit={handleSubmit}

        >

          

            autoFocus

            className="p-2 border border-gray-300 rounded shadow-xl outline-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 flex-grow max-w-xl"

            value={input}

            placeholder="Задайте свой вопрос по SQL.."

            onChange={handleInputChange}

          />

          

            className="border p-2 px-4 rounded shadow-xl border-gray-300 bg-purple-500 text-white"

            type="submit"

          >

            Отправить

          

        

      

    

  );

}

Добавим немного пояснений:

  1. Мы применяем компонент для визуализации сообщений и форму для отправки сообщений пользователем:

    'use client';

  2. Так как API возвращает ответы в формате markdown, мы используем библиотеку react-markdown для их интерпретации.

    import Markdown from 'react-markdown';

  3. Хук useChat предназначен для создания интерфейса чата в нашем приложении с интеграцией чат-бота. Он облегчает процесс отображения сообщений от нашего AI-провайдера, управления вводом в чате и обновления UI при поступлении новых сообщений. Хук также поддерживает различные опции, и в нашем случае мы используем параметр initialMessages для настройки начального поведения системы.

    import { useChat } from 'ai/react';

    const { messages, input, handleInputChange, handleSubmit } = useChat({

        initialMessages: INITIAL_MESSAGES,

      });

  4. Также мы настраиваем отображение сообщений, пришедших от API. Учитывая, что мы задали системе настраиваемый промт, мы отсееваем его и оставляем только сообщения пользователя и эксперта:

            {messages

              .filter((m) => m.role !== 'system')

              .map((m) => (

                

                  key={m.id}

                  className="bg-gray-100 p-4 rounded flex gap-2 flex-col"

                >

                  

                    {m.role === 'user' ? 'Вы' : 'Эксперт'}

                  

                  {m.content}

                

              ))}

    ...

  • Мы реализуем форму для отправки сообщений пользователями. Для обработки события отправки формы применяем функцию handleSubmit, которую предоставляет хук useChat

  • В качестве механизма управления вводом данных в текстовое поле используем функцию handleInputChange в сочетании с состоянием input

  • Кроме того, мы оснащаем форму кнопкой, предназначенной для ее отправки:

            ...

            

              className="flex gap-4 fixed bottom-0 w-full mb-8"

              onSubmit={handleSubmit}

            >

              

                autoFocus

                className="p-2 border border-gray-300 rounded shadow-xl outline-purple-500 focus:outline-none focus:ring-2 focus:ring-purple-500 flex-grow max-w-xl"

                value={input}

                placeholder="Задайте свой вопрос по SQL.."

                onChange={handleInputChange}

              />

              

                className="border p-2 px-4 rounded shadow-xl border-gray-300 bg-purple-500 text-white"

                type="submit"

              >

                Отправить

              

            

  • Благодаря Vercel AI SDK у нас есть такие инструменты, как хук useChat, облегчающий работу, начиная от отображения сообщений до управления пользовательским вводом.

    Мы успешно разработали UI для нашего SQL Expert bot, а это значит, что пора запустить сервер разработки и провести тестирование.

    Тест бота

    Запустим сервер следующей командой в терминале:

    pnpm run dev

    ИЛИ

    yarn run dev

    ИЛИ

    npm run dev

    Перейдем по адресу http://localhost:3000 в нашем браузере.

    f66abaed6d26a61cc704b4fbf60195ef.png

    Вы можете опробовать бота в работе со следующими примерами промтов:

    1. «Сформулируй SQL-запрос для выявления суммарного числа заказов, сделанных каждым клиентом за прошедший год, с сортировкой по убыванию количества заказов.»

    2. «Напиши SQL-запрос для идентификации клиентов, чьи расходы превысили $1000 за последние три месяца.»

    3. «Разработай SQL-запрос для определения среднего времени выполнения заказа, исходя из временных отметок его размещения и завершения…»

    4. «Спроектируй SQL-запрос для выявления продуктов с самой высокой прибыльностью, учитывая их себестоимость и цену продажи.»

    5. «Сконструируй SQL-запрос для анализа тренда ежемесячного дохода за последний год, с разбивкой по месяцам.»

    6. «Определи через SQL-запрос клиентов, которые не совершали покупок за последние 6 месяцев.»

    7. «Составь SQL-запрос для выявления пяти категорий товаров с наибольшим объемом продаж за последний квартал.»

    8. «Разработай SQL-запрос для определения заказов, включающих товары, отсутствующие на складе в момент покупки.»

    9. «Вычисли через SQL-запрос общий доход от постоянных клиентов по сравнению с новыми за последний месяц.»

    10. «Сформулируй SQL-запрос для выявления аномалий или отклонений в количестве заказов по сравнению со средними показателями каждого товара за определенные исторические периоды.»

    Для наглядности, взгляните на демонстрацию работы следующего промта:

    "Представим, твоей задачей стоит оптимизация производительности базы данных крупной компании в сфере электронной коммерции. Составь SQL-запрос для выявления десяти наиболее продаваемых товаров по доходу за последний месяц, учитывая количество продаж и цену за единицу."

    Заключение

    В этом гайде мы с вами написали функционирующий SQL Expert Bot. Попробуйте настроить его, согласно своим предпочтениям, экспериментируйте и делитесь своими результатами!

    Полезные ссылки:

    Благодарю за внимание!

    Habrahabr.ru прочитано 14509 раз