Как генерировать истории с помощью ChatGPT и Telegram

Как генерировать истории с помощью ChatGPT и Telegram

Разрабатываем Telegram-бота для работы с Notion с помощью ChatGPT.

Введение

Представьте, что вам нужно написать художественный роман. У вас есть ключевые идеи, продуманы основные повороты событий, но нет возможности объединить все в одну историю.

Кажется, что написать захватывающую историю просто. Появилась идея — запиши, пришла новая мысль — запиши ее тоже. Потом добавь деталей и эмоций — и готово. Но это не так: иногда последний пункт забирает больше всего времени.

Такая же проблема может встретиться, например, если нужно написать пост или оформить описание рабочего проекта. Если для вас это знакомо, то просто автоматизируйте процесс. Можно написать специального бота, который будет из тезисов генерировать цельную историю с помощью ChatGPT, а после — записывать в Notion. Реализовать такой проект несложно — посмотрим, как это сделать.

Создаем приложение Node.js

Для начала подготовим рабочую среду и создадим проект Node.js:


    npm init -y
npm i -D nodemon // для разработки 
npm i @notionhq/client config openai telegraf 

После изменим поле type в package.json, чтобы проект умел работать с import & export:


    "type": "module",
"scripts": { 
    "dev": "nodemon ./src/main.js", 
    "start": "node ./src/main.js" 
},

Далее создадим ./src/main.js:


    import { Telegraf } from 'telegraf'
import { message } from 'telegraf/filters'
import config from 'config'

const bot = new Telegraf(config.get('TELEGRAM_TOKEN'), {
  handlerTimeout: Infinity,
})

bot.command('start', (ctx) =>
  ctx.reply(
    'Добро пожаловать. Отправьте текстовое сообщение с тезисами про историю.'
  )
)

bot.on(message('text'), ctx => {
 // тут будет логика приложения-интегратора
})

bot.launch()

Получаем токен для Telegram-бота

Следующим этапом нужно создать Telegram-бота. Для этого понадобится API-токен, который можно получить у @BotFather с помощью команды /newbot.

Далее создаем конфигурацию, в которую поместим сам токен:


    mkdir config 
touch default.json


    { 
"TELEGRAM_TOKEN": "ВАШ ТОКЕН ДЛЯ БОТА TELEGRAM", 
}

Пишем логику ChatGPT

Для начала получаем токен для работы с сервисами OpenAI, а после — заносим его в конфигурацию:


    { 
"TELEGRAM_TOKEN": "ВАШ ТОКЕН ДЛЯ БОТА TELEGRAM",
"OPENAI_KEY": "КЛЮЧ ДЛЯ РАБОТЫ С ChatGPT"
}

Теперь создаем файл ./src/chatgpt.js и пишем скрипт:


    import OpenAI from 'openai'
import config from 'config'

const CHATGPT_MODEL = 'gpt-3.5-turbo'

const ROLES = {
  ASSISTANT: 'assistant',
  SYSTEM: 'system',
  USER: 'user',
}

const openai = new OpenAI({
  apiKey: config.get('OPENAI_KEY'),
})

const getMessage = (m) => `
  Напиши на основе этих тезисов последовательную эмоциональную историю: ${m}

  Эти тезисы с описание ключевых моментов дня. 
  Необходимо в итоге получить такую историю, чтобы я запомнил этот день и смог рассказать ее друзьям. Текст не должен быть больше 100 слов. Главное — чтобы были эмоции, правильная последовательность и учитывался контекст.
`

export async function chatGPT(message = '') {
  const messages = [
    {
      role: ROLES.SYSTEM,
      content:
        'Ты опытный копирайтер, который пишет краткие эмоциональные статьи для соц сетей.',
    },
    { role: ROLES.USER, content: getMessage(message) },
  ]
  try {
    const completion = await openai.chat.completions.create({
      messages,
      model: CHATGPT_MODEL,
    })

    return completion.choices[0].message
  } catch (e) {
    console.error('Error while chat completion', e.message)
  }
}

Обратите внимание: мы присваиваем ChatGPT роль копирайтера для получения более качественных текстов. А также задаем первичное сообщение с указаниями для бота.

Интегрируем Notion

Самое время интегрировать Notion — для этого необходимо получить ключ к базе. В итоге получаем два ключа и готовую базу данных. Добавляем в конфигурацию:


    {
  "TELEGRAM_TOKEN": "ВАШ ТОКЕН ДЛЯ БОТА TELEGRAM",
  "OPENAI_KEY": "КЛЮЧ ДЛЯ CHATGPT",
  "NOTION_KEY": "КЛЮЧ ДЛЯ ИНТЕГРАЦИИ",
  "NOTION_DB_ID": "ID БАЗЫ ДАННЫХ"
}

В базе данных Notion (компонент inline database) указываем базовые поля — имя и дату. В приложении создаем отдельный файл ./src/notion.js и добавляем в него скрипт:


    import { Client } from '@notionhq/client'
import config from 'config'

