123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- # -*- 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, '<img src={} class="img"/>'.format(img))
- urls = re.findall(url_pattern, text)
- for url in urls:
- text = text.replace(url, '<a href={} target="_blank">{}</a>'.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
|