诗三百·人工智能在线诗歌写作平台开发教程 2
回答: 诗三百·人工智能在线诗歌写作平台开发教程 1 由 桂花酒 于 2020-11-12 10:10
封装成类之后,就可以通过flask发布了,#!/usr/bin/env python3
#-*- coding:utf-8 -*-import os,sys
import json
import datetime
import time
#from io import BytesIO
from flask import Flask, request
#from gevent.wsgi import WSGIServer#from gevent.pywsgi import WSGIServer
#from multiprocessing import cpu_count, Process
#from impala.dbapi import connect
import tensorflow as tf
from keras.backend.tensorflow_backend import set_sessionos.environ['CUDA_VISIBLE_DEVICES']='0' # 指定GPU 0
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.08
config.gpu_options.allow_growth = True
set_session(tf.Session(config=config))print('server start...')from bertutil import BertUtil#flask app
app = Flask(__name__)# BERTUTIL
bertutil = BertUtil()
bertutil.init_seq2seq(premodel='roberta',type='coupletpoem')
print('-----------BERT SEQ2SEQ初始化完毕------------')# seq2seq请求
@app.route("/zqcloudapi/v1.0/nlp/bertseq2seq", methods=['GET','POST'])
def bertseq2seq():
start =time.time()
data = request.values['data'] if 'data' in request.values else '虎啸青山抒壮志&&上联'
type = request.values['type'] if 'type' in request.values else 'coupletpoem'
topk = int(request.values['topk']) if 'topk' in request.values else 1
r = bertutil.predict_seq2seq(type=type, text=data, topk=topk)
end = time.time()
res={}
res['result'] = r
res['timeused'] = int(1000 * (end - start))
print('使用时间:%sms\n---------' %(res['timeused']))
return json.dumps(res)# 跨域支持
def after_request(resp):
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp@app.after_request
def cors(environ):
environ.headers['Access-Control-Allow-Origin']='*'
environ.headers['Access-Control-Allow-Method']='*'
environ.headers['Access-Control-Allow-Headers']='x-requested-with,content-type'
return environdef start_web_server(host='0.0.0.0', port=11456):
print('listen %s:%s' %(host, port))
app.run(host, port)if __name__ == "__main__":
start_web_server()保存文件名为server_poem.py, 用python3 server_poem.py就可以启动了, 服务用0.0.0.0:11456端口监听,如果需要让其他的客户端用ip访问,监听host需要是0.0.0.0,不能是127.0.0.1,否则只能本地访问,可以用netstat查看服务是否启动成功netstat -nlp|grep 11456
启动成功后,就可以通过浏览器或客户端脚本访问 http://ip:11456/zqcloudapi/v1.0/nlp/bertseq2seq 并传入参数返回结果Vue前端开发
前端最原始的就是html + css + js, 随着技术的发展,出现了bootstrap,vue, react等框架,这里采用Vue框架用于前端开发。前端主要的功能就是给用户提供良好的人机交互界面,把用户输入的主题通过ajax或fetch传给后端,后端计算后并返回给前端展示,这里就不在详细介绍了,有问题的同学可以自己补习了前端相关知识,不是太复杂。fetch(url, {
headers: {
'Accept': 'text/plain',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
method: 'post',
body: param
})
.then(res => {
return res.text();
})
.then(res => {
callback(res);
})
.catch(err => {
errcallback(err);
});
高并发架构优化
上面前后端已经实现了完整的功能,在本地自己部署自己用用已经没有问题了,但是部署到云服务器上,给几百成千甚至上万的用户用,并发瓶颈就出来了,甚至会导致服务器卡死宕机, 下面分别从服务器,模型,后端,接口,前端介绍一下优化的过程:1、服务器本项目采用了阿里云服务器,由于写诗模型是用RoBerta seq2seq训练的,权重模型大概有300多兆,使用CPU跑特别慢,在不考虑并发的情况下光写一首诗大概就要好5-9秒,一般用户最大的耐心是3s左右,如果超过3s,网站的体验效果就比较差了,有些用户也不一定有耐心继续往下等,可能就直接关掉了,所以必须使用GPU服务器来跑写诗模型。但是阿里云的GPU服务器特别贵,一块8G显存的Nvidia P4显卡就要8万一年左右,成本太高,可以买配置不错的多卡物理机了,不过土豪可以忽略。所以这里采用本地GPU物理机来跑写诗模型,在Nvidia RTX2080Ti不考虑并发的条件下,平均单次写诗时间在300-600ms左右,但是本地物理机没有公网IP,云服务器无法直接访问,这里采用了autossh反向代理穿透到内网,把本地GPU服务器的端口映射到云服务器上,这样云服务器就可以访问本地物理机端口服务了。autossh -M 5686 -fCNR *:8888:localhost:11456 user@xxx.xxx.xxx.xxx
其中,xxx.xxx.xxx.xxx 是云服务器的ip,user是用户账号, 8888是云服务器访问端口,可以自行设定,11456是本地GPU服务器flask监听的端口,这样就可以在云服务器上通过访问 127.0.0.1:8888既可以访问本地GPU服务器flask发布的11456服务2、模型从模型角度优化时间,可以从两块进行考虑,一块选择较小的模型,另一块对BeamSearch进行优化,下面详细介绍:目前选择的预训练模型是RoBERTa, 如果需要缩短时间,可以选择albert, RoBERTa-small, RoBERTa-tiny, 我用RoBERTa-small尝试了一下,预测时间和权重文件缩小了一倍,并发可以提升四倍,但是我让我诗词界的朋友看了一下写诗质量,下降太多,我就放弃了,还是选择RoBERTa来训练写诗模型;另一块就是seq2seq的BeamSearch优化,模型生成诗是一个字一个字预测的,每次用Topk个候选集预测,再选择当前最优的Topk个候选集作为下一次预测的输入,直到碰到截止符为止,所以TopK越大,相应的预测时间就越长,生成诗的质量也相对会好一点,但是不绝对。总得来说通过BeamSearch生成的诗质量相对好一点,但是比较单一,多样性比较差。所以我想了一个办法,每次从topk里面按loss概率分布随机选一个值,作为下一次预测的输入,这样作诗时间就不会受topk的影响,同时增加了生成古诗的多样性。我个人感觉挺好,我把生成的诗给我诗词界的朋友又看了一下,他说作诗质量不如之前的好,我问他你喜欢之前的还是现在多样性丰富的作诗机,他说他还是更看重作诗的质量。这时,我苦恼了,不知道怎么权衡好,因为之前beamsearch的topk大于8时,时间会到达好几秒,不仅影响用户体验,同时增加服务器压力,减少并发能力。有一天晚上,我突然灵机一动,想到了一个折中的方法,就是前端输入的topk小于等于3时,采用传统的beamsearch生成古诗;当大于3时,采用第二种随机选择的方法。这样既能保证作诗质量,同时能增加生成古诗的多样性,而且还不会太多增加单次作诗的平均时间,保证作诗网站的并发能力。if topk {
url = Config.host + url;
const key = md5(url + method + JSON.stringify(object));
// 判断本地localstorage数据是否有效
const data = getDataFromLocalStorage(key, period);
if (!data) {
getData(url, method, object, text => {
const resultobj = JSON.parse(text);
// console.log(resultobj);
if (resultobj.errcode === 0) {
if (period > 0) {
resultobj.result.time = new Date().getTime(); // 添加当前时间
localStorageUtil.save(key, resultobj.result);
}
callback(resultobj.result);
} else {
// console.log('业务逻辑异常:', resultobj.errmsg);
errcallback('业务逻辑异常: ' + resultobj.errmsg);
}
}, err => {
errcallback(err);
});
}
else {
callback(data);
}
};
如果这个接口明文传输的话,可能会被第三方的爬虫脚本盯上,大大增加服务器的压力,影响前端的写诗性能。所以需要对接口的参数和返回结果进行加密,比如参数可以采用AES加密,返回结果可以采用base64 + AES + DES多级加密,每个的key和iv都可以不一样,提升破解难点。敏感词过滤
在大陆上线带文本输入的AI产品,这一步非常重要,秉着宁可错杀1000,也尽量不要遗漏一个的原则,要不然容易被请去喝茶,请自重!如果有钱的话可以直接调用百度文本审核API,这个大概1.5分一条,个人实名认证可以赠送5万条,企业实名认证可以赠送50万条,由于我多的时候每天有10w+次请求,这点赠送量是不够的,下面是我做敏感词过滤的几道防线,供参考:1、国家现核心领导人前领导人名字及其他核心敏感词拼音级过滤,如果用汉字,如细净瓶,吸金瓶,供惨谠等等,字太多很难遍历全,还是拼音过滤省事一点;npm 有拼音库,安装后可以直接调用,把汉字转换成拼音,详见NPM汉字拼音转换工具介绍。npm install pinyin
2、国家现核心领导人前领导人名字及其他核心敏感词包含过滤,只要输入的文本里面出现这几个字,无论什么顺序,中间夹杂了多少个字全部过滤,如习惯平易近人,习惯禁止评论,长江恩泽于民众等等,虽然这样可能会错杀一些输入文本,但是总比遗漏一个请去喝茶要好一点;
3、某些相近的字也需要过滤,如习和刁等;
4、国家核心领导人去过的某些地方,吃过的某些东西,说过的某些话,做过的某些事情及长的像的某些东西等等都要过滤,比如庆丰包子,蛤膜,维尼熊等等;
5、根据第三方开源的敏感词库进行过滤;
6、定期调用百度文本审核API标注日志中的样本,并用albert训练自己的敏感词二分类识别模型,不需要GPU,可以在云服务器的CPU上跑,每条文本大概6-7ms左右,判别过的就可以放到Redis缓存里,不需要重复判断。具体模型训练方式可以参考苏老师bert4keras的情感二分类例子。上述前五条都可以在前端完成,如果校验不通过直接提示“您输入的主题无法作诗,请重新输入”,不需要增加服务端的压力,前端校验通过后,第六条需要在后端完成,再加一道保险。前端过滤代码参考如下:export const checkKeys = (text) => {
let flag = true;
// 根据白名单判断
if (keyobj['whitekeys'].indexOf(text) >= 0) {
return true;
}
// 剔除非法字符
text = text.replace(/[\s+\-\.\。\,\;\?\?\!\!\…\+\!\@\#\$\%\^\&\*()\(\)\¥\[\]]/g,"");
if (words.indexOf(text) >=0) {
return false;
} // 转换成拼音并判断,如果文本中包含核心敏感词的拼音,就返回false
let py = pinyin(text, {
style: pinyin.STYLE_NORMAL
});
py = py.join(''); for (let i = 0; i-1) {
console.log(text, py, pinyins[i]);
return false;
}
} py = pinyin(text);
py = py.join('');
console.log(py); for (let i = 0; i-1) {
console.log(text, py, pinyins2[i]);
return false;
}
} // 根据敏感词判断,只要输入文本包含敏感词就返回false
for (let i = 0; i < keyobj['keys'].length; i++) {
if (text.indexOf(keyobj['keys'][i])>=0) {
console.log(text, keyobj['keys'][i]);
flag = false;
return false;
}
} // 根据核心敏感词判断,只要输入出现敏感词这几个字,不论什么顺序,中间夹了多少个字,都返回false
for (let i = 0; i < keyobj['subkeys'].length; i++) {
let j = 0;
let item = keyobj['subkeys'][i];
let newtext = text;
for (j = 0; j < item.length; j ++) {
if (newtext.indexOf(item[j]) < 0){
break;
}
newtext = newtext.replace(item[j],'');
}
if (j == item.length) {
return false;
}
}
return flag;
};
运营推广SEO优化
上线之后就可以推广了,首先是在各大诗词群里面推广,然后在贴吧,论坛,知乎,CSDN,豆瓣等平台发帖,大家觉得好玩之后,也会自己在常用的平台上发帖,让更多的人参与进来。
接下来就是要通过SEO优化了,提升百度、谷歌、搜狗、360、神马等搜索引擎的搜索排名,通过搜索引擎来导流,主要包括以下几点:优化首页meta标签的标题,关键词及描述,尽量能包含你想要的搜索关键词,比如我想要的关键词就是AI写诗,在线作诗机,藏头诗生成器,自动对联等,就可以着重描述这些关键词;
和高权重的网站相互友情链接,需要发邮件和网站负责人一个个联系,互挂友情链接,网站权重可以在这里查询;
在贴吧,论坛,知乎,CSDN,豆瓣等平台多发帖,并附上网站链接,增加外链数量
以上的做法都是为了提升网站权重,从而提升搜索引擎的搜索权重,提升排名,增加流量,如果不差钱的话当然也可以选择付费推广,用户更精准成效也更快。生成效果
avatar七律·咏梅
一枝清瘦倚疏篱,不与群花较等差。
雪里有香浑是玉,月中无影更多葩。
孤山处士曾题品,姑射仙人合赋家。
莫道广平心似铁,也能吟咏到昏鸦。藏头诗·不负韶华
不见当年李谪仙,
负图千古恨绵延。
韶华过眼成陈迹,
华表空留鹤一传。蝶恋花·柳絮
一片闲愁随水去。桃李无言,不觉春光暮。官柳倡狂遮大路。游丝莫系相思树。
人比花枝能解语。镜里蛾眉,犹是当初否。心似行云年似雾。东风又绿罗巾露。上联:虎啸青山抒壮志
下联:龙腾碧海展宏图上联:望江楼上望江流,江楼千古,江流千古
下联:观海岛中观海涌,海岛万家,海涌万家上面是诗三百·人工智能诗歌写作平台,从模型训练到前后端开发到优化推广的所有过程,如果大家觉得写得好,欢迎给个star,有什么不足的地方也欢迎给出宝贵的建议!相关网站:
诗三百·人工智能诗歌写作平台: https://www.aichpoem.com/
清华九歌·人工智能诗歌写作系统: http://jiuge.thunlp.org/jueju.html
华为乐府·人工智能作诗小程序: 微信公众号搜索 “乐府AI”
微软小冰·AI现代诗歌创作系统: https://poem.msxiaobing.com/
微软亚洲研究院·电脑对联系统: https://duilian.msra.cn/app/couplet.aspx
王斌·人工智能自动对对联系统: https://ai.binwang.me/couplet/
特别鸣谢:
科学空间博主苏剑林老师开源bert4keras
Werneror老师开源85万首古诗词数据集
王斌老师开源70万首对联数据集
合作建议:
QQ: 540629297
E-mail: wangjiezju@163.com
内容来自网友分享,若违规或者侵犯您的权益,请联系我们
所有跟帖: ( 主贴楼主有权删除不文明回复,拉黑不受欢迎的用户 )
楼主前期社区热帖:
>>>>查看更多楼主社区动态...