目前正在阅读《Beginning Ruby》第 12 章,它构建了一个对话机器人。运行 basic_client.rb 文件时,机器人会加载。当给定输入“我讨厌电视”时,机器人应该识别带有“讨厌”一词的模式并根据该模式返回响应。
相反,它会从 bot 文件中返回一些名称错误。这些都与 wordplay.rb 文件相关,但我不确定是什么原因造成的。任何帮助,将不胜感激。
/bot.rb:73:in `block (2 levels) in possible_responses': uninitialized constant Bot::Wordplay (NameError)
/bot.rb:69:in `collect'
/bot.rb:69:in `block in possible_responses'
/bot.rb:59:in `each'
/bot.rb:59:in `possible_responses'
/bot.rb:27:in `response_to'
from basic_client.rb:8:in `<main>'
正在运行的文件:basic_client.rb
`require './bot'
bot = Bot.new(:name => 'Fred', :data_file => 'fred.bot')
puts bot.greeting
while input = gets and input.chomp != 'end'
puts '>> ' + bot.response_to(input)
end
puts bot.farewell`
所需的bot.rb:
require 'yaml'
require './wordplay'
class Bot
attr_reader :name
def initialize(options)
@name = options[:name] || "Unnamed Bot"
begin
@data = YAML.load(File.read(options[:data_file]))
rescue
raise "Can't load bot data"
end
end
def greeting
random_response :greeting
end
def farewell
random_response :farewell
end
def response_to(input)
prepared_input = preprocess(input.downcase)
sentence = best_sentence(prepared_input)
responses = possible_responses(sentence)
responses[rand(responses.length)]
end
private
def random_response(key)
random_index = rand(@data[:responses][key].length)
@data[:responses][key][random_index].gsub(/\[name\]/, @name)
end
def preprocess(input)
perform_substitutions(input)
end
def perform_substitutions(input)
@data[:presubs].each { |s| input.gsub!(s[0], s[1]) }
input
end
def best_sentence(input)
hot_words = @data[:responses].keys.select do |k|
k.class == String && k =~ /^\w+$/
end
WordPlay.best_sentence(input.sentences, hot_words)
end
def possible_responses(sentence)
responses = []
# Find all patterns to try to match against
@data[:responses].keys.each do |pattern|
next unless pattern.is_a?(String)
# For each pattern, see if the supplied sentence contains
# a match. Remove substitution symbols (*) before checking.
# Push all responses to the responses array.
if sentence.match('\b' + pattern.gsub(/\*/, '') + '\b')
# If the pattern contains substitution placeholders, perform the substitutions
if pattern.include?('*')
responses << @data[:responses][pattern].collect do |phrase|
# Erase everything before the placeholder, leaving everything after it
matching_section = sentence.sub(/^.*#{pattern}\s+/, '')
# Then substitute the text after the placeholder with the pronouns switched
phrase.sub('*', Wordplay.switch_pronouns(matching_section))
end
else
responses << @data[:responses][pattern]
end
end
end
# If there were no matches, add the default ones
responses << @data[:responses][:default] if responses.empty?
# Flatten the blocks of responses to a flat array
responses.flatten
end
end
文字游戏文件:
class String
def sentences
self.gsub(/\n|\r/, ' ').split(/\.\s*/)
end
def words
self.scan(/\w[\w\'\-]*/)
end
end
class WordPlay
def self.switch_pronouns(text)
text.gsub(/\b(I am|You are|I|You|Your|My|Me)\b/i) do |pronoun|
case pronoun.downcase
when "i"
"you"
when "you"
"me"
when "me"
"you"
when "i am"
"you are"
when "you are"
"i am"
when "your"
"my"
when "my"
"your"
end
end.sub(/^me\b/i, 'i')
end
def self.best_sentence(sentences, desired_words)
ranked_sentences = sentences.sort_by do |s|
s.words.length - (s.downcase.words - desired_words).length
end
ranked_sentences.last
end
end