ChatBot 设计方案

最近公司有个客服机器人的需求,下午大概看了一下网上现有的一些方案,总感觉不是特别满意,而且整个 AI 圈子都透露出一点点的浮躁。其实对话机器人这个主题并不新颖,但对我来说,最早是在大学期间(2004-2008年)了,那时候的对话机器人都是基于模板的,印象很深刻有个网页版的机器人,名字叫 God,闲聊非常顺溜;再往后一点,记得在 2009 年看到的一篇文章,当时就特别想做一个,可惜不会写代码;然后就到了刚转行做技术的 2017 年,那时候有了 DeepLearning,也有了 RNN,于是就用对话语料自己训练了一个玩儿。

现在莫名其妙突然火起来我猜一方面是客服机器人确实解决了企业部分的需求;另一方面是这方面的技术更加成熟了。去看了一下发现虽然没有什么新东西(比如,意图理解是一个分类器,多轮对话是设计好的模板,甚至对话的生成也是基于模板),有点莫名其妙,可能还是得益于 NLP 基础技术不断取得的效果。还有一些借助知识图谱(又一个很早就提出最近突然火的东西)的客服机器人,看了几个项目,发现非常基础和简单粗暴,完全没有感觉到 AI 在哪里。感觉还不如三年前 memect 的 memect/kg-beijing: 北京知识图谱学习小组

冷静点看,现在的人工智能其实过于依赖数据,这究竟是聪明还是愚蠢只能见仁见智了。想想先哲们六七十年代从事 AI 所做的工作,直感觉汗颜不已,都是利益造就啊。有时候不得不感慨,人一旦对某一事物开始投入就会逐渐变得盲目,随着投入的不断增加会越来越盲目。经济学把这叫沉没成本,心理学上也有类似的研究,大家都把精力和金钱砸进来了,谁会说不好呢?明知道不好也要说好,还要继续增加投入,当然有些人纯粹是起哄或者薅羊毛。说的有点偏,倒不是说对 AI 没有信心,而是觉得被过于神化(人们总是喜欢一拥而上),在没有解决意识问题之前,它看起来再怎么 “聪明” 也就是个工具而已,对于一个工具自然应该以对待 “工具” 的方式去看。

言归正传,对话机器人既然有这么悠久的历史,我们当然不应该完全忽视先哲们的研究,所以我决定结合历史 AI 技术和现在新的 AI 技术,以自己的理解去做一个工业级别、开源的客服机器人系统。这篇文章要谈的就是机器人整个架构的设计以及背后的思想和逻辑。

基本思想

整体上是一种拟人化的思想,具体的细节来源于之前的一篇博客:NLP 与人工智能 | Yam。其实这也算是人类美好的愿望吧,要不然也不会叫 “机器人”、“人工智能” 了。这个愿望到底对不对目前是没有答案的,但效果却是实实在在的,那就把这个问题交给哲学家们吧。

既然是拟人化的,那我们自然要接受这样一种设定:不同的 “人” 的知识层次和认知水平不同。原因当然是 “成长环境” 和 “接受能力” 等方面不同引起的,前者决定了输入,后者决定了输出。

  • 记忆
    • 需要区分短时记忆和长时记忆:短时记忆限于当次对话,且更加关注最近的记录;长时记忆是一种持久的记忆,信息会经过处理变为某种知识然后以某种方式存储起来。
    • 短时记忆依靠模板、模型;长时记忆不仅会发生在 “训练”(学习)过程,同样会发生在 “执行”(交流)过程。也就是说,当你与他进行对话时,他已经开始对你所说的话进行处理并根据情况选择性存储了。
  • 推理
    • 即根据记忆与当前对话进行推理,然后将推理结果表达出来。
    • 推理使用贝叶斯方法,记忆不同,同样的对话推理出来的结果也不同。
  • 分层
    • 记忆分为三个层级:
      • 客观存在及其具有的属性和关系,比如 “蓝色” 可以表示 “颜色” 属性 或 “忧郁” 关系
      • 不同类别及其具有的属性和关系,上面两者分别对应 “色彩” 和 “心情” 类别
      • 具体事物及其具有的属性和关系,进而分别对应 “描述实体” 和 “描述人”
    • 推理分为三个层级:
      • 具体事物推出具体表征,比如 “他失恋了,感觉整个生活都是蓝色的”,我们知道是 “描述人”。
      • 不同类别推出类别表征,对应的,我们知道他是 “心情” 方面的意思。
      • 客观存在推出客观表征,再对应的,我们知道他是 “忧郁” 了。

