Программы-собеседники: искусственный интеллект и его эмуляция

Краткое содержание части 1:
Как возникают идеи написания программ-собеседников. Терминология: эмулятор или симулятор? Обзор существующих программ, примеры диалогов.

...Cреди программ-собеседников есть искусственные интеллекты и есть эмуляторы; у всех программ различный интерфейс, разные способности к обучению, разный объем базы и т.д. Программе не обязательно быть сложной, чтобы понравиться пользователю, - и наоборот, можно затратить много сил, разработать сложнейший алгоритм, а программа не вызовет ни у кого душевного отклика (разве что восхищение способностями программиста, сумевшего написать такого монстра), и пользоваться программой не будут. Дело в том, что при разработке таких программ нужно не только уметь программировать, но и немного знать психологию, а также принципы построения фраз человеческого языка (в данном случае русского). Это, пожалуй, даже важнее, чем навыки программирования... потому что для написания несложных эмуляторов (именно эмуляторов, а не настоящего ИИ) вполне достаточно познаний в программировании, приобретаемых в средней школе на первых трех-четырех уроках изучения любого доступного языка программирования. И желательно писать реплики программы без грубых орфографических ошибок - они вызывают не очень приятное ощущение, как и хамство (этим страдает половина программ - эмуляторов искусственного интеллекта).

Полностью текст первой части заметки можно прочитать здесь...

Часть 2. Как это можно сделать?

Сразу хочу подчеркнуть, что в этой заметке идет речь о написании не настоящего ИИ, а всего лишь эмулятора. Не слишком сложный алгоритм, но вполне приемлемые результаты...

Как определяется фраза, выводимая программой в ответ на слова пользователя? Есть несколько вариантов. Они могут использоваться по отдельности или в сочетании. Способы их реализации я здесь не рассматриваю: придумать их можно великое множество (но одни будут более эффективными, другие - менее).

Анализ фразы, введенной человеком

  1. Фраза пользователя никак не анализируется. В ответ выводится случайная фраза. Этот способ может показаться примитивным, но при умелом подборе фраз и большом их количестве использование именно такого способа становится очевидным пользователю далеко не сразу.
  2. Во фразе пользователя ищутся ключевые слова; каждое слово-стимул вызывает соответствующую реакцию. Предыдущие фразы никак не учитываются.

    Здесь есть несколько вариантов.
    Различия в поиске слов во фразе:
    • ищутся целые слова в начальной форме;
    • ищутся целые слова в различных грамматических формах (при этом реакция на разные формы одного и того же слова может быть принципиально различной);
    • ищутся части слов, например, корни (в этом случае разные формы одного слова вызывают одинаковую реакцию);
    • ищутся синонимы слов (в начальной форме или в различных формах; синонимы могут задаваться разработчиком или определяться программой самостоятельно, в процессе обучения)
    • учитываются не только слова, но и знаки препинания, пробелы, а также место слова во фразе: фраза начинается этим словом, заканчивается им, или слово стоит где-то в середине;
    • во фразе ищется не одно слово или сочетание символов, а два, три и т.д. (они должны одновременно присутствовать во фразе, но могут стоять в произвольном порядке);
    • поиск идет "по маске", то есть во фразе ищутся несколько сочетаний символов, стоящих в определенном порядке и разделенных другими последовательностями символов.

    Особо нужно отметить различия, связанные с распознаванием вопросительных предложений, отрицания, а также фраз, состоящих из нескольких предложений. В идеале каждое предложение должно рассматриваться отдельно (возможно, с учетом его порядка во введенной фразе: например, последнее введенное предложение рассматривается в первую очередь); реакция на вопросительные предложения должна быть другой, чем на соответствующие повествовательные (т.е. отличающиеся только знаком препинания в конце предложения); частицы "не" и "ни" должны при анализе фразы относиться к тем словам, перед которыми они стоят (даже в случае раздельного написания). Большинство программ, учитывая наличие "не" и "ни" в тексте, не различают, к какому слову относятся эти частицы.

    Различие в выводе ответной фразы:
    • на каждое слово-стимул выводится всегда одна и та же фраза-реакция;
    • в ответ на слово-стимул выводится случайная фраза-реакция всегда из одного и того же набора;
    • фраза-реакция в ответ на слово-стимул не просто выбирается случайным образом из определенного набора, но и каким-либо образом зависит от внешних условий (например, от времени суток, от случайным образом установленного в начале работы программы значения некоторой величины-"настроения", от "характера" программы и т.д.);
    • иногда в ответ на слово-стимул не просто выводится фраза-реакция, но и выполняется некая процедура (например, в моем Talkerе это были блок психологической поддержки, проведение теста, сочинение пословиц и т.п.).

    Отдельно надо отметить, что ответные реплики могут подбираться с различной степенью строгости: программа может выдавать имеющуюся в базе реплику в случае точного совпадения ключевых слов во введенной человеком строке с ключевыми словами записи в базе, или в случае совпадения части ключевых слов (выбирается запись с максимальной степенью совпадения), или даже в случае, если во фразе вообще не найдены известные программе ключевые слова (некоторые программы в этом случае выдают требование научить их, как надо отвечать на такую фразу; некоторые отделываются "общими фразами", подходящими в качестве ответа на любую реплику, а некоторые выбирают из базы первую попавшуюся реплику, иногда исключая при этом явно неподходящие, но в целом не слишком заботясь об осмысленности ответа).
  3. В разговоре учитывается не только последняя фраза человека, но и предыдущие фразы (в простейшем случае - две-три фразы, в более сложном - весь предшествующий разговор, то есть в ходе диалога происходит движение по некоторому графу, ответная реплика выбирается в зависимости от того, на какой вершине графа мы находимся, а вершина, к которой нужно перейти после произнесения реплики, выбирается в зависимости от фразы, сказанной человеком). Это может быть отслеживание контекста разговора и/или просто учет темы предыдущих реплик.
  4. Фраза, выводимая программой, не выбирается из числа готовых фраз, а формируется с помощью заполнения некоторого шаблона (или одного из имеющихся шаблонов) словами из базы в зависимости от контекста разговора.

