A simple prompt-chatting AI based on wechaty and fintuned NLP model
一个简单的基于prompt的预训练大模型中文聊天人工智能框架,仅限交流与科普。
AntiFraudChatBot是基于大规模预训练中文模型、语义识别与检测、对话意图等技术所构建的生成式对话QA框架,目前第一版模型针对反诈骗的场景化任务,对比传统的BertQA模型或non-prompt模型,在真实测试中AI对话的流畅度有明显提高。
项目作者 | 主页1 | 主页2 |
---|---|---|
Y1ran | CSDN | Github |
- 基于wechaty框架,AI可以7x24的实时、无缝进行微信对话
- 对话核心是YUAN1.0——2457亿参数的开源中文预训练大模型
- 框架模块化设计,支持替换其他对话模型接口(chatGPT、文心等)
- 端到端生成,服务启动后可以持续对话(除非云服务器宕机)
- Ubuntu 18.04.2/ Windows10 x86
- Python >= 3.7
- Tensorflow-gpu 1.15.2
- paddlenlp 2.4.2
- paddlepaddle 2.0.0
- CUDA >= 10.0
- CuDNN >= 7.6.0
- Wechat 3.3.0.115
整个框架分为服务器端、本地端和模型端3个模块,每个模块之间解耦,可单独迭代或替换。
YUAN-1.0是国内最新的预训练大模型,整体参数量2457亿,预训练语料5000G,超过GPT-3。在中文语言理解评测基准CLUE榜单的零样本学习(zero-shot)和小样本学习(few-shot)都拿过总榜第一。用这个的原因也很简单——API接口使用方便、最主要是免费调用:YUAN-1.0。如果想替换成其他模型,请直接修改代码中API对应的传参。
YUAN-1.0开源预训练中文模型
- 设定每条信息的回复间隔,模拟真实打字速度(total_len / 10 * 2s)
- 加入通用emoji替换关键词,但目前还不支持表情包
- 连续语句拼接,当对面在限定时间内说了多段话时,wechaty会hold本轮对话,直到对方结束
- 这种情况下,对方的输入会被拼接成一句话之后输入AI,只回复一次
源1.0采用了目前python API调用所需的主流依赖库,用如下命令安装或确认相关依赖:
pip install requests hashlib json
完成安装后在硬盘上任意位置,用如下命令将GitHub上的代码fork下来即可。
git clone https://github.com/Shawn-Inspur/Yuan-1.0.git
需要注意的是,GitHub
上下载的代码包含了三个部分,src
中是模型训练的代码,sandbox
中是web示例开发使用的沙箱代码,需要额外安装yarn
,yuan_api
中是采用API进行推理的示例代码和工具。
这里给大家演示不基于wechaty框架,如何用YUAN-1.0来构建一个对话机器人的过程。
首先确认项目工作目录为yuan_api
,然后在examples
目录下新建一个python
文件:dialog.py
。
from inspurai import Yuan, set_yuan_account,Example
代码中首先从inspurai
导入Yuan
和Example
这两个类,以及set_yuan_account
函数。其中Yuan
类中包含了用于提交API
请求以及获取推理结果的各种函数,具体将在后文中进行解释。Example
类用于构建输入输出示例,通过对yuan
实例中添加example
,即可实现one-shot或few-shot。
在YUAN的官网注册后,请用申请API时使用的账号和手机号来获得授权。
# 1. set account
set_yuan_account("用户名", "手机号")
初始化Yuan
实例yuan
,并对其加入一个样例:
yuan = Yuan(input_prefix="对话:“",
input_suffix="”",
output_prefix="答:“",
output_suffix="”",)
# 3. add examples if in need.
yuan.add_example(Example(inp="对百雅轩798艺术中心有了解吗?",
out="有些了解,它位于北京798艺术区,创办于2003年。"))
其中`input_prefix`和`input_suffix`分别为输入的前缀和后缀。`output_prefix`和`output_suffix`为输出的前缀和后缀。 如果对实例`yuan`添加了`example`,则会在提交query前在`example`的输入和输出部分分别添加前缀和后缀。如果有需要,实例`yuan`中还可以继续添加更多`example`,实现few-shot。其他参数将在后面详细介绍。
至此一个问答机器人就已经完成了,接下来就可以提问了。把问题放在prompt
变量里,然后提交给yuan
的API。
prompt = "故宫的珍宝馆里有什么好玩的?"
response = yuan.submit_API(prompt=prompt,trun="”")
其中trun
为截断符,yuan API推理服务返回的生成结果有可能包含重复的答案,通过设置trun
可以在第一次出现该字符时截断返回结果。因为我们在之前设置的输出后缀为‘”’,对于推理返回的结果,我们可以将trun设为‘”’,在返回完第一个完整输出时将其截断。因为截断时最后这个字符并不会被保留,为了保持我们对话机器人输出符号的对称性,我们人为在打印时加上后引号。
注:这种设计是必要的,因为对于更普遍的任务而言,加入的后缀是无意义的,仅作为语句分割用。我们并不希望这种字符被返回。
为了能够连续进行对话,我们将上面提交prompt和返回结果的过程重构如下:
print("====问答机器人====")
while(1):
print("输入Q退出")
prompt = input("问:")
if prompt.lower() == "q":
break
response = yuan.submit_API(prompt=prompt,trun="”")
print(response+"”")
这样一个简单的问答机器人就开发完毕,此时就可以在命令行和他互动了。
“杀猪盘”是一种规则化、模式化的对话博弈,传统的无目标导向的“开放域对话”或“词槽式目的域对话”方案都表现不佳。而源1.0作为一种生成式预训练模型,擅长零样本(Zero-Shot)和小样本(Few-Shot)学习,而非目前更多模型所擅长的微调学习(finetune)。 因此,少量(1~ 3个)规则化的example示范下,模型可以很好的理解我们希望实现的“对话策略”,比如反套路、用语料抛梗等等,让AI看起来能够对骗子具备识别能力,本质上这也是一种query->value的查询匹配,在搜索引擎和注意力机制中很常见。
在一开始的测试中我们发现,如果没有example,模型的生成非常不靠谱,甚至会出现答非所问的情况。因此,关键就在于如何针对“反诈骗”这一场景选择适当的example供给模型。
我们最终参考AI剧本杀的方案:基于模型的few-shot能力建立example语料库,针对每次提问从语料库中选择最贴近的top-k个example作为模型生成的prompt输入。这里我们选择了百度飞桨@PaddlePaddle发布的预训练模型——simnet_bow ,它能够自动计算短语相似度,基于百度海量搜索数据预训练,实际效果不错,主要是运算速度快,不影响对话的实时性能。
example语料主要抽取自B站和贴吧的热门评论,一来因为评论是天然的对话形式,有显式的回复与被回复关系。二来自古评论出人才,一些金句和梗可以把人机对话变得不那么生硬。具体语料经过人工筛选,过滤不当言论,再处理成prompt格式。
下述文本展示了Prompt Example
的生成样例。
说明 | 样例 |
---|---|
原始Json | {"comment":"你这算什么?知乎都人均百万了,我自己年薪200个也没说啥","reply1":"富哥V50",..} |
抽取文本 | [你/这/算什么/?/知乎/都/人均/百万/了,富哥/V/50] |
Prompt检索 | 查询抽取文本List[0]与当前对话的Query相似度,加入对话Example |
生成Example | {"对话":"你这算什么?知乎都人均百万了,我自己年薪200个也没说啥","小源":"富哥V50"} |
最后,由于微信聊天是多轮对话,AI有时并不记得自己或对方上一句说过什么。比如输入我想去杭州,再问她刚才我想去哪,AI多数时候都是答非所问。 为了解决这个问题,我参考LSTM的思想,为系统增加了记忆机制,具体机制如下:
- 聊天记录放入记忆区,在每次回复时计算相似度
- 超过相似度阈值的历史对话将被AI读取使用
- 设定遗忘窗口M,超过M/2轮次的对话将被pop() 这样,AI就能够实现简单的长短期对话记忆,比如昨天聊过的内容或上一轮对话内容。
注意,对于example语料匹配度比较低的提问,过长的记忆机制反而可能让生成效果下降,最典型的情况是造成"重复回答",即AI会在后续轮次的对话中一直重复之前已经说过的话,比如:
至此对话核心部分已经基本优化完毕,接下来是如何基于wechaty来构建一个无缝对话的AI聊天机器人。
Wechaty 是一个开源聊天机器人框架SDK,具有高度封装、高可用的特性,支持NodeJs, Python, Go 和Java 等多语言版本。在过去的4年中,服务了数万名开发者,收获了 Github 的 1w+ Star。同时配置了完整的 DevOps 体系并持续按照 Apache 的方式管理技术社区。 开发前需要准备:
- Linux服务器(CentOS 8.0+,Python环境,Docker)
- 本地Python开发环境(我个人使用Anaconda+Intelij)
- 申请一个Wechaty秘钥Token(有免费的也有收费的)
- 一个AI专用的微信号(不建议用个人号)
npm init
npm install wechaty
# create your first bot.js file, you can copy/paste from the above "The World's Shortest ChatBot Code: 6 lines of JavaScript"
# then:
node bot.js
Linux服务器下载Wechaty的docker镜像:
docker pull wechaty/wechaty:0.65
安装完成后输入
export WECHATY_PUPPET=wechaty-puppet-padlocal
export WECHATY_PUPPET_PADLOCAL_TOKEN=puppet_padlocal_xxxxxxxxx
export WECHATY_TOKEN=your_uuid4_token
export WECHATY_PUPPET_SERVER_PORT=8788
export WECHATY_LOG=verbose
docker run -ti \
--name wechaty_gateway \
--rm \
-e WECHATY_LOG \
-e WECHATY_PUPPET \
-e WECHATY_PUPPET_PADLOCAL_TOKEN \
-e WECHATY_PUPPET_SERVER_PORT \
-e WECHATY_TOKEN \
-p "$WECHATY_PUPPET_SERVER_PORT:$WECHATY_PUPPET_SERVER_PORT" \
wechaty/wechaty:0.65
注:0.65版本比较稳定,也可以用最新的
如果docker是部署在虚拟服务器上,还需要在Python代码入口文件中额外加一个参数
os.environ['WECHATY_PUPPET_SERVICE_ENDPOINT']='127.198.0.0:0000(你的虚拟服务器IP+端口号)'
至此,机器人的本地Grpc依赖服务已启动。
使用git clone https://github.com/wechaty/python-wechaty
选择一个puppet服务实例(除了第一个限制调用次数的service是免费的,其他应该都要付费)
Protocol | NPM |
---|---|
Puppet Service | wechaty-puppet-service |
Whatsapp Web | wechaty-puppet-whatsapp |
WeChat Web | wechaty-puppet-wechat |
WeChat Pad | wechaty-puppet-padlocal |
Visit our website to learn more about Wechaty Puppet Service Providers
打开\app\dialog.py,在图示位置添加秘钥和配置环境变量:
运行dialog.py,坐等QR code出现扫码就好
- 2022.09.23 本地项目建立
- 2022.09.30 整体模型架构搭建,demo测试
- 2022.10.08 Prompt语料收集、处理
- 2022.10.11 接入API后wecahty对话测试
- 2022.10.15 各平台注册寻找测试对象
- 2022.10.23 开始真实场景聊天
- 2022.11.07 数据收集反馈
- 2022.11.18 优化Prompt设计与参数
- 2022.12.09 代码Review与开源发布
@misc{AntiFraudChatBot,
author = {Turing's Cat},
title = {AntiFraud AI Framework},
year = {2022},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/Turing-Project/AntiFraudChatBot}},
}
[1] Long Time No See! Open-Domain Conversation with Long-Term Persona Memory
[2] Yuan 1.0: Large-Scale Pre-trained Language Model in Zero-Shot and Few-Shot Learning
[3] ERNIE: Enhanced Representation through Knowledge Integration
[4] Language Models are Unsupervised Multitask Learners
[5] Pre-train, Prompt, and Predict: A Systematic Survey of Prompting Methods in Natural Language Processing
[6] The Power of Scale for Parameter-Efficient Prompt Tuning
[7] PPT: Pre-trained Prompt Tuning for Few-shot Learning
[8] AI剧本杀:https://github.com/bigbrother666sh/shezhangbujianle
[9] Wechaty:https://github.com/wechaty/wechaty
[10] PaddlePaddle:https://github.com/PaddlePaddle/PaddleNLP
[11] PadLocal:https://wechaty.js.org/2021/03/08/python-wechaty-and-wechaty-puppet-padlocal/
[12] 知乎:杀猪盘的套路明明很简单,为什么还是会有大量的女性相信,并且愿意掏钱上当受骗
该项目中的内容仅供技术研究与科普,不作为任何结论性依据,不提供任何商业化应用授权