架构设计

  • 基本流程:预处理 → 输入 → 语义 → 记忆 → 推理 → 表达

    • 预处理 → 输入:直接输入机器能识别的标准化结果(比如分好词的 token),而非原始数据。
    • 输入 → 语义:将输入提取语义结果。
    • 语义 → 记忆:语义结果根据实际情况并入记忆库。
    • 记忆 → 推理:根据语义理解结果和记忆库的结果完成推理。
    • 推理 → 表达:根据推理结果生成表达语句输出。
  • 充分利用模板:

    • 对于能利用模板匹配或生成的,可以跳过基本运作流程的中间处理步骤。
    • 模板本质是 “快速思考” 的替代。
  • 领域知识学习:
    • 具备学习不同领域知识的能力,并能与已有知识产生关联。
    • 可以通过领域内对话逐渐实现,也可以通过大量数据集中实现。
  • 模块化:可拆卸安装,零件可更换
    • 运作流程角度看,每一步都应该可以使用任何模型。
    • 横向上看,不同领域可以随意添加或移除。

实现思路

之前看了不少资料(见参考资源),发现有两个还挺不错的项目:

前者可以自动从对话中学习,后者可以对接知识图谱和定制多轮对话,这两个项目将作为重要参考。

其实在灵活定制方面我一直有个想法(但不知道是否可行),那就是架构中的基本流程全部可以定制。比如我们的输入就只接受分好词的 token + Pos + Ner + 句法 + 语义角色等,至于这些结果怎么来完全由用户选择自己的模型去实现。架构就像一个管道一样,它只把输入进来的句子经过各种转换变为输出,中间使用什么方法都可以,只要符合我们设计的数据规范就行。也就是我们只做架构和规范,以及一点点的基本功能,中间具体的技术都只提供一个默认版本或者干脆不提供,这些都将通过配置的方式实现(这点可以像 Rasa 学习)。

首先确定基本的东西:

  • 数据库方面,毋庸置疑选择图数据库,重难点在于如何设计。
  • 服务提供将采用 RPC 和 package 两种方式,方便部署使用。
  • 编程语言使用 Python。

然后是主要模块:

  • 解析模块:用于解析用户输入的原始数据或者相关的语料。
  • 理解模块:用于自然语言理解。
  • 记忆模块:用于将理解后的内容以某种方式(maybe 分层的知识图谱)存储起来。
  • 推理模块:用于自然语言推理,主要在记忆模块(也就是知识图谱)中执行。
  • 生成模块:用于自然语言生成,主要是将推理的结果生成自然的句子。

最后应该是配置文件:

  • 服务相关的:比如模型文件、自定义词典等
  • 训练相关的

题外

剩下的应该就是具体实现了,虽然无法预估日期,但我感觉这肯定是一个非常好玩儿的过程。总之,无论工作还是生活,好玩儿、有趣非常重要,要不然每天活着该多痛苦。

最近正在看尼克的《人工智能简史》,着实又一次被图灵、冯诺依曼等人折服,感觉完全是神一般的存在,在他们面前我都感觉自己像只蝼蚁。中间有一章专门讲自然语言处理的,我不剧透了,只想引用一句书中前言的话:

就像蒙克所说,历史可以帮助内行了解知识的进化并获得新的视角,同时也为外行人了解专业知识提供入门的台阶或向导。

回看历史,其实目前我们在自然语言处理领域并没有比先辈们强多少,每当想起曾经那个明星闪耀的时代,我都会不由自主地心生膜拜之情和敬畏之心(自惭形秽都不够格),正如叔本华所言:

Talent hits a target no one else can hit; Genius hits a target no one else can see.

我知道自己肯定不是 talent,只能算是一个极为普通的普通人,称为平庸之才毫不为过,如果有人这么说我,我一定不会生气。

再说说对人工智能的一些观点。目前非常前沿的探索有一些转向研究儿童如何学习,维诺格拉德当时也是这么做的,但当他在研读了基本儿童百科全书后觉得儿童的知识还是太深,后来就创造了 SHRDLU,一个虚拟的积木世界,可以根据人的指令进行虚拟操作。这玩意儿除了涉及自然语言理解外,还有行为规划和知识表示,同时还有很深的哲学意义(维特根斯坦后期哲学关于语言游戏的理论)。图灵在他的《计算机与智能》中也提到一个观点:“教育机器的工作量和教育一个人类儿童应该基本是一样的”,他基于此做了很多关于学习机器的论述。从认知方面进行探索在 IMB 的 Watson 时代就开始了,但目前这个领域依然值得继续投入。还有一些研究哲学、心理学、语言学,以及那个终极的 “意识” 方向的,人工智能领域依然像它诞生之初那样,处在多个学科的交叉。我觉得这可能也是它的众多迷人之处之一吧。所以所谓的派别之争其实并无必要,而事实上进行派别之争的往往也是在某一方面非常卓越,比如 IBM 的贾里尼克那句名言:“我每开除一名语言学家,语音识别系统的性能就提高一点。”乔姆斯基则对 “统计派” 异常排斥,他觉得不可解释的其实并没有提供知识,不过后来老爷子还是对他的观点做了一些调整。语言学的规则到底在自然语言处理上有没有用呢?我觉得可以引用 Aarne Ranta 的一个观点:“Don’t guess if you know: if there’s a grammar, use it”,有兴趣的可以看下他的 GF - Grammatical Framework