使用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将xml xsl文件生成html文件存储示例讲解
Dec 03 Python
python+selenium识别验证码并登录的示例代码
Dec 21 Python
Python深度优先算法生成迷宫
Jan 22 Python
Django数据库表反向生成实例解析
Feb 06 Python
Tensorflow 利用tf.contrib.learn建立输入函数的方法
Feb 08 Python
替换python字典中的key值方法
Jul 06 Python
python 获取sqlite3数据库的表名和表字段名的实例
Jul 17 Python
在pytorch中对非叶节点的变量计算梯度实例
Jan 10 Python
Python运行提示缺少模块问题解决方案
Apr 02 Python
python如何解析复杂sql,实现数据库和表的提取的实例剖析
May 15 Python
Windows 下更改 jupyterlab 默认启动位置的教程详解
May 18 Python
Python Pivot table透视表使用方法解析
Sep 11 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 防止单引号,双引号在接受页面转义
2008/07/10 PHP
php 获取mysql数据库信息代码
2009/03/12 PHP
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
PHP中的常见魔术方法功能作用及用法实例
2015/07/01 PHP
微信支付开发告警通知实例
2016/07/12 PHP
PHP中的多种加密技术及代码示例解析
2016/10/20 PHP
php统计数组不同元素的个数的实例方法
2019/09/26 PHP
Yii框架的redis命令使用方法简单示例
2019/10/15 PHP
prototype 1.5 &amp; scriptaculous 1.6.1 学习笔记
2006/09/07 Javascript
javascript如何创建表格(javascript绘制表格的二种方法)
2013/12/10 Javascript
自定义百度分享的分享按钮
2015/03/18 Javascript
jQuery实现鼠标双击Table单元格变成文本框及输入内容后更新到数据库的方法
2015/11/25 Javascript
jQuery封装的屏幕居中提示信息代码
2016/06/08 Javascript
禁止弹窗中蒙层底部页面跟随滚动的几种方法
2017/12/07 Javascript
vue之浏览器存储方法封装实例
2018/03/15 Javascript
vue.js实现图书管理功能
2019/09/24 Javascript
Vue.js 中制作自定义选择组件的代码附演示demo
2020/02/28 Javascript
JavaScript实现放大镜效果代码示例
2020/04/29 Javascript
Vue文本模糊匹配功能如何实现
2020/07/30 Javascript
详解Python编程中time模块的使用
2015/11/20 Python
Python中动态创建类实例的方法
2017/03/24 Python
Python使用re模块实现信息筛选的方法
2018/04/29 Python
Python中跳台阶、变态跳台阶与矩形覆盖问题的解决方法
2018/05/19 Python
python实现简单加密解密机制
2019/03/19 Python
Python实现FM算法解析
2019/06/18 Python
Python3+Appium实现多台移动设备操作的方法
2019/07/05 Python
Django RBAC权限管理设计过程详解
2019/08/06 Python
Python数据可视化:幂律分布实例详解
2019/12/07 Python
pycharm 实现光标快速移动到括号外或行尾的操作
2021/02/05 Python
CSS3截取字符串实例代码【推荐】
2018/06/07 HTML / CSS
党校学习自我鉴定
2014/02/24 职场文书
入党积极分子自我鉴定范文
2014/03/25 职场文书
活动总结怎么写啊
2014/05/07 职场文书
质量负责人岗位职责
2015/02/15 职场文书
html+css实现环绕倒影加载特效
2021/07/07 HTML / CSS
uni-app 微信小程序授权登录的实现步骤
2022/02/18 Javascript