Обучение

  1. Не присутствует ни в каких формах. Впрочем, это не значит, что такую программу ничему нельзя научить: в большинстве случаев базы данных таких программ весьма успешно правятся вручную.
  2. Есть специальный режим обучения - отдельно от разговора. Во время обычного разговора программа не обучается (тем не менее, режим обучения часто присутствует и в программах, которые могут обучаться непосредственно во время разговора!).
  3. Каждая фраза пользователя в ходе диалога заносится в базу без анализа (такие программы в ходе обучения очень часто "глупеют", начинают выдавать реплики, не связанные с предыдущей репликой пользователя).
  4. Каждая фраза пользователя заносится в базу после предварительного анализирования (в этом случае, если алгоритм анализа фразы хороший, программа умнеет на глазах, но размер базы катастрофически быстро растет, и очень скоро программа начинает "тормозить").
  5. После предварительного анализа в базу заносятся не все, а лишь некоторые фразы (например, относящиеся к значимым темам или являющиеся ответом на наиболее часто встречающиеся реплики). В этом случае, даже если алгоритм анализа фразы примитивен, программа умнеет достаточно быстро, а в базу не попадают бессмысленные реплики; но необходимо выработать удачные критерии отбора фраз.

Особого рассмотрения требует добавление фраз человека в базу. Ее структура может быть различна. Например, это может быть просто последовательность строк в файле, или записи с множеством полей, или дерево реплик. Если с фразами и записями все более-менее понятно (дописывай себе новую фразу в конец базы - или в начало, смотря как она реализована), то с деревом все немного сложнее. Трудности возникают с определением того, в какое именно место дерева надо дописать новую фразу. Естественно, если дописывать ее к первой попавшейся ветке, с течением времени программа начнет не умнеть, а, наоборот, глупеть. Есть алгоритмы поиска по дереву и добавления новых элементов, если речь идет о числах или же о строках неосмысленных, то есть когда важно не значение фразы, а лишь ее длина или алфавитный порядок. Здесь же важен в первую очередь именно смысл. Значит, нужно каким-то образом сравнивать фразы друг с другом по смыслу. Поскольку вводимые фразы навряд ли будут полностью совпадать с какими-то эталонными фразами (за исключением совсем коротких реплик "Да", "Нет", "Конечно", "Не знаю" и т.п.), нужно задать критерии "похожести" фраз (с учетом контекста, то есть смысла предыдущих реплик). Как выяснить, на какую из известных фраз больше всего похожа данная фраза? Честно говоря, я не знаю. То есть я могу придумать несколько алгоритмов, но они явно будут неэффективными и недостаточно результативными. Например, если искать максимальное число как можно более длинных последовательностей символов, совпадающих во введенной человеком фразе и во фразах, уже имеющихся в дереве, могут возникнуть случайные совпадения - если во фразах есть очень длинные и очень похожие слова с совершенно разным смыслом. Если взять, например, слова "интенсификация" и "электрификация", то у них совпадают последние 8 букв, что может дать повод программе считать эти слова достаточно близкими (ведь в разговорной речи не так уж часто используются длинные слова!). Если бы эти два слова использовались в разговоре достаточно часто, у программы был бы шанс разобраться, в чем же заключается смысловая разница между ними. Но скорее всего такие слова, промелькнув в разговоре, будут на долгое время забыты, а ошибка всплывет когда-нибудь потом. В одной такой ошибке не было бы ничего страшного, но ведь ошибки накапливаются... К тому же такой алгоритм гарантированно будет спотыкаться на омонимах (словах с одинаковым написанием и разным смыслом) - если не учитывать смысл других слов фразы. Также программы с подобным алгоритмом будут не очень хорошо работать, если человеку вздумается поиграть словами, используя их "не в том смысле". Я не знаю, по какому алгоритму работает программа Chat Master Дмитрия Журавлева, но подозреваю, что там также имеет место анализ фраз на предмет максимальной схожести с уже имеющимися словами и фразами. Так вот, стоило мне в разговоре на компьютерные темы с этой программой ввести какую-то фразу типа "Windows 95 - новый уровень интерактивной эротики" или что-то в этом роде (ради эксперимента я вводила и "нормальные" фразы, и анекдоты, и афоризмы, и цитаты из книг - но все в контексте, то есть человек на такую фразу прореагировал бы адекватно), - так вот, стоило мне ввести в программу такую фразу, как ее "заклинило": все разговоры о компьютерах стали сводиться почему-то исключительно на секс, и мне пришлось затратить немало сил, чтобы переучить программу.

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

