Чат-бот Python, який вміє шукати відповіді у Wikipedia
Всім привіт!
Давно хотів зробити свій власний Jarvis. Нещодавно вдалася вільна хвилинка, і я його зробив. Він вміє переписуватись з Вами, а також шукати відповіді на Ваші запитання у Wikipedia. Для його реалізації я використовував мову Python.
Для початку встановимо всі необхідні бібліотеки. Їх три: pyTelegramBotAPI, fuzzy-wuzzy, і навіть Wikipedia. Встановлюються вони просто:
pip install pyTelegramBotAPI
pip install Wikipedia
pip install fuzzywuzzy
Після встановлення всіх бібліотек приступаємо до розробки. Для початку імпортуємо всі бібліотеки, встановимо мову для Вікіпедії та підключимо телеграм бота:
import telebot, wikipedia, re
from fuzzywuzzy import process
from random import choice
alphabet = "1234567890йцукнегшщзхїєждлорпавіфячсмитьбюґ.,%?():;@"
wikipedia.set_lang("ukr")
bot = telebot.TeleBot('Ваш ключ, отриманий від BotFather')
Тепер напишемо код для очищення всіх непотрібних нам знаків, які вводить користувач:
def clean_str(r):
r = r.lower()
r = [c for c in r if c in alphabet]
return ''.join(r)
Також Вам необхідно створити в папці, де знаходиться Ваш код файл dialogues.txt, в ньому ми створюватимемо репліки на які має відповідати бот. Ось приклад цього файлу:
Привіт\привіт[email protected]хелоу[email protected]як сам?
Як справи?\дуже добре[email protected]гарно
Рядок до знака \ означає питання користувача, а після відповідь нашого бота. Відповіді поділяються знаком @. Він поділяє фрази бота одна від одної, щоб бот міг вибирати рандомні фрази з кількох запропонованих, для імітації більш живої розмови. Після чого напишемо такий код у наш файл з ботом:
def update():
with open('dialogues.txt', encoding='utf-8') as f:
content = f.read()
blocks = content.split('\n')
dataset = []
for block in blocks:
replicas = block.split('\\')[:2]
if len(replicas) == 2:
pair = [clean_str(replicas[0]), clean_str(replicas[1])]
if pair[0] and pair[1]:
dataset.append(pair)
global X_text
global y
for question, answer in dataset[:10000]:
X_text.append(question)
y += [answer]
update()
Цей шматок коду читає файл dialogues.txt, потім перетворює репліки на так звані вектори, за допомогою яких наш бот шукатиме найбільш відповідну відповідь до заданого нами питання. Наприклад, якщо Ви написали у файлі dialogues.txt питання «Ти знаєш Надію?», а відповідь на нього «Так, звичайно», то бот буде відповідати також і на схожі питання, наприклад «Ти знаєш Васю».
Тепер напишемо шматок коду, який генеруватиме відповіді на основі векторів:
def get_generative_replica(text):
global X_text
global y
question = process.extractOne(text, X_text)[0]
answer = y[X_text.index(question)]
answer = answer.split('@')
return choice(answer)
Цей шматок коду приймає запитання від користувача та повертає відповідь від бота, рандомно обравши один з поданих варіантів (якщо вони є), за допомогою бібліотеки random та fuzzywuzzy.
Тепер напишемо функцію для пошуку інформації у Вікіпедії:
def getwiki(s):
try:
ny = wikipedia.page(s)
wikitext=ny.content[:1000]
wikimas=wikitext.split('.')
wikimas = wikimas[:-1]
wikitext2 = ''
for x in wikimas:
if not('==' in x):
if(len((x.strip()))>3):
wikitext2=wikitext2+x+'.'
else:
break
wikitext2=re.sub('\{[^\{\}]*\}', '', wikitext2)
return wikitext2
except Exception as e:
return 'У вікіпедії немає інформації про це :('
Цей шматок коду отримує питання користувача, потім шукає відповідь на нього у Вікіпедії і якщо відповідь знайдена, то віддає її користувачеві, а якщо відповідь не знайдена, то пише, що «Вікіпедія не має інформації про це».
Тепер пишемо останній шматок коду:
@bot.message_handler(commands=['start'])
def start_message(message):
bot.send_message(message.chat.id,"Доброго дня!")
question = ""
@bot.message_handler(content_types=['text'])
def get_text_messages(message):
command = message.text.lower()
if command =="не так":
bot.send_message(message.from_user.id, "а як?")
bot.register_next_step_handler(message, wrong)
else:
global question
question = command
reply = get_generative_replica(command)
if reply=="вики ":
bot.send_message(message.from_user.id, getwiki(command))
else:
bot.send_message(message.from_user.id, reply)
def wrong(message):
a = f"{question}\{message.text.lower()} \n"
with open('dialogues.txt', "a", encoding='utf-8') as f:
f.write(a)
bot.send_message(message.from_user.id, "Готово")
update()
У цьому шматку коду телеграм бот при отриманні повідомлення від користувача відповідає на нього і якщо відповідь не вірна, то користувач пише «не так». Якщо бот отримує повідомлення «не так», він бере останнє запитання користувача і запитує «а як?», після чого користувач повинен відправити йому правильну відповідь. Після цього бот оновлює свою базу даних питань та відповідей і за наступних питань користувача відповідає на них правильно. І якщо відповідь на запитання бот повинен був взяти з Вікіпедії, то користувач у відповідь на запитання «а як?» повинен написати «wiki». Залишилося наприкінці приписати рядок:
bot.polling(none_stop=True)
І можна запускати та тестувати бота.
Сподіваюся стаття вам сподобалася :). Протестувати цього бота ви можете на моєму сайті. Весь код файлу з ботом прикладаю нижче:
import telebot, wikipedia, re
from fuzzywuzzy import process
from random import choice
alphabet = "1234567890йцукнегшщзхїєждлорпавіфячсмитьбюґ.,%?():;@"
wikipedia.set_lang("ukr")
bot = telebot.TeleBot('Ваш ключ, отриманий від BotFather')
def clean_str(r):
r = r.lower()
r = [c for c in r if c in alphabet]
return ''.join(r)
def update():
with open('dialogues.txt', encoding='utf-8') as f:
content = f.read()
blocks = content.split('\n')
dataset = []
for block in blocks:
replicas = block.split('\\')[:2]
if len(replicas) == 2:
pair = [clean_str(replicas[0]), clean_str(replicas[1])]
if pair[0] and pair[1]:
dataset.append(pair)
global X_text
global y
for question, answer in dataset[:10000]:
X_text.append(question)
y += [answer]
update()
def get_generative_replica(text):
global X_text
global y
question = process.extractOne(text, X_text)[0]
answer = y[X_text.index(question)]
answer = answer.split('@')
return choice(answer)
def getwiki(s):
try:
ny = wikipedia.page(s)
wikitext=ny.content[:1000]
wikimas=wikitext.split('.')
wikimas = wikimas[:-1]
wikitext2 = ''
for x in wikimas:
if not('==' in x):
if(len((x.strip()))>3):
wikitext2=wikitext2+x+'.'
else:
break
wikitext2=re.sub('\{[^\{\}]*\}', '', wikitext2)
return wikitext2
except Exception as e:
return 'У вікіпедії немає інформації про це :('
@bot.message_handler(commands=['start'])
def start_message(message):
bot.send_message(message.chat.id,"Доброго дня!")
question = ""
@bot.message_handler(content_types=['text'])
def get_text_messages(message):
command = message.text.lower()
if command =="не так":
bot.send_message(message.from_user.id, "а як?")
bot.register_next_step_handler(message, wrong)
else:
global question
question = command
reply = get_generative_replica(command)
if reply=="вики ":
bot.send_message(message.from_user.id, getwiki(command))
else:
bot.send_message(message.from_user.id, reply)
def wrong(message):
a = f"{question}\{message.text.lower()} \n"
with open('dialogues.txt', "a", encoding='utf-8') as f:
f.write(a)
bot.send_message(message.from_user.id, "Готово")
update()
bot.polling(none_stop=True)
6 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів