我正在用Python制作一个简单的聊天机器人。它有一个带有正则表达式的文本文件,有助于生成输出。用户输入和bot输出由|
字符分隔。
my name is (?P<'name'>\w*) | Hi {'name'}!
这适用于单组输入和输出响应,但我希望机器人能够存储用户输入的正则表达式值,然后再次使用它们(即给机器人一个'记忆')。例如,我想让bot存储'name'的值输入,以便我可以在规则中使用它:
my name is (?P<'word'>\w*) | You said your name is {'name'} already!
my name is (?P<'name'>\w*) | Hi {'name'}!
对于'name'没有任何价值,机器人将首先输出'Hi steve',一旦机器人确实有这个值,'word'规则将适用。鉴于我构建程序的方式,我不确定这是否可行。我做了这个,以便将文本文件制作成字典,其中键和值由|分隔当用户输入一些文本时,程序会比较用户输入是否与字典中存储的输入相匹配,并打印出相应的机器人响应(如果没有找到匹配,也会有“其他”情况)。
我必须在过程的比较部分发生一些事情,以便保存用户的正则表达式文本,然后以某种方式替换回字典。我的所有正则表达式都有不同的名称与它们相关联(没有两个'word'实例,例如......有'word','word2'等),我这样做是因为我认为它会使这个部分过程更容易。尽管如此,我可能已经完全错误地构建了这个任务。
编辑:代码
import re
io = {}
with open("rules.txt") as brain:
for line in brain:
key, value = line.split('|')
io[key] = value
string = str(raw_input('> ')).lower()+' word'
x = 1
while x == 1:
for regex, output in io.items():
match = re.match(regex, string)
if match:
print(output.format(**match.groupdict()))
string = str(raw_input('> ')).lower()+' word'
else:
print ' Sorry?'
string = str(raw_input('> ')).lower()+' word'
答案 0 :(得分:0)
好的,让我看看我是否明白这一点:
在我看来,您需要附加规则的更多信息。例如,您在上面给出的“单词”规则实际上不应该在字典中添加“单词”,否则它只会应用一次(想象一下,如果用户一直试图说“我的名字是x”超过两次)。< / p>
这会让您对如何继续进行更多了解吗?
哦,顺便说一下,我认为“|”对于分隔符来说是一个糟糕的选择,因为它可以出现在正则表达式中。不知道该建议:“||”怎么样?
答案 1 :(得分:0)
我很难理解算法的原理,因为我不习惯使用命名组 以下代码是我解决问题的方法,我希望它会给你一些想法。
我认为只有一本字典不是一个好的原则,它增加了推理和算法的复杂性。所以我将代码基于两个词典:direg和memory
这两个词典的键是组的索引,而不是所有索引,只有一些特定的索引,组的索引是每个单独模式中的最后一个。
因为,为了好玩,我决定正则表达式必须能够有几个组。
我在代码中称为单个模式的是以下字符串:
"[mM]y name [Ii][sS] (\w*)"
"[Ii]n repertory (\w*) I [wW][aA][nN][tT] file (\w*)"
"[Ii] [wW][aA][nN][tT] to ([ \w]*)"
您看到第二个单独的模式有2个捕获组:因此有3个单独的模式,但在所有各个组中总共有4个组。
因此,字典的创建需要额外注意,以考虑最后一个匹配组的索引(我使用正则表达式MatchObject的名称 lastindex 的属性帮助) )可能与正则表达式中存在的单个正则表达式的编号不对应:解释比理解更难。这就是为什么我在函数 distr()中计算字符串 {0} {1} {2} {3} {4}等的出现,其数量必须是与相应的单个模式中定义的组数相同。
我发现Laurence D'Oliveiro建议使用'||'而不是'|'作为分隔符有趣。
我的代码模拟了一个会话,其中完成了几个输入:
import re
regi = ("[mM]y name [Ii][sS] (\w*)"
"||Hi {0}!"
"||You said that your name was {0} !!!",
"[Ii]n repertory (\w*) I [wW][aA][nN][tT] file (\w*)"
"||OK here's your file {0}\\{1} :"
"||I already gave you the file {0}\\{1} !",
"[Ii] [wW][aA][nN][tT] to ([ \w]*)"
"||OK, I will do {0}"
"||You already did {0}. Do yo really want again ?")
direg = {}
memory = {}
def distr(regi,cnt = 0,di = direg,mem = memory,
regnb = re.compile('{\d+}')):
for i,el in enumerate(regi,start=1):
sp = el.split('||')
cnt += len(regnb.findall(sp[1]))
di[cnt] = sp[1]
mem[cnt] = sp[2]
yield sp[0]
regx = re.compile('|'.join(distr(regi)))
print 'direg :\n',direg
print
print 'memory :\n',memory
for inp in ('I say that my name is Armano the 1st',
'In repertory ONE I want file SPACE',
'I want to record music',
'In repertory ONE I want file SPACE',
'I say that my name is Armstrong',
'But my name IS Armstrong now !!!',
'In repertory TWO I want file EARTH',
'Now my name is Helena'):
print '\ninput ==',inp
mat = regx.search(inp)
if direg[mat.lastindex]:
print 'output ==',direg[mat.lastindex]\
.format(*(d for d in mat.groups() if d))
direg[mat.lastindex] = None
memory[mat.lastindex] = memory[mat.lastindex]\
.format(*(d for d in mat.groups() if d))
else:
print 'output ==',memory[mat.lastindex]\
.format(*(d for d in mat.groups() if d))
if not memory[mat.lastindex].startswith('Sorry'):
memory[mat.lastindex] = 'Sorry, ' \
+ memory[mat.lastindex][0].lower()\
+ memory[mat.lastindex][1:]
结果
direg :
{1: 'Hi {0}!', 3: "OK here's your file {0}\\{1} :", 4: 'OK, I will do {0}'}
memory :
{1: 'You said that your name was {0} !!!', 3: 'I already gave you the file {0}\\{1} !', 4: 'You already did {0}. Do yo really want again ?'}
input == I say that my name is Armano the 1st
output == Hi Armano!
input == In repertory ONE I want file SPACE
output == OK here's your file ONE\SPACE :
input == I want to record music
output == OK, I will do record music
input == In repertory ONE I want file SPACE
output == I already gave you the file ONE\SPACE !
input == I say that my name is Armstrong
output == You said that your name was Armano !!!
input == But my name IS Armstrong now !!!
output == Sorry, you said that your name was Armano !!!
input == In repertory TWO I want file EARTH
output == Sorry, i already gave you the file ONE\SPACE !
input == Now my name is Helena
output == Sorry, you said that your name was Armano !!!