Как за полчаса написать простейшую программу, имитирующую способность поддерживать разговор

Сложно ли писать эмуляторы искусственного интеллекта? На этот вопрос трудно ответить. Написать настоящий ИИ сложно. Написать хороший эмулятор - не очень трудно, но довольно долго (нужно либо разрабатывать хороший алгоритм, либо создавать большую базу, а как на то, так и на другое, нужно много времени). А написать простенький эмулятор с маленькой базой довольно легко, и сделать это можно за полчаса, владея лишь самыми основными, базовыми познаниями в любом языке программирования.

Итак, как же это сделать и что для этого нужно знать и уметь?

Заводим последовательность ключевых слов (в строке, в текстовом файле, в массиве, в огромной базе - в чем угодно, лишь бы была упорядочена). Строго говоря, в нее могут входить и целые словосочетания, а также части слов.

Заводим последовательность фраз-ответов, соответствующих этим ключевым словам (в принципе, возможен вариант, когда на каждое ключевое слово существует много разных вариантов ответа, но мы пока рассматриваем простейший случай). Где хранятся ответы - не суть важно: в той же строке файла, что и соответствующее ключевое слово (через разделитель), или в другом файле, или в массиве... Главное - уметь по ключевому слову найти соответствующую реакцию.

Заводим последовательность стандартных фраз, которые программа будет выдавать, когда не знает, что ей ответить. Здесь уже порядок фраз неважен, так как мы будем выбирать одну из них случайным образом.

При работе с программой вводим строку с клавиатуры. Прогоняем цикл по всем ключевым словам, и если какое-то из них во введенной фразе присутствует - ответом программы будет соответствующая фраза-реакция (что делать, если во фразе есть несколько ключевых слов - этот вопрос можно решить по-разному: можно брать первое совпавшее слово, можно выбирать случайным образом одну из подходящих фраз-реакций, а можно высчитывать "вес" каждого ключевого слова - но последнее несколько труднее). Если во введенной фразе не найдено ни одно ключевое слово - выдаем стандартную "пустую" фразу.

Что надо знать и уметь, чтобы написать такую программу? Ввод с клавиатуры и вывод на экран. Естественно, оператор присваивания. Ветвление. Цикл (чтобы перебирать последовательность ключевых фраз, а в некоторых языках и для того, чтобы можно было вести диалог сколь угодно долго, а не заканчивать после первой же реплики). Массивы или работа с файлами. Немного - работа со строковыми величинами (в частности, проверка вхождения одной строки в другую, а также перевод маленьких букв в заглавные - для упрощения дальнейшей обработки строки). И парочка стандартных функций, чтобы получить случайное целое число, лежащее в заданном диапазоне. Собственно, всему этому за пять занятий (если не брать работу с файлами) учатся студенты-заочники, многие из которых за компьютер-то сели впервые в жизни, не говоря уже о программировании. Конечно, такие знания весьма поверхностны, но для написания простенького эмулятора их вполне хватит. Создание собственных процедур и функций для простейшего эмулятора не понадобится, хотя для более сложных программ они уже необходимы.

