简易AI聊天机器人

news/2024/12/19 8:16:24/

最近我自己搞了个简单的聊天机器人(类似淘宝机器客服一般的),他可以帮你查询疫情的最新消息、汇报天气情况、给你讲笑话、陪你聊天等一些基本的功能。下面就来介绍一下它。

一、制作流程

  1. 制作思路
    要做一个聊天机器人那么首先你要有一个聊天的界面,设计这个聊天界面,让它尽量好看,符合你的想法就好。然后就要想一下这个聊天界面需要什么内容:a.图标,我们打开这个页面左上方应该要有一个小图标。b.要有显示聊天记录的地方。c.要有一个输入框。d.要有一个发送的按钮。再其次是设计这个聊天机器人及其功能。

  2. 再次完善
    a.聊天页面:这里就看自己的设计了,我自己设计的比较一般般,效果就会在最后给大家展示。
    b.界面的内容:在聊天记录的那一栏,我们要知道是谁发的消息,所以我选择了使用头像这样子来表现。然后就是在发送按钮上面,我设计了一个功能,当你鼠标放在上面的时候可以显示出 “点击发送” 的字样
    c.聊天机器人:我是打算接入一个百度unit平台的API,借助百度来使我的机器人更加智能化。当然也有一些部分的应答打算我自己来写函数。

  3. 程序框架

Created with Raphaël 2.3.0 开始 窗口绘制 机器人启动 等待输入信息 机器人作出应答 是否点击退出按钮? 结束 yes no yes no

二、代码分析

要使用的库:

import json
import sys
import requests
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *

以下是主函数的部分

# 实例化一个应用对象app = QtWidgets.QApplication(sys.argv)

先建立一个应用对象app

 # 实例化聊天窗win = ChatBox()win.show()sys.exit(app.exec_())

然后我们创建了一个窗口类ChatBox(具体这个类如何写的后面会有介绍,这边先这样子说),建立了一个对象win。利用show函数把这个窗口显示出来。然后因为要实现这个窗口的关闭所以要用sys库中的exit函数。

以下是函数封装部分讲解
ChatBox(建立的python类)

class ChatBox(QWidget):

这是一个子类,父类是QWidget。

    def __init__(self):# 初始化父类构造函数# super会找到ChatBox继承的父类QWindegt, 去实例化父类的构造函数super(ChatBox, self).__init__()# 绘制界面方法# 初始化界面self.AI_robot = Chat_robot()self.initUI()

super(ChatBox, self).init()这句的意思是:super会找到ChatBox继承的父类QWindegt, 去实例化父类的构造函数。self.AI_robot = Chat_robot()这里我实例化了一个AI机器人,Chat_robot也是一个类。self.initUI()这是初始化窗口的函数。
下面是initUI()函数的内部组成

