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

Компания Vercel внесла свой вклад, разработав AI SDK для создания интерактивных пользовательских интерфейсов с использованием TypeScript и JavaScript. Примечательно, что этот SDK является проектом с открытым исходным кодом и поддерживает Vercel Edge runtime.
В рамках данной статьи мы создадим SQL Expert ChatBot, применив API OpenAI и SDK от Vercel. Мы рассмотрим вопросы стриминговых ответов, настройки запросов и многое другое.
Получение API ключа
Первым шагом будет создание аккаунта на OpenAI и получение ключа для API. Сперва мы проходим регистрацию и после того, как мы выполнили вход в свой аккаунт, нам нужно перейти в раздел управления API-ключами. Здесь мы можем сгенерировать новый ключ и дать ему имя, в моем случае — vercel-ai-sdk, но вы можете выбрать другое наименование на свое усмотрение.

Предлагаю не медлить и перейти к обзору 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
Проверьте, чтобы конфигурация вашего проекта была следующей:

Создаем файл .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); }
Немного пояснений:
-
Сперва мы предоставляем ключ API для настройки экземпляра OpenAI:
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); -
С помощью этой строки мы указываем Next.js использовать среду выполнения на краю (edge runtime) для обработки API-запросов:
export const runtime = 'edge'; -
Для извлечения данных из поля messages, , которые приходят в теле JSON-запроса мы используем
POST-функцию. -
Далее мы применяем метод
openai.chat.completions.createдля отправки этих сообщений в модельgpt-3.5-turboдля дальнейшей обработки. Этот метод генерирует ответы, основываясь на введенных сообщениях. -
Параметр
streamмы устанавливаем в значениеtrue, поскольку это позволяет передавать ответы в формате реального времени. -
ППолучив ответ от OpenAI, код трансформирует его в формат удобного текстового потока с использованием функции
OpenAIStream. -
И в завершение, функция формирует ответ, включающий в себя текстовые потоки, созданные 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 ( <div> <div className="text-center py-8"> <h2 className="text-center text-2xl font-bold mb-2">Эксперт SQL</h2> <p> Добро пожаловать в Эксперта SQL. Вы можете задать любые вопросы, связанные с SQL, и эксперт вам поможет. </p> </div> <div className="flex flex-col w-full max-w-2xl pb-24 mx-auto stretch gap-4"> {messages .filter((m) => m.role !== 'system') .map((m) => ( <div key={m.id} className="bg-gray-100 p-4 rounded flex gap-2 flex-col" > <span className="font-medium"> {m.role === 'user' ? 'Вы' : 'Эксперт'} </span> <Markdown>{m.content}</Markdown> </div> ))} <form className="flex gap-4 fixed bottom-0 w-full mb-8" onSubmit={handleSubmit} > <input 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} /> <button className="border p-2 px-4 rounded shadow-xl border-gray-300 bg-purple-500 text-white" type="submit" > Отправить </button> </form> </div> </div> ); }
Добавим немного пояснений:
-
Мы применяем компонент для визуализации сообщений и форму для отправки сообщений пользователем:
'use client'; -
Так как API возвращает ответы в формате markdown, мы используем библиотеку
react-markdownдля их интерпретации.import Markdown from 'react-markdown'; -
Хук
useChatпредназначен для создания интерфейса чата в нашем приложении с интеграцией чат-бота. Он облегчает процесс отображения сообщений от нашего AI-провайдера, управления вводом в чате и обновления UI при поступлении новых сообщений. Хук также поддерживает различные опции, и в нашем случае мы используем параметрinitialMessagesдля настройки начального поведения системы.import { useChat } from 'ai/react'; const { messages, input, handleInputChange, handleSubmit } = useChat({ initialMessages: INITIAL_MESSAGES, }); -
Также мы настраиваем отображение сообщений, пришедших от API. Учитывая, что мы задали системе настраиваемый промт, мы отсееваем его и оставляем только сообщения пользователя и эксперта:
<div className="flex flex-col w-full max-w-2xl pb-24 mx-auto stretch gap-4"> {messages .filter((m) => m.role !== 'system') .map((m) => ( <div key={m.id} className="bg-gray-100 p-4 rounded flex gap-2 flex-col" > <span className="font-medium"> {m.role === 'user' ? 'Вы' : 'Эксперт'} </span> <Markdown>{m.content}</Markdown> </div> ))} ... </div> -
Мы реализуем форму для отправки сообщений пользователями. Для обработки события отправки формы применяем функцию
handleSubmit, которую предоставляет хукuseChat. -
В качестве механизма управления вводом данных в текстовое поле используем функцию
handleInputChangeв сочетании с состояниемinput. -
Кроме того, мы оснащаем форму кнопкой, предназначенной для ее отправки:
<div className="flex flex-col w-full max-w-2xl pb-24 mx-auto stretch gap-4"> ... <form className="flex gap-4 fixed bottom-0 w-full mb-8" onSubmit={handleSubmit} > <input 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} /> <button className="border p-2 px-4 rounded shadow-xl border-gray-300 bg-purple-500 text-white" type="submit" > Отправить </button> </form> </div>
Благодаря Vercel AI SDK у нас есть такие инструменты, как хук useChat, облегчающий работу, начиная от отображения сообщений до управления пользовательским вводом.
Мы успешно разработали UI для нашего SQL Expert bot, а это значит, что пора запустить сервер разработки и провести тестирование.
Тест бота
Запустим сервер следующей командой в терминале:
pnpm run dev
ИЛИ
yarn run dev
ИЛИ
npm run dev
Перейдем по адресу http://localhost:3000 в нашем браузере.

Вы можете опробовать бота в работе со следующими примерами промтов:
-
«Сформулируй SQL‑запрос для выявления суммарного числа заказов, сделанных каждым клиентом за прошедший год, с сортировкой по убыванию количества заказов.»
-
«Напиши SQL‑запрос для идентификации клиентов, чьи расходы превысили $1000 за последние три месяца.»
-
«Разработай SQL‑запрос для определения среднего времени выполнения заказа, исходя из временных отметок его размещения и завершения.»
-
«Спроектируй SQL‑запрос для выявления продуктов с самой высокой прибыльностью, учитывая их себестоимость и цену продажи.»
-
«Сконструируй SQL‑запрос для анализа тренда ежемесячного дохода за последний год, с разбивкой по месяцам.»
-
«Определи через SQL‑запрос клиентов, которые не совершали покупок за последние 6 месяцев.»
-
«Составь SQL‑запрос для выявления пяти категорий товаров с наибольшим объемом продаж за последний квартал.»
-
«Разработай SQL‑запрос для определения заказов, включающих товары, отсутствующие на складе в момент покупки.»
-
«Вычисли через SQL‑запрос общий доход от постоянных клиентов по сравнению с новыми за последний месяц.»
-
«Сформулируй SQL‑запрос для выявления аномалий или отклонений в количестве заказов по сравнению со средними показателями каждого товара за определенные исторические периоды.»
Для наглядности, взгляните на демонстрацию работы следующего промта:
"Представим, твоей задачей стоит оптимизация производительности базы данных крупной компании в сфере электронной коммерции. Составь SQL-запрос для выявления десяти наиболее продаваемых товаров по доходу за последний месяц, учитывая количество продаж и цену за единицу."
Заключение
В этом гайде мы с вами написали функционирующий SQL Expert Bot. Попробуйте настроить его, согласно своим предпочтениям, экспериментируйте и делитесь своими результатами!
Полезные ссылки:
Благодарю за внимание!
ссылка на оригинал статьи https://habr.com/ru/articles/800505/
Добавить комментарий