Проблема Chatbot - бесконечная рекурсия - Вопрос Codecademy - PullRequest
1 голос
/ 19 апреля 2020

Я учусь кодировать, используя Codecademy, и я действительно застрял в вопросе и хотел бы, чтобы меня указывали в правильном направлении!

Код по большей части работает, я просто не могу получить это правильно ответить на функцию .match_reply. Идея состоит в том, что чат-бот должен определить регулярное выражение в self.alienbabble и ответить соответствующим ответом. Тем не менее, он глючит с бесконечной рекурсией всех ответов этой функции.

# importing regex and random libraries
import re
import random

class AlienBot:
  # potential negative responses
  negative_responses = ("no", "nope", "nah", "naw", "not a chance", "sorry")
  # keywords for exiting the conversation
  exit_commands = ("quit", "pause", "exit", "goodbye", "bye", "later")
  # random starter questions
  random_questions = (
        "Why are you here? ",
        "Are there many humans like you? ",
        "What do you consume for sustenance? ",
        "Is there intelligent life on this planet? ",
        "Does Earth have a leader? ",
        "What planets have you visited? ",
        "What technology do you have on this planet? "
    )

  def __init__(self):
    self.alienbabble = {'describe_planet_intent': '.*\s*your planet.*','answer_why_intent': 'why\sare.*', 'cubed_intent': '.*cube.*(\d+)'}

  # Define .greet() below:
  def greet(self):
    self.name = input("Hello. What is your name?")
    will_help = input(f"Hi {self.name}, I'm Etcetera. I'm not from this planet. Will you help me learn about your planet? ")
    if will_help in self.negative_responses:
      print ("Ok, have a nice Earth day!")
      return
    self.chat()

  # Define .make_exit() here:
  def make_exit(self, reply):
    for word in self.exit_commands:
      if word in reply:
        print ("Ok, have a nice Earth day!")
        return True

  # Define .chat() next:
  def chat(self):
    reply = input(random.choice(self.random_questions)).lower()
    while not self.make_exit(reply):
      reply = input(self.match_reply(reply))

  # Define .match_reply() below:
  def match_reply(self, reply):
    for key, value in self.alienbabble.items():
      intent = key
      regex = value
      #regex = 'describe_planet_intent'
      #reply = input(random.choice(self.random_questions)).lower()
      found_match = re.match(regex, reply)
      if found_match and intent == 'describe_planet_intent':
        return self.describe_planet_intent()
      elif found_match and intent == 'answer_why_intent':
        return self.answer_why_intent()
      elif found_match and intent == 'cubed_intent':
        return self.cubed_intent(found_match.groups()[0])
      else:
        return self.no_match_intent()

  # Define .describe_planet_intent():
  def describe_planet_intent(self):
    responses = ("My planet is a utopia of diverse organisms and species. ", "I am from Opidipus, the capital of the Wayward Galaxies. ")
    return random.choice(responses)

  # Define .answer_why_intent():
  def answer_why_intent(self):
    responses = ("I come in peace. ", "I am here to collect data on your planet and its inhabitants. ", "I heard the coffee is good. ")
    return random.choice(responses)

  # Define .cubed_intent():
  def cubed_intent(self, number):
    number = int(number)
    cubed_number = number * number * number
    return (f"The cube of {number} is {cubed_number}. Isn't that cool? ")

  # Define .no_match_intent():
  def no_match_intent(self):
    responses = ("Please tell me more. ", "Tell me more! ", "Why do you say that? ", "I see. Can you elaborate? ", "Interesting. Can you tell me more? ", "I see. How do you think? ", "Why? ", "How do you think I feel when you say that? ")
    return random.choice(responses)

# Create an instance of AlienBot below:
my_bot = AlienBot()
my_bot.greet()

Я чувствую, что есть действительно простое решение, я кодирую только 1 неделю, так что это действительно ново для меня, и я ценю вашу помощь:)

1 Ответ

4 голосов
/ 21 апреля 2020

Ответ действительно прост. Сократим ваш код до минимально воспроизводимого:

def match_reply(self, reply):
    for key, value in self.alienbabble.items():
      # I omitted the 3 lines that were here - defining 'intent', 'regex_pattern' and 'regex' - 
      # since at this point they're yet not used
      reply = input(self.match_reply(reply)) # oops! self.match_reply is called again!

Как видите, вы рекурсивно вызываете self.match_reply, не останавливая его.

РЕДАКТИРОВАТЬ:

Есть еще 2 вещи, которые нужно исправить:

  1. Давайте изменим match_reply:

    a. Давайте дадим ему более подходящее имя match_alien_response.
    b. Давайте сделаем так, как должны: просто сопоставьте ответ. Таким образом, нам не нужно получать еще один вход от пользователя.
    c. Давайте удостоверимся, что он повторяет все ключи в alienbabble и не возвращает сразу.
    d. Нам нужно использовать re.findall, чтобы получить все совпадения в строке

    Все эти изменения дают нам следующий код:

    def match_alien_response(self, userReply):
      found = False
      for intent, regPattern in self.alienbabble.items():
        found_match = re.findall(regPattern, userReply)
        if found_match and intent == 'describe_planet_intent':
          return self.describe_planet_intent()
        elif found_match and intent == 'answer_why_intent':
          return self.answer_why_intent()
        elif found_match and intent == 'cubed_intent':
          return self.cubed_intent(found_match[0])
      if not found:
        return self.no_match_intent()
    
  2. Внутри no_match_intent, это должно быть responses = вместо responses:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...