# -*- coding: utf-8-*-
from .sdk import unit
from robot import logging
from abc import ABCMeta, abstractmethod
logger = logging.getLogger(__name__)
[文档]class AbstractNLU(object):
"""
Generic parent class for all NLU engines
"""
__metaclass__ = ABCMeta
[文档] @classmethod
def get_config(cls):
return {}
[文档] @classmethod
def get_instance(cls):
profile = cls.get_config()
instance = cls(**profile)
return instance
[文档] @abstractmethod
def parse(self, query, **args):
"""
进行 NLU 解析
:param query: 用户的指令字符串
:param **args: 可选的参数
"""
return None
[文档] @abstractmethod
def getIntent(self, parsed):
"""
提取意图
:param parsed: 解析结果
:returns: 意图数组
"""
return None
[文档] @abstractmethod
def hasIntent(self, parsed, intent):
"""
判断是否包含某个意图
:param parsed: 解析结果
:param intent: 意图的名称
:returns: True: 包含; False: 不包含
"""
return False
[文档] @abstractmethod
def getSlots(self, parsed, intent):
"""
提取某个意图的所有词槽
:param parsed: 解析结果
:param intent: 意图的名称
:returns: 词槽列表。你可以通过 name 属性筛选词槽,
再通过 normalized_word 属性取出相应的值
"""
return None
[文档] @abstractmethod
def getSlotWords(self, parsed, intent, name):
"""
找出命中某个词槽的内容
:param parsed: 解析结果
:param intent: 意图的名称
:param name: 词槽名
:returns: 命中该词槽的值的列表。
"""
return None
[文档] @abstractmethod
def getSay(self, parsed, intent):
"""
提取回复文本
:param parsed: 解析结果
:param intent: 意图的名称
:returns: 回复文本
"""
return ""
[文档]class UnitNLU(AbstractNLU):
"""
百度UNIT的NLU API.
"""
SLUG = "unit"
def __init__(self):
super(self.__class__, self).__init__()
[文档] @classmethod
def get_config(cls):
"""
百度UNIT的配置
无需配置,所以返回 {}
"""
return {}
[文档] def parse(self, query, **args):
"""
使用百度 UNIT 进行 NLU 解析
:param query: 用户的指令字符串
:param **args: UNIT 的相关参数
- service_id: UNIT 的 service_id
- api_key: UNIT apk_key
- secret_key: UNIT secret_key
:returns: UNIT 解析结果。如果解析失败,返回 None
"""
if 'service_id' not in args or \
'api_key' not in args or \
'secret_key' not in args:
logger.critical('{} NLU 失败:参数错误!'.format(self.SLUG))
return None
return unit.getUnit(query,
args['service_id'],
args['api_key'],
args['secret_key'])
[文档] def getIntent(self, parsed):
"""
提取意图
:param parsed: 解析结果
:returns: 意图数组
"""
return unit.getIntent(parsed)
[文档] def hasIntent(self, parsed, intent):
"""
判断是否包含某个意图
:param parsed: UNIT 解析结果
:param intent: 意图的名称
:returns: True: 包含; False: 不包含
"""
return unit.hasIntent(parsed, intent)
[文档] def getSlots(self, parsed, intent):
"""
提取某个意图的所有词槽
:param parsed: UNIT 解析结果
:param intent: 意图的名称
:returns: 词槽列表。你可以通过 name 属性筛选词槽,
再通过 normalized_word 属性取出相应的值
"""
return unit.getSlots(parsed, intent)
[文档] def getSlotWords(self, parsed, intent, name):
"""
找出命中某个词槽的内容
:param parsed: UNIT 解析结果
:param intent: 意图的名称
:param name: 词槽名
:returns: 命中该词槽的值的列表。
"""
return unit.getSlotWords(parsed, intent, name)
[文档] def getSay(self, parsed, intent):
"""
提取 UNIT 的回复文本
:param parsed: UNIT 解析结果
:param intent: 意图的名称
:returns: UNIT 的回复文本
"""
return unit.getSay(parsed, intent)
[文档]def get_engine_by_slug(slug=None):
"""
Returns:
An NLU Engine implementation available on the current platform
Raises:
ValueError if no speaker implementation is supported on this platform
"""
if not slug or type(slug) is not str:
raise TypeError("无效的 NLU slug '%s'", slug)
selected_engines = list(filter(lambda engine: hasattr(engine, "SLUG") and
engine.SLUG == slug, get_engines()))
if len(selected_engines) == 0:
raise ValueError("错误:找不到名为 {} 的 NLU 引擎".format(slug))
else:
if len(selected_engines) > 1:
logger.warning("注意: 有多个 NLU 名称与指定的引擎名 {} 匹配").format(slug)
engine = selected_engines[0]
logger.info("使用 {} NLU 引擎".format(engine.SLUG))
return engine.get_instance()
[文档]def get_engines():
def get_subclasses(cls):
subclasses = set()
for subclass in cls.__subclasses__():
subclasses.add(subclass)
subclasses.update(get_subclasses(subclass))
return subclasses
return [engine for engine in
list(get_subclasses(AbstractNLU))
if hasattr(engine, 'SLUG') and engine.SLUG]