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

OpenAI заложила фундамент для революции в сфере ИИ с появлением ChatGPT, открывая новую эру в области AI, которую активно используют как отдельные люди, так и бизнес-сообщества.

fbea2efb8de627f85fe938c82c17f74b.png

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

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

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

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

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

0d206dc0a4510949db3b29fd1236ee52.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

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

b7453ad5aa8cb02d2055a1ed014db104.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 Expert. Вы можете задать любые вопросы, связанные с 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 в нашем браузере.

    4876e5c320c81b9b756f375dc7f2035d.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 прочитано 18475 раз