Чат-программа «AI»

Я собрал эту простую программу чата, и пока она работает. Я думаю, что это может, конечно, использовать некоторое улучшение. Вот как это работает.

  1. Получить пользовательский ввод, удалив всю пунктуацию из входной строки, разделив ее на пробел и превратив ее в set.
  2. Прокрутите список возможных наборов входных данных и проверьте следующее условие: \ $ \ text {Возможный набор ввода} \ subseteq \ text {Набор пользовательских входов} \ $
  3. Возвращает случайный ответ на основе вышеуказанного условия и выводит ответ.

Можно ли сделать это более гибким и расширяемым?

from re import sub as rsub
from random import choice


def obtain_user_input(prompt: str) -> set:
    """
    Obtains user input. This function 
    removes all punctuation, lowers text, 
    splits on whitespace, and returns a
    set of all the unique elements. An
    example input value could be:

        "Hello, hello, there, there"

    And the return value would be:

        ["hello", "there"]
    """
    user_input = input(prompt)
    user_input = rsub("[^a-zA-Z0-9\s]*", user_input, "")
    user_input = user_input.lower()
    user_input = user_input.split(" ")
    return set(user_input)


def get_replies(user_input: set) -> str:
    """
    This function returns a string as
    a "reply" to user input. This is done
    by checking if any of the possible
    inputs are subsets of the user's input.
    If so, then a random "reply" is returned.
    """
    possible_replies = [
        [{"hi"}, ["Hello there.", "Hello.", "Hi."]],
        [{"hello"}, ["Hello there.", "Hello.", "Hi."]],
        [{"goodbye"}, ["Goodbye user.", "Goodbye", "Bye."]],
        [{"your", "name"}, ["My name is not known.", "I cannot tell you my name,"]],
        [{"idiot"}, ["And so are you.", "Likewise."]],
        [{"you", "are", "smart"}, ["Why thank you!", "Thanks!"]]
    ]

    for possible_reply in possible_replies:
        if possible_reply[0].issubset(user_input):
            return choice(possible_reply[1])
    return "Say again?"


def main():
    while True:
        user_input = obtain_user_input("> ")
        reply = get_replies(user_input)
        print(reply)


if __name__ == "__main__":
    main()
11 голосов | спросил Ethan Bierlein 14 J000000Tuesday15 2015, 01:19:11

3 ответа


10

Ваше кодирование на Python велико, я ничего не могу придумать, что влияет на ваш стиль.

Мне нравится базовая идея вашей системы simple AI, но ее нужно немного уточнить, чтобы сделать ее эффективной на практике. Кроме того, вы можете расширить его с помощью множества напуганных вещей.

Проблемы

Сначала давайте посмотрим на часть выбора подмножества. Здесь я вижу 3 потенциальные проблемы.

  1. Что происходит, когда кто-то отправляет предложение, содержащее слова подмножеств multiple ? Например. Привет как тебя зовут? - > содержит Hi , ваши и имя . Я считаю, что ответ будет в виде Привет. или Здравствуйте, в ответ.
  2. Некоторые группы, похоже, перекрываются: Привет и Здравствуйте кажутся мне одной и той же группой подмножеств.
  3. Слова типа являются и you , например: thanks , которые могут быть абсолютно не связаны с вопросом.

Как их исправить?

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

  • Избегайте слов, которые не важны для сообщения в ответе системы AI. Такие слова, как , , вы , ... Они вызовут множество ложных срабатываний. Что решает проблему 3.
  • Группируйте похожие слова, которые должны совпадать с тем же набором ответов, например. ( 'Привет', 'Hello') . Я считаю, что это была ваша первоначальная идея в начале, но вам нужно ее использовать;). Это может решить проблему 2.
  • Решение проблемы 1. имеет много возможных подходов, я считаю, что самым простым было бы проверить входную строку для совпадений с несколькими подмножествами. Сохраняйте какую-то иерархию или порядок ранжирования, из которых подмножество должно быть первым. Положите ответы в очереди на основе этого порядка и ответьте им один за другим. например Если вход: «Привет, как ваше имя» => 'Привет, там.', 'Я не могу сказать вам свое имя'

Немного подробнее

Я предлагаю вам ознакомиться с библиотекой nltk . Эта библиотека предлагает широкий набор функций для обработки естественного языка. Кроме того, он предлагает классную классификацию, анализ и большую функциональность, что позволяет вам делать намного больше (продвинутых) вещей, связанных с ИИ.

