🎯 О чём этот конспект: Пошаговое руководство по созданию современного чатбота с потоковой (streaming) передачей ответов, используя последнюю версию Vercel AI SDK (v5), Next.js App Router и библиотеку компонентов Chakra UI. Разбирается как бэкенд-логика взаимодействия с OpenAI GPT-4o, так и фронтенд-часть с поддержкой Markdown.
👤 Кому будет полезно: Вайбкодерам и Fullstack-разработчикам, которые хотят быстро развернуть кастомный интерфейс для LLM с минимальным написанием шаблонного кода.
✨ Что получите: Готовый работающий чатбот, который имитирует поведение ChatGPT (стриминг текста), умеет рендерить сложные Markdown-ответы (списки, заголовки) и легко масштабируется под любые модели (Anthropic, Google, и др.).
1. Инициализация проекта и установка стека
Контекст: Для создания современного AI-приложения важна скорость работы и типизация. Автор использует Next.js с App Router и бета-версию Vercel AI SDK v5, которая значительно упрощает работу с потоками данных. Chakra UI выбрана как гибкая система компонентов для быстрой верстки интерфейса.
Выгода: Быстрый старт с актуальными библиотеками, исключающий конфликты версий и устаревшие методы обработки потоков.
Как применить:
- Шаг 1: Создание проекта — В терминале выполните команду для развертывания Next.js:
npx create-next-app@latest vercel-chakra-ai-demo- Шаг 2: Установка зависимостей — Перейдите в папку и установите SDK (используем флаг beta, так как v5 на момент записи в этом статусе):
cd vercel-chakra-ai-demo
npm install ai @ai-sdk/openai @ai-sdk/react- Шаг 3: Настройка API ключа — Создайте файл
.env.localв корне проекта и добавьте ваш ключ OpenAI:
OPENAI_API_KEY=your_api_key_hereРезультат: Подготовленная среда разработки с установленными SDK для работы с AI.
2. Настройка бэкенд-роута (API Route Handler)
Контекст: В Vercel AI SDK v5 процесс обработки сообщений стал более декларативным. Нам нужно создать эндпоинт, который принимает сообщения от пользователя, конвертирует их в формат, понятный модели (Model Messages), и возвращает поток (stream). Важный нюанс: настройка maxDuration необходима, чтобы Vercel не обрывал долгие ответы нейросети.
Выгода: Стабильный стриминг ответов без таймаутов и корректная передача контекста диалога.
Как применить:
- Шаг 1: Создание структуры — Создайте файл
app/api/chat/route.ts. - Шаг 2: Реализация логики — Скопируйте следующий код:
import { openai } from '@ai-sdk/openai';
import { streamText, convertToCoreMessages } from 'ai';
// Позволяет стримингу длиться до 30 секунд (важно для Next.js)
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages } = await req.json();
const result = await streamText({
model: openai('gpt-4o'), // Можно заменить на gpt-4-turbo или другие
messages: convertToCoreMessages(messages),
});
return result.toDataStreamResponse();
}Результат: Работающий API-эндпоинт /api/chat, готовый принимать запросы и транслировать ответы GPT-4o в реальном времени.
3. Фронтенд: Интеграция Chakra UI и хука useChat
Контекст: Для создания интерфейса используется Chakra UI. Важное изменение в новых версиях SDK: хук useChat больше не управляет состоянием инпута автоматически, поэтому нам нужно создавать отдельный useState для текстового поля. Мы строим интерфейс из двух частей: область сообщений с разным выравниванием (пользователь справа, AI слева) и фиксированная форма ввода снизу.
Выгода: Профессиональный UI с четким разделением ролей сообщений и удобным управлением состоянием.
Как применить:
- Шаг 1: Настройка провайдера — Оберните приложение в
Providerв файлеlayout.tsxсогласно документации Chakra UI. - Шаг 2: Создание интерфейса чата — В файле
page.tsxиспользуйте следующий код:
'use client';
import { useChat } from '@ai-sdk/react';
import { useState } from 'react';
import { Box, Button, HStack, Input, Stack, Text } from '@chakra-ui/react';
export default function Chat() {
const [input, setInput] = useState('');
const { messages, append } = useChat();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!input) return;
await append({ content: input, role: 'user' });
setInput('');
};
return (
<Box p={4} pb="100px">
<Stack gap={4}>
{messages.map((m) => (
<Box
key={m.id}
alignSelf={m.role === 'user' ? 'flex-end' : 'flex-start'}
bg={m.role === 'user' ? 'blue.200' : 'gray.200'}
p={3}
borderRadius="lg"
maxW="80%"
>
<Text>{m.content}</Text>
</Box>
))}
</Stack>
<Box
as="form"
onSubmit={handleSubmit}
position="fixed"
bottom={0}
left={0}
right={0}
p={4}
bg="white"
borderTop="1px solid"
borderColor="gray.100"
>
<HStack>
<Input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Задайте вопрос..."
/>
<Button type="submit" colorScheme="blue">Отправить</Button>
</HStack>
</Box>
</Box>
);
}Результат: Визуально приятный чат, где сообщения корректно отображаются и отправляются.
4. Рендеринг Markdown и улучшение читаемости
Контекст: По умолчанию LLM возвращает текст с Markdown-разметкой (заголовки, списки, жирный шрифт). Если выводить его просто через тег <Text>, пользователь увидит сырые символы ### или *. Для исправления этого используются библиотеки react-markdown и компонент Prose от Chakra UI.
Выгода: Ответы нейросети выглядят как структурированные статьи, их легко читать.
Как применить:
- Шаг 1: Установка библиотек — Выполните в терминале:
npm install react-markdown- Шаг 2: Добавление Prose — Установите сниппет
proseчерез CLI Chakra UI (если используете v3+) или настройте стили для типографики. - Шаг 3: Обновление вывода сообщения — Замените
<Text>{m.content}</Text>на связку Markdown + Prose:
import Markdown from 'react-markdown';
// Импорт Prose зависит от вашей настройки Chakra компонентов
import { Prose } from '@/components/ui/prose';
// Внутри цикла map:
<Box ...>
<Prose>
<Markdown>{m.content}</Markdown>
</Prose>
</Box>Результат: Красивое отображение списков, таблиц и заголовков в ответах чатбота.
FAQ
В: Почему в Vercel AI SDK v5 нужно вручную управлять состоянием инпута? О: Разработчики SDK решили сделать хук useChat более гибким и менее "магическим". Это позволяет разработчикам легче интегрировать кастомные поля ввода, загрузку файлов или сложные формы, не конфликтуя с внутренним состоянием хука.
В: Как сменить модель с GPT-4o на Claude 3.5 Sonnet? О: Вам нужно установить пакет @ai-sdk/anthropic, добавить ANTHROPIC_API_KEY в .env и в файле route.ts заменить импорт openai на anthropic, а в вызове streamText указать model: anthropic('claude-3-5-sonnet-20240620').
В: Зачем нужен convertToCoreMessages? О: Сообщения на фронтенде часто содержат лишние для AI данные (ID для React-ключей, локальные таймстампы). Эта функция очищает массив сообщений, оставляя только role и content, что экономит токены и предотвращает ошибки API.
В: Что делать, если стриминг обрывается на середине длинного ответа? О: Проверьте параметр maxDuration в route.ts. На бесплатном тарифе Vercel лимит составляет 10 секунд, на Pro — до 300. Также убедитесь, что вы используете result.toDataStreamResponse(), который корректно обрабатывает протокол стриминга.
В: Можно ли добавить системный промпт (инструкцию для бота)? О: Да, в функции streamText добавьте поле system: streamText({ model: ..., system: "Ты — эксперт по коду, отвечай кратко", messages: ... }).
Конспект создан на основе видео «Build an AI Chatbot with Vercel AI SDK and Chakra UI» канала Esther Adebayo. Все права на оригинальный материал принадлежат авторам. Источник: https://www.youtube.com/watch?v=lp1RtS7RKtw