我做了一个聊天机器人,当你和它交谈的时候,它学会了回应。但是它说话的方式很奇怪,所以如果你对如何使它的反应更具人情味有任何想法,那么请说出来。
不管怎样,你得开始一个新的聊天机器人了。你会注意到,当你开始的时候,他的回答将是难以置信的愚蠢。一旦你和他谈得够多,他就会变得更有人情味,但不会有多大的收获。
我不是要求你审查代码中的特性,而是要求对代码和整体风格进行审查。
import random, pickle, os
import os.path
startmes = """Machine Learning Conversational Program by Jake Speiran, 2015. ver 1.0
Hello! In a moment you will begin chatting with Machine Learning Conversational
Program, or MLCP. Everything you say he will learn, and every response you make
he will remember. The goal is that he will someday be able to talk. Type
"#help" to learn more. To quit the program, type "#quit" into the command
prompt.
"""
helpmes = """This is the help message for MLCP.
In order to communicate with the bot, simply type what you want to say into the
input space. When typing please use only lower case characters and no special
characters.
So this:
"You're a real star!"
Becomes this:
"youre a real star"
The reason for this is that otherwise you would have many entries that are
copies of the same word, ie Hey, hey, hey! and Hey all mean the same thing
but would be entered differently.
Sometimes what the bot says can be hard to interpret, but keep trying and
use your imagination.
"""
class bot():
def __init__(self, autosave, deldups, autocount, maxwords, maxresp):
self.autosave = autosave
self.autocount = autocount
self.deldups = deldups
self.maxwords = maxwords
self.maxresp = maxresp
self.known = {}
self.wordcount = 0
self.sescount = 0
os.system("cls")
print(startmes)
if os.path.isfile("known.data"):
self.known = pickle.load(open('known.data', "rb"))
print("Save file loaded!")
else:
print("No save file found.")
print()
for key, value in self.known.items():
self.wordcount += 1
def question(self, x):
self.wordcount += 1
a = "w" + str(self.wordcount)
d = {"name": x, "resp": [x], "uses": 0}
self.known[a] = d
def talk(self):
talking = True
prevres = ""
while talking:
if self.autosave:
self.sescount += 1
if self.sescount >= self.autocount:
self.sescount = 0
pickle.dump(self.known, open('known.data', 'wb'))
print("Saving...")
if self.deldups:
for key, value in self.known.items():
value["resp"] = list(set(value["resp"]))
if len(self.known.keys()) > self.maxwords:
count = 0
for key, value in self.known.items():
count += value["uses"]
for i in range(self.wordcount):
for key, value in self.known.items():
if value["uses"] <= count/self.wordcount:
self.wordcount -= 1
self.known.pop(key, None)
break
for key, value in self.known.items():
if len(value["resp"]) > self.maxresp:
rem = random.choice(value["resp"])
value["resp"].remove(rem)
res = ""
a = input("You: ")
if "#" in a:
if "quit" in a:
pickle.dump(self.known, open('known.data', 'wb'))
print("Saving...")
exit()
if "help" in a:
print(helpmes)
a = ""
data = prevres.split(" ")
inp = a.split(" ")
for x in data:
for key, value in self.known.items():
if x == value["name"]:
value["resp"].extend(inp)
for x in inp:
if a == "":
break
names = []
for key, value in self.known.items():
names.append(value["name"])
if x not in names:
self.question(x)
else:
for key, value in self.known.items():
if x == value["name"]:
xyz = random.randrange(0,4)
for i in range(xyz):
res = res + " {0}".format(random.choice(value["resp"]))
value["uses"] += 1
if res == "":
res = " ..."
print("Bot:{0}".format(res))
prevres = res
sauce = bot(True, True, 25, 1000, 15)
sauce.talk()发布于 2015-07-19 19:57:15
我不喜欢Bot对象处于当前状态。你刚刚把你所有的代码都塞进去了。我宁愿看到您将独立的事物隔离到它们自己的对象/函数中。我认为Bot类应该只处理问题的机器学习部分,即取一个字符串并返回一个响应。它不应该处理终端I/O或提示循环等。
class Bot:
def save_to_file(file_object):
"""Pickle to file."""
def load_from_file(file_object):
"""Unpickle from file."""
def respond(user_input):
"""Save input words and return a response."""
return response顶级范围内的
不要在顶级范围内执行您的程序。一旦将机器人隔离到它自己的类中,您就会意识到它是可重用的。您(或其他人)也可以在另一个程序中使用这个机器人,任何来源的字符串!但是如果您是import chatbot,它实际上将在从脚本返回之前运行整个交互式提示符。有一个简单的方法来解决这个问题。来自Python的字节:
if __name__ == '__main__':
print 'This program is being run by itself'
else:
print 'I am being imported from another module'正如@Ethan已经提到的,不要做os.system("cls")。它既不轻便,也不优雅。他没有提到的是,实际上有一种方法可以在没有os模块的情况下以可移植的方式实现。标准Python发行版中包含的curses库是C库ncurses的包装器。它是为这种更高级的终端设备操作设计的接口。
curses的流程是首先获得一个带有curses.initscr的屏幕对象,一个do可选设置。然后,通过screen.getstr、screen.addstr等将所有输入和输出发送到终端。退出时,应用程序必须恢复以前的终端设置,否则启动应用程序的终端将处于修改状态。最简单的方法是将整个脚本包装在一个try/ done块中。
curses库一开始看起来很让人望而生畏,但它提供了一些非常好的特性。
给应用程序的文件取有意义的名称,就像使用变量一样。当我在一个月后回到我的Code目录时,我将不知道known.data文件属于哪个程序。更明显的是,如果您将其命名为chatbot.data,这样用户就可以了解磁盘上的文件是干什么用的。更重要的是,当用户从未被告知该文件时,并且无法自定义它的名称。
发布于 2015-07-23 23:35:32
既然您问到如何使机器人的响应更人性化,我建议您研究一下自然语言处理。试图通过机器学习实现一个半途而废的聊天机器人将需要大量的时间和调整。
让机器人识别词性和句子结构的各个部分将为它学习的单词提供更多的语境。利用这些信息试图在回答中建立一个句子结构,可以帮助实现更自然的词流。
注意:有关网站和感兴趣资源的链接,请参见这个职位。
与其要求用户给自己带来不便,不如让程序自动过滤掉标点符号,并打开输入小写。
import string
def strip_and_lower(string_input):
"""
Will remove punctuation from an inputted string and
return the lowercase version of that parsed string.
Any innuendo is unintentional.
"""
table = string_input.maketrans(
{symbol: None for symbol in string.punctuation}
)
string_wo_punc = string_input.translate(table)
return string_wo_punc.lower()
inString = "You're a real star!"
outString = strip_and_lower(inString)
print(outString)
# 'youre a real star'如果您在保持代码整洁方面有问题,请首先确保代码遵循PEP 0008。一个简单的方法是使用在线PEP 0008检查器。只有在您确信代码遵循惯例之后,才会对代码进行检查,因为这将使您更容易阅读,并将建议的真正内容留给您。
https://codereview.stackexchange.com/questions/94232
复制相似问题