- PVSM.RU - https://www.pvsm.ru -
Т.к. мой классификатор из прошлого поста [1] таки работает (впрочем, параметры «из коробки» не всегда удачны, потому я вынес возможность слегка настроить Conv1d-слои и скрытый слой) — я решил прикрутить его к боту. Да, запоздал я на этот хайп :-). Кстати, заранее уточню, что прикрутить русский я пока таки не пробовал, хотя это не должно стать проблемой — в nltk поддерживаются нужные фичи, обучение word2vec концептуально не отличается от английского, да и предобученные модели вроде бы имеются.
Ну и сходу возникают вопросы:
Понадобятся:
import logging
from robotframework_telegram import RobotFrameworkTelegram
from config import config
if __name__ == '__main__':
bots = RobotFrameworkTelegram({
'DATABASE_URI': 'URI',
'KEEP_WORD_VECTORS': 3,
'ROBOT_CONFIGURATIONS': 'robot_configurations',
'KEEP_ROBOTS': 5,
'OUTPUT_HANDLERS': {},
'TOKENS': [
# Your tokens here
],
'NO_ANSWER_MESSAGE': 'Sorry, I can't answer now.',
'NO_INSTANCE_MESSAGE': 'Sorry, robot not instantiated yet. ' +
'You'll get answer after instantiation - it can take few minutes',
'TELEGRAM_WORKERS_PER_BOT': 1,
'WORKER_COUNT': 2,
'WORKER_SLEEP_TIME': 0.2,
'LOGGER': logging,
})
bots.start_polling()
За данными (структура и дамп postgres-й БД, word2vec, конфиг обученного бота) — сюда [7].
В моём случае сценарий бота может быть описан как дерево (ну, на самом деле — с учётом «goto» — скорее граф), узел которого может содержать условия:
Кроме дерева в сценарии указаны:
Например
script:
text: Hello. I'm weather robot. How can I help you?
name: main
children:
-
name: city_conditions
text: "Conditions in {%print $city%} is next."
conditions:
class: conditions
entity_variables:
city: $city
-
name: city_temperature
text: "Temperature in {%print $city%} is next."
conditions:
class: temperature
entity_variables:
city: $city
-
name: conditions
text: Okay, type city name.
conditions:
class: conditions
children:
-
name: conditions_city_selected
text: "{%goto city_conditions%}"
conditions:
entity_variables:
city: $city
-
name: temperature
text: Okay, type city name.
conditions:
class: temperature
children:
-
name: temperature_city_selected
text: "{%goto city_temperature%}"
conditions:
entity_variables:
city: $city
entities:
city:
- Moscow
- Tokyo
- Ottava
synonyms:
Moscow:
- default city
- DC
classes:
temperature:
- How hot is it today?
- Is it hot outside?
- Will it be uncomfortably hot?
- Will it be sweltering?
- How cold is it today?
- Is it cold outside?
- Will it be uncomfortably cold?
- Will it be frigid?
- What is the expected high for today?
- What is the expected temperature?
- Will high temperatures be dangerous?
- Is it dangerously cold?
- When will the heat subside?
- Is it hot?
- Is it cold?
- How cold is it now?
- Will we have a cold day today?
- When will the cold subside?
- What highs are we expecting?
- What lows are we expecting?
- Is it warm?
- Is it chilly?
- What's the current temp in Celsius?
- What is the temperature in Fahrenheit?
conditions:
- Is it windy?
- Will it rain today?
- What are the chances for rain?
- Will we get snow?
- Are we expecting sunny conditions?
- Is it overcast?
- Will it be cloudy?
- How much rain will fall today?
- How much snow are we expecting?
- Is it windy outside?
- How much snow do we expect?
- Is the forecast calling for snow today?
- Will we see some sun?
- When will the rain subside?
- Is it cloudy?
- Is it sunny now?
- Will it rain?
- Will we have much snow?
- Are the winds dangerous?
- What is the expected snowfall today?
- Will it be dry?
- Will it be breezy?
- Will it be humid?
- What is today's expected humidity?
- Will the blizzard hit us?
- Is it drizzling?
classifier_params:
filter_sizes: [1]
hidden_size: 100
nb_filter: 150
min_class_confidence: 0.8
Переключение из 1 состояния в другое (а заодно — извлечение сущностей) в другое происходит так:
Ужасный код на bitbucket [3]. Для начала — выделил такие сущности
Теперь возможно такое:
script = Script.load(os.path.join(os.path.dirname(__file__), "script.yaml"))
text_processor = TextProcessor("english",
[["turn", "on"], ["turn", "off"]],
Word2Vec.load_word2vec_format(
os.path.join(os.path.dirname(__file__), "100d.txt")
))
robot = Robot(script, text_processor)
state, output = robot.output()
self.assertEqual(output, "Hello. I'm weather robot. How can I help you?")
self.assertIsNotNone(state)
self.assertEqual(state.stage, "main")
self.assertEqual(state.variables, {})
state, output = robot.answer(state, "How cold it'll be in Moscow today?")
self.assertIsNotNone(state)
self.assertEqual(state.stage, "city_temperature")
self.assertEqual(state.variables, {"$city": ["Moscow"]})
self.assertEqual(output, "Temperature in Moscow is next.")
Уже можно пытаться что-нибудь запустить, но я пошёл дальше.
Ещё более ужасный код на bitbucket [4]. Опять делим сущности:
Как-то так:
Пример кода:
from robotframework import *
from sqlalchemy import select
app = Application({
'DATABASE_URI': '',
'KEEP_WORD_VECTORS': 4
})
robot = Robot.filter(lambda query: query.where(Robot.id == 1))[0]
user = User.filter(lambda query: query.where(User.id == 1))[0]
conversation = robot.converse(user)
#print(robot.instance)
items = lambda: print([str(item) for item in conversation.items])
items()
conversation.output()
conversation.answer('How hot it'll be in Moscow today?')
conversation.answer('Okay, turn off')
items()
Ну и в результате
[] ["Hello. I'm weather robot. How can I help you?", "How hot it'll be in Moscow today", "Temperature in Moscow is next", ""]
Последняя запись пуста, т.к. в сценарии нет узла по которому можно перейти в этом случае.
В конфигурации — следующие опции
{
'DATABASE_URI' : '', # URI для подлючения sqlalchemy к СУБД
'KEEP_WORD_VECTORS': 3, # одновременно хранится не более заданного числа "словарей" word2vec, иначе будет выгружен тот, к которому (относительно) давно не было обращений
'KEEP_ROBOTS': 3, # число хранимых одновременно роботов
'ROBOT_CONFIGURATIONS': 'robot_configurations', # директория, где хранятся конфигурации обученных роботов,
'OUTPUT_HANDLERS': {}
}
Теперь у нас вроде бы есть все средства для более или менее адекватного хранения роботов, их состояний и вспомогательных данных. И — возможность прикручивать их к различным мессенджерам (да и не только), прикрутив соответсвующую обёртку.
Перед просмотром кода рекомендуется запастись успокоительными [5]. Обёртка добавляет к моделям ещё пару полей (telegram_chat_id в Conversation, telegram_bot_id в Robot). Ну и многопоточность во все поля.
Вот пример:
import logging
from robotframework_telegram import RobotFrameworkTelegram
from config import config
if __name__ == '__main__':
bots = RobotFrameworkTelegram({
'DATABASE_URI': 'URI',
'KEEP_WORD_VECTORS': 3,
'ROBOT_CONFIGURATIONS': 'robot_configurations',
'KEEP_ROBOTS': 5,
'OUTPUT_HANDLERS': {},
'TOKENS': [
# Your tokens here
],
'NO_ANSWER_MESSAGE': 'Sorry, I can't answer now.',
'NO_INSTANCE_MESSAGE': 'Sorry, robot not instantiated yet. ' +
'You'll get answer after instantiation - it can take few minutes',
'TELEGRAM_WORKERS_PER_BOT': 1,
'WORKER_COUNT': 2,
'WORKER_SLEEP_TIME': 0.2,
'LOGGER': logging,
})
bots.start_polling()
И диалог полученный при тесте
[7:14:55 AM] #: /start [7:14:56 AM] robotframework_demo_weather: Sorry, robot not instantiated yet. You'll get answer after instantiation - it can take few minuutes Hello. I'm weather robot. How can I help you? [7:16:07 AM] #: It's cold? [7:16:08 AM] robotframework_demo_weather: Okay, type city name. [7:16:11 AM] #: Moscow [7:16:11 AM] robotframework_demo_weather: Temperature in Moscow is next. [7:40:25 AM] #: /start [7:40:26 AM] robotframework_demo_weather: Hello. I'm weather robot. How can I help you? [7:40:48 AM] #: What is your destination, robot? Seems like you mustn't answer [7:40:48 AM] robotframework_demo_weather: Sorry, I can't answer now.
Автор: alex4321
Источник [18]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/mashinnoe-obuchenie/217155
Ссылки в тексте:
[1] прошлого поста: https://habrahabr.ru/post/315118/
[2] pynlc: https://bitbucket.org/alex43210/pynlc
[3] robot: https://bitbucket.org/alex43210/robot
[4] robotframework: https://bitbucket.org/alex43210/robotframework
[5] robotframework_telegram: https://bitbucket.org/alex43210/robotframework_telegram
[6] python-telegram-bot: https://github.com/python-telegram-bot/python-telegram-bot
[7] сюда: https://drive.google.com/file/d/0B7cY3wBgM-aBRG02RDlPc0t0ejg/view?usp=sharing
[8] robot/script.py: https://bitbucket.org/alex43210/robot/src/c2570efb2af8fe11077b2f466a926be27f44eef4/robot/script.py?at=master&fileviewer=file-view-default
[9] robot/robot_state.py: https://bitbucket.org/alex43210/robot/src/c2570efb2af8fe11077b2f466a926be27f44eef4/robot/robot_state.py?at=master&fileviewer=file-view-default
[10] robot/output_processing.py: https://bitbucket.org/alex43210/robot/src/c2570efb2af8fe11077b2f466a926be27f44eef4/robot/output_processing.py?at=master&fileviewer=file-view-default
[11] robot/robot.py: https://bitbucket.org/alex43210/robot/src/c2570efb2af8fe11077b2f466a926be27f44eef4/robot/robot.py?at=master&fileviewer=file-view-default
[12] robotframework/models/language.py: https://bitbucket.org/alex43210/robotframework/src/48748769f358a4694080fda8294f6241b2e771ed/robotframework/models/language.py?at=master&fileviewer=file-view-default
[13] robotframework/models/domain.py: https://bitbucket.org/alex43210/robotframework/src/48748769f358a4694080fda8294f6241b2e771ed/robotframework/models/domain.py?at=master&fileviewer=file-view-default
[14] robotframework/models/robot.py: https://bitbucket.org/alex43210/robotframework/src/48748769f358a4694080fda8294f6241b2e771ed/robotframework/models/robot.py?at=master&fileviewer=file-view-default
[15] robotframework/models/user.py: https://bitbucket.org/alex43210/robotframework/src/48748769f358a4694080fda8294f6241b2e771ed/robotframework/models/user.py?at=master&fileviewer=file-view-default
[16] robotframework/models/conversation.py: https://bitbucket.org/alex43210/robotframework/src/48748769f358a4694080fda8294f6241b2e771ed/robotframework/models/conversation.py?at=master&fileviewer=file-view-default
[17] robotframework/models/conversation_item.py: https://bitbucket.org/alex43210/robotframework/src/48748769f358a4694080fda8294f6241b2e771ed/robotframework/models/conversation_item.py?at=master&fileviewer=file-view-default
[18] Источник: https://habrahabr.ru/post/316838/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.