DevGang
Авторизоваться

Как сделать чат-бота для 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:

  1. /r/{subreddit}/{listing}.json: извлекает истории из определенного субреддита в зависимости от типа листинга (горячие, новые, растущие и т. д.).
  2. /{listing}.json: извлекает истории из всех субреддитов в зависимости от типа листинга.
  3. /r/{subreddit}/search.json: позволяет нам искать тему в любом субреддите.
  4. /search.json: включает поиск по всем субреддитам.
  5. /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 для встраивания. Я использую бесплатный аккаунт. Я следовал этому руководству. Вот шаги:

Основные шаги

  1. Создайте бесплатную учетную запись Chatwith здесь
  2. Во время регистрации выберите опцию 'Chat with API'
  3. Нажмите 'Install' на карточке 'API'
  4. Введите данные нашего API во всплывающем окне
  5. Завершите процесс регистрации и перейдите на панель управления, чтобы добавить системное приглашение и настроить чат-бота

Установка навыка API

Вот скриншот того, как выглядит установка всплывающего окна навыков. Вы должны указать URL-адрес файла спецификации OpenAPI и URL-адреса API (но не локальный хост! Должен быть общедоступным URL-адресом после развертывания, например, на Vercel).

Добавляем системную подсказку

Чтобы дать чат-боту инструкции по использованию API, мы заполним поле 'System Prompt' в разделе 'Settings' на панели управления.

Вот подсказка:

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

Вы можете расширить подсказку, чтобы добавить в чат-бот больше персонажей, например: пусть он использует смайлы или забавный язык.

Тестирование чат-бота

Мы почти закончили! Чат-бот должен работать. Давайте перейдем в раздел 'Preview' панели управления, чтобы протестировать чат-бота. Вы можете начать с вопроса типа Summarize hottest posts!

Заключение

Надеюсь, на данный момент у вас есть классный чат-бот, который может общаться с API 👏 Если что-то не сработало или у вас есть вопросы, пишите мне в комментариях!

В качестве следующих шагов вы можете добавить больше навыков своему чат-боту (т. е. добавить больше конечных точек API для его использования) и настроить его внешний вид на панели управления Chatwith. После обновления API обязательно сохраните навык в Chatwith еще раз, чтобы чат-бот знал об изменениях.

Источник:

#JavaScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу