使用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 相关文章推荐
win7安装python生成随机数代码分享
Dec 27 Python
python实现爬虫下载漫画示例
Feb 16 Python
python之消除前缀重命名的方法
Oct 21 Python
pyqt5让图片自适应QLabel大小上以及移除已显示的图片方法
Jun 21 Python
基于Pycharm加载多个项目过程图解
Jan 19 Python
jupyter notebook参数化运行python方式
Apr 10 Python
关于jupyter打开之后不能直接跳转到浏览器的解决方式
Apr 13 Python
浅谈keras中的batch_dot,dot方法和TensorFlow的matmul
Jun 18 Python
Python 字符串池化的前提
Jul 03 Python
Python进行特征提取的示例代码
Oct 15 Python
如何向scrapy中的spider传递参数的几种方法
Nov 18 Python
基于django和dropzone.js实现上传文件
Nov 24 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
PHP安全防范技巧分享
2011/11/03 PHP
使用PHP备份MYSQL数据的多种方法
2014/01/15 PHP
PHPExcel笔记, mpdf导出
2016/05/03 PHP
thinkPHP中配置的读取与C方法详解
2016/12/05 PHP
基于JQuery框架的AJAX实例代码
2009/11/03 Javascript
JQuery下的Live方法和$.browser方法使用代码
2010/06/02 Javascript
复制小说文本时出现的随机乱码的去除方法
2010/09/07 Javascript
一个简单的js树形菜单
2011/12/09 Javascript
浅谈关于JavaScript的语言特性分析
2013/04/11 Javascript
extjs_02_grid显示本地数据、显示跨域数据
2014/06/23 Javascript
VUEJS实战之修复错误并且美化时间(2)
2016/06/13 Javascript
js遮罩效果制作弹出注册界面效果
2017/01/25 Javascript
vue项目实现记住密码到cookie功能示例(附源码)
2018/01/31 Javascript
js中apply和Math.max()函数的问题及区别介绍
2018/03/27 Javascript
微信小程序实现日历功能
2018/11/27 Javascript
Vue实现的父组件向子组件传值功能示例
2019/01/19 Javascript
详解使用angular框架离线你的应用(pwa指南)
2019/01/31 Javascript
微信小程序利用swiper+css实现购物车商品删除功能
2019/03/06 Javascript
Python实现识别图片内容的方法分析
2018/07/11 Python
详解python读取image
2019/04/03 Python
如何基于python3和Vue实现AES数据加密
2020/03/27 Python
全面总结使用CSS实现水平垂直居中效果的方法
2016/03/10 HTML / CSS
HTML5实现移动端弹幕动画效果
2019/08/01 HTML / CSS
联想墨西哥官方网站:Lenovo墨西哥
2016/08/17 全球购物
英国名牌服装购物网站:OD’s Designer
2019/09/02 全球购物
简述安装Slackware Linux系统的过程
2012/01/12 面试题
大学毕业感言
2014/01/10 职场文书
骨干教师培训感言
2014/01/16 职场文书
阿德的梦教学反思
2014/02/06 职场文书
党的群众路线教育实践活动总结报告
2014/04/28 职场文书
普通话宣传标语
2014/06/26 职场文书
2014年工程工作总结
2014/11/25 职场文书
五年级下册复习计划
2015/01/19 职场文书
反腐倡廉主题教育活动总结
2015/05/07 职场文书
2016民族团结先进个人事迹材料
2016/02/26 职场文书
用Python写一个简易版弹球游戏
2021/04/13 Python