# -*- coding: utf-8 -*-
from __future__ import division
from .__load__ import *
# 大脑,技能,记忆
class Brain(object):
def init(self, robot):
# vecan机器人
self.robot = robot
# 记忆
self.memory = []
# 询问模式
self.hasPardon = False
self.handling = False
return self
def isImmersive(self, skill, text, parsed):
return self.robot.getImmersiveMode() == skill.__name__ and \
skill.matchImmersive(text, parsed)
def loadSkill(self):
self.skills = []
loadSkill = []
locations = [
File.path() + 'service/skill',
'~/.vecan/skill',
]
for skill in Demeter.getPath(locations):
skill = getattr(skill, skill.__name__.capitalize())
self.skills.append(skill)
loadSkill.append(skill.__name__)
self.robot.logger.info(self.log('载入技能:{}'.format(loadSkill)))
def wakeup(self):
self.loadSkill()
def query(self, text):
args = {
"service_id": "S13442",
}
parsed = self.robot.doParse(text, **args)
return parsed
for skill in self.skills:
if not skill.match(text, parsed) and not self.isImmersive(skill, text, parsed):
continue
skill.init(self.robot)
self.robot.logger.info(self.log("'{}' 命中技能 {}".format(text, skill.__name__)))
self.robot.matchskill = skill.__name__
if skill.IS_IMMERSIVE:
self.robot.setImmersiveMode(skill.__name__)
continueHandle = False
try:
self.handling = True
continueHandle = skill.handle(text, parsed)
self.handling = False
except Exception:
self.robot.logger.critical('Failed to execute skill',
exc_info=True)
reply = u"抱歉,插件{}出故障了,晚点再试试吧".format(skill.__name__)
self.robot.say(reply, skill=skill.__name__)
else:
self.robot.logger.debug(self.log("Handling of phrase '%s' by " +
"skill '%s' completed", text,
skill.__name__))
finally:
if not continueHandle:
return True
self.robot.logger.debug(self.log("No skill was able to handle phrase {} ".format(text)))
return False
""" 恢复某个技能的处理 """
def restore(self):
if not self.robot.immersiveMode:
return
for skill in self.skills:
if skill.__name__ == self.robot.immersiveMode and skill.restore:
skill.restore()
""" 暂停某个技能的处理 """
def pause(self):
if not self.robot.immersiveMode:
return
for skill in self.skills:
if skill.__name__ == self.robot.immersiveMode and skill.pause:
skill.pause()
def understand(self, fp):
if self.robot and self.robot.tool['asr']:
return self.robot.tool['asr'].asr(fp)
return None
def say(self, msg, cache=False):
if self.robot and self.robot.tool['tts']:
self.robot.tool['tts'].tts(msg)
def think(self, query, uid='', onSay=None):
# 统计
#statistic.report(1)
self.robot.stop()
self.addMemory(0, query, uid)
if onSay:
self.onSay = onSay
if query.strip() == '':
self.pardon()
return
lastImmersiveMode = self.robot.immersiveMode
if not self.query(query):
# 没命中技能,使用机器人回复
msg = self.robot.tool['ai'].ai(query)
self.robot.say(msg, True, completed=self.robot.checkRestore)
else:
if lastImmersiveMode is not None and lastImmersiveMode != self.robot.matchskill:
time.sleep(1)
if self.checkSpeeker():
self.robot.logger.debug(self.log('等说完再checkRestore'))
self.speaker.appendOnCompleted(lambda: self.checkRestore())
else:
self.robot.logger.debug(self.log('checkRestore'))
self.robot.checkRestore()
# 询问
def doubt(self, msg):
if Demeter.config['snowboy']['active_mode'] and (msg.endswith('?') or msg.endswith(u'?') or u'告诉我' in msg or u'请回答' in msg):
query = self.robot.ear.listen()
self.think(query)
# 没听清
def pardon(self):
if not self.hasPardon:
self.robot.say('抱歉,刚刚没听清,能再说一遍吗?', completed=lambda: self.think(self.robot.ear.listen()))
self.hasPardon = True
else:
self.robot.say('没听清呢')
self.hasPardon = False
def getMemory(self):
return self.memory
def addMemory(self, t, text, uid=''):
if t in (0, 1) and text != '':
if text.endswith(',') or text.endswith(','):
text = text[:-1]
if uid == '' or uid == None or uid == 'null':
uid = Demeter.uuid(__name__)
# 将图片处理成HTML
pattern = r'https?://.+\.(?:png|jpg|jpeg|bmp|gif|JPG|PNG|JPEG|BMP|GIF)'
url_pattern = r'^https?://.+'
imgs = re.findall(pattern, text)
for img in imgs:
text = text.replace(img, ''.format(img))
urls = re.findall(url_pattern, text)
for url in urls:
text = text.replace(url, '{}'.format(url, url))
# 后续存入数据库,分为永久记忆、临时记忆、碎片记忆
self.memory.append({'type': t, 'text': text, 'time': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), 'uid': uid})
def log(self, text):
return 'Brain:' + text