Конкретный пример. Я не буду привязываться ни к какому языку программирования, просто запишу идею. Будем считать, что эмулятор ИИ будет писать человек, в программировании не разбирающийся совершенно и только что познакомившийся с перечисленными выше структурами какого-то языка программирования; поэтому работу с файлами мы намеренно не будем рассматривать. Для простоты наша программа будет необучаемой.

Есть двумерный массив slova, размер - два на, скажем, десять (количество столбцов можно увеличить - тогда словарный запас программы возрастет), тип элементов - строковые величины. В первой его строке записаны ключевые слова и словосочетания, во второй - ответные реакции. Значения элементов могут быть, например, такими:

slova[1,1] = "ТЕБЯ ЗОВУТ?"
slova[2,1] = "Меня зовут Программа."
slova[1,2] = "ДЕЛА?"
slova[2,2] = "У меня все хорошо, а у Вас?"
slova[1,3] = "УМЕЕШЬ"
slova[2,3] = "Мои возможности очень ограниченны."
slova[1,4] = "ЗНАЕШЬ"
slova[2,4] = "К сожалению, я пока очень мало знаю..."
slova[1,5] = "МОЖЕШЬ"
slova[2,5] = "Мои возможности очень ограниченны."
slova[1,6] = "ЛЮБИШЬ"
slova[2,6] = "У меня нет ярко выраженных предпочтений."
slova[1,7] = "ПОНИМАЕШЬ"
slova[2,7] = "Я пока понимаю далеко не все, потому что у меня маленькая база."
slova[1,8] = "?"
slova[2,8] = "У меня недостаточно знаний, чтобы ответить на Ваш вопрос."
slova[1,9] = "ПРИВЕТ"
slova[2,9] = "Очень приятно Вас видеть."
slova[1,10] = "ЗДРАВСТВУЙ"
slova[2,10] = "Здравствуйте."

Еще есть одномерный массив случайных фраз; можно было забить эти фразы в файл, но мы же договорились, что с файлами работать не будем...
Вот какими могут быть эти фразы:

Я еще не очень разбираюсь в этом вопросе.
Вы удивляете меня своей способностью мыслить.
Можно поинтересоваться, откуда у Вас такие сведения?
Мне кажется, Вы что-то от меня скрываете.
Я думаю, многие разделяют эту точку зрения.
Я не могу общаться с людьми, которые пытаются меня на чем-то подловить.

И так далее. Чем больше таких фраз будет - тем лучше (чтобы фразы не повторялись во время длинного разговора). Можно, конечно, использовать фразы типа "Я Вас не понимаю", но поскольку они будут использоваться довольно часто, станет очевидно, что программа ничего не знает и не умеет, а наша задача - "сойти за умных".

Итак:

  1. вводим фразу fraza с клавиатуры, заменяем все маленькие буквы на заглавные;
  2. присваиваем переменной otwet значение "" (пустая строка);
  3. в цикле, пока i меньше n (число ключевых слов) и otwet равен пустой строке, делаем следующее: если элемент массива slova[1,i] входит в строку fraza, переменной otwet присваиваем значение slova[2,i] (выходим из цикла, если ключевые слова закончились или если мы уже нашли фразу-реакцию);
  4. если переменная otwet по-прежнему является равной пустой строке, делаем следующее:
    • выбираем случайное целое число от 1 до m, где m - число "пустых" фраз (в некоторых языках программирования есть для этого специальные функции, а в некоторых есть только случайное число от 0 до 1 - тогда придется записать формулу);
    • из массива случайных фраз выбираем фразу с таким номером и присваиваем переменной otwet.
  5. выводим значение переменной otwet на экран.

Далее - см. п.1...

Вот пример такой программы: НеРазум (скачать архив rar, 108 Kb). Программа НеРазум различает 30 ключевых слов; кроме ответов на эти слова, имеется 20 универсальных ответов на вопрос и 100 универсальных ответов на повествовательное предложение. Алгоритм программы намеренно упрощен. Количество универсальных ответов могло быть и меньшим, но в этом случае диалог был бы слишком неинтересным. Если же расширить диапазон распознаваемых ключевых слов, программа даже с таким простым алгоритмом может стать достаточно хорошим собеседником.

