Sähkebotin kirjoittaminen R:ssä (osa 4): johdonmukaisen, loogisen dialogin rakentaminen botin kanssa

Jos olet jo lukenut edellisen kolme artikkelia tästä sarjasta, tiedät jo kuinka kirjoittaa täysimittaisia ​​sähkebotteja näppäimistöllä.

Tässä artikkelissa opimme kirjoittamaan botin, joka ylläpitää johdonmukaista vuoropuhelua. Nuo. Botti kysyy sinulta kysymyksiä ja odottaa, että annat joitain tietoja. Syöttämiesi tietojen mukaan botti suorittaa joitain toimintoja.

Myös tässä artikkelissa opimme käyttämään tietokantaa botin kannen alla, esimerkissämme se on SQLite, mutta voit käyttää mitä tahansa muuta DBMS:ää. Kirjoitin tarkemmin vuorovaikutuksesta R-kielellä olevien tietokantojen kanssa tässä artikkelissa.

Sähkebotin kirjoittaminen R:ssä (osa 4): johdonmukaisen, loogisen dialogin rakentaminen botin kanssa

Kaikki artikkelit sarjasta "Sähköbotin kirjoittaminen R:ssä"

  1. Luomme botin ja käytämme sitä viestien lähettämiseen sähkeissä
  2. Lisää komentotuki ja viestisuodattimet bottiin
  3. Kuinka lisätä näppäimistötukea bottiin
  4. Luo johdonmukainen, looginen vuoropuhelu botin kanssa

Pitoisuus

Jos olet kiinnostunut data-analyysistä, saatat olla kiinnostunut minun sähke и youtube kanavia. Suurin osa sisällöstä on omistettu R-kielelle.

  1. Esittely
  2. Botin rakennusprosessi
  3. Bottiprojektin rakenne
  4. Botin konfiguraatio
  5. Luo ympäristömuuttuja
  6. Tietokannan luominen
  7. Toimintojen kirjoittaminen tietokannan kanssa työskentelemiseen
  8. Bottimenetelmät
  9. Viestisuodattimet
  10. Käsittelijät
  11. Botin käynnistyskoodi
  12. Johtopäätös

Esittely

Jotta botti voi pyytää sinulta tietoja ja odottaa, että annat tiedot, sinun on tallennettava dialogin nykyinen tila. Paras tapa tehdä tämä on käyttää jonkinlaista sulautettua tietokantaa, kuten SQLite.

Nuo. Logiikka tulee olemaan seuraava. Kutsumme bot-menetelmää, ja botti pyytää meiltä tietoja peräkkäin, ja jokaisessa vaiheessa se odottaa näiden tietojen syöttämistä ja voi tarkistaa ne.

Kirjoitamme yksinkertaisimman mahdollisen botin, joka kysyy ensin nimeäsi, sitten ikääsi ja tallentaa vastaanotetut tiedot tietokantaan. Ikää kysyessään se tarkistaa, että syötetyt tiedot ovat numeroita eikä tekstiä.

Tällaisella yksinkertaisella dialogilla on vain kolme tilaa:

  1. start on botin normaali tila, jossa se ei odota sinulta mitään tietoa
  2. odota_nimi - tila, jossa botti odottaa nimen syöttämistä
  3. wait_age on tila, jossa botti odottaa ikäsi syöttämistä, kokonaisten vuosien lukumäärä.

Botin rakennusprosessi

Artikkelin aikana rakennamme botin askel askeleelta; koko prosessi voidaan kuvata kaavamaisesti seuraavasti:
Sähkebotin kirjoittaminen R:ssä (osa 4): johdonmukaisen, loogisen dialogin rakentaminen botin kanssa

  1. Luomme bot-konfiguraation, johon tallennamme joitain asetuksia. Meidän tapauksessamme bot-tunnus ja polku tietokantatiedostoon.
  2. Luomme ympäristömuuttujan, johon tallennetaan polku bottiin sisältävään projektiin.
  3. Luomme itse tietokannan ja useita toimintoja, jotta botti voi olla vuorovaikutuksessa sen kanssa.
  4. Kirjoitamme bottimenetelmiä, ts. toiminnot, joita se suorittaa.
  5. Viestisuodattimien lisääminen. Jonka avulla botti pääsee tarvittaviin menetelmiin, riippuen chatin nykytilasta.
  6. Lisäämme käsittelijöitä, jotka yhdistävät komennot ja viestit tarvittaviin bottimenetelmiin.
  7. Käynnistetään botti.

