Paddlehub+wechaty实现一个智能微信机器人-好友友好账户管家
Paddlehub+wechaty实现一个智能微信机器人-好友友好账户管家前言本项目是AI ChatBot创意赛的参赛项目比赛官方地址:https://aistudio.baidu.com/aistudio/competition/detail/79项目展示1. 比赛重点难点剖析比赛要求同时使用paddlehub和wechaty,有的小伙伴可能两个都不熟悉项目本质上是使用wechaty构建一个Ch
Paddlehub+wechaty实现一个智能微信机器人-好友友好账户管家
前言
本项目是AI ChatBot创意赛的参赛项目
比赛官方地址:https://aistudio.baidu.com/aistudio/competition/detail/79
项目展示
1. 比赛重点难点剖析
-
比赛要求同时使用paddlehub和wechaty,有的小伙伴可能两个都不熟悉
-
项目本质上是使用wechaty构建一个ChatBot
-
在此基础上接入paddlehub可以使我们的ChatBot变得更智能
-
当然,最重要的是创意,创意,创意!!
2. 项目思路介绍
项目的产生背景
-
现代人的好友数量众多
-
仅凭我们自己可能无法判别哪些好友是友好的,哪些是不友好的
-
有没有一种方式可以方便我们快速的判断
关于好友友好账户的解释
-
好友友好账户里存的是每一个好友的友好分数
-
好友发送的消息越友好,友好分数越高
-
好友发送的消息次数多,友好分数越高
3. 运行环境的配置
可以去看我另一个项目:教你用AI Studio+wechaty+阿里云白嫖一个智能微信机器人
4. 项目的大概流程讲解
-
机器人应该先识别出主人,并初始化好友列表以及好友友好账户
-
判断机器人收到的消息是来自主人还是好友
-
机器人收到主人的特定消息,执行特定功能
-
机器人收到好友发送的文本消息之后调用paddlehub模型分析友好分数,并记录在好友友好账户里
我使用的模型是ernie_skep_sentiment_analysis
模型地址:https://www.paddlepaddle.org.cn/hubdetail?name=ernie_skep_sentiment_analysis&en_category=SentimentAnalysis
5. 上代码
5.1 脚本文件run.sh
pip install --upgrade pip
pip install wechaty==0.7dev17
# 下载模型
hub install ernie_skep_sentiment_analysis==1.0.0
# 设置环境变量
export WECHATY_PUPPET=wechaty-puppet-service
export WECHATY_PUPPET_SERVICE_TOKEN=puppet_padlocal_xxxxxx # 填写你自己的token
# 设置使用GPU进行模型预测
export CUDA_VISIBLE_DEVICES=0
python run.py
5.2 python文件run.py
import re
import asyncio
import logging
import os
import random
import paddlehub as hub
from tkinter.constants import NO
from typing import List, Optional, Union
from wechaty_grpc.wechaty.puppet import ContactType
from wechaty_puppet import FileBox, ScanStatus # type: ignore
from wechaty import Wechaty, Contact
from wechaty.user import Message, Room, contact
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)
# 定义模型
modle = hub.Module(name="ernie_skep_sentiment_analysis")
def analyse_kind(text, local=False):
'''
分析好友所发消息的友好分数
text: 输入文本
local: 是否在本地运行
'''
if local:
# 在本地测试,不调用模型
score_kind = random.randint(-5, 5)
return score_kind
else:
# 转换文本为列表形式
text = [text]
# 模型输出结果
results = modle.predict_sentiment(text, use_gpu=True)
result = results[0]
# 如果消息是友好的
if result['sentiment_label'] == 'positive':
score_kind = result['positive_probs'] * 5
score_kind = round(score_kind, 2)
# 如果消息是不友好的
elif result['sentiment_label'] == 'negative':
score_kind = result['negative_probs'] * (-5)
score_kind = round(score_kind, 2)
return score_kind
class MyBot(Wechaty):
"""
listen wechaty event with inherited functions, which is more friendly for
oop developer
"""
def __init__(self):
super().__init__()
# 主人的contact
self.host_contact = None
# 好友的contact
self.contacts = None
# 给主人打招呼
self.say_hello = '你好我的主人,我是主人的好友友好账户管家,主要的功能有: \n1. 管理主人好友的友好账户\n2. 查询主人好友的友好账户\n主人回复相应数字即可查看详细功能'
# 好友的友好账户
self.account_kind = {}
async def on_message(self, msg: Message):
"""
listen for message event
"""
from_contact = msg.talker()
text = msg.text()
room = msg.room()
# 识别主人
if text == '你好我的机器人' and self.host_contact is None:
# 记录主人的contact
self.host_contact = from_contact
# 列举所有好友的contact
contacts: List[Contact] = await self.Contact.find_all()
# 过滤一些contact
self.contacts = [contact for contact in contacts if len(contact.contact_id) > 50]
# 移除主人的contact
self.contacts.remove(self.host_contact)
# 初始化好友的友好账户
self.account_kind = {contact: 0 for contact in self.contacts}
# 给主人发消息
conversation = self.host_contact
await conversation.ready()
await conversation.say(self.say_hello)
# 打印好友的contact
# for contact in self.contacts:
# print(contact.name, contact.payload.alias)
# 如果是主人的消息
if from_contact == self.host_contact:
conversation = self.host_contact
await conversation.ready()
if text == 'ding':
await conversation.say('dong')
if text == '1':
await conversation.say('当有好友给主人发消息时,将自动分析这句话的友好分数,并记录在主人的好友友好账户上')
if text == '2':
await conversation.say('主人按照以下格式即可查询好友的友好账户\n查询 好友 张三\n\n主人按照以下格式即可查询好友友好账户排名前五\n查询 前5\n\n主人按照以下格式即可查询好友友好账户排名后五\n查询 后5')
if '查询 好友' in text:
# 提取好友备注或昵称
friend_name = text.split(' ')[-1]
# 遍历字典,找打好友的友好账户分数并返回
for contact, score in list(self.account_kind.items()):
if friend_name == contact.name or friend_name == contact.payload.alias:
friend_score_kind = round(score, 2)
break
await conversation.say(f'亲爱的主人,{friend_name}目前的友好分数为:{friend_score_kind}')
if '查询 前' in text:
# 提取数字
number = re.findall(r'\d+', text)
number = int(number[0])
# 按照账户分数大小给字典排序
sorted_account_kind = {contact: score for contact, score in sorted(self.account_kind.items(), key=lambda item: item[1], reverse=True)}
# 给主人发的消息内容
msg_to_host = f'亲爱的主人,目前好友友好账户排名前{number}的是:'
for contact, score in list(sorted_account_kind.items())[:number]:
# 获取好友备注或昵称
friend_name = contact.payload.alias if contact.payload.alias != '' else contact.name
msg_to_host += f'\n{friend_name}:{round(score, 2)}'
await conversation.say(msg_to_host)
if '查询 后' in text:
# 提取数字
number = re.findall(r'\d+', text)
number = int(number[0])
sorted_account_kind = {contact: score for contact, score in sorted(self.account_kind.items(), key=lambda item: item[1])}
# 给主人发的消息内容
msg_to_host = f'亲爱的主人,目前好友友好账户排名后{number}的是:'
for contact, score in list(sorted_account_kind.items())[:number]:
# 获取好友备注或昵称
friend_name = contact.payload.alias if contact.payload.alias != '' else contact.name
msg_to_host += f'\n{friend_name}:{round(score, 2)}'
await conversation.say(msg_to_host)
# 好友的消息
if from_contact in self.contacts and room is None and msg.type() == Message.Type.MESSAGE_TYPE_TEXT:
# 计算好友消息的友好分数
msg_score_kind = analyse_kind(text, local=False)
# 更新好友的友好账户
self.account_kind[from_contact] += msg_score_kind
self.account_kind[from_contact] = round(self.account_kind[from_contact], 2)
# 获取好友备注或昵称
friend_name = from_contact.payload.alias if from_contact.payload.alias != '' else from_contact.name
# 给主人汇报消息
conversation = self.host_contact
await conversation.ready()
await conversation.say(f'亲爱的主人,{friend_name}给您发了一条消息\n消息内容是: {text}\n友好分数是: {msg_score_kind}\n{from_contact.name}目前的友好分数为:{self.account_kind[from_contact]}')
async def on_login(self, contact: Contact):
print(f'user: {contact} has login')
async def on_scan(self, status: ScanStatus, qr_code: Optional[str] = None,
data: Optional[str] = None):
contact = self.Contact.load(self.contact_id)
print(f'user <{contact}> scan status: {status.name} , '
f'qr_code: {qr_code}')
bot: Optional[MyBot] = None
async def main():
"""doc"""
# pylint: disable=W0603
global bot
bot = MyBot()
await bot.start()
asyncio.run(main())
6. 项目完善(使用多个模型协同进行文本分析)
-
关于情感分析模型的对比,可以看我的另一个项目: 情感分析模型的对比
-
分析可知模型ernie_skep_sentiment_analysis的准确率较高
-
模型ernie_skep_sentiment_analysis对于一些具有明显感情色彩的文本给出的置信度并不是很高
-
但其他几个模型能给出较高的置信度
-
于是我们可以使用ernie_skep_sentiment_analysis模型作为主模型,判断情感色彩是正面还是负面
-
使用其他几个模型作为辅助模型,当情感色彩与主模型一致时,分数记录下来,最后取平均
代码如下
from numpy import mean
# 定义主模型
modle_main = hub.Module(name="ernie_skep_sentiment_analysis")
# 定义辅助模型
model_lstm = hub.Module(name="senta_lstm")
model_bilstm = hub.Module(name="senta_bilstm")
model_gru = hub.Module(name="senta_gru")
def analyse_kind(text):
# 转换文本为列表形式
text = [text]
# 主模型输出结果
results_main = modle_main.predict_sentiment(text, use_gpu=True)
result_main = results_main[0]
# 辅助模型输出结果
results_lstm = model_lstm.sentiment_classify(text, use_gpu=True)
result_lstm = results_lstm[0]
results_bilstm = model_bilstm.sentiment_classify(text, use_gpu=True)
result_bilstm = results_bilstm[0]
results_gru = model_gru.sentiment_classify(text, use_gpu=True)
result_gru = results_gru[0]
results = [result_lstm, result_bilstm, result_gru]
list_score = []
# 如果消息是友好的
if result_main['sentiment_label'] == 'positive':
score = result_main['positive_probs'] * 5
list_score.append(score)
for result in results:
if result['sentiment_label'] == 'positive':
score = result['positive_probs'] * 5
list_score.append(score)
# 如果消息是不友好的
elif result_main['sentiment_label'] == 'negative':
score = result_main['negative_probs'] * (-5)
list_score.append(score)
for result in results:
if result['sentiment_label'] == 'negative':
score = result['negative_probs'] * (-5)
list_score.append(score)
score = mean(list_score)
score = round(score, 2)
core.append(score)
for result in results:
if result['sentiment_label'] == 'negative':
score = result['negative_probs'] * (-5)
list_score.append(score)
score = mean(list_score)
score = round(score, 2)
return score
后记
机器人还不太完善的地方
-
如果消息中有表情,不能准确判断友好分数
-
对于少部分消息内容不能准确判断友好分数
改进完善方向
同时使用多个paddlehub模型协同进行预测可能效果会更好(已完善)
更多功能
-
请访问我的GitHub仓库: https://github.com/Lovely-Pig/paddlehub-wechaty
-
如果GitHub打不开的话,我在AI Studio上也准备了一个相同的仓库: https://aistudio.baidu.com/aistudio/projectdetail/1886330
-
觉得不错的话给我一个Star哦🎉🎉🎉
飞桨使用体验
飞桨PaddlePaddle是百度自研的开源深度学习平台,有全面的官方支持的工业级应用模型,涵盖自然语言处理、计算机视觉、推荐引擎等多个领域,拥有EasyDL、AI Studio等服务平台,并为开发者开放PaddleHub、PaddleX、VisualDL等一系列深度学习工具组件,更有PaddleNLP、PaddleCV、PaddleRec等基础模型库,帮助开发者快速落地AI应用。总之,飞桨PaddlePaddle简直就是宝藏!!
参考资料
-
paddlehub官网:https://www.paddlepaddle.org.cn/hub
-
wechaty官网:https://wechaty.js.org
更多推荐
所有评论(0)