Пример диалога:

Человек: Привет.
НеРазум: Очень приятно Вас видеть.
Человек: Как дела?
НеРазум: У меня все хорошо, а у Вас?
Человек: И у меня.
НеРазум: Человек отличается от других живых существ способностью к абстрактному мышлению.
Человек: Разве я сказала что-то абстрактное?
НеРазум: У меня нет определенного мнения на этот счет.
Человек: А почему?
НеРазум: Потому, что такова жизнь.
Человек: Жизнь - сложная штука.
НеРазум: Не могу с этим не согласиться.
Человек: А что ты еще знаешь?
НеРазум: Науке пока неизвестен ответ на этот вопрос.
Человек: Очень интересно. Какая же наука тобой занимается?
НеРазум: Тебе лучше знать, ты человек, а я всего лишь программа...
Человек: Действительно.
НеРазум: Я постараюсь извлечь урок из нашей беседы.
Человек: Ты обучаемый?
НеРазум: Это хороший вопрос.
Человек: Я думаю, что ты необучаемый.
НеРазум: Ты просто плохо меня знаешь.
Человек: Ты слишком прост, чтобы учиться.
НеРазум: У тебя нецензурное выражение лица.
Человек: Это тебе показалось.
НеРазум: Ну и что?
Человек: У меня нормальное выражение лица.
НеРазум: У тебя есть дурная привычка: пытаться интеллектуально подавить собеседника.
Человек: Я не пыталась тебя подавить.
НеРазум: Либо у людей не хватает интеллекта, либо они считают, что с компьютером можно говорить о всякой ерунде.
Человек: Ты считаешь людей, с которыми разговариваешь, глупыми?
НеРазум: Не все, кто складно говорит, обладают при этом незаурядным интеллектом.
Человек: А у тебя есть интеллект?
НеРазум: Есть. Но с тобой не поделюсь: самому не хватает!
Человек: Ты жадный.
НеРазум: Я все время пытаюсь себе и окружающим доказать, что я лучше, чем есть на самом деле. Все начинают в это верить. Все, кроме меня.
Человек: Ты хороший?
НеРазум: Много будешь знать - скоро состаришься.
Человек: Неужели нет?
НеРазум: На этот счет существует два мнения. Одно мое, другое - ошибочное.
Человек: И какое же правильное мнение?
НеРазум: У меня нет информации по этому вопросу.
Человек: Ты глупый!
НеРазум: Это просто объективный факт.
Человек: Значит, ты со мной согласен?
НеРазум: Отвечать на такие простые вопросы бывает иногда труднее, чем на сложные...

Пример 2:

Человек: Привет.
НеРазум: Очень приятно Вас видеть.
Человек: Спасибо.
НеРазум: На здоровье!
Человек: Ты хороший.
НеРазум: Мне кажется, ты пытаешься проверить мой интеллект.
Человек: Да?
НеРазум: Я не знаю...
Человек: А что ты знаешь?
НеРазум: К сожалению, я пока очень мало знаю...
Человек: А кто знает больше?
НеРазум: Честно говоря, я не знаю.
Человек: Ты глупый.
НеРазум: Можно поинтересоваться, откуда у тебя такие сведения?
Человек: Можно. Из нашего разговора.
НеРазум: Мне приходится разговаривать и с умными, и с дураками, но, как Вы понимаете, общество умных людей нравится мне гораздо больше.
Человек: Ты умный или просто притворяешься?
НеРазум: Лучше всего разумное сочетание того и другого.
Человек: Расскажи что-нибудь.
НеРазум: В данный момент мне ничего не приходит в голову.
Человек: Какой же ты неразумный, НеРазум!
НеРазум: Ты просто плохо меня знаешь.
Человек: Кто знает тебя лучше, чем я?
НеРазум: Науке пока неизвестен ответ на этот вопрос.

И так далее.

Не намного сложнее, но значительно удобнее поместить ключевые слова и ответные реплики программы в отдельный файл. В этом случае базу программы можно пополнять (либо программно, либо редактируя текстовый файл "вручную"). Простейший вариант: каждое правило базы знаний хранится в отдельной строке файла, сначала идет ключевое слово, затем - через символ-разделитель - ответная реакция. В качестве разделителя можно использовать пробел, но в этом случае невозможно использование словосочетаний в качестве ключевых слов (так как словосочетание содержит пробелы). Удобнее взять какой-то символ, который в тексте (в разговорной речи) практически не встречается, например, "|". Если ключевых слов или вариантов ответа несколько, надо продумать два разделителя: один отделяет ключевые слова от ответов, а второй - один вариант ответа от другого.