Bottiprojektin rakenne

Mukavuuden vuoksi jaamme bottimme koodin ja muut siihen liittyvät tiedostot seuraavaan rakenteeseen.

  • bot.R - bottimme pääkoodi
  • db_bot_function.R — koodilohko, jossa on toimintoja tietokannan kanssa työskentelyä varten
  • bot_methods.R — bot-menetelmien koodi
  • message_filters.R - viestisuodattimet
  • käsittelijät.R -käsittelijät
  • config.cfg - botin konfigurointi
  • create_db_data.sql — SQL-skripti taulukon luomiseen tietokannassa olevien keskustelutietojen kanssa
  • create_db_state.sql — SQL-skripti, jolla luodaan taulukko nykyisestä keskustelutilasta tietokannassa
  • bot.db - bot-tietokanta

Voit tarkastella koko bottiprojektia tai скачать minun arkisto GitHubissa.

Botin konfiguraatio

Käytämme kokoonpanona tavallista ini tiedosto, seuraavalla lomakkeella:

[bot_settings]
bot_token=ТОКЕН_ВАШЕГО_БОТА

[db_settings]
db_path=C:/ПУТЬ/К/ПАПКЕ/ПРОЕКТА/bot.db

Konfigissa kirjoitetaan bot-tunnus ja polku tietokantaan, ts. bot.db-tiedostoon; luomme itse tiedoston seuraavassa vaiheessa.

Monimutkaisemmille boteille voit luoda monimutkaisempia määrityksiä, eikä ini-konfiguraatiota tarvitse kirjoittaa, voit käyttää mitä tahansa muuta muotoa, mukaan lukien JSON.

Luo ympäristömuuttuja

Jokaisella PC:llä kansio, jossa bot-projekti voi sijaita eri hakemistoissa ja eri asemissa, joten koodissa projektikansion polku asetetaan ympäristömuuttujan kautta. TG_BOT_PATH.

Ympäristömuuttujan luomiseen on useita tapoja, yksinkertaisin on kirjoittaa se tiedostoon .Renviron.

Voit luoda tai muokata tätä tiedostoa komennolla file.edit(path.expand(file.path("~", ".Renviron"))). Suorita se ja lisää tiedostoon yksi rivi:

TG_BOT_PATH=C:/ПУТЬ/К/ВАШЕМУ/ПРОЕКТУ

Tallenna seuraavaksi tiedosto .Renviron ja käynnistä RStudio uudelleen.

Tietokannan luominen

Seuraava vaihe on tietokannan luominen. Tarvitsemme 2 pöytää:

  • chat_data — tiedot, jotka botti pyysi käyttäjältä
  • chat_state — kaikkien keskustelujen nykyinen tila

Voit luoda nämä taulukot käyttämällä seuraavaa SQL-kyselyä:

CREATE TABLE chat_data (
    chat_id BIGINT  PRIMARY KEY
                    UNIQUE,
    name    TEXT,
    age     INTEGER
);

CREATE TABLE chat_state (
    chat_id BIGINT PRIMARY KEY
                   UNIQUE,
    state   TEXT
);

Jos latasit bot-projektin osoitteesta GitHub, sitten tietokannan luomiseen voit käyttää seuraavaa koodia R:ssä.

# Скрипт создания базы данных
library(DBI)     # интерфейс для работы с СУБД
library(configr) # чтение конфига
library(readr)   # чтение текстовых SQL файлов
library(RSQLite) # драйвер для подключения к SQLite

# директория проекта
setwd(Sys.getenv('TG_BOT_PATH'))

# чтение конфига
cfg <- read.config('config.cfg')

