使用Python AIML搭建聊天机器人的方法示例


Posted in Python onJuly 09, 2018

AIML全名为Artificial Intelligence Markup Language(人工智能标记语言),是一种创建自然语言软件代理的XML语言,是由RichardS. Wallace 博士和Alicebot开源软件组织于1995-2000年间发明创造的。AIML是一种为了匹配模式和确定响应而进行规则定义的 XML 格式。

AIML的设计目标如下:

  1. AIML应当为大众所易学易会。
  2. AIML应当使最小的概念得以编码使之基于L.I.C.E支持一种刺激-响应学科系统组件。
  3. AIML应当兼容XML。
  4. 书写AIML可处理程序文件应当简单便捷。
  5. AIML对象应当对人而言具有良好的可读性和清晰度。
  6. AIML的设计应当正式而简洁。
  7. AIML应当包含对其他语言的依附性。

关于AIML详细的初级读物,可翻阅Alice Bot's AIML Primer。你同样可以在AIML Wikipedia page了解更多 AIML 的内容以及它能够做什么。借助 Python 的 AIML 包,我们很容易实现人工智能聊天机器人。

1、安装Python aiml库

pip install aiml

2、获取alice资源

Python aiml安装完成后在Python安装目录下的 Lib/site-packages/aiml下会有alice子目录,这个是系统自带的一个简单的语料库。

3、Python下加载alice

取得alice资源之后就可以直接利用Python aiml库加载alice brain了。

# -*- coding: utf-8 -*-
import aiml
import sys
import os
 
 
def get_module_dir(name):
  path = getattr(sys.modules[name], '__file__', None)
  if not path:
    raise AttributeError('module %s has not attribute __file__' % name)
  return os.path.dirname(os.path.abspath(path))
 
 
alice_path = get_module_dir('aiml') + '/alice'
#切换到语料库所在工作目录
os.chdir(alice_path)
 
alice = aiml.Kernel()
alice.learn("startup.xml")
alice.respond('LOAD ALICE')
 
while True:
print alice.respond(raw_input("Enter your message >> "))

上述流程非常的简单,接下来我们要自己从0开始创建自己的机器人。

创建标准启动文件

标准的做法是,创建一个名为std-startup.xml的启动文件,作为加载AIML文件的主入口点。在这个例子中,我们将创建一个基础的文件,它匹配一个模式,并且返回一个相应。我们想要匹配模式load aiml b,然后让它加载我们的aiml大脑作为响应。我们将在一步内创建basic_chat.aiml文件。

<aiml version="1.0.1" encoding="UTF-8">
  <!-- std-startup.xml -->
 
  <!-- Category是一个自动的AIML单元 -->
  <category>
 
    <!-- Pattern用来匹配用户输入 -->
    <!-- 如果用户输入 "LOAD AIML B" -->
    <pattern>LOAD AIML B</pattern>
 
    <!-- Template是模式的响应 -->
    <!-- 这里学习一个aiml文件 -->
    <template>
      <learn>basic_chat.aiml</learn>
      <!-- 你可以在这里添加更多的aiml文件 -->
      <!--<learn>more_aiml.aiml</learn>-->
    </template>
 
  </category>
 
</aiml>

创建一个AIML文件

在上面,我们创建的AIML文件只能处理一个模式:load aiml b。当我们向机器人输入那个命令时,它将会尝试加载basic_chat.aiml。除非我们真的创建了它,否则无效。下面是你可以写进basic_chat.aiml的内容。我们将匹配两个基本的模式和响应。

<aiml version="1.0.1" encoding="UTF-8">
<!-- basic_chat.aiml -->
<aiml>
 
  <category>
    <pattern>HELLO</pattern>
    <template>
      Well, hello!
    </template>
  </category>
 
  <category>
    <pattern>WHAT ARE YOU</pattern>
    <template>
      I'm a bot, silly!
    </template>
  </category>
 
</aiml>

随机响应

你也可以像下面这样添加随机响应。它将在接受到一个以”One time I”开头的消息的时候随机响应。*是一个匹配任何东西的通配符。

<category>
    <pattern>ONE TIME I *</pattern>
    <template>
      <random>
        <li>Go on.</li>
        <li>How old are you?</li>
        <li>Be more specific.</li>
        <li>I did not know that.</li>
        <li>Are you telling the truth?</li>
        <li>I don't know what that means.</li>
        <li>Try to tell me that another way.</li>
        <li>Are you talking about an animal, vegetable or mineral?</li>
        <li>What is it?</li>
      </random>
    </template>
  </category>

使用已存在的AIML文件

编写你自己的AIML文件是一个很有趣的事,但是它将花费很大的功夫。我觉得它需要大概10,000个模式才会开始变得真实起来。幸运的是,ALICE基金会提供了大量免费的AIML文件。在Alice Bot website上浏览AIML文件。

测试新建的机器人