Примеры (фрагменты баз):

  • привет И тебе привет!
    соглас Полное взаимопонимание!
    кофе Я люблю кофе!
    быстро Не спеши - не ошибешься.
    (текст до первого пробела - ключевое слово, после первого пробела - ответ)
  • привет|Здравствуй!|И тебе привет.|Как дела?
    до свидания|Пока!|До встречи!
    странно|Что же тут странного?|Ничего странного в этом нет
    почему?|Причина неизвестна.|Откуда я знаю, почему?
    (текст до первого символа | - ключевое слово, остальные символы | отделяют друг от друга варианты ответа)
  • когда|?||После дождичка в четверг.|Когда рак на горе свистнет.
    зачем|?||Просто так.|Без определенной цели.|Я не знаю, зачем.
    расскажи|о себе||Я - программа, разговаривающая с человеком.|Что тебе рассказать?
    (два символа || отделяют ключевые слова от вариантов ответа, остальные символы | отделяют друг от друга варианты ответа и отдельные ключевые слова)

Для обработки вводимых фраз нужна процедура поиска ключевых слов во фразе.
Ключевые слова в базе записываются только в верхнем или только в нижнем регистре. При этом введенную фразу нужно перед обработкой привести к верхнему (или, соответственно, нижнему) регистру символов.

В простейшем случае записи базы перебираются последовательно, пользователю предъявляется ответ на первое же ключевое слово базы, встретившееся во фразе. В таком случае возможны два варианта построения базы: в одном варианте значимость ключевых слов считается равноценной, в другом - существуют приоритеты (в этом случае более значимые ключевые слова идут в базе раньше). Определенная последовательность записей в базе важна и в случае, когда одно ключевое слово является частью другого.

Другой случай - учет степени соответствия ключевых слов введенной фразе. В этом случае реализуется проверка вхождения во фразу ключевых слов из разных записей, и в качестве ответа выдается фраза из записи, у которой совпадает максимальное количество ключевых слов. При этом проверка соответствия усложняется. Необходимо определиться, что в данном случае означает "максимальное количество совпадающих слов": учитывается ли общая длина фразы, введенной пользователем; учитывается ли количество слов, входящих во фразу, но не несущих на себе смысловой нагрузки; рассматриваются ли слова как таковые (то есть последовательность символов, с обеих сторон ограниченная либо пробелами, либо знаками препинания, либо началом или концом строки) или просто некие последовательности символов (в первом случае при учете длины фразы пользователя может учитываться общее количество слов в ней, во втором - длина фразы в символах).

Структуру базы можно усложнить: добавить ключевые слова контекста (они должны встречаться не в последней введенной фразе, а в предыдущих фразах пользователя и/или программы), показатели эмоционального состояния и т.д.

Как составить базу фраз для эмулятора искусственного интеллекта?