# подключение к SQLite
con <- dbConnect(SQLite(), cfg$db_settings$db_path)

# Создание таблиц в базе
dbExecute(con, statement = read_file('create_db_data.sql'))
dbExecute(con, statement = read_file('create_db_state.sql'))

Toimintojen kirjoittaminen tietokannan kanssa työskentelemiseen

Meillä on jo määritystiedosto valmiina ja tietokanta luotu. Nyt sinun on kirjoitettava funktioita tietojen lukemiseksi ja kirjoittamiseksi tähän tietokantaan.

Jos latasit projektin osoitteesta GitHub, löydät toiminnot tiedostosta db_bot_function.R.

Toimintokoodi tietokannan kanssa työskentelemiseen

# ###########################################################
# Function for work bot with database

# получить текущее состояние чата
get_state <- function(chat_id) {

  con <- dbConnect(SQLite(), cfg$db_settings$db_path)

  chat_state <- dbGetQuery(con, str_interp("SELECT state FROM chat_state WHERE chat_id == ${chat_id}"))$state

  return(unlist(chat_state))

  dbDisconnect(con)
}

# установить текущее состояние чата
set_state <- function(chat_id, state) {

  con <- dbConnect(SQLite(), cfg$db_settings$db_path)

  # upsert состояние чата
  dbExecute(con, 
            str_interp("
            INSERT INTO chat_state (chat_id, state)
                VALUES(${chat_id}, '${state}') 
                ON CONFLICT(chat_id) 
                DO UPDATE SET state='${state}';
            ")
  )

  dbDisconnect(con)

}

# запись полученных данных в базу
set_chat_data <- function(chat_id, field, value) {

  con <- dbConnect(SQLite(), cfg$db_settings$db_path)

  # upsert состояние чата
  dbExecute(con, 
            str_interp("
            INSERT INTO chat_data (chat_id, ${field})
                VALUES(${chat_id}, '${value}') 
                ON CONFLICT(chat_id) 
                DO UPDATE SET ${field}='${value}';
            ")
  )

  dbDisconnect(con)

}

# read chat data
get_chat_data <- function(chat_id, field) {

  con <- dbConnect(SQLite(), cfg$db_settings$db_path)

  # upsert состояние чата
  data <- dbGetQuery(con, 
                     str_interp("
            SELECT ${field}
            FROM chat_data
            WHERE chat_id = ${chat_id};
            ")
  )

  dbDisconnect(con)

  return(data[[field]])

}

Loimme 4 yksinkertaista toimintoa:

  • get_state() - saada nykyinen keskustelutila tietokannasta
  • set_state() — kirjoita nykyinen keskustelutila tietokantaan
  • get_chat_data() — vastaanottaa käyttäjän lähettämiä tietoja
  • set_chat_data() — tallentaa käyttäjältä saadut tiedot

Kaikki toiminnot ovat melko yksinkertaisia, ne joko lukevat tietoja tietokannasta komennolla dbGetQuery(), tai sitoutua UPSERT toimintoa (olemassa olevien tietojen muuttaminen tai uuden tiedon kirjoittaminen tietokantaan) käyttämällä toimintoa dbExecute().

UPSERT-toiminnon syntaksi on seuraava:

INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}') 
ON CONFLICT(chat_id) 
DO UPDATE SET ${field}='${value}';

Nuo. taulukkokentässämme chat_id on ainutlaatuisuusrajoitus ja se on taulukoiden ensisijainen avain. Aluksi yritämme lisätä tietoja taulukkoon ja saamme virheilmoituksen, jos nykyisen keskustelun tiedot ovat jo olemassa, jolloin päivitämme tämän keskustelun tiedot.

Seuraavaksi käytämme näitä toimintoja botin menetelmissä ja suodattimissa.

Bottimenetelmät

Seuraava askel bottimme rakentamisessa on menetelmien luominen. Jos latasit projektin osoitteesta GitHub, kaikki menetelmät ovat tiedostossa bot_methods.R.

Botin menetelmäkoodi

# ###########################################################
# bot methods

# start dialog
start <- function(bot, update) {

  # 

  # Send query
  bot$sendMessage(update$message$chat_id, 
                  text = "Введи своё имя")

  # переключаем состояние диалога в режим ожидания ввода имени
  set_state(chat_id = update$message$chat_id, state = 'wait_name')

}

# get current chat state
state <- function(bot, update) {

  chat_state <- get_state(update$message$chat_id)

  # Send state
  bot$sendMessage(update$message$chat_id, 
                  text = unlist(chat_state))

}

# reset dialog state
reset <- function(bot, update) {

  set_state(chat_id = update$message$chat_id, state = 'start')

}

# enter username
enter_name <- function(bot, update) {

  uname <- update$message$text

  # Send message with name
  bot$sendMessage(update$message$chat_id, 
                  text = paste0(uname, ", приятно познакомится, я бот!"))

  # Записываем имя в глобальную переменную
  #username <<- uname
  set_chat_data(update$message$chat_id, 'name', uname) 

  # Справшиваем возраст
  bot$sendMessage(update$message$chat_id, 
                  text = "Сколько тебе лет?")

  # Меняем состояние на ожидание ввода имени
  set_state(chat_id = update$message$chat_id, state = 'wait_age')

}

# enter user age
enter_age <- function(bot, update) {

  uage <- as.numeric(update$message$text)

  # проверяем было введено число или нет
  if ( is.na(uage) ) {

    # если введено не число то переспрашиваем возраст
    bot$sendMessage(update$message$chat_id, 
                    text = "Ты ввёл некорректные данные, введи число")

  } else {

    # если введено число сообщаем что возраст принят
    bot$sendMessage(update$message$chat_id, 
                    text = "ОК, возраст принят")

    # записываем глобальную переменную с возрастом
    #userage <<- uage
    set_chat_data(update$message$chat_id, 'age', uage) 

    # сообщаем какие данные были собраны
    username <- get_chat_data(update$message$chat_id, 'name')
    userage  <- get_chat_data(update$message$chat_id, 'age')

    bot$sendMessage(update$message$chat_id, 
                    text = paste0("Тебя зовут ", username, " и тебе ", userage, " лет. Будем знакомы"))

    # возвращаем диалог в исходное состояние
    set_state(chat_id = update$message$chat_id, state = 'start')
  }

}

Loimme 5 menetelmää:

  • aloita — Käynnistä valintaikkuna
  • tila — Hae nykyinen keskustelutila
  • nollaa — Nollaa nykyinen chat-tila
  • enter_name – Botti kysyy nimeäsi
  • enter_age — Botti kysyy ikäsi

menetelmä start kysyy nimeäsi ja muuttaa keskustelutilaksi odota_nimi, eli valmiustilaan nimesi kirjoittamista varten.

Seuraavaksi lähetät nimen ja se käsitellään menetelmällä enter_name, botti tervehtii sinua, kirjoittaa vastaanotetun nimen tietokantaan ja vaihtaa chatin tilaan odotusikä.

Tässä vaiheessa botti odottaa sinun syöttävän ikäsi. Lähetät ikäsi, botti tarkistaa viestin, jos lähetit tekstiä numeron sijaan, se sanoo: Ты ввёл некорректные данные, введи число, ja odottaa, että syötät tietosi uudelleen. Jos lähetit numeron, botti ilmoittaa hyväksyneensä ikäsi, kirjoittaa vastaanotetut tiedot tietokantaan, raportoi kaikki sinulta saadut tiedot ja palauttaa chat-tilan alkuperäiseen asentoonsa, ts. V start.

Kutsumalla menetelmää state voit pyytää nykyistä chat-tilaa milloin tahansa ja käyttämällä reset palauttaa chatin alkuperäiseen tilaan.

Viestisuodattimet

Meidän tapauksessamme tämä on yksi tärkeimmistä osista botin rakentamisessa. Juuri viestisuodattimien avulla botti ymmärtää, mitä tietoa se odottaa sinulta ja miten se tulisi käsitellä.

Projektissa päällä GitHub suodattimet on rekisteröity tiedostoon message_filters.R.

Viestisuodatinkoodi:

# ###########################################################
# message state filters

# фильтр сообщений в состоянии ожидания имени
MessageFilters$wait_name <- BaseFilter(function(message) {
  get_state( message$chat_id )  == "wait_name"
}
)

# фильтр сообщений в состоянии ожидания возраста
MessageFilters$wait_age <- BaseFilter(function(message) {
  get_state( message$chat_id )   == "wait_age"
}
)

Suodattimissa käytämme aiemmin kirjoitettua funktiota get_state(), jotta voit pyytää chatin nykyistä tilaa. Tämä toiminto vaatii vain 1 argumentin, chat-tunnuksen.

Seuraava suodatin odota_nimi käsittelee viestejä, kun chat on tilassa wait_nameja vastaavasti suodatin odotusikä käsittelee viestejä, kun chat on tilassa wait_age.

Käsittelijät

Käsittelijöiden sisältävää tiedostoa kutsutaan käsittelijät.R, ja siinä on seuraava koodi:

# ###########################################################
# handlers

# command handlers
start_h <- CommandHandler('start', start)
state_h <- CommandHandler('state', state)
reset_h <- CommandHandler('reset', reset)

# message handlers
## !MessageFilters$command - означает что команды данные обработчики не обрабатывают, 
## только текстовые сообщения
wait_age_h  <- MessageHandler(enter_age,  MessageFilters$wait_age  & !MessageFilters$command)
wait_name_h <- MessageHandler(enter_name, MessageFilters$wait_name & !MessageFilters$command)

Ensin luomme komentokäsittelijät, joiden avulla voit käynnistää valintaikkunan, nollata sen ja tehdä kyselyn nykyisestä tilasta.

Seuraavaksi luomme 2 viestinkäsittelijää käyttämällä edellisessä vaiheessa luotuja suodattimia ja lisäämme niihin suodattimen !MessageFilters$command, jotta voimme käyttää komentoja missä tahansa keskustelutilassa.

Botin käynnistyskoodi

Nyt meillä on kaikki valmiina käynnistykseen, pääkoodi botin käynnistämiseksi on tiedostossa bot.R.

library(telegram.bot)
library(tidyverse)
library(RSQLite)
library(DBI)
library(configr)

# переходим в папку проекта
setwd(Sys.getenv('TG_BOT_PATH'))

# читаем конфиг
cfg <- read.config('config.cfg')

# создаём экземпляр бота
updater <- Updater(cfg$bot_settings$bot_token)

# Загрузка компонентов бота
source('db_bot_function.R') # функции для работы с БД
source('bot_methods.R')     # методы бота
source('message_filters.R') # фильтры сообщений
source('handlers.R') # обработчики сообщений

# Добавляем обработчики в диспетчер
updater <- updater +
  start_h +
  wait_age_h +
  wait_name_h +
  state_h +
  reset_h

# Запускаем бота
updater$start_polling()

Tuloksena saimme tämän botin:
Sähkebotin kirjoittaminen R:ssä (osa 4): johdonmukaisen, loogisen dialogin rakentaminen botin kanssa

Milloin tahansa komennolla /state voimme tiedustella nykyistä keskustelutilaa ja käyttämällä komentoa /reset palauta keskustelu alkuperäiseen tilaan ja aloita dialogi uudelleen.

Johtopäätös

Tässä artikkelissa selvitimme, kuinka käyttää tietokantaa botin sisällä ja kuinka luoda peräkkäisiä loogisia dialogeja tallentamalla keskustelutila.

Tässä tapauksessa tarkastelimme alkeellisinta esimerkkiä, jotta sinun olisi helpompi ymmärtää ajatus tällaisten robottien rakentamisesta; käytännössä voit rakentaa paljon monimutkaisempia dialogeja.

Tämän sarjan seuraavassa artikkelissa opimme rajoittamaan botin käyttäjien oikeuksia käyttää sen eri menetelmiä.

Lähde: will.com

Lisää kommentti