目前为止,所有 XML 格式的 AIML 文件都准备好了。作为机器人大脑的组成部分,它们都很重要,不过目前它们只是信息(information)而已。机器人需要活过来。你可以借助任何语言定制 AIML。这里还是使用Python。

# -*- coding: utf-8 -*-
import aiml
import os
 
 
mybot_path = './mybot'
#切换到语料库所在工作目录
os.chdir(mybot_path)
 
mybot = aiml.Kernel()
mybot.learn("std-startup.xml")
mybot.respond('load aiml b')
 
while True:
  print mybot.respond(raw_input("Enter your message >> "))

这是我们可以开始的最简单的程序。它创建了一个aiml对象,学习启动文件,然后加载剩余的aiml文件。然后,它已经准备好聊天了,而我们进入了一个不断提示用户消息的无限循环。你将需要输入一个机器人认识的模式。这个模式取决于你加载了哪些AIML文件。我们将启动文件作为一个单独的实体创建,这样,我们之后可以向机器人添加更多的aiml文件,而不需要修改任何程序源码。我们可以在启动xml文件中添加更多的可供学习的文件。

加速Brain加载

当你开始拥有很多AIML文件时,它将花费很长的时间来学习。这就是brain文件从何而来。在机器人学习所有的AIML文件后,它可以直接将它的大脑保存到一个文件中,这个文件将会在后续的运行中动态加速加载时间。

# -*- coding: utf-8 -*-
import aiml
import os
 
 
mybot_path = './mybot'
#切换到语料库所在工作目录
os.chdir(mybot_path)
 
mybot = aiml.Kernel()
 
if os.path.isfile("mybot_brain.brn"):
  mybot.bootstrap(brainFile="mybot_brain.brn")
else:
  mybot.bootstrap(learnFiles="std-startup.xml", commands="load aiml b")
  mybot.saveBrain("mybot_brain.brn")
 
while True:
  print mybot.respond(raw_input("Enter your message >> "))

记住,如果你使用了上面写的brain方法,在运行的时候加载并不会将新增改变保存到brain中。你将需要删除brain文件以便于它在下一次启动的时候重建,或者需要修改代码,使得它在重新加载后的某个时间点保存brain。

增加Python命令

如果你想要为你的机器人提供一些特殊的运行Python函数的命令,那么,你应该为机器人捕获输入消息,然后在将它发送给mybot.respond()之前处理它。在上面的例子中,我们从raw_input中获得了用户的输入。然而,我们可以从任何地方获取输入。可能是一个TCP socket,或者是一个语音识别源码。在它进入到AIML之前处理这个消息。你可能想要在某些特定的消息上跳过AIML处理。

while True:
  message = raw_input("Enter your message >> ")
  if message == "quit":
    exit()
  elif message == "save":
    mybot.saveBrain("bot_brain.brn")
  else:
    bot_response = mybot.respond(message)
    # Do something with bot_response

会话与断言

通过指定一个会话,AIML可以为不同的人剪裁不同的会话。例如,如果某个人告诉机器人,他的名字是Alice,而另一个人告诉机器人他的名字是Bob,机器人可以区分不同的人。为了指定你所使用的会话,将其作为第二个参数传给respond()

sessionId = 12345
mybot.respond(raw_input(">>>"), sessionId)

这对于为每一个客户端定制个性化的对话是很有帮助的。你将必须以某种形式生成自己的会话ID,并且跟踪它。注意,保存brain文件不会保存所有的会话值。

sessionId = 12345
 
  # 会话信息作为字典获取. 包含输入输出历史,
  # 以及任何已知断言
  sessionData = mybot.getSessionData(sessionId)
 
  # 每一个会话ID需要时一个唯一值。
  # 断言名是机器人在与你的会话中了解到的某些/某个名字 
  # 机器人可能知道,你是"Billy",而你的狗的名字是"Brandy"
  mybot.setPredicate("dog", "Brandy", sessionId)
  clients_dogs_name = mybot.getPredicate("dog", sessionId)
 
  mybot.setBotPredicate("hometown", "127.0.0.1")
  bot_hometown = mybot.getBotPredicate("hometown")

在AIML中,我们可以使用模板中的set响应来设置断言

<aiml version="1.0.1" encoding="UTF-8">
  <category>
   <pattern>MY DOGS NAME IS *</pattern>
   <template>
     That is interesting that you have a dog named <set name="dog"><star/></set>
   </template> 
  </category> 
  <category>
   <pattern>WHAT IS MY DOGS NAME</pattern>
   <template>
     Your dog's name is <get name="dog"/>.
   </template> 
  </category> 
</aiml>

使用上面的AIML,你可以告诉机器人:

My dogs name is Max

而机器人会回答你:

That is interesting that you have a dog named Max

然后,如果你问机器人:

What is my dogs name?

机器人将会回答:

Your dog's name is Max.

