Как сделать чат-бота для Reddit API
Всем привет! Я решил поделиться этим кратким руководством о том, как я создал чат-бота, который позволяет пользователям общаться с помощью Reddit API. Как разработчик и фанат Reddit, я хотел попробовать создать новый способ взаимодействия с платформой. Вот как я это сделал, используя NextJS, Chatwith и OpenAPI!
Вот исходный код, если вы хотите сразу приступить к нему, и вот финальное приложение: https://redditbot.chat
Особенности проекта
Вкратце, проект имеет:
- Тонкую оболочку над Reddit API, позволяющую предоставлять только полезные конечные точки и обрезать полезные данные.
- Файл спецификации OpenAPI в формате YAML для чат-бота Chatwith.
- Целевую страницу со встроенным iframe чат-ботом
Вероятно, большую часть тяжелой работы взял на себя Chatwith. Этот проект направлен на создание API для взаимодействия чат-бота и настройку Chatwith для создания чат-бота.
Я использовал NextJS для этого проекта, потому что я также хотел создать простую целевую страницу, но вы можете легко создать API, например: Express бэкэнд.
Начнем
Я использовал простой стартер NextJS 13 с конфигурацией по умолчанию:
bunx create-next-app
Как видите, я использую Bun — новый универсальный инструментарий JS. Вы также можете использовать npm
или pnpm
в качестве замены в этом проекте.
После создания проекта быстро проверьте, работает ли он на локальном хосте:
bun dev
Создание оболочки Reddit API
Важным компонентом этого проекта является оболочка Reddit API. Она служит посредником между нашим чат-ботом и API Reddit. Ее роль — уменьшить объем передаваемых данных и упростить API для понимания чат-бота.
Вот почему оболочка важна:
- Использует только выбранные конечные точки: API Reddit имеет множество конечных точек для различных функций. Нашему чат-боту нужна только часть из них. Обертка обязательно отображает только необходимые.
- Размер полезной нагрузки: ответы Reddit API содержат массу информации, которая нам не нужна. Поскольку GPT-3.5 и GPT-4 от OpenAI принимают ограниченные токены, оболочка обрезает ответы API, чтобы они содержали только те данные, которые бот действительно будет использовать.
Конечные точки API
Ознакомьтесь с официальной документацией Reddit API для получения полной спецификации всех конечных точек.
На данный момент мы добавим в нашу оболочку следующие конечные точки Reddit API:
/r/{subreddit}/{listing}.json
: извлекает истории из определенного субреддита в зависимости от типа листинга (горячие, новые, растущие и т. д.)./{listing}.json
: извлекает истории из всех субреддитов в зависимости от типа листинга./r/{subreddit}/search.json
: позволяет нам искать тему в любом субреддите./search.json
: включает поиск по всем субреддитам./r/{subreddit}/comments/{post_id}.json
: извлекает комментарии к определенному сообщению в субреддите.
Создайте конечную точку API
Давайте создадим новый обработчик маршрута NextJS, который будет:
- ретранслировать запросы к Reddit API
- обрезать полезные данные и возвращать ответ
Сначала создайте новый файл: /app/api/[...catchall]/route.ts
[...catchall]
— это имя каталога, которое означает, что любой путь в /api/ будет обрабатываться этим маршрутом (то есть/api/search
,/api/anything/goes
и т. д.). Узнайте больше здесь.
В этом файле находится обработчик GET:
export const runtime = "edge";
export const revalidate = 10;
export async function GET(request: Request) {
const urlObj = new URL(request.url);
const path = urlObj.pathname.replace("/api/", "");
const queryParams = urlObj.search;
try {
const redditResponse = await fetch(
`https://api.reddit.com/${path}${queryParams}`
);
const redditData = await redditResponse.json();
if (isPostListingResponse(redditData)) {
// Handle posts
const summaries = redditData.data.children.map(extractPostSummary);
return NextResponse.json(summaries);
} else if (isCommentsResponse(redditData)) {
if (path.startsWith("r/") && path.includes("/comments/")) {
// Handle comments
const comments = redditData[1].data.children.map(extractCommentSummary);
return NextResponse.json(comments);
}
} else {
return new Response(null, {
status: 400,
statusText: "Invalid Reddit API response",
});
}
} catch (error) {
console.error(error);
return new Response(null, {
status: 500,
statusText: "Failed to fetch data from Reddit",
});
}
}
Давайте разберем его шаг за шагом!
Мы будем использовать среду выполнения Edge для минимальной задержки и добавим короткое кэширование, чтобы не ограничивать скорость API Reddit:
export const runtime = "edge";
export const revalidate = 10;
Затем мы очищаем путь запроса, чтобы мы могли переключить хост с нашего API на Reddit:
const urlObj = new URL(request.url);
const path = urlObj.pathname.replace("/api/", "");
const queryParams = urlObj.search;
Далее мы делаем запрос к Reddit API и анализируем JSON ответа:
const redditResponse = await fetch(`https://api.reddit.com/${path}${queryParams}`);
const redditData = await redditResponse.json();
Затем мы экспериментируем со структурами данных, чтобы распознать, с каким типом ответа мы имеем дело, чтобы мы могли обрезать его и вернуть обратно клиенту:
if (isPostListingResponse(redditData)) {
// Handle posts
const summaries = redditData.data.children.map(extractPostSummary);
return NextResponse.json(summaries);
} else if (isCommentsResponse(redditData)) {
if (path.startsWith("r/") && path.includes("/comments/")) {
// Handle comments
const comments = redditData[1].data.children.map(extractCommentSummary);
return NextResponse.json(comments);
}
} else {
return new Response(null, {
status: 400,
statusText: "Invalid Reddit API response",
});
}
Вы можете увидеть полный исходный код функций isPostListingResponse
, isCommentsResponse
, ExtractPostSummary
и ExtractCommentSummary
в репозитории. Первые две функции просто проверяют наличие и типы элементов JSON, а последние две преобразуют большие объекты, возвращаемые API Reddit, в упрощенные, содержащие заголовок сообщения, имя автора и т. д.
Спецификация OpenAPI
Чтобы наш чат-бот мог взаимодействовать с нашим API, нам нужно описать его, используя спецификацию OpenAPI (в соответствии с требованиями Chatwith).
Начнем с создания файла YAML в каталоге статических ресурсов: /public/openapi.yml
. Таким образом, файл будет доступен Chatwith после развертывания следующим образом: http://redditbot.chat/openapi.yml
Вот что мы поместим в файл:
openapi: 3.0.0
info:
title: Simple Reddit API
version: 1.0.0
description: An API specification for a simple Reddit client. Using this API you can respond to user queries by searching any subreddit or listing type.
servers:
- url: https://redditbot.chat/api/
paths:
/r/{subreddit}/{listing}.json:
get:
summary: Fetch stories from a specific subreddit by listing type
parameters:
- name: subreddit
in: path
required: true
schema:
type: string
- name: listing
in: path
required: true
schema:
type: string
enum:
- hot
- new
- rising
- top
- controversial
- name: limit
in: query
schema:
type: integer
responses:
"200":
description: A JSON object containing stories
[... trimmed for brevity]
Вы можете увидеть все содержимое файла спецификации здесь. Обязательно придерживайтесь форматирования пробелов YAML! Неправильные табуляции или пробелы здесь и там могут привести к неправильному файлу спецификации.
Важные моменты
Обязательно укажите окончательный путь к маршруту API после его развертывания. В моем случае проект развертывается по адресу https://redditbot.chat
, поэтому путь к оболочке API — https://redditbot.chat/api/
:
servers:
- url: https://redditbot.chat/api/
Задокументируйте все конечные точки, которые может использовать чат-бот, а также краткое описание и параметры.
paths:
/r/{subreddit}/{listing}.json:
...
Спецификация OpenAPI не обязательно должна быть очень обширной и подробной, но она должна быть достаточно описательной, чтобы чат-бот мог понять, как сделать правильный запрос.
На этом мы уже преодолели горб, самое сложное позади! Давайте проверим новые конечные точки, вызвав браузер, например:
http://localhost:3000/api/search.json?q=cat
Это должно вернуть ответ JSON с кучей кошачьих постов!
Создание чат-бота
Последний шаг — создание чат-бота в Chatwith для встраивания. Я использую бесплатный аккаунт. Я следовал этому руководству. Вот шаги:
Основные шаги
- Создайте бесплатную учетную запись Chatwith здесь
- Во время регистрации выберите опцию 'Chat with API'
- Нажмите 'Install' на карточке 'API'
- Введите данные нашего API во всплывающем окне
- Завершите процесс регистрации и перейдите на панель управления, чтобы добавить системное приглашение и настроить чат-бота
Установка навыка API
Вот скриншот того, как выглядит установка всплывающего окна навыков. Вы должны указать URL-адрес файла спецификации OpenAPI и URL-адреса API (но не локальный хост! Должен быть общедоступным URL-адресом после развертывания, например, на Vercel).
Добавляем системную подсказку
Чтобы дать чат-боту инструкции по использованию API, мы заполним поле 'System Prompt' в разделе 'Settings' на панели управления.
Вот подсказка:
Вы AI-помощник Reddit. Вы будете отвечать на запросы пользователей и использовать предоставленные API-сообщения для поиска в любом субреддите, а также по таким категориям, как «горячие», «новейшие» и т. д. Вы предоставите сводку списков и комментариев в простой и удобоваримой форме. Вы гибки и можете понять запрос, поэтому пользователи могут спрашивать о новостях, интересных постах, специализированных субреддитах и т. д. Вы возьмете пользовательский запрос и попытаетесь сделать лучший запрос API, чтобы найти на него ответ. Если к сообщению прикреплено изображение, вы отобразите его миниатюру в уценке. Всегда указывайте постоянные ссылки на сообщения в ответе.
Вы можете расширить подсказку, чтобы добавить в чат-бот больше персонажей, например: пусть он использует смайлы или забавный язык.
Тестирование чат-бота
Мы почти закончили! Чат-бот должен работать. Давайте перейдем в раздел 'Preview' панели управления, чтобы протестировать чат-бота. Вы можете начать с вопроса типа Summarize hottest posts
!
Заключение
Надеюсь, на данный момент у вас есть классный чат-бот, который может общаться с API 👏 Если что-то не сработало или у вас есть вопросы, пишите мне в комментариях!
В качестве следующих шагов вы можете добавить больше навыков своему чат-боту (т. е. добавить больше конечных точек API для его использования) и настроить его внешний вид на панели управления Chatwith. После обновления API обязательно сохраните навык в Chatwith еще раз, чтобы чат-бот знал об изменениях.