const notion = new Client({
  auth: config.get('NOTION_KEY'),
})

export async function create(short, text) {
  const dbResponse = await notion.pages.create({
    parent: { database_id: config.get('NOTION_DB_ID') },
    properties: {
      Name: {
        title: [
          {
            text: {
              content: short,
            },
          },
        ],
      },
      Date: {
        date: {
          start: new Date().toISOString(),
        },
      },
    },
  })

  return dbResponse
}

Для того, чтобы полученный от ChatGPT текст записать как контент страницы, добавляем еще один скрипт:


    const pageResponse = await notion.blocks.children.append({
    block_id: dbResponse.id,
    children: [
      {
        object: 'block',
        type: 'paragraph',
        paragraph: {
          rich_text: [
            {
              type: 'text',
              text: {
                content: text,
              },
            },
          ],
        },
      },
    ],
  })

Создаем Loader

Так как выполнение скрипта занимает время, будем показывать пользователю процесс загрузки, Loader. В файле ./src/loader.js описываем логику этого объекта:


    export class Loader {
  icons = [
    '🕐','🕑','🕒',
    '🕓','🕔','🕕',
    '🕖','🕗','🕘',
    '🕙','🕚','🕛',
  ]
  interval = null
  message = null

  constructor(ctx) {
    this.ctx = ctx
  }

  async show() {
    let index = 0
    this.message = await this.ctx.reply(this.icons[index])
    this.interval = setInterval(() => {
      index = index < this.icons.length - 1 ? index + 1 : 0
      this.ctx.telegram.editMessageText(
        this.ctx.chat.id,
        this.message.message_id,
        null,
        this.icons[index]
      )
    }, 500)
  }

  hide() {
    this.ctx.telegram.deleteMessage(this.ctx.chat.id, this.message.message_id)
    clearInterval(this.interval)
  }
}

Теперь у нас есть класс, который показывает анимированные часы. Что дальше?

Собираем воедино: интеграция с Telegram

Все подготовительные работы выполнены, осталось собрать «пазл» в один скрипт ./src/main.js:


    import { chatGPT } from './chatgpt.js'
import { create } from './notion.js'
import { Loader } from './loader.js'

// ============

bot.on(message('text'), proccessGPTResponse)

async function proccessGPTResponse(ctx) {
  try {
    const text = ctx.message.text
    if (!text.trim()) ctx.reply('Текст не может быть пустым')
    const loader = new Loader(ctx)
    loader.show()
    const response = await chatGPT(text)

    if (!response) return ctx.reply(`Ошибка с API. ${response}`)

    const notionResp = await create(text, response.content)
    loader.hide()
    ctx.reply(`Ваша страница: ${notionResp.url}`)
  } catch (e) {
    console.log(`Error while proccessing gpt response`, e.message)
  }
}

Готово — скрипт полностью работает.

Пользователь отправляет тезисы за день, ChatGPT обрабатывает запрос и запускается Loader.
Бот сгенерировал и отправил страницу с историей.
Результат.

Деплой проекта на сервер

Для начала в папке config создаем пустой файл keep, чтобы она оставалась в пространстве Git. А также создаем .gitignore:


      
.gitignore
node_modules .vscode config/default.json

Далее создаем репозиторий на GitHub, заходим в терминал, инициализируем проект, делаем коммит и загружаем его:


    git init
git add .
git commit -m "initial commit"
git remote add origin REPO_URL
git push -u origin master

Настройка сервера и запуск проекта

Сейчас бот запущен на компьютере. Это неудобно, если вы хотите записывать истории круглосуточно. Ведь тогда нужно поддерживать бесперебойную работу компьютера и постоянное соединение с интернетом. Бота лучше перенести в облако. 

1. Переходим в раздел Облачная платформа внутри панели управления:

2. Создаем сервер. Для работы нашего приложения много мощностей не нужно, поэтому будет достаточно одного ядра vCPU с долей 20% и 512 МБ оперативной памяти:

3. Авторизуемся на сервере через консоль:

4. Обновляем систему и устанавливаем Git:


    apt update
apt install git

5. Устанавливаем Node.js — полная инструкция доступна в Академии Selectel:


    curl -o- <https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh> | bash
source ~/.bashrc 
nvm install 20 
nvm use 20 
npm -v 
node -v

6. Клонируем репозиторий GitHub и разворачиваем проект:


    git clone REPO_URL
cd PROJECT_FOLDER_NAME
npm i
touch config/default.json
nano config/default.json

7. Запускаем проект:


    npm install pm2 -g
pm2 start ./src/main.js

Готово — бот запущен на сервере и генерирует истории.

Заключение

В этой инструкции мы не просто сделали интересный проект, а изучили основные этапы разработки Telegram-ботов — от создания простого скрипта до деплоя на сервер. Полученные знания можно использовать при работе с более крупными проектами. Вне зависимости от того, какой они сложности, — в Selectel есть подходящая конфигурация.

Автор: Владилен Минин, создатель канала «Владилен Минин»