© Dmitry Bodyonov (aka dimkazavr), 2005.
# python
Говорящий робот delta – демо-версия.
Введите свой текст в поле и нажмите кнопку отправки справа (или [ENTER]) чтобы получить ответ робота.
Описание
delta – программа автоответчик. Может использоваться как самостоятельная программа (в том числе, как сетевой демон в linux/*nix системах), либо как часть другой программы на python.
В delta используется простой контекстно-независимый алгоритм (без сохранения контекста разговора), выбирающий ответ соответствующий шаблону. В шаблонах возможно использовать регулярные выражения, ответ выбирается случайно из списка возможных для данного шаблона. Ответы могут содержать макроопределения, которые рекурсивно раскрываются при формировании результата.
Формат словарей
Словари хранятся в формате xml, возможна загрузка нескольких словарей. Декларация типа документа (DTD) для словаря имеет вид:
<!DOCTYPE dictionary [
<!-- Словарь состоит из необязательного описания и набора записей -->
<!ELEMENT dictionary (description?, entry*) >
<!-- Обязательно указание версии формата словаря в виде атрибуда тега-->
<!ATTLIST dictionary version CDATA #REQUIRED>
<!-- В описании может быть имя автора, дата и коментарии -->
<!ELEMENT description (author?, date?, comments?)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT date (#PCDATA)>
<!ELEMENT comments (#PCDATA)>
<!-- Каждая запись словаря состоит из списков шаблонов и ответов -->
<!ELEMENT entry (patterns, answers)>
<!-- Для записи можно указать приоритет -->
<!ATTLIST entry priority CDATA #IMPLIED>
<!-- Список шаблонов состоит из шаблонов -->
<!ELEMENT patterns (pattern+)>
<!-- Шаблон -- это любые текстовые данные -->
<!ELEMENT pattern (#PCDATA)>
<!-- Шаблон может иметь атрибут типа -->
<!ATTLIST pattern type (macro|exc|asis) #IMPLIED>
<! Список ответов состоит из ответов -->
<!ELEMENT answers (answer+)>
<!-- Ответ -- это любые текстовые данные -->
<!ELEMENT answer (#PCDATA)>
]>Пример простейшего словаря:
<?xml version = '1.0'?>
<dictionary version="1.0">
<entry>
<patterns>
<pattern>hello</pattern>
<pattern>good morning</pattern>
</patterns>
<answers>
<answer>hi!</answer>
<answer>hello</answer>
</answers>
</entry>
</dictionary>
В описании шаблонов используются регулярные выражения, потому часть символов представляет собой специальные последовательности, например '.', '*', '?', '+', '^', '$', '\b', '\s', '\w' ... (полный список специальных символов и их описание приведен в Python Library Reference). Если необходимо использовать специальные символы в самой строке шаблона их необходимо отделить символом '\', или же указать атрибут type="asis".
Примеры шаблонов:
.......
<pattern>кто здесь\?</pattern>
<pattern>я люблю .*</pattern>
<pattern>^да$</pattern>
.......Если для шаблона указан тип 'exc', то данный шаблон будет отнесен в список шаблонов исключений для данной записи.
При поиске варианта ответа будет выбрана запись, имеющая наибольший приоритет, а также имеющая совпадение хотя бы одного шаблона со входной строкой и не имеющая совпадений с шаблонами из списка исключений. Более высокий приоритет имеют записи, определения которых в xml файле идут раньше. Также возможно явное указание приритета с помощью атрибута priority в теге entry.
Ответ выбирается случайно из списка возможных ответов для выбранной записи. Строка ответа может содержать специальные макроопределения, которые раскрываются рекурсивно. Имя макроопределения начинается и заканчивается символом '$'. Если необходимо использовать символ '$' в самой строке, следует удвоить этот символ – '$$'.
Макроопределения $1$, $2$ и т.д. заменяются на части входной строки, соответствующие выделенным группам в регулярном выражении шаблона. Например
....
<pattern>я хочу(.*)</pattern>
....
<answer>я не хочу $1$</answer>
....Для остальных макроопределений производится поиск в основном словаре подходящей записи. Такая запись должна содержать шаблон вида
....
<pattern>\$macroname\$</pattern>
....Можно не использовать символы '\$' по краям строки, а указать тип шаблона, type="macro".
Описание файлов
- delta.py
-
основной модуль, реализация 'движка' автоответчика.
Соджержит набор классов для организации словарей и работы с ними.
Главным классом, реализующим собственно интерфейс движка является
класс delta. У него доступны следующие методы:
- LoadDictionary (FILENAME)
- Загрузка словаря из файла. Метод возвращает количество загруженных записей в случае успеха, в случае неудачи возбуждает исключение. Регулярные выражения для шаблонов для записей во время загрузки компилируются чтобы уменьшить время поиска ответов, соответственно это сказывается на времени загрузки каждого словаря.
- Parse(INPUT)
- Генерация ответа на исходную строку INPUT. Строка INPUT должна быть типа unicode.
- SetDebugMode (mode)
- Установка режима отладки. При значениях больше 0, сообщения будут выводится на стандартный поток вывода.
Пример использования модуля:
# подключение модуля import delta # создание экземпляра движка E = delta.delta() # загрузка словаря E.LoadDictionary ("dictionary.xml") # печать ответа на строку 'hello' print E.Parse("hello") - commander-delta.py
программа с комманднострочным интерфейсом для delta.
Имеет следующий формат вызова:
commander-delta.py [-d] [-p] [-l LNAG] [dictrionary 1] ...Опция '-p' включает повторный вывод исходных строк вместе с результатом. Опция '-d' увеличивает степень подробности сообщений отладки, можно указать несколько опций '-d', тогда уровень будет выше. Опция '-l' задает локаль, в которой должна работать программа. Для корректной обработки строк необходимо правильное зачение локали, а также указание кодировки, используемой для входных и выходных файлов. Если опция не задана, то будет использовано значение переменной окружения $LANG.
Пример работы программы:
dima@fedik> ./commander-delta.py ===================================================== = Command line interface for the delta. = ===================================================== (c) Dmitry Bodyonov 2005 bodyonov<>karelia.ru ===================================================== [*] Applying locale settings (ru_RU.KOI8-R) [*] Creating delta instance [*] Loading dictionary ( dictionary.xml ) Done. Have fun! :) > hello ну привет- tk-delta.py
программа с графическим интерфейсом на основе Tk для delta.
(На некоторых системах (RH9) наблюдались проблемы с выводом русских символов. Возможно это является результатом недостаточного опыта или количества серого вещества у меня, однако на большинстве проверенных систем (SuSE9.1, SuSE9.3, WinXP) таких проблем нет.)
- server-delta.py
Простой tcp сервер для delta.
Так как время загрузки большого словаря может быть значительным (до нескольких секунд), то это может стать проблемой в случае когда нужно выполнять серию независымых запросов. Логичным вариантом выглядит запуск единого сервера, однажды загрузившего словари, и принимающего запросы от клиентов, в том числе и находящихся на других хостах.
Параметры вызова сервера:
server-delta.py [-p PORT] [-a ADDR] [-d] [-l LANG] [ dictionary 1 ] ...Возможно указать порт на котором должен слушать сервер (по умолчанию 17777), а также адрес к которому необходимо привязаться (по умолчанию 127.0.0.1) Опция '-d' увеличивает уровень отладочных сообщений.
Сервер реализует простейшую итеративную модель обработки – в каждый момент времени может обслуживаться не более одного клиента. В текущей версии сервер не уходит в фон при запуске и не ограничивает время общения с клиентом.
Протокол общения с сервером имеет следующий формат:
- клиент устанавливает соединение
- клиентом посылается исходная строка в формате UTF8
- сервером посылается строка в ответ в формате UTF8
- соединение закрывается сервером
- client-delta.py
клиент для tcp сервера delta.
Все строки пользователя клиент отправляет на сервер и печатает полученный от него результат.
Формат вызова клиента:
client-delta.py [-a ADDR] [-p PORT] [-l LANG] [-r] [-s TEXT] [-q]ADDR и PORT определяют адрес и порт сервера, по умолчанию используются значения 127.0.0.1:17777. Опиция '-l' позволяет указать локаль и кодировку, если опция пропущена, то используется переменная окружения $LANG. Опция '-r' включает режим печати исходных строк. Опция '-q' выключает вывод сообщений диагностики. Если задана опция '-s', то ее параметр будет использован как строка введенная пользователем, после обработки этого запроса клиент закончит работу.
Пример работы клиента:
dima@fedik> ./client-delta.py ===================================================== = Client for the delta server. = ===================================================== (c) Dmitry Bodyonov 2005 bodyonov<>karelia.ru ===================================================== [*] Creating encoder for your locale ( ru_RU.KOI8-R ) Done. Have fun! :) > hello hello > how are you? [error]: Connection to 127.0.0.1:17777 failed- dictionary-russian.xml, dictionary-mat.xml
- Мои словари, составленные на основе разговоров по icq.
Демо версия
Желающие проверить работу автоответчика могут пообщаться с роботом по
icq #251019635 (если он будет online, состояние в данный момент:
).
В качестве icq клиента используется centericq, delta вызывается в
качестве "внешного действия" следующим образом:
dima@research> cat ~/.centericq/external
%action Answering machine
event msg
proto all
status all
options stdout stdin
%exec
#!/bin/bash
msg=`cat`
/home/dima/Work/Projects/delta/release/client-delta.py -q -r -s "$msg" 2>/dev/null
Запуск программы
Для запуска программы требуется наличие python версии не ниже 2.2, а также наличие модуля xml.
Благодарности
За помощь в составлении словарей, а также за тестирование робота выражается благодарность Заморской Наталье (Belka UIN=47367313) и Романчуку Алексею (Mad_Dog).
