brain.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # -*- coding: utf-8 -*-
  2. from __future__ import division
  3. from .__load__ import *
  4. # 大脑,技能,记忆
  5. class Brain(object):
  6. def init(self, robot):
  7. # vecan机器人
  8. self.robot = robot
  9. # 记忆
  10. self.memory = []
  11. # 询问模式
  12. self.hasPardon = False
  13. self.handling = False
  14. return self
  15. def isImmersive(self, skill, text, parsed):
  16. return self.robot.getImmersiveMode() == skill.__name__ and \
  17. skill.matchImmersive(text, parsed)
  18. def loadSkill(self):
  19. self.skills = []
  20. loadSkill = []
  21. locations = [
  22. File.path() + 'service/skill',
  23. '~/.vecan/skill',
  24. ]
  25. for skill in Demeter.getPath(locations):
  26. skill = getattr(skill, skill.__name__.capitalize())
  27. self.skills.append(skill)
  28. loadSkill.append(skill.__name__)
  29. self.robot.logger.info(self.log('载入技能:{}'.format(loadSkill)))
  30. def wakeup(self):
  31. self.loadSkill()
  32. def query(self, text):
  33. args = {
  34. "service_id": "S13442",
  35. }
  36. parsed = self.robot.doParse(text, **args)
  37. return parsed
  38. for skill in self.skills:
  39. if not skill.match(text, parsed) and not self.isImmersive(skill, text, parsed):
  40. continue
  41. skill.init(self.robot)
  42. self.robot.logger.info(self.log("'{}' 命中技能 {}".format(text, skill.__name__)))
  43. self.robot.matchskill = skill.__name__
  44. if skill.IS_IMMERSIVE:
  45. self.robot.setImmersiveMode(skill.__name__)
  46. continueHandle = False
  47. try:
  48. self.handling = True
  49. continueHandle = skill.handle(text, parsed)
  50. self.handling = False
  51. except Exception:
  52. self.robot.logger.critical('Failed to execute skill',
  53. exc_info=True)
  54. reply = u"抱歉,插件{}出故障了,晚点再试试吧".format(skill.__name__)
  55. self.robot.say(reply, skill=skill.__name__)
  56. else:
  57. self.robot.logger.debug(self.log("Handling of phrase '%s' by " +
  58. "skill '%s' completed", text,
  59. skill.__name__))
  60. finally:
  61. if not continueHandle:
  62. return True
  63. self.robot.logger.debug(self.log("No skill was able to handle phrase {} ".format(text)))
  64. return False
  65. """ 恢复某个技能的处理 """
  66. def restore(self):
  67. if not self.robot.immersiveMode:
  68. return
  69. for skill in self.skills:
  70. if skill.__name__ == self.robot.immersiveMode and skill.restore:
  71. skill.restore()
  72. """ 暂停某个技能的处理 """
  73. def pause(self):
  74. if not self.robot.immersiveMode:
  75. return
  76. for skill in self.skills:
  77. if skill.__name__ == self.robot.immersiveMode and skill.pause:
  78. skill.pause()
  79. def understand(self, fp):
  80. if self.robot and self.robot.tool['asr']:
  81. return self.robot.tool['asr'].asr(fp)
  82. return None
  83. def say(self, msg, cache=False):
  84. if self.robot and self.robot.tool['tts']:
  85. self.robot.tool['tts'].tts(msg)
  86. def think(self, query, uid='', onSay=None):
  87. # 统计
  88. #statistic.report(1)
  89. self.robot.stop()
  90. self.addMemory(0, query, uid)
  91. if onSay:
  92. self.onSay = onSay
  93. if query.strip() == '':
  94. self.pardon()
  95. return
  96. lastImmersiveMode = self.robot.immersiveMode
  97. if not self.query(query):
  98. # 没命中技能,使用机器人回复
  99. msg = self.robot.tool['ai'].ai(query)
  100. self.robot.say(msg, True, completed=self.robot.checkRestore)
  101. else:
  102. if lastImmersiveMode is not None and lastImmersiveMode != self.robot.matchskill:
  103. time.sleep(1)
  104. if self.checkSpeeker():
  105. self.robot.logger.debug(self.log('等说完再checkRestore'))
  106. self.speaker.appendOnCompleted(lambda: self.checkRestore())
  107. else:
  108. self.robot.logger.debug(self.log('checkRestore'))
  109. self.robot.checkRestore()
  110. # 询问
  111. def doubt(self, msg):
  112. if Demeter.config['snowboy']['active_mode'] and (msg.endswith('?') or msg.endswith(u'?') or u'告诉我' in msg or u'请回答' in msg):
  113. query = self.robot.ear.listen()
  114. self.think(query)
  115. # 没听清
  116. def pardon(self):
  117. if not self.hasPardon:
  118. self.robot.say('抱歉,刚刚没听清,能再说一遍吗?', completed=lambda: self.think(self.robot.ear.listen()))
  119. self.hasPardon = True
  120. else:
  121. self.robot.say('没听清呢')
  122. self.hasPardon = False
  123. def getMemory(self):
  124. return self.memory
  125. def addMemory(self, t, text, uid=''):
  126. if t in (0, 1) and text != '':
  127. if text.endswith(',') or text.endswith(','):
  128. text = text[:-1]
  129. if uid == '' or uid == None or uid == 'null':
  130. uid = Demeter.uuid(__name__)
  131. # 将图片处理成HTML
  132. pattern = r'https?://.+\.(?:png|jpg|jpeg|bmp|gif|JPG|PNG|JPEG|BMP|GIF)'
  133. url_pattern = r'^https?://.+'
  134. imgs = re.findall(pattern, text)
  135. for img in imgs:
  136. text = text.replace(img, '<img src={} class="img"/>'.format(img))
  137. urls = re.findall(url_pattern, text)
  138. for url in urls:
  139. text = text.replace(url, '<a href={} target="_blank">{}</a>'.format(url, url))
  140. # 后续存入数据库,分为永久记忆、临时记忆、碎片记忆
  141. self.memory.append({'type': t, 'text': text, 'time': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), 'uid': uid})
  142. def log(self, text):
  143. return 'Brain:' + text