self.setWindowTitle("快来聊天啊!")
self.setGeometry(500, 100, 800, 700)
# 美化窗口+添加控件
# 窗口图标
self.icon = QtGui.QIcon()
self.icon.addPixmap(QtGui.QPixmap("picture.png"),    # 图标路径QtGui.QIcon.Normal,QtGui.QIcon.Off)
self.setWindowIcon(self.icon)

我们先设置窗口的标题,然后就是设置窗口的位置和大小,然后我们用picture这张图做了一个图标(这里要注意这个图片要放在这个工程下)。

self.left_box = QWidget(self)
self.left_box.setGeometry(10, 10, 200, 680)
self.left_box.setStyleSheet("background-color: rgb(200, 200, 169)")   
# 设置背景色
self.AI = QLabel("专属机器人在线中", self)
self.AI.setGeometry(11, 11, 200, 120)
self.AI.setStyleSheet("background-color: rgb(0, 245, 255); color: black; font-size:22px")

我设计了一个边框,位置大概是在左边区域(setGeometry这个函数是确定位置的,后面的也是如此。),里面我就做了简单的一个背景色设置和一个标签“专属机器人在线中”以及标签的背景颜色和字的颜色、大小。

self.chatBox = QListWidget(self)
# 设置位置
self.chatBox.setGeometry(210, 10, 590, 600)
# 设置样式
self.chatBox.setStyleSheet("background-image: url(background.png);border:2px solid #c4c4c4; font-size:30px")
# 设置图标大小
self.chatBox.setIconSize(QSize(40, 40))

我这里绘制了一个聊天窗口,显示聊天内容的地方,setIconSize这个函数是设置说话的人的头像大小,我这里还用background这张图片做了个背景图。

self.char_input = QLineEdit(self)
self.char_input.setGeometry(210, 615, 480, 80)
self.char_input.setStyleSheet("color:black; font-size:30px; border: 10px solid #f4f4f4;""background-color: rgb(255, 255, 255);")

这个是发送消息的部分,设置了位置,字的颜色大小,待发消息框的背景色。

self.submit = QPushButton('发送', self)  # 按钮显示的文字
self.submit.setToolTip('点击发送')  # 当鼠标放上去后显示的内容
self.submit.setGeometry(695, 615, 100, 80)   # 位置
self.submit.setStyleSheet("color:black; font-size:20px; font-weight:bold; border-radius:2;""background-color: rgb(131, 175, 155);")

这是发送按钮的设计,包括了按钮上面的文字,位置,字体的颜色,大小,背景色。

item = QListWidgetItem(QIcon("AI_robot.png"), "你好!有什么可以为你服务的?", self.chatBox)
self.submit.clicked.connect(self.send_message)    # 信号与槽的连接

第一句代码是,当你启动程序的时候这个机器人会自动的说一句“你好!有什么可以为你服务的?”。QIcon(“AI_robot.png”)这个是设置机器人的头像。self.chatBox这个是说,显示在chatBox这一部分(即聊天记录框)。后面一句代码是说当你点击这个按钮是程序的反应,反应函数是send_message。

对send_message这个函数的讲解:

def send_message(self):# 用户输出什么信息content = self.char_input.text()if len(content) == 0:return     # 函数终结# 把输入的信息显示在聊天区item = QListWidgetItem(QIcon("USER.png"), content, self.chatBox)# 清空输入框self.char_input.clear()

我们先从待发消息去获取你要发的消息给content。当然如果是空消息就发不出去了,所以会有个判断。然后就是把这个消息放在聊天区中,同时显示头像,并清除待发消息区的消息。

robot_reply = self.AI_robot.get_reply(content)

我同过AI_robot这个对象里面的get_reply函数来得到机器人的回答。robot_reply 就是机器人要回答的内容部分。

# 当询问天气等缺少地点元素的时候
global connect_flag, word_flag
if connect_flag:content = content + connect_word    # 连接两个字符串robot_reply = self.AI_robot.get_reply(content)connect_flag = False

这里做的处理是说,当我们问“天气如何”时机器人会回答一个“你要问的是哪里的天气呢”,那么我就要将这两次的消息进行拼接,在发给机器人,不然机器人没办法做到将这两次的消息连接起来,他只会当成一个问题来回答。connect_flag这是一个标志位,当有连接的时候是True,不需要时是False。
在这里插入图片描述

self.deal_message(robot_reply, content)
#  下面的函数是另外定义的,放在这里只是为了一次解释清楚罢了def deal_message(self, robot_reply, content):# 处理句子的连接for index, item in enumerate(key_word):if item in robot_reply:global connect_flagconnect_flag = True# 处理重复输入global word_flag, connect_wordif word_flag == 0:connect_word = contentif connect_word == content:word_flag = word_flag + 1    # word_flag 记录出现的次数else:word_flag = 0# 处理背景的改变global bg_flagfor index, item in enumerate(weather):if item in robot_reply:bg_flag = index+1     # bg_flag 这是背景的选择,0~4,分别对应着不同的天气背景breakelse:bg_flag = 0

这个函数是用来处理句子连接、重复输入以及背景的改变这三个功能的标志位,具体函数的处理在后面。哦对了,这里使用的标志位都是全局变量。

robot_reply = self.deal_reprtion(robot_reply) # 处理重复输入多次函数
#  下面的函数是另外定义的,放在这里只是为了一次解释清楚罢了def deal_reprtion(self, robot_reply):global word_flagif word_flag == 2:robot_reply = '这个问题我已经回答过了'elif word_flag == 3:robot_reply = '你是憨憨嘛?都说了回答了你还问,再问就不理你了。'elif word_flag == 4:robot_reply = '不理你了'elif word_flag >= 5:robot_reply = Nonereturn robot_reply

当你重复输入同一个问题时,机器人就不会再回答你一边,而是会说你了
在这里插入图片描述

# 改变背景
self.change_background()
#  下面的函数是另外定义的,放在这里只是为了一次解释清楚罢了def change_background(self):global bg_flagif bg_flag == 1:self.chatBox.setStyleSheet("background-image: url(sunny.png);border:2px solid #c4c4c4; font-size:30px")elif bg_flag == 2:self.chatBox.setStyleSheet("background-image: url(foggy.png);border:2px solid #c4c4c4; font-size:30px")elif bg_flag == 3:self.chatBox.setStyleSheet("background-image: url(rainy.png);border:2px solid #c4c4c4; font-size:30px")elif bg_flag == 4:self.chatBox.setStyleSheet("background-image: url(cloudy.png);border:2px solid #c4c4c4; font-size:30px")else:self.chatBox.setStyleSheet("background-image: url(background.png);border:2px solid #c4c4c4; font-size:30px")

每一个标志位对应着一种天气背景,在信息处理函数时,会去遍历机器人回答的字符串,当有涉及到天气的因素时就会记录下来,同时会改变标志的值。效果展示,就像是那个询问天气的图片。

self.reply(robot_reply)  # 消息的回复
#  下面的函数是另外定义的,放在这里只是为了一次解释清楚罢了def reply(self, robot_reply):if robot_reply is None:returnif len(robot_reply) >= 16:count = int(len(robot_reply)/16)for i in range(0, count):if i ==0:res = robot_reply[16*i:(16*(i+1)-1)]item = QListWidgetItem(QIcon("AI_robot.png"), res, self.chatBox)else:res = robot_reply[16*i-1:(16 * (i+1)-1)]item = QListWidgetItem(res, self.chatBox)if len(robot_reply)/16 > count:res = robot_reply[16*count-1:]item = QListWidgetItem(res, self.chatBox)returnitem = QListWidgetItem(QIcon("AI_robot.png"), robot_reply, self.chatBox)

消息的回复这个函数,我计算了一下它的长度,如果长度超过窗口长度则它会分行、多次输出,同时只有第一次输出的才会带头像。最后一句话是保证不超行的时候可以正常输出。开头的if robot_reply is None:判断是为了配合之前那个输入多次后不理你这个功能的。中间的就是用来处理字符长度的。

下面讲解机器人这个对象:

class Chat_robot:def __init__(self):self.AK = AKself.SK = SKself.access_token = self.get_access_token()

先建立一个机器人类。__init__这是一个构造函数,里面放的是这个机器人的属性。因为我们的机器人是用百度unit平台的机器人,所以这里要调用人家的API,AK,SK对应这API Key 和 Secret Key 。access_token 对应这token,具体怎么获取百度unit平台的token,参考百度的文档获取access_token。当然这里我也会介绍python获取token的方法。

def get_access_token(self):host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' +\self.AK + '&client_secret=' + self.SKresponse = requests.get(host).json()return response['access_token']

上面的函数就是python获取token带的方式。要详细了解里面的参数的意义,要通读上面的文档。

    def get_reply(self, user_input):post_data = json.dumps({"log_id": "UNITTEST_10000","version": "2.0","service_id": "S29968","session_id": "","request": {"query": user_input,"user_id": "8888",},"dialog_state": {"contexts": {"SYS_REMEMBERED_SKILLS": ["1028652"]}}})# json.dumps() 用于将dict类型的数据转成str,因为如果直接将dict类型的数据写入json文件中会发生报错,因此在将数据写入时需要用到该函数url = 'https://aip.baidubce.com/rpc/2.0/unit/service/chat?access_token=' + self.access_tokenheaders = {'content-type': 'application/x-www-form-urlencoded'}response = requests.post(url, data=post_data, headers=headers).json()if response:return response['result']['response_list'][0]['action_list'][0]['say']

上面这个函数是,用来得到机器人的回答内容的。这里要注意的是,我们在API文档中他的post_data 这个数据是采用字符串的形式写的,我们在python中没办法识别它,所以我们要用上面的这个dumps函数写入json文件之中。

三、整体代码展示

import json
import sysimport requests
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *
# 表示从PyQt5的QtWidgets中引用全部函数(*表示全部)
# 1.应答核心--in判断成员是否在list中
# 2. 百度unitAPI接进来# 常量
AK = 'LNsYReyUKb9idkO9OHHnanm0'
SK = '28iTb65vBPmSR05vyNU6pnYjIa739KP7'key_word = ('你要找', '你要查')
weather = ('晴', '雾', '雨', '阴')
connect_flag = False
connect_word = '初始化'
word_flag = 0
bg_flag = 0# 继承
class ChatBox(QWidget):def __init__(self):# 初始化父类构造函数# super会找到ChatBox继承的父类QWindegt, 去实例化父类的构造函数super(ChatBox, self).__init__()# 绘制界面方法# 初始化界面self.AI_robot = Chat_robot()self.initUI()def initUI(self):self.setWindowTitle("快来聊天啊!")self.setGeometry(500, 100, 800, 700)# 美化窗口+添加控件# 窗口图标self.icon = QtGui.QIcon()self.icon.addPixmap(QtGui.QPixmap("picture.png"),    # 图标路径QtGui.QIcon.Normal,QtGui.QIcon.Off)self.setWindowIcon(self.icon)# 左侧栏self.left_box = QWidget(self)self.left_box.setGeometry(10, 10, 200, 680)self.left_box.setStyleSheet("background-color: rgb(200, 200, 169)")   # 设置背景色self.AI = QLabel("专属机器人在线中", self)self.AI.setGeometry(11, 11, 200, 120)self.AI.setStyleSheet("background-color: rgb(0, 245, 255); color: black; font-size:22px")# 右上方聊天区self.chatBox = QListWidget(self)# 设置位置self.chatBox.setGeometry(210, 10, 590, 600)# 设置样式self.chatBox.setStyleSheet("background-image: url(background.png);border:2px solid #c4c4c4; font-size:30px")# 设置图标大小self.chatBox.setIconSize(QSize(40, 40))# 右下方内容准备self.char_input = QLineEdit(self)self.char_input.setGeometry(210, 615, 480, 80)self.char_input.setStyleSheet("color:black; font-size:30px; border: 10px solid #f4f4f4; ""background-color: rgb(255, 255, 255);")# 发送按钮self.submit = QPushButton('发送', self)self.submit.setToolTip('点击发送')  # 当鼠标放上去后显示的内容self.submit.setGeometry(695, 615, 100, 80)self.submit.setStyleSheet("color:black; font-size:20px; font-weight:bold; border-radius:2;""background-color: rgb(131, 175, 155);")# 点击发送按钮,发送消息item = QListWidgetItem(QIcon("AI_robot.png"), "你好!有什么可以为你服务的?", self.chatBox)self.submit.clicked.connect(self.send_message)    # 信号与槽的连接def send_message(self):# 用户输出什么信息content = self.char_input.text()if len(content) == 0:return     # 函数终结# 把输入的信息显示在聊天区item = QListWidgetItem(QIcon("USER.png"), content, self.chatBox)# 清空输入框self.char_input.clear()robot_reply = self.AI_robot.get_reply(content)# 当询问天气等缺少地点元素的时候global connect_flag, word_flagif connect_flag:content = content + connect_wordrobot_reply = self.AI_robot.get_reply(content)connect_flag = Falseself.deal_message(robot_reply, content)## 下面这个是处理重复输入多次函数robot_reply = self.deal_reprtion(robot_reply)# 改变背景self.change_background()self.reply(robot_reply)# 消息回复def reply(self, robot_reply):if robot_reply is None:returnif len(robot_reply) >= 16:count = int(len(robot_reply)/16)for i in range(0, count):if i ==0:res = robot_reply[16*i:(16*(i+1)-1)]item = QListWidgetItem(QIcon("AI_robot.png"), res, self.chatBox)else:res = robot_reply[16*i-1:(16 * (i+1)-1)]item = QListWidgetItem(res, self.chatBox)if len(robot_reply)/16 > count:res = robot_reply[16*count-1:]item = QListWidgetItem(res, self.chatBox)returnitem = QListWidgetItem(QIcon("AI_robot.png"), robot_reply, self.chatBox)def deal_message(self, robot_reply, content):# 处理句子的连接for index, item in enumerate(key_word):if item in robot_reply:global connect_flagconnect_flag = True# 处理重复输入global word_flag, connect_wordif word_flag == 0:connect_word = contentif connect_word == content:word_flag = word_flag + 1else:word_flag = 0# 处理背景的改变global bg_flagfor index, item in enumerate(weather):if item in robot_reply:bg_flag = index+1breakelse:bg_flag = 0def deal_reprtion(self, robot_reply):global word_flagif word_flag == 2:robot_reply = '这个问题我已经回答过了'elif word_flag == 3:robot_reply = '你是憨憨嘛?都说了回答了你还问,再问就不理你了。'elif word_flag == 4:robot_reply = '不理你了'elif word_flag >= 5:robot_reply = Nonereturn robot_replydef change_background(self):global bg_flagif bg_flag == 1:self.chatBox.setStyleSheet("background-image: url(sunny.png);border:2px solid #c4c4c4; font-size:30px")elif bg_flag == 2:self.chatBox.setStyleSheet("background-image: url(foggy.png);border:2px solid #c4c4c4; font-size:30px")elif bg_flag == 3:self.chatBox.setStyleSheet("background-image: url(rainy.png);border:2px solid #c4c4c4; font-size:30px")elif bg_flag == 4:self.chatBox.setStyleSheet("background-image: url(cloudy.png);border:2px solid #c4c4c4; font-size:30px")else:self.chatBox.setStyleSheet("background-image: url(background.png);border:2px solid #c4c4c4; font-size:30px")class Chat_robot:def __init__(self):self.AK = AKself.SK = SKself.access_token = self.get_access_token()def get_access_token(self):host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' +\self.AK + '&client_secret=' + self.SKresponse = requests.get(host).json()return response['access_token']def get_reply(self, user_input):post_data = json.dumps({"log_id": "UNITTEST_10000","version": "2.0","service_id": "S29968","session_id": "","request": {"query": user_input,"user_id": "8888",},"dialog_state": {"contexts": {"SYS_REMEMBERED_SKILLS": ["1028652"]}}})# json.dumps() 用于将dict类型的数据转成str,因为如果直接将dict类型的数据写入json文件中会发生报错,因此在将数据写入时需要用到该函数url = 'https://aip.baidubce.com/rpc/2.0/unit/service/chat?access_token=' + self.access_tokenheaders = {'content-type': 'application/x-www-form-urlencoded'}response = requests.post(url, data=post_data, headers=headers).json()if response:return response['result']['response_list'][0]['action_list'][0]['say']# 控件  位置  样式
# 程序的主入口会有main函数
# python把每一个py脚本看成模块,可以单独运行
if __name__ == "__main__":# 实例化一个应用对象app = QtWidgets.QApplication(sys.argv)# 实例化聊天窗win = ChatBox()win.show()sys.exit(app.exec_())

四、不足之处

这个项目还有很多待改进之处,下面就来说说:

  1. 在拼接字符串的那个功能的时候,你会发现它单纯的拼接,不能做到比较智能化,就是把你输入的这两句话组合成一句比较通顺的话。
  2. 在处理消息很长分段时,你会发现每一行并不是满的,有时候会出现上面一行很短,下面一行是长的。
  3. 背景的变化,这里识别多个的天气关键词的时候(例如阴雨天气)他会默认跑出天气标志位比较大的那个对应的图片,可以考虑完善一下天气的关键词和图片。
  4. 界面可以在变的美观一些。
  5. 可以利用PyQt5这个库设计更多的功能

五、收获

通过这次的小项目,让我更加熟练的掌握了python的用法和基础语法以及利用类去封装函数,还学会了如何去读API文档,以及对API的调用。更加的我还认识到了PyQt5这个库。


http://www.ppmy.cn/news/698803.html

相关文章

ChatGPT| 人工智能时代最强大的聊天机器人!|小智ai

ChatGPT丨小智ai丨chatgpt丨人工智能丨OpenAI丨聊天机器人丨AI语音助手丨GPT-3.5丨开源AI平台 【前言】 近年来,随着人工智能技术的不断发展,越来越多的机器人开始进入人们的生活,并且逐渐融入到人类社会中。其中,聊天机器人成为了…

小微-你的专属聊天机器人

云服务器部署微信自动聊天机器人 环境要求 云服务器(腾讯云学生服务器)Python环境itchat库图灵机器人api 环境搭建 云服务器:云服务器的购买及搭建 Python环境安装:Linux下安装Anaconda(64位)详细过程 Itchat的安装: 请在终端(Terminal)…

快来动手训练属于自己的聊天机器人吧!

活动时间 北京时间2023年3月16日15:00-17:00 活动形式 在线直播——动手训练营 动手实践 使用 Amazon SageMaker 构建基于开源 GPT-J 模型的对话机器人应用 难度:入门 时间:20 分钟 开发者可以使用 Amazon SageMaker 构建一个交互式的人机对话应用 DEMO…

微信智能机器人助手,基于hook技术,自动聊天机器人

微信智能助手说明文档 资料获取方式,关注公总号RaoRao1994,查看往期精彩-所有文章,即可获取资源下载链接 更多资源获取,请关注公总号RaoRao1994 简介 微信智能助手是一款基于PC微信研发的微信助手类软件,能帮助大家…

python微信机器人

原文链接python微信机器人制作教程源码_全栈川川-CSDN博客 本文为我个人的学习笔记 前言:继QQ机器人以来,川川大佬的微信机器人再一次上线了,微信风控比较严,所以测试中确实会出现报错的情况,不过没关系,最后还是成功了…

python聊天机器人

import subprocess import pyautogui import uiautomation as auto import time import requests import pyperclip muo[] new_data[]#存放消息的列表 list_data["66778899","几点","课表","时间戳"]#存放指定回复列表 new_data.appen…

Python 微信机器人

使用python构造一个微信聊天机器人 最近在学python的过程中无意间发现一个python库:wxpy,其可以实现让微信自动接收、处理消息并进行回复的一系列功能。感觉挺有意思的,便自行摸索学习,并成功地实现了其功能,故写下此…

练手小项目(1)——智能聊天机器人

我一直坚信着,即使一个最简单的APP,也有他的难点,如果一个复杂的APP你无法做出来,那肯定是你基础不扎实,我身边的人总是问我,安卓为什么学了有忘记了,总是学不好,有些东西记不住&…