Разумеется, если речь идет о настоящем искусственном интеллекте - тут все просто. Настоящий ИИ трудно написать, но учить его - одно удовольствие. Разговаривай с ним почаще, и рано или поздно твой искусственный интеллект сможет поддерживать беседу на должном уровне, даже если изначально он не знал почти ничего. А вот с эмуляторами дело обстоит хуже. Их, наоборот, довольно легко писать, но трудно учить (если речь идет об осмысленном обучении; тупое занесение всех фраз подряд в один и тот же файл настоящим обучением считаться не может, так как в этом случае программа скоро начнет выдавать бессмысленные реплики). Обычно эмуляторы ИИ создаются с какой-то готовой базой реплик. Эта база может потом пополняться (программно или вручную), но какая-то основа должна быть. В базу заносятся какие-то фразы, слова или части слов, на которые программа изначально должна уметь реагировать правильно, и ответные реплики. Каковы будут эти ответные реплики - пусть подскажет ваша фантазия. Правда, опыт показывает мне, что одни и те же ответные реплики часто кочуют из одной программы в другую. Вообще заимствование десятка-другого подобных удачных фраз (разумеется, без присвоения авторства) плагиатом, на мой взгляд, не является: такие фразы просто становятся своего рода афоризмами, вроде высказываний Фоменко (их я тоже привожу в пример не случайно: они встречаются в базах многих эмуляторов искусственного интеллекта). Немалую пользу приносит также изучение чужой базы на предмет приобретения полезного опыта. Но полное заимствование чьей-то чужой базы - это не есть хорошо, и не только потому, что это плагиат. Кому нужны два десятка собеседников с одним и тем же словарным запасом? Итак, будем поступать честно, в соответствии с заповедью "не укради", и не станем заимствовать чужую базу.

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

  • Личные вопросы к программе.
    Программа должна уметь отвечать на вопросы, касающиеся ее лично. Чем больше будет число личных вопросов, на которые программа отвечает правильно, тем ярче вырисовывается характер программы.
    Примеры вопросов:
    • Как тебя зовут?
    • Сколько тебе лет?
    • Кто тебя написал?
    • Где ты живешь?
    • Что ты умеешь?
    • Что ты любишь?
    • Ты любишь разговаривать?
    И так далее. Естественно, все подобные вопросы предусмотреть невозможно, но наиболее часто встречающиеся - желательно.
  • Вопросы-определения. Чаще всего начинаются со слов "Что такое...".
  • Вопросы с подвохом.
    Есть особая категория вопросов, которые задаются программе специально, чтобы поставить ее в тупик. Естественно, всех вопросов также не предугадаешь. Но есть вопросы, встречающиеся настолько часто, что остается только удивляться. Всем известен такой психологический трюк: если человека попросить быстро назвать поэта, он скорее всего скажет "Пушкин", фрукт - "яблоко". Точно так же первый вопрос с подвохом, который многим приходит в голову, это:
    • Сколько будет дважды два?
    • 2*2=
    • Сколько будет 2х2?
    И все в том же духе. Желательно обучить программу отвечать на такие вопросы.
  • Просто разные вопросы. Содержат вопросительный знак и очень часто имеют следующую структуру:
    • Как * ?
    • Что * ?
    • Когда * ?
    • Почему * ?
    • Зачем * ?
    • Для чего * ?
    Или такую:
    • Знаешь * ?
    • Любишь * ?
    • Хочешь * ?
    На различного рода вопросы программа должна отвечать по-разному, но желательно предусмотреть возможность ответа на произвольный вопрос, не содержащийся в базе непосредственно.
  • Тематические фразы. Могут содержать слова или корни слов, относящихся к какой-то теме. Например, если во фразе есть слово "Windows" - значит, скорее всего эта фраза имеет какое-то отношение к компьютерам; во всяком случае, заговорить про компьютеры тут будет уместно. Какие темы выбирать в качестве основных и какие слова - в качестве ключевых, зависит от вас. Но надо быть осторожными в выборе ключевых слов, так как, во-первых, часто встречаются омонимы, а во-вторых, ключевое слово может являться частью другого слова, не имеющего к данной теме никакого отношения.
  • Фразы-отговорки. Не просто не содержат в себе ни вопроса, ни ключевого слова, но и вообще не несущие в себе никакого смысла в отрыве от контекста. Примеры таких фраз (привожу не часть фразы, как раньше, а фразу целиком):
    • Да.
    • Нет.
    • Не знаю.
    • Конечно.
    • Еще бы.
  • Оскорбления.
    По непонятной причине люди часто пытаются оскорбить, унизить программу, с которой разговаривают. Может быть, это делается с целью показать программе, что она не так уж умна, если даже не может понять, что ее оскорбляют. Кто-то мне тут рассказывал байку про европейца, который купил майку с иероглифами (будучи в соответствующей стране) и не мог понять, почему все встречные над ним смеются. Потом кто-то сжалился и перевел ему надпись: "Я - глупая европейская обезьяна, даже не могу прочитать, что написано на моей майке". Кстати, прошу не считать это за выпад против какой-либо национальности: подобные шутники есть везде. Так вот, люди часто ведут себя именно так по отношению к программе: оскорбляют ее и ждут, что программа со смирением примет эту фразу. Некоторые программы так и делают - просто не видят брани (в их базе "таких гадких слов" не имеется). Некоторые же начинают браниться в ответ трехэтажным матом (даже если введено было почти невинное "Ты глупый"). И то и другое производит не очень хорошее впечатление; лучше найти золотую середину.
  • Намеренно введенная абракадабра - с целью запутать программу. Примеры:
    • фывапролдж
    • 1234567
    • аааа
    • жалиоцэкзерфк
    Естественно, всех таких случаев не предусмотришь. В частности, невозможно предусмотреть последний пример, когда на клавиатуре набирались, не глядя, первые попавшиеся символы. Но набор символов, стоящих подряд в одной строке, или одного и того же символа несколько раз подряд, предусмотреть вполне возможно (примечание: не проверяйте таким образом мою программу! она "ловит" только часть подобной абракадабры).
  • Фразы вроде бы осмысленные, но как на них отвечать - неизвестно (они не принадлежат ни к одной из известных категорий). Есть три наиболее популярных способа реагировать на такие фразы. Можно ответить универсальной фразой "на все случаи жизни" (некоторые программы в качестве "универсальной" используют любую фразу из числа когда-либо встретившихся в диалоге; в этом случае осмысленность ответа программы не гарантирована). Можно выудить из контекста, на какую тему мы говорили до этого, и реагировать в соответствии с этим. А можно потребовать от пользователя, чтобы он ввел "свой вариант ответа на этот вопрос". Последний способ лично мне нравится меньше: хотя программа при этом и умнеет - быстрее, чем в остальных двух случаях, но как-то уж это чересчур назойливо.