Но библиотека nltk особенно полезна в вашем случае для этапа предварительной обработки кода user_input.

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

  • Прежде всего, вы можете обозначить текст, который разделит текст в токенах. Это похоже на разделение на пробелы.
  • Вы можете выполнить удаление стоп-слова . Удаление стоп-слова удалит простые слова из input_text, слова типа «the», «a» и т. д. Они не дают никакого значимого значения.
  • Затем вы можете выполнить создание , которое преобразует слова типа working, worked, works в форме стебля: work. Таким образом вам не нужны несколько глагольных форм в ваших подмножествах, только ствол будет делать.
  • Последний и самый важный Я бы предложил использовать n-граммы, возможно биграмм или триграмм, в дополнение к вашим униграммам. Биграм - это каждый последовательность двух смежных элементов в строке токенов.

Выполняя все это, вы можете добиться следующих результатов:

user_input:

  

Привет, как вас зовут?

предобработкиприведет к списку слов /токенов:

  

[Hi, what, be, your,name, Hi_what, what_is, is_your, your_name]   на основе которых вы можете построить свои подмножества и изменить: [{"your", "name"}, ["My name is not known.", "I cannot tell you my name,"]], в [{"your_name"}, ["My name is not known.", "I cannot tell you my name,"]],

Я только коснулся этих вещей вкратце, и вам, вероятно, нужно еще раз взглянуть на него самостоятельно. Но это может сделать ваш "простой" AI, немного больше "advanced" . ;)

Удачи!

ответил DJanssens 14 J000000Tuesday15 2015, 02:52:59
4

Точность в документах

Я смотрю

"""
Obtains user input. This function 
removes all punctuation, lowers text, 
splits on whitespace, and returns a
set of all the unique elements. An
example input value could be:

    "Hello, hello, there, there"

And the return value would be:

    ["hello", "there"]
"""

За исключением того, что возвращаемое значение не так. Это набор, поэтому он должен иметь фигурные скобки вокруг.

Чтобы избежать таких неточностей и проверить свой код в одно и то же время, я предлагаю вам использовать doctest (просто введите import doctest и help(doctest), чтобы узнать больше).

Один лайнер

Функция obtain_user_input хороша и распространена, но в Python такая тривиальная функция обычно записывается в одну или две строки, чтобы избежать отвлечения временные переменные (или переназначения).

ответил Caridorc 14 J000000Tuesday15 2015, 14:16:20
1
from re import sub as rsub

[...]

def obtain_user_input(prompt: str) -> set:
    [...]
    user_input = rsub("[^a-zA-Z0-9\s]*", user_input, "")

Моя первая реакция была: «Что такое rsub? hmm ... О, возможно, он был импортирован». Требуется 3-4 секунды, чтобы выяснить, какая функция вы вызываете. Почему бы просто не сделать

import re

[...]

def obtain_user_input(prompt: str) -> set:
    [...]
    user_input = re.sub("[^a-zA-Z0-9\s]*", user_input, "")

Импорт намного короче + вызов очень явный за счет только двух дополнительных символов ...


from random import choice

[...]

def get_replies(user_input: set) -> str:
   [...]
            return choice(possible_reply[1])

Похоже, но хуже. Единственная причина, по которой choice() имеет смысл, что я использую random.choice() так много в моих программах.

random.choice() читает так прекрасно, что сокращение его должно быть преступлением.

В принципе, вы просите читателя отобразить choice() на random.choice() в голове.


def obtain_user_input(prompt: str) -> set:
    """
    Obtains user input. This function 
    removes all punctuation, lowers text, 
    splits on whitespace, and returns a
    set of all the unique elements. An
    example input value could be:

        "Hello, hello, there, there"

    And the return value would be:

        ["hello", "there"]
    """
    user_input = input(prompt)
    user_input = rsub("[^a-zA-Z0-9\s]*", user_input, "")
    user_input = user_input.lower()
    user_input = user_input.split(" ")
    return set(user_input)

Докшрин длиннее кода, который должен быть короче в любом случае.

def obtain_user_input(prompt: str) -> set:
    user_input = input(prompt)
    user_input = rsub("[^a-zA-Z0-9\s]*", user_input, "")
    return set(user_input.lower().split(" "))

Я не вижу необходимости поставить docstring на такую ​​простую функцию.

ответил vDvWnd3F 22 J000000Wednesday15 2015, 19:14:54

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132