aiml可以用来实现对话机器人,但是用于中文有以下问题:

  • 中文规则库较少。规则库相当于对话机器人的“大脑”,一般来说,规则库越丰富,对话机器人的应对就更像人。目前英文的规则库已经很丰富,涵盖面很广,而且是公开可获取的。但公开的中文规则库就基本没有。
  • AIML解释器对中文支持不好。实际上,Python下的Pyaiml模块(解析器)已经能比较好的支持中文,但是也存在以下问题:英文单词间一般都有空格或标点区分,因此具备一种“自然分词”特性,由于中文输入没有以空格分隔的习惯,以上会在实践中造成一些不便。比如要实现有/无空格的输入匹配,就需要在规则库中同时包含这两种模式。

解决方案:

  • 自己搭建语料库(比如从字幕文件中获取训练)
  • 自己中文分词工具(如jieba)

相关开源项目:

https://github.com/leo108/aliceCN
https://github.com/messense/wechat-bot
https://github.com/Program-O/Program-O

参考资料:

http://www.w3ii.com/aiml/aiml_introduction.html
http://www.devdungeon.com/content/ai-chat-bot-python-aiml
http://www.alicebot.org/documentation/aiml-reference.html

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python使用django获取用户IP地址的方法
May 11 Python
使用Python内置的模块与函数进行不同进制的数的转换
Mar 12 Python
基于Python中capitalize()与title()的区别详解
Dec 09 Python
浅谈Python中的全局锁(GIL)问题
Jan 11 Python
详解django+django-celery+celery的整合实战
Mar 19 Python
Django 数据库同步操作技巧详解
Jul 19 Python
Python流程控制 while循环实现解析
Sep 02 Python
python科学计算之narray对象用法
Nov 25 Python
jupyter notebook 多行输出实例
Apr 09 Python
Python Serial串口基本操作(收发数据)
Nov 06 Python
详解python的内存分配机制
May 10 Python
Python基于百度AI实现抓取表情包
Jun 27 Python
Python迭代器与生成器用法实例分析
Jul 09 #Python
numpy的文件存储.npy .npz 文件详解
Jul 09 #Python
Python实现聊天机器人的示例代码
Jul 09 #Python
Atom的python插件和常用插件说明
Jul 08 #Python
Python中pip更新和三方插件安装说明
Jul 08 #Python
python中sys.argv函数精简概括
Jul 08 #Python
python输出100以内的质数与合数实例代码
Jul 08 #Python
You might like
mysql_fetch_assoc和mysql_fetch_row的功能加起来就是mysql_fetch_array
2007/01/15 PHP
php htmlspecialchars加强版
2010/02/16 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
2013/07/03 PHP
php判断是否为json格式的方法
2014/03/04 PHP
PHP中预定义的6种接口介绍
2015/05/12 PHP
Laravel框架路由和控制器的绑定操作方法
2018/06/12 PHP
javascript下操作css的float属性的特殊写法
2007/08/22 Javascript
jquery控制listbox中项的移动并排序的实现代码
2010/09/28 Javascript
遨游,飞飞,IE,空中网 浏览器无提示关闭方法
2011/07/11 Javascript
javascript定义变量时有var和没有var的区别探讨
2014/07/21 Javascript
node.js中的http.response.removeHeader方法使用说明
2014/12/14 Javascript
jQuery实现简单的文件上传进度条效果
2020/03/26 Javascript
轻松实现jquery手风琴效果
2016/01/14 Javascript
Angular实现form自动布局
2016/01/28 Javascript
聊一聊JS中this的指向问题
2016/06/17 Javascript
基于JS实现回到页面顶部的五种写法(从实现到增强)
2016/09/03 Javascript
JS实现购物车特效
2017/02/02 Javascript
Vue.js原理分析之observer模块详解
2017/02/17 Javascript
用Nodejs搭建服务器访问html、css、JS等静态资源文件
2017/04/28 NodeJs
使用D3.js制作图表详解
2017/08/13 Javascript
javascript(基于jQuery)实现鼠标获取选中的文字示例【测试可用】
2019/10/26 jQuery
JavaScript原型继承和原型链原理详解
2020/02/04 Javascript
vue实现简单瀑布流布局
2020/05/28 Javascript
使用Python脚本将Bing的每日图片作为桌面的教程
2015/05/04 Python
在Linux系统上部署Apache+Python+Django+MySQL环境
2015/12/24 Python
Python使用win32com实现的模拟浏览器功能示例
2017/07/13 Python
Java编程迭代地删除文件夹及其下的所有文件实例
2018/02/10 Python
python mac下安装虚拟环境的图文教程
2019/04/12 Python
Python线程条件变量Condition原理解析
2020/01/20 Python
办公室内勤工作职责
2013/12/11 职场文书
便利店的创业计划书
2014/01/15 职场文书
幼儿园秋游感想
2014/03/12 职场文书
终止劳动合同协议书
2014/04/14 职场文书
和解协议书
2014/04/16 职场文书
篝火晚会策划方案
2014/05/16 职场文书
python单元测试之pytest的使用
2021/06/07 Python