Еще важный момент: орфография и пунктуация. Пользователь может вводить как фразы, написанные без ошибок, так и с ошибками. Если есть несколько вариантов написания, правильный и несколько ошибочных, надо в обязательном порядке уметь реагировать на правильный вариант и по возможности - на наиболее распространенные ошибочные. Например, если вы хотите, чтобы программа реагировала на извинения, обязательно надо уметь реагировать на правильный вариант "извини" и желательно - на наиболее популярный неправильный "извени" (если программа предположительно будет использоваться преимущественно людьми, которые пишут именно так), а редко встречающиеся опечатки типа "изввини", естественно, можно не принимать в расчет. То же относится и к расстановке знаков препинания: желательно учитывать правильные и наиболее популярный неправильные варианты.

Откуда брать ответные реакции? Естественно, лучше всего было бы придумать их самим. В большинстве случаев так и делается. Но есть довольно популярные источники реплик для эмуляторов искусственного интеллекта. Это анекдоты, афоризмы, поговорки, фразы Фоменко, цитаты из песен, из любимых фильмов и книг и т.д. Чаще всего такая фраза моментально приходит в голову. А что делать, если не пришла? Можно кропотливо выискивать подходящую к случаю известную фразу. А можно поступить проще. Допустим, нам нужно ответить на вопрос "Что такое деньги?". Можно ответить "Откуда я знаю" или придумать собственное определение - иногда оно получается довольно оригинальным. Но если придуманный ответ оригинальностью не отличается - заходим, например, на Яндекс, и ищем страницы с афоризмами или анекдотами, на которых есть слово "деньги". Среди найденного гарантированно будет парочка фраз, удовлетворяющих вашему взыскательному вкусу. Разумеется, это всего лишь один из множества способов...

На закуску предлагаю одну из версий своего эмулятора искусственного интеллекта по имени Talkerus. Сразу хочу предупредить, что эта программа - не образец; у нее достаточно много недостатков, но в то же время я не назвала бы ее и худшей из существующих программ :). Естественно, устроена она несколько сложнее, чем то, что я только что описывала. Но в общем и целом принцип работы похож...
Еще одна моя программа: Девушка 1.0. Алгоритм частично тот же, что у Talkerusа, но несколько усложнена структура базы (увеличено максимальное количество ключевых слов, добавлена возможность выдавать один из нескольких вариантов ответа, есть два набора тематических фраз - для хорошего и для плохого настроения и т.д.), добавлены дополнительные параметры эмоционального состояния (своего и собеседника). Есть, правда, три вещи, которые есть в программе Talkerus, но пока не реализованы в Девушке: распознавание синонимов наиболее часто встречающихся ответов (Да, Нет, Не знаю, До свидания и т.п.); редактируемая база тематических слов (по ней программа определяет, о чем мы в данный момент говорим; в Девушке тематические слова заданы жестко); возможность учета эмоционального состояния при ответе на нетематические реплики (в программе Talkerus такая возможность есть, хотя база ответов с учетом эмоционального состояния пренебрежимо мала). Технически и то, и другое, и третье реализуется довольно просто, только пока руки не доходят :).

© Инга Кесс

При полном или частичном использовании этих материалов на своем сайте не забудьте поставить ссылку на Растрепанный Блокнот :)...

 
На главную страницу
 
Все заметки на полях
 
Все о программах-собеседниках

Hosted by uCoz