先下载github代码,下面的操作,都是基于这个版本来的!

注意:由于涉及到版权问题,此附件没有图片和音乐。请参考链接,手动采集一下!

请参考链接:

一、玩具与玩具之间的对话

app消息提醒

之前实现了App发送语音消息给web端玩具,web端有消息提醒。现在app端,也需要消息提醒!

那么在后端,需要判断。这个消息是人还是玩具发送的消息。加一个user_type

玩具表增加user_type

修改玩具表toys。这里的小鱼,表示用户!

增加user_type

toys表的其他记录,也需要一并修改

务必保证 friend_list里面的每一条记录。都有user_type字段!

务必保证,每一个玩具都有2个好友。一个是主人,一个是除自己之外的玩具。

用户表增加user_type

修改用户表

修改第一个好友,增加user_type字段,toy表示玩具

修改另外一条记录

完整数据如下:

{"_id" : ObjectId("5b9bb768e1253281608e96eb"),"username" : "xiao","password" : "202cb962ac59075b964b07152d234b70","age" : "20","nickname" : "xiao","gender" : "1","phone" : "1234567","avatar" : "boy.jpg","bind_toy": ["5ba0f1f2e12532418089bf88","5ba21c84e1253229c4acbd12"],"friend_list": [

{"friend_id" : "5ba0f1f2e12532418089bf88","friend_name" : "小可爱","friend_remark" : "小甜甜","friend_avatar" : "girl.jpg","friend_chat" : "5ba0f1f2e12532418089bf87","user_type" : "toy"},

{"friend_id" : "5ba21c84e1253229c4acbd12","friend_name" : "嘻嘻","friend_remark" : "小豆芽","friend_avatar" : "girl.jpg","friend_chat" : "5ba21c84e1253229c4acbd11","user_type" : "toy"}

]

}

View Code

务必保证 friend_list里面的每一条记录。都有user_type字段!

后台逻辑修改

进入flask项目,修改 serv--> friend.py,增加user_type

from flask importBlueprint, request, jsonifyfrom setting importMONGO_DBfrom setting importRETfrom bson importObjectId

fri= Blueprint("fri", __name__)

@fri.route("/friend_list", methods=["POST"])def friend_list(): #好友列表

user_id = request.form.get("user_id")#查询用户id信息

res = MONGO_DB.users.find_one({"_id": ObjectId(user_id)})

friend_list= res.get("friend_list") #获取好友列表

RET["code"] =0

RET["msg"] = ""RET["data"] =friend_listreturnjsonify(RET)

@fri.route("/add_req", methods=["POST"])def add_req(): #添加好友请求

user_id = request.form.get("user_id") #有可能是 toy_id or user_id

friend_id = request.form.get("friend_id") #100%是toy_id

req_type = request.form.get("req_type")

req_msg= request.form.get("req_msg") #描述

remark = request.form.get("remark") #备注

if req_type == "toy":

user_info= MONGO_DB.toys.find_one({"_id": ObjectId(user_id)})else:

user_info= MONGO_DB.users.find_one({"_id": ObjectId(user_id)})

req_str={"req_user": str(user_info.get("_id")),"req_type": req_type,"req_toy": friend_id,"req_msg": req_msg,"avatar": user_info.get("avatar"),"user_remark": remark,#昵称,玩具是没有的

"user_nick": user_info.get("nickname") if user_info.get("nickname") else user_info.get("baby_name"),#状态,1通过,2拒绝,0中间状态(可切换到1和2)。

"status": 0

}

MONGO_DB.req.insert_one(req_str)

RET["code"] =0

RET["msg"] = "请求发送成功"RET["data"] ={}returnjsonify(RET)

@fri.route("/req_list", methods=["POST"])def req_list(): #添加请求列表

user_id = request.form.get("user_id")

user_info= MONGO_DB.users.find_one({"_id": ObjectId(user_id)})

bind_toy= user_info.get("bind_toy")

reqs= list(MONGO_DB.req.find({"req_toy": {"$in": bind_toy}, "status": 0}))for index, req inenumerate(reqs):

reqs[index]["_id"] = str(req.get("_id"))

RET["code"] =0

RET["msg"] = ""RET["data"] =reqsreturnjsonify(RET)

@fri.route("/get_req", methods=["POST"])def get_req(): #获取一个好友请求

req_id = request.form.get("req_id")

req_info= MONGO_DB.req.find_one({"_id": ObjectId(req_id)})

req_info["_id"] = str(req_info.get("_id"))

RET["code"] =0

RET["msg"] = ""RET["data"] =req_inforeturnjsonify(RET)

@fri.route("/acc_req", methods=["POST"])def acc_req(): #允许一个好友请求

req_id = request.form.get("req_id")

remark= request.form.get("remark")

req_info= MONGO_DB.req.find_one({"_id": ObjectId(req_id)})#1. 为 user 或 toy 添加 toy

if req_info.get("req_type") == "toy":

user_info= MONGO_DB.toys.find_one({"_id": ObjectId(req_info.get("req_user"))})

user_type= "toy"

else:

user_info= MONGO_DB.users.find_one({"_id": ObjectId(req_info.get("req_user"))})

user_type= "user"toy= MONGO_DB.toys.find_one({"_id": ObjectId(req_info.get("req_toy"))})

chat_window= MONGO_DB.chat.insert_one({"user_list": [str(toy.get("_id")), str(user_info.get("_id"))]})

friend_info={"friend_id": str(toy.get("_id")),"friend_name": toy.get("baby_name"),"friend_remark": req_info.get("user_remark"),"friend_avatar": toy.get("avatar"),"friend_chat": str(chat_window.inserted_id),"user_type": "toy"}if req_info.get("req_type") == "toy":

MONGO_DB.toys.update_one({"_id": ObjectId(req_info.get("req_user"))},

{"$push": {"friend_list": friend_info}})else:

MONGO_DB.users.update_one({"_id": ObjectId(req_info.get("req_user"))},

{"$push": {"friend_list": friend_info}})#2. 为 toy 添加 user 或 toy

user_name = user_info.get("nickname") if user_info.get("nickname") else user_info.get("baby_name")

friend_info2={"friend_id": str(user_info.get("_id")),"friend_name": user_name,#同意方的备注

"friend_remark": remark if remark elseuser_name,"friend_avatar": user_info.get("avatar"),"friend_chat": str(chat_window.inserted_id),"user_type":user_type #用户类型

}

MONGO_DB.toys.update_one({"_id": ObjectId(req_info.get("req_toy"))},

{"$push": {"friend_list": friend_info2}})

RET["code"] =0

RET["msg"] = f"添加好友{remark}成功"RET["data"] ={}

MONGO_DB.req.update_one({"_id": ObjectId(req_id)}, {"$set": {"status": 1}})returnjsonify(RET)

@fri.route("/ref_req", methods=["POST"])def ref_req(): #拒绝一个好友请求

req_id = request.form.get("req_id")

MONGO_DB.req.update_one({"_id": ObjectId(req_id)}, {"$set": {"status": 2}})

RET["code"] =0

RET["msg"] = "已拒绝好友请求"RET["data"] ={}return jsonify(RET)

View Code

修改 serv--> devices.py,增加user_type

from flask importBlueprint, request, jsonifyfrom setting importMONGO_DBfrom setting importRETfrom bson importObjectId

devs= Blueprint("devs", __name__)

@devs.route("/yanzheng_qr", methods=["POST"])def yanzheng_qr(): #验证二维码

device_id = request.form.get("device_id") #获取设备id

print(device_id)if MONGO_DB.devices.find_one({"device_id": device_id}): #从数据库中查询设备id

#查询该玩具是不是已被用户绑定

toy_info = MONGO_DB.toys.find_one({"device_id": device_id})#未绑定开启绑定逻辑

if nottoy_info:

RET["code"] =0

RET["msg"] = "感谢购买本公司产品"RET["data"] ={}#如果被绑定加好友逻辑开启

iftoy_info:

RET["code"] = 1RET["msg"] = "添加好友"RET["data"] = {"toy_id": str(toy_info.get("_id"))}else:

RET["code"] = 2RET["msg"] = "二货,这不是本公司设备,快去买正版!"RET["data"] ={}returnjsonify(RET)

@devs.route("/bind_toy", methods=["POST"])def bind_toy(): #绑定玩具

chat_window = MONGO_DB.chat.insert_one({}) #插入一个空数据

chat_id = chat_window.inserted_id #获取聊天id

user_id= request.form.get("user_id") #用户id

res = MONGO_DB.users.find_one({"_id": ObjectId(user_id)}) #查询用户id是否存在

device_id= request.form.get("device_id") #设备id

toy_name = request.form.get("toy_name") #玩具的昵称

baby_name = request.form.get("baby_name") #小主人的名字

remark = request.form.get("remark") #玩具主人对您的称呼

gender = request.form.get("gender") #性别

toy_info={"device_id": device_id,"toy_name": toy_name,"baby_name": baby_name,"gender": gender,"avatar": "boy.jpg" if gender == 1 else "girl.jpg",#绑定用户

"bind_user": str(res.get("_id")),#第一个好友

"friend_list": [{"friend_id": str(res.get("_id")), #好友id

"friend_name": res.get("nickname"), #好友昵称

"friend_remark": remark, #好友称呼

"friend_avatar": res.get("avatar"), #好友头像

"friend_chat": str(chat_id), #好友聊天id

"user_type":"user" #用户类型

}]

}

toy_res= MONGO_DB.toys.insert_one(toy_info) #插入玩具表数据

if res.get("friend_list"): #判断用户好友列表是否为空

#追加好友

res["bind_toy"].append(str(toy_res.inserted_id))

res["friend_list"].append({"friend_id": str(toy_res.inserted_id),"friend_name": toy_name,"friend_remark": baby_name,"friend_avatar": toy_info.get("avatar"),"friend_chat": str(chat_id),"user_type": "toy" #用户类型

})else:#更新好友

res["bind_toy"] =[str(toy_res.inserted_id)]

res["friend_list"] =[{"friend_id": str(toy_res.inserted_id),"friend_name": toy_name,"friend_remark": baby_name,"friend_avatar": toy_info.get("avatar"),"friend_chat": str(chat_id),"user_type": "toy" #用户类型

}]

MONGO_DB.users.update_one({"_id": ObjectId(user_id)}, {"$set": res}) #更新用户记录

#更新聊天表

#user_list有2个值。第一个是玩具id,第2个是用户id

#这样,用户和玩具就能通讯了

MONGO_DB.chat.update_one({"_id": chat_id},

{"$set":

{"user_list":

[str(toy_res.inserted_id),

str(res.get("_id"))]}})

RET["code"] =0

RET["msg"] = "绑定成功"RET["data"] ={}return jsonify(RET)

View Code

修改 utils-->baidu_ai.py,增加user_type

from aip importAipSpeechimportos

BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #项目根目录

importsys

sys.path.append(BASE_DIR)#加入到系统环境变量中

import setting #导入setting

from uuid importuuid4#from setting import MONGO_DB#import setting

importosfrom bson importObjectId

client=AipSpeech(setting.APP_ID,setting.API_KEY,setting.SECRET_KEY)deftext2audio(text):

res= client.synthesis(text, "zh", 1, setting.SPEECH)

file_name= f"{uuid4()}.mp3"file_path=os.path.join(setting.CHAT_FILE, file_name)

with open(file_path,"wb") as f:

f.write(res)returnfile_namedefget_file_content(filePath):

os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")

with open(f"{filePath}.pcm", 'rb') as fp:returnfp.read()defaudio2text(file_name):#识别本地文件

liu =get_file_content(file_name)

res= client.asr(liu, 'pcm', 16000, {'dev_pid': 1536,

})if res.get("result"):return res.get("result")[0]else:returnres#text2audio("你好")

defmy_nlp(q,toy_id):#1. 假设玩具说:q = 我要给爸爸发消息

print(q,"百度q")if "发消息" inq:

toy= setting.MONGO_DB.toys.find_one({"_id":ObjectId(toy_id)})#print(toy.get("friend_list"))

for i in toy.get("friend_list"):#print(i.get("friend_remark"),i.get("friend_name"),'iiiiiiiii')

if i.get("friend_remark") in q or i.get("friend_name") inq :

res= text2audio(f"可以按消息键,给{i.get('friend_remark')}发消息了")

send_str={"code": 0,"from_user": i.get("friend_id"),"msg_type": "chat","data": res,"user_type":i.get("user_type")

}returnsend_strif "我要听" in q or "我想听" in q or "唱一首" inq:

sources=setting.MONGO_DB.sources.find({})for i insources:if i.get("title") inq:

send_str={"code": 0,"from_user": toy_id,"msg_type": "music","data": i.get("audio")

}returnsend_str

res= text2audio("对不起,我没明白你的意思")

send_str={"code": 0,"from_user": toy_id,"msg_type": "chat","data": res

}return send_str

View Code

修改 im_serv.py,增加user_type

from flask importFlask, requestfrom geventwebsocket.websocket importWebSocketfrom geventwebsocket.handler importWebSocketHandlerfrom gevent.pywsgi importWSGIServerimportjson, osfrom uuid importuuid4from setting importAUDIO_FILE,CHAT_FILEfrom serv importcontentfrom utils importbaidu_aifrom utils importchat_redisimportsettingfrom bson importObjectIdimporttime

app= Flask(__name__)

user_socket_dict= {} #空字典,用来存放用户名和发送消息

@app.route("/toy/")def toy(tid): #玩具连接

#获取请求的WebSocket对象

user_socket = request.environ.get("wsgi.websocket") #type:WebSocket

ifuser_socket:#设置键值对

user_socket_dict[tid] =user_socketprint(user_socket_dict)#{'123456': }

file_name= ""to_user= ""

#循环,接收消息

whileTrue:

msg=user_socket.receive()if type(msg) ==bytearray:

file_name= f"{uuid4()}.wav"file_path=os.path.join(CHAT_FILE, file_name)

with open(file_path,"wb") as f:

f.write(msg)else:

msg_dict=json.loads(msg)

to_user= msg_dict.get("to_user")

msg_type= msg_dict.get("msg_type")

user_type= msg_dict.get("user_type")if to_user andfile_name:

other_user_socket=user_socket_dict.get(to_user)if msg_type == "ai":

q=baidu_ai.audio2text(file_path)print(q)

ret=baidu_ai.my_nlp(q, tid)

other_user_socket.send(json.dumps(ret))else:if user_type == "toy":

res= setting.MONGO_DB.toys.find_one({"_id": ObjectId(to_user)})

fri= [i.get("friend_remark") for i in res.get("friend_list") if i.get("friend_id") ==tid][0]

msg_file_name= baidu_ai.text2audio(f"你有来自{fri}的消息")

send_str={"code": 0,"from_user": tid,"msg_type": "chat","user_type": "toy","data": msg_file_name

}else:

send_str={"code": 0,"from_user": tid,"msg_type": "chat","data": file_name,

}if other_user_socket: #当websocket连接存在时

chat_redis.save_msg(tid, to_user) #保存消息到redis

#发送数据

other_user_socket.send(json.dumps(send_str))else:#离线消息

chat_redis.save_msg(tid, to_user)#保存聊天记录到MongoDB

_add_chat(tid, to_user, send_str.get("data"))

to_user= ""file_name= ""@app.route("/app/")def user_app(uid): #手机app连接

user_socket = request.environ.get("wsgi.websocket") #type:WebSocket

ifuser_socket:

user_socket_dict[uid]=user_socket#{ uid : websocket}

print(user_socket_dict)

file_name= ""to_user= ""

while True: #手机听歌 把歌曲发送给 玩具 1.将文件直接发送给玩具 2.将当前听的歌曲名称或ID发送到玩具

msg =user_socket.receive()if type(msg) == bytearray: #判断类型为bytearray

file_name = f"{uuid4()}.amr" #文件后缀为amr,安卓和ios通用

file_path = os.path.join(CHAT_FILE, file_name) #存放在chat目录

print(msg)

with open(file_path,"wb") as f:

f.write(msg)#写入文件

#将amr转换为mp3,因为html中的audio不支持amr

os.system(f"ffmpeg -i {file_path} {file_path}.mp3")else:

msg_dict=json.loads(msg)

to_user= msg_dict.get("to_user") #获取目标用户

if msg_dict.get("msg_type") == "music":

other_user_socket=user_socket_dict.get(to_user)

send_str={"code": 0,"from_user": uid,"msg_type": "music","data": msg_dict.get("data")

}

other_user_socket.send(json.dumps(send_str))#res = content._content_one(content_id)

if file_name and to_user: #如果文件名和发送用户同上存在时

#查询玩具信息

res = setting.MONGO_DB.toys.find_one({"_id": ObjectId(to_user)})#获取friend_remark

fri = [i.get("friend_remark") for i in res.get("friend_list") if i.get("friend_id") ==uid][0]

msg_file_name= baidu_ai.text2audio(f"你有来自{fri}的消息")#获取websocket对象

other_user_socket =user_socket_dict.get(to_user)#构造数据

send_str ={"code": 0,"from_user": uid,"msg_type": "chat", #聊天类型

#后缀必须是mp3的

"data": msg_file_name

}ifother_user_socket:

chat_redis.save_msg(uid, to_user)#发送数据给前端页面

other_user_socket.send(json.dumps(send_str))else:#保存redis

chat_redis.save_msg(uid, to_user)#添加聊天记录到数据库

_add_chat(uid, to_user, f"{file_name}.mp3")#最后一定要清空这2个变量,否则造成混乱

file_name = ""to_user= ""

def _add_chat(sender, to_user, msg): #添加聊天记录到数据库

chat_window = setting.MONGO_DB.chat.find_one({"user_list": {"$all": [sender, to_user]}})if not chat_window.get("chat_list"):

chat_window["chat_list"] =[{"sender": sender,"msg": msg,"updated_at": time.time(),

}]

res= setting.MONGO_DB.chat.update_one({"_id": ObjectId(chat_window.get("_id"))}, {"$set": chat_window})else:

chat={"sender": sender,"msg": msg,"updated_at": time.time(),

}

res= setting.MONGO_DB.chat.update_one({"_id": ObjectId(chat_window.get("_id"))}, {"$push": {"chat_list": chat}})returnresif __name__ == '__main__':#创建一个WebSocket服务器

http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)#开始监听HTTP请求

http_serv.serve_forever()'''{

"code": 0,

"from_user": uid, # APP用户id

"data": music_name # 歌曲名

}'''

View Code

修改 templates-->index.html,增加user_type

Title

玩具开机键

开始废话

发送语音

录制消息

发送语音消息

收取消息

var ws_serv= "ws://127.0.0.1:9528";//获取音频文件

var get_music= serv + "/get_audio/";

var get_chat= serv + "/get_chat/";

var ws= null; //WebSocket 对象

var reco=null;//创建AudioContext对象

var audio_context=new AudioContext();

var toy_id=null;//要获取音频和视频

navigator.getUserMedia= (navigator.getUserMedia ||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia);//拿到媒体对象,允许音频对象

navigator.getUserMedia({audio: true}, create_stream, function (err) {

console.log(err)

});//创建媒体流容器

function create_stream(user_media) {

var stream_input=audio_context.createMediaStreamSource(user_media);//给Recoder 创建一个空间,麦克风说的话,都可以录入。是一个流

reco=new Recorder(stream_input);

}

function start_reco() {//开始录音

reco.record();//往里面写流

}

function stop_reco() {//停止录音

reco.stop();//停止写入流

get_audio();//调用自定义方法

reco.clear();//清空容器

}

{#function get_audio() { // 获取音频#}

{#reco.exportWAV(function (wav_file) {#}

{#ws.send(wav_file); //使用websocket连接发送数据给后端#}

{#})#}

{#}#}

function send_reco() {

reco.stop();

send_audio();

reco.clear();

}

function send_audio() {

var to_user= document.getElementById("to_user").innerText;

var user_type= document.getElementById("user_type").innerText;

var send_str={"to_user": to_user,"user_type":user_type

};

ws.send(JSON.stringify(send_str));

reco.exportWAV(function (wav_file) {

ws.send(wav_file);

})

}

function get_audio() {

var send_str={"to_user": toy_id,"msg_type": "ai"};

ws.send(JSON.stringify(send_str));

reco.exportWAV(function (wav_file) {

ws.send(wav_file);

})

}

function start_toy() {//玩具开机//获取输入的设备id

var device_id= document.getElementById("device_id").value;//发送post请求

$.post(// 这里的地址必须是127.0.0.1,否则会有跨域问题"http://127.0.0.1:9527/device_toy_id",//发送设备id

{device_id: device_id},

function (data) {

console.log(data);

toy_id= data.data.toy_id; //玩具id//修改audio标签的src属性

document.getElementById("player").src = get_music +data.data.audio;if (toy_id) { //判断玩具id存在时

ws= new WebSocket(ws_serv + "/toy/" +toy_id);

ws.onmessage=function (data) {// console.log(get_music +data.data);

var content= JSON.parse(data.data); //反序列化数据

{#console.log(content);#}

//判断消息类型if (content.msg_type == "chat") {

document.getElementById("player").src = get_chat +content.data;

document.getElementById("to_user").innerText =content.from_user;

document.getElementById("user_type").innerText =content.user_type;

console.log(content.from_user+ "给你发送了一条消息");

}if (content.msg_type == "music") {

document.getElementById("player").src = get_music +content.data;

console.log(content.from_user+ "给你点播了歌儿");

}

};

ws.onclose=function () {

window.location.reload();

}

}

},"json"

//规定预期的服务器响应的数据类型为json

);

}

function recv_msg() {

var to_user= document.getElementById("to_user").innerText;

var player= document.getElementById("player");

to_user= document.getElementById("to_user").innerText;

$.post(

serv+ "/get_msg",

{user_id: toy_id, sender: to_user},

function (data) {//shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值

var msg=data.data.shift();

document.getElementById("to_user").innerText =msg.sender;

player.src= get_chat + msg.msg; //修改audio标签src属性// onended 事件在视频/音频(audio/video)播放结束时触发

player.οnended=function () {//如果长度大于0,也就是有1条或者多条时if(data.data.length >0){//修改audio标签src属性,有多条时,会轮询触发

player.src= get_chat +data.data.shift().msg;

}else{returnnull;

}

}

},"json")

}

View Code

重启manager.py和im_serv.py

重新访问网页,让2个玩具开机。左边是小甜甜,右边是小豆芽

为了保证给对方发消息的时候,不造成混乱!

修改 玩具表toys,将toy_name和baby_name改成一样的。

完整数据如下:

/* 1 createdAt:2018/9/19 下午5:53:08*/{"_id" : ObjectId("5ba21c84e1253229c4acbd12"),"device_id" : "02cc0fc7490b6ee08c31f38ac7a375eb","toy_name" : "小豆芽","baby_name" : "小豆芽","gender" : "2","avatar" : "girl.jpg","bind_user" : "5b9bb768e1253281608e96eb","friend_list": [

{"friend_id" : "5b9bb768e1253281608e96eb","friend_name" : "xiao","friend_remark" : "小鱼","friend_avatar" : "boy.jpg","friend_chat" : "5ba21c84e1253229c4acbd11","user_type" : "user"},

{"friend_id" : "5ba0f1f2e12532418089bf88","friend_name" : "小甜甜","friend_remark" : "小甜甜","friend_avatar" : "girl.jpg","friend_chat" : "5bab7c19e125327ffc804459","user_type" : "toy"}

]

},/* 2 createdAt:2018/9/18 下午8:39:14*/{"_id" : ObjectId("5ba0f1f2e12532418089bf88"),"device_id" : "01f9bf1bac93eddd8397d0455abbeddb","toy_name" : "小甜甜","baby_name" : "小甜甜","gender" : "2","avatar" : "girl.jpg","bind_user" : "5b9bb768e1253281608e96eb","friend_list": [

{"friend_id" : "5b9bb768e1253281608e96eb","friend_name" : "xiao","friend_remark" : "小鱼","friend_avatar" : "boy.jpg","friend_chat" : "5ba21c84e1253229c4acbd11","user_type" : "user"},

{"friend_id" : "5ba21c84e1253229c4acbd12","friend_name" : "小豆芽","friend_remark" : "小豆芽","friend_avatar" : "girl.jpg","friend_chat" : "5bab7c19e125327ffc804459","user_type" : "toy"}

]

}

View Code

修改 用户表users,也是将toy_name和baby_name改成一样的

{"_id" : ObjectId("5b9bb768e1253281608e96eb"),"username" : "xiao","password" : "202cb962ac59075b964b07152d234b70","age" : "20","nickname" : "xiao","gender" : "1","phone" : "1234567","avatar" : "boy.jpg","bind_toy": ["5ba0f1f2e12532418089bf88","5ba21c84e1253229c4acbd12"],"friend_list": [

{"friend_id" : "5ba0f1f2e12532418089bf88","friend_name" : "小甜甜","friend_remark" : "小甜甜","friend_avatar" : "girl.jpg","friend_chat" : "5ba0f1f2e12532418089bf87","user_type" : "toy"},

{"friend_id" : "5ba21c84e1253229c4acbd12","friend_name" : "小豆芽","friend_remark" : "小豆芽","friend_avatar" : "girl.jpg","friend_chat" : "5ba21c84e1253229c4acbd11","user_type" : "toy"}

]

}

View Code

修改 chat表,请确保 主人-->小甜甜-->小豆芽。这3者之间必须要有3条记录!

分别是:

主人--> 小甜甜

主人--> 小豆芽

小甜甜--> 小豆芽

这样,就可以实现3者之间的聊天通信了!

chat完整记录如下:

/* 1 createdAt:2018/9/25 下午9:05:46*/{"_id" : ObjectId("5baa32aae125320598c912f3"),"user_list": ["5ba0f1f2e12532418089bf88","5ba21c84e1253229c4acbd12"]

},/* 2 createdAt:2018/9/19 下午5:53:08*/{"_id" : ObjectId("5ba21c84e1253229c4acbd11"),"user_list": ["5b9bb768e1253281608e96eb","5ba21c84e1253229c4acbd12"]

},/* 3 createdAt:2018/9/18 下午8:39:14*/{"_id" : ObjectId("5ba0f1f2e12532418089bf87"),"user_list": ["5b9bb768e1253281608e96eb","5ba0f1f2e12532418089bf88"]

}

View Code

进入左边网页,点击 开始废话,说: 发消息给 小豆芽 。再点击发送语音!

网页会说:可以按消息键,给 小豆芽 发消息了!

这里会出现 toy,表示给玩具发消息。左边的id,就是 小豆芽的id

点击 录制消息,说:你好, 我是小甜甜!

点击 发送语音消息

这个时候,网页会有提示: 你有来自 小甜甜 的消息

切换到第二个网页,会出现设备id,这个是 小甜甜的。

点击 收取消息

会播放: 你好, 我是小甜甜!

这样,就实现了,玩具之间的通信了!

二、基于jieba gensim  pypinyin实现的自然语言处理

jieba

jieba分词,完全开源,有集成的python库,简单易用。

jieba分词是基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG),动态规划查找最大概率路径, 找出基于词频的最大切分组合

安装

pip install gensim

由于包很大,如果安装比较慢,可以使用国内更新源安装

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba

使用

我们通常把这个库叫做 结巴分词 确实是结巴分词,而且这个词库是 made in china , 基本用一下这个结巴分词:

importjieba

key_word= "我的妈妈真伟大" #定义一句话,基于这句话进行分词

cut_word= jieba.cut(key_word) #使用结巴分词中的cut方法对"我的妈妈真伟大" 进行分词

print(cut_word) # 不懂生成器的话,就忽略这里

cut_word_list= list(cut_word) #如果不明白生成器的话,这里要记得把生成器对象做成列表

print(cut_word_list) #['我', '的', '妈妈', '真', '伟大']

测试代码就很明显了,它很清晰的把咱们的中文字符串转为列表存储起来了

如果需要将 "真伟大" 变成一个词,需要添加词库,使用add_word

importjieba

key_word= "我的妈妈真伟大" #定义一句话,基于这句话进行分词

jieba.add_word("真伟大") #添加词库

cut_word = jieba.cut(key_word) #使用结巴分词中的cut方法对"我的妈妈真伟大" 进行分词

cut_word_list= list(cut_word) #如果不明白生成器的话,这里要记得把生成器对象做成列表

print(cut_word_list) #['我', '的', '妈妈', '真伟大']

pypinyin

将汉字转为拼音。可以用于汉字注音、排序、检索(Russian translation) 。

特性

根据词组智能匹配最正确的拼音。

支持多音字。

简单的繁体支持, 注音支持。

支持多种不同拼音/注音风格。

安装

pip install pypinyin

使用

from pypinyin importlazy_pinyin,TONE2

key_word= "我的妈妈真伟大" #定义一句话

res = lazy_pinyin(key_word,style=TONE2) #设置拼音风格

print(res) #['wo3', 'de', 'ma1', 'ma1', 'zhe1n', 'we3i', 'da4']

拼音声调是指普通话中的声调,通常叫四声,即阴平(第一声),用“ˉ”表示,如lā;阳平第二声,用“ˊ”表示,如lá;上声(第三声),用“ˇ”表示,如lǎ;去声(第四声),用“ˋ”表示,如;là。

wo3 最后面的3表示声调。它是第三声!

看下面的例子,这些字也是同音

from pypinyin importlazy_pinyin,TONE2

key_word= "贝贝蓓蓓背背" #定义一句话

res = lazy_pinyin(key_word,style=TONE2) #设置拼音风格

print(res) #['be4i', 'be4i', 'be4i', 'be4i', 'be4i', 'be4i']

gensim

Gensim是一款开源的第三方Python工具包,用于从原始的非结构化的文本中,无监督地学习到文本隐层的主题向量表达。

它支持包括TF-IDF,LSA,LDA,和word2vec在内的多种主题模型算法,

支持流式训练,并提供了诸如相似度计算,信息检索等一些常用任务的API接口

基本概念

语料(Corpus):一组原始文本的集合,用于无监督地训练文本主题的隐层结构。语料中不需要人工标注的附加信息。在Gensim中,Corpus通常是一个可迭代的对象(比如列表)。每一次迭代返回一个可用于表达文本对象的稀疏向量。

向量(Vector):由一组文本特征构成的列表。是一段文本在Gensim中的内部表达。

稀疏向量(SparseVector):通常,我们可以略去向量中多余的0元素。此时,向量中的每一个元素是一个(key, value)的元组

模型(Model):是一个抽象的术语。定义了两个向量空间的变换(即从文本的一种向量表达变换为另一种向量表达)。

安装

pip install jieba

使用

这个训练库很厉害, 里面封装很多机器学习的算法, 是目前人工智能的主流应用库,这个不是很好理解, 需要一定的Python数据处理的功底

importjiebaimportgensimfrom gensim importcorporafrom gensim importmodelsfrom gensim importsimilarities

l1= ["你的名字是什么", "你今年几岁了", "你有多高你心情怎么样", "你心情怎么样"]

a= "你今年多大了"

#制作语料库

all_doc_list =[]for doc inl1:

doc_list= [word for word injieba.cut(doc)]

all_doc_list.append(doc_list)print(all_doc_list)#[['你', '的', '名字', '是', '什么'],#1 4 2 3 0#['你', '今年', '几岁', '了'],#1 6 7 5

#将问题分词

doc_test_list = [word for word injieba.cut(a)]#['你', '今年', '多大', '了']#1 6 5

#制作词袋

dictionary =corpora.Dictionary(all_doc_list)#词袋的理解#词袋就是将很多很多的词,进行排列形成一个 词(key) 与一个 标志位(value) 的字典#例如: {'什么': 0, '你': 1, '名字': 2, '是': 3, '的': 4, '了': 5, '今年': 6, '几岁': 7, '多': 8, '心情': 9, '怎么样': 10, '有': 11, '高': 12}#至于它是做什么用的,带着问题往下看

print("token2id", dictionary.token2id)print("dictionary", dictionary, type(dictionary))

corpus= [dictionary.doc2bow(doc) for doc inall_doc_list]#语料库:#这里是将all_doc_list 中的每一个列表中的词语 与 dictionary 中的Key进行匹配#得到一个匹配后的结果,例如['你', '今年', '几岁', '了']#就可以得到 [(1, 1), (6, 1), (7, 1), (5, 1)]#1代表的的是 你 1代表出现一次, 5代表的是 了 1代表出现了一次, 以此类推 6 = 今年 , 7 = 几岁

print("corpus", corpus, type(corpus))#将需要寻找相似度的分词列表 做成 语料库 doc_test_vec

doc_test_vec =dictionary.doc2bow(doc_test_list)print("doc_test_vec", doc_test_vec, type(doc_test_vec))#将corpus语料库(初识语料库) 使用Lsi模型进行训练

lsi =models.LsiModel(corpus)#这里的只是需要学习Lsi模型来了解的,这里不做阐述

print("lsi", lsi, type(lsi))#语料库corpus的训练结果

print("lsi[corpus]", lsi[corpus])#获得语料库doc_test_vec 在 语料库corpus的训练结果 中的 向量表示

print("lsi[doc_test_vec]", lsi[doc_test_vec])#文本相似度#稀疏矩阵相似度 将 主 语料库corpus的训练结果 作为初始值

index = similarities.SparseMatrixSimilarity(lsi[corpus], num_features=len(dictionary.keys()))print("index", index, type(index))#将 语料库doc_test_vec 在 语料库corpus的训练结果 中的 向量表示 与 语料库corpus的 向量表示 做矩阵相似度计算

sim =index[lsi[doc_test_vec]]print("sim", sim, type(sim))#对下标和相似度结果进行一个排序,拿出相似度最高的结果#cc = sorted(enumerate(sim), key=lambda item: item[1],reverse=True)

cc = sorted(enumerate(sim), key=lambda item: -item[1])print(cc)

text=l1[cc[0][0]]print(a,text)

View Code

执行输出:

[['你', '的', '名字', '是', '什么'], ['你', '今年', '几岁', '了'], ['你', '有', '多', '高', '你', '心情', '怎么样'], ['你', '心情', '怎么样']]

token2id {'什么': 0, '你': 1, '名字': 2, '是': 3, '的': 4, '了': 5, '今年': 6, '几岁': 7, '多': 8, '心情': 9, '怎么样': 10, '有': 11, '高': 12}

dictionary Dictionary(13 unique tokens: ['什么', '你', '名字', '是', '的']...) corpus [[(0,1), (1, 1), (2, 1), (3, 1), (4, 1)], [(1, 1), (5, 1), (6, 1), (7, 1)], [(1, 2), (8, 1), (9, 1), (10, 1), (11, 1), (12, 1)], [(1, 1), (9, 1), (10, 1)]] doc_test_vec [(1, 1), (5, 1), (6, 1)] lsi LsiModel(num_terms=13, num_topics=200, decay=1.0, chunksize=20000) lsi[corpus]lsi[doc_test_vec] [(0,0.900230201263672), (1, 0.3426436202483724), (2, -1.1659919622685817)]

indexsim [0.2956978 0.99180055 0.44080025 0.38174424] [(1, 0.99180055), (2, 0.44080025), (3, 0.38174424), (0, 0.2956978)]

你今年多大了 你今年几岁了

View Code

噼里啪啦写了这一堆代码,到底干了啥哟?看了一脸懵逼!

大概意思就是。我抛出了一个问题,就是变量a

你今年多大了

在问题库里面,有这些问题

["你的名字是什么", "你今年几岁了", "你有多高你心情怎么样", "你心情怎么样"]

经过 矩阵相似度计算之后,得到一个最优的结果

你今年几岁了

也就是说,我问:你今年多大了,机器认为我的问题是:你今天几岁了

这2句话,其实是一个意思!

集成到flask

进入flask项目,进入utils目录,新建文件lowB_plus.py

importjiebaimportsettingfrom gensim importcorporafrom gensim importmodelsfrom gensim importsimilarities

l1=[]for i insetting.MONGO_DB.sources.find({}):

l1.append(i.get("title"))defmy_nlp(text):#制作语料库

all_doc_list =[]for doc inl1:

doc_list= [word for word injieba.cut(doc)]

all_doc_list.append(doc_list)print(all_doc_list)#[['你', '的', '名字', '是', '什么'],

#1 4 2 3 0

#['你', '今年', '几岁', '了'],

#1 6 7 5

#['你', '有', '多', '高', '你', '胸多大'],

#1 9 8 11 1 10

#['你', '胸多大']]

#1 10

#将问题分词

doc_test_list = [word for word injieba.cut(text)]print(doc_test_list)#['你', '今年', '多大', '了']

#1 6 5

#制作词袋

dictionary =corpora.Dictionary(all_doc_list)#词袋的理解

#词袋就是将很多很多的词,进行排列形成一个 词(key) 与一个 标志位(value) 的字典

#例如: {'什么': 0, '你': 1, '名字': 2, '是': 3, '的': 4, '了': 5, '今年': 6, '几岁': 7, '多': 8, '有': 9, '胸多大': 10, '高': 11}

#至于它是做什么用的,带着问题往下看

print("token2id", dictionary.token2id)print("dictionary", dictionary, type(dictionary))

corpus= [dictionary.doc2bow(doc) for doc inall_doc_list]#语料库:

#这里是将all_doc_list 中的每一个列表中的词语 与 dictionary 中的Key进行匹配

#得到一个匹配后的结果,例如['你', '今年', '几岁', '了']

#就可以得到 [(1, 1), (5, 1), (6, 1), (7, 1)]

#1代表的的是 你 1代表出现一次, 5代表的是 了 1代表出现了一次, 以此类推 6 = 今年 , 7 = 几岁

print("corpus", corpus, type(corpus))#将需要寻找相似度的分词列表 做成 语料库 doc_test_vec

doc_test_vec =dictionary.doc2bow(doc_test_list)print("doc_test_vec", doc_test_vec, type(doc_test_vec))#[(1, 1), (5, 1), (6, 1)]

#将corpus语料库(初识语料库) 使用Lsi模型进行训练

lsi =models.LsiModel(corpus)#这里的只是需要学习Lsi模型来了解的,这里不做阐述

print("lsi", lsi, type(lsi))#语料库corpus的训练结果

print("lsi[corpus]", lsi[corpus])#获得语料库doc_test_vec 在 语料库corpus的训练结果 中的 向量表示

print("lsi[doc_test_vec]", lsi[doc_test_vec])#文本相似度

#稀疏矩阵相似度 将 主 语料库corpus的训练结果 作为初始值

index = similarities.SparseMatrixSimilarity(lsi[corpus], num_features=len(dictionary.keys()))print("index", index, type(index))#向量表示:

#(0.387654321,0.84382974,0.4297589245,1.2439785,3.9867462154)

#((0.387654321,0.84382974,0.4297589245,1.2439786,3.9867462154),(0.387654321,0.84382974,0.4297589245,1.2439786,3.9867462154),(0.387654321,0.84382974,0.4297589245,1.2439786,3.9867462154),(0.387654321,0.84382974,0.4297589245,1.2439786,3.9867462154))

#将 语料库doc_test_vec 在 语料库corpus的训练结果 中的 向量表示 与 语料库corpus的 向量表示 做矩阵相似度计算

sim =index[lsi[doc_test_vec]]print("sim", sim, type(sim))#对下标和相似度结果进行一个排序,拿出相似度最高的结果

#cc = sorted(enumerate(sim), key=lambda item: item[1],reverse=True)

cc = sorted(enumerate(sim), key=lambda item: -item[1])print(cc)

text=l1[cc[0][0]]return text

View Code

由于还不够智能,所以叫 lowB_plus

修改 utils-->baidu_ai.py,使用 lowB_plus

from aip importAipSpeechimportos

BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #项目根目录

importsys

sys.path.append(BASE_DIR)#加入到系统环境变量中

import setting #导入setting

from uuid importuuid4#from setting import MONGO_DB#import setting

importosfrom bson importObjectIdfrom utils importlowB_plusfrom pypinyin importlazy_pinyin, TONE2

client=AipSpeech(setting.APP_ID,setting.API_KEY,setting.SECRET_KEY)deftext2audio(text):

res= client.synthesis(text, "zh", 1, setting.SPEECH)

file_name= f"{uuid4()}.mp3"file_path=os.path.join(setting.CHAT_FILE, file_name)

with open(file_path,"wb") as f:

f.write(res)returnfile_namedefget_file_content(filePath):

os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")

with open(f"{filePath}.pcm", 'rb') as fp:returnfp.read()defaudio2text(file_name):#识别本地文件

liu =get_file_content(file_name)

res= client.asr(liu, 'pcm', 16000, {'dev_pid': 1536,

})if res.get("result"):return res.get("result")[0]else:returnres#text2audio("你好")

defmy_nlp(q,toy_id):#1. 假设玩具说:q = 我要给爸爸发消息

if "发消息" inq:

q= "".join(lazy_pinyin(q, style=TONE2))print(q)

toy= setting.MONGO_DB.toys.find_one({"_id": ObjectId(toy_id)})#print(toy.get("friend_list"))

for i in toy.get("friend_list"):#转换成拼音,即使同音字也能匹配

remark_pinyin = "".join(lazy_pinyin(i.get("friend_remark"), style=TONE2))

name_pinyin= "".join(lazy_pinyin(i.get("friend_name"), style=TONE2))print(name_pinyin)if remark_pinyin in q or name_pinyin inq:

res= text2audio(f"可以按消息键,给{i.get('friend_remark')}发消息了")

send_str={"code": 0,"from_user": i.get("friend_id"),"msg_type": "chat","data": res,"user_type":i.get("user_type")

}returnsend_strif "我要听" in q or "我想听" in q or "唱一首" inq:

q= str(q).replace("我要听", "")

q= str(q).replace("我想听", "")

q= str(q).replace("唱一首", "")print(q)

title=lowB_plus.my_nlp(q)

sources= setting.MONGO_DB.sources.find_one({"title": title})for i insources:if i.get("title") inq:

send_str={"code": 0,"from_user": toy_id,"msg_type": "music","data": i.get("audio")

}returnsend_str

res= text2audio("对不起,我没明白你的意思")

send_str={"code": 0,"from_user": toy_id,"msg_type": "chat","data": res

}return send_str

View Code

测试

重启 manager.py和im_serv.py

重新访问网页,让2个玩具开机。左边是小甜甜,右边是小豆芽

使用 小甜甜给小豆芽发送消息。注意:说话的时候,可以使用儿化音。

比如:发消息 给 小豆芽儿

查看Pycharm控制台输出:

发消息给小豆芽儿

fa1xia1oxi1ge3ixia3odo4uya2e2r

第二个网页,小豆芽,也可以接收消息!

测试同音字

打开玩具表toys,找到  小甜甜的记录,将小豆芽,改成晓逗牙

再次测试发送语音给 小豆芽

小豆芽,一样也可以收到消息!

注意:尽可能避免多音字。否则会无法匹配到!

接入图灵

如果说别的话,比如:今天天气怎么样?网页会提示: 对不起,我没明白你的意思

这样用户体验不好,那么这种匹配不到的问题,扔给图灵来处理就可以了!

修改 setting.py,增加图灵配置

importpymongoimportosimportredis#数据库配置

client = pymongo.MongoClient(host="127.0.0.1", port=27017)

MONGO_DB= client["bananabase"]

REDIS_DB= redis.Redis(host="127.0.0.1",port=6379)

RET={#0: false 2: True

"code": 0,"msg": "", #提示信息

"data": {}

}

XMLY_URL= "http://m.ximalaya.com/tracks/" #喜马拉雅链接

CREATE_QR_URL = "http://qr.liantu.com/api.php?text=" #生成二维码API

#文件目录

AUDIO_FILE= os.path.join(os.path.dirname(__file__), "audio") #音频

AUDIO_IMG_FILE = os.path.join(os.path.dirname(__file__), "audio_img") #音频图片

DEVICE_CODE_PATH= os.path.join(os.path.dirname(__file__), "device_code") #二维码

CHAT_FILE = os.path.join(os.path.dirname(__file__), "chat") #聊天

#百度AI配置

APP_ID = '11793552'API_KEY= 'uA6sToQWcvYt2lT6qTW6WFrG'SECRET_KEY= '5rZ1XGYMV39LQBVT4Y1yLNCsmueVe8RQ'SPEECH={"spd": 4,'vol': 5,"pit": 8,"per": 4}#图灵配置:

TL_URL = "http://openapi.tuling123.com/openapi/api/v2"TL_DATA={#请求的类型 0 文本 1 图片 2 音频

"reqType": 0,#// 输入信息(必要参数)

"perception": {#文本信息

"inputText": {#问题

"text": "北京未来七天,天气怎么样"}

},#用户必要信息

"userInfo": {#图灵机器人的apikey

"apiKey": "8fc493d348704ba4af5413e67e6fc90b",#用户唯一标识

"userId": "xiao"}

}

View Code

进入utils目录,新建文件  tuling.py

importrequestsimportjsonfrom setting importTL_URL as tuling_urlfrom setting importTL_DATA as datadefto_tuling(q,user_id):

data["perception"]["inputText"]["text"] =q

data["userInfo"]["userId"] =user_id

res= requests.post(tuling_url, json=data)

res_dic= json.loads(res.content.decode("utf8")) #type:dict

res_type = res_dic.get("results")[0].get("resultType")

result= res_dic.get("results")[0].get("values").get(res_type)print(result)return result

View Code

修改 utils-->baidu_ai.py,接入图灵

from aip importAipSpeechimportos

BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #项目根目录

importsys

sys.path.append(BASE_DIR)#加入到系统环境变量中

import setting #导入setting

from uuid importuuid4#from setting import MONGO_DB#import setting

importosfrom bson importObjectIdfrom utils importlowB_plusfrom pypinyin importlazy_pinyin, TONE2from utils importtuling

client=AipSpeech(setting.APP_ID,setting.API_KEY,setting.SECRET_KEY)deftext2audio(text):

res= client.synthesis(text, "zh", 1, setting.SPEECH)

file_name= f"{uuid4()}.mp3"file_path=os.path.join(setting.CHAT_FILE, file_name)

with open(file_path,"wb") as f:

f.write(res)returnfile_namedefget_file_content(filePath):

os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")

with open(f"{filePath}.pcm", 'rb') as fp:returnfp.read()defaudio2text(file_name):#识别本地文件

liu =get_file_content(file_name)

res= client.asr(liu, 'pcm', 16000, {'dev_pid': 1536,

})if res.get("result"):return res.get("result")[0]else:returnres#text2audio("你好")

defmy_nlp(q,toy_id):#1. 假设玩具说:q = 我要给爸爸发消息

if "发消息" inq:

q= "".join(lazy_pinyin(q, style=TONE2))print(q)

toy= setting.MONGO_DB.toys.find_one({"_id": ObjectId(toy_id)})#print(toy.get("friend_list"))

for i in toy.get("friend_list"):#转换成拼音,即使同音字也能匹配

remark_pinyin = "".join(lazy_pinyin(i.get("friend_remark"), style=TONE2))

name_pinyin= "".join(lazy_pinyin(i.get("friend_name"), style=TONE2))print(name_pinyin)if remark_pinyin in q or name_pinyin inq:

res= text2audio(f"可以按消息键,给{i.get('friend_remark')}发消息了")

send_str={"code": 0,"from_user": i.get("friend_id"),"msg_type": "chat","data": res,"user_type":i.get("user_type")

}returnsend_strif "我要听" in q or "我想听" in q or "唱一首" inq:

q= str(q).replace("我要听", "")

q= str(q).replace("我想听", "")

q= str(q).replace("唱一首", "")print(q)

title=lowB_plus.my_nlp(q)

sources= setting.MONGO_DB.sources.find_one({"title": title})for i insources:if i.get("title") inq:

send_str={"code": 0,"from_user": toy_id,"msg_type": "music","data": i.get("audio")

}returnsend_str

answer=tuling.to_tuling(q, toy_id)

res=text2audio(answer)

send_str={"code": 0,"from_user": toy_id,"msg_type": "chat","data": res

}return send_str

View Code

重启 manager.py和im_serv.py

让2个玩具开机,说一段话: 上海的天气怎么样

网页会播放: 上海:周四,多云转阴 东北风4-5级,最低气温22度,最高气温27度

查看Pycharm控制台输出:

上海的天气怎么样

上海:周四,多云转阴 东北风4-5级,最低气温22度,最高气温27度

三、打包apk

单击打原生安装包

必须要登录账号才行

注意:默认是使用HBuilder的图标,这样不好。

点击android。因为苹果要相关证书才行,我没有。

去掉下面的广告。点击参数配置

输入应用名称

点击图标配置

上传一个图标图片,必须是png格式的!

点击自动生成并替换

点击启动图片配置,就是 app启动的时候,加载的图片

找到android,选择1080p图片,并上传!

这里有很多sdk,可以配置

这里都不用sdk

点击模块权限配置

默认是这些权限,右侧可以增加

点击代码视图

这个,就是刚刚所有的配置, 使用Ctrl+s 进行保存

保存就是这个文件

重新点击 打原生安装包

点击忽略

点击确认

它就会在云端打包,它会给你加一个壳子

如果提示报错

点击 重新打包原生,点击参数配置,在这类,重新云端获取!

打包成功后,查看打包状态

这样,表示成功了!

点击手动下载,下载成功!

直接将apk拖动过去,点击应用

效果如下:

总结:

1.说说你智能玩具的项目:

目的:关爱留守儿童, 让玩具成为父母间沟通的桥梁, 让玩具成为孩子的玩伴

实现无屏社交,依靠孩子的语音指令做出响应,例如我要和爸爸聊天,玩具会提示可以和爸爸聊天了并打开与app通讯的链接

我要听世上只有妈妈好,玩具就会依照指令播放相应的内容2.智能玩具有什么功能:

功能: 玩具可以语音点播朗诵诗歌,播放音乐,做游戏-成语接龙,与智能机器人聊天,玩具与玩具之间的通讯

手机app的im通讯 ,手机app可以为玩具点播歌曲,通过手机app管理玩具

高人:3.智能部分使用了什么算法:

两种回答:1.使用百度ai中的语音合成和语音识别,点播功能是使用Gensim jieba 库进行训练的,聊天做游戏是用的图灵机器人+百度语音合成2.使用百度ai中的语音合成和语音识别 NLP自然语言处理 点播功能基于百度NLP,聊天做游戏是用的图灵机器人+百度语音合成4.IM通讯使用了什么机制:

Websocket

magicString5.手机app是怎么做的(使用什么方式):

mui+html5plus6.谈谈你对人工智能的理解(说出人工智能技术的关键字至少5个):

语音类 : 语音识别 语音合成

图像类 : 图像识别 文字识别 人脸识别 视频审核

语言类 : 自然语言处理 机器翻译 词法分析 依存句法分析 文本纠错 对话情绪识别 词向量表示 短文本相似度

词义相似度 情感倾向分析7.mongodb相关:1.修改器: $push $set $pull $inc $pop2.说说你对 $ 的理解 : $ 我的理解就是代指符号,代指所查询到的数据或索引位置3.Mongodb中的数据类型 : ObjectID String Boolean Integer Double Arrays Object(Dict) Null Timestamp Date4.mongodb的比较符 : $lt $gt $lte $gte ":"

8.公司组织架构:1.综合人力财务行政:1个小姐姐2.营销部:老张3.产品部:老李 +UI小姐姐4.软件部:闫帅 + 前端小姐姐 +我5.硬件部:江老师9.项目不做底层,只使用三方的原因:

制作底层大量占用人力,公司资金不足以支撑底层研发

将大量成本投入到硬件研发中10. 项目中,涉及到的技术

智能语音识别-第三方百度ai

开机提示

自然语言处理(nlp)

点歌 :内容点播

开启消息发送

基于通讯录的即时通讯(IM)

websocket

不用第三方的原因 保护隐私

管理玩具的功能:1.通过扫描二维码 绑定玩具2.玩具通讯录管理

View Code

完整终极代码,请参考github:

附带项目需要的所有文件,包括音频,图片,数据库等等

python编程玩具有哪些_python 全栈开发,Day133(玩具与玩具之间的对话,基于jieba gensim pypinyin实现的自然语言处理,打包apk)...相关推荐

  1. python 全栈开发,Day133(玩具与玩具之间的对话,基于jieba gensim pypinyin实现的自然语言处理,打包apk)...

    python 全栈开发,Day133(玩具与玩具之间的对话,基于jieba gensim pypinyin实现的自然语言处理,打包apk) 先下载github代码,下面的操作,都是基于这个版本来的! ...

  2. python实现四位一并法_python 全栈开发,Day4(列表切片,增删改查,常用操作方法,元组,range,join)...

    一.列表 列表是python中的基础数据类型之一,它是以[]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如: li = ['alex',123,Ture,(1,2,3,'wusir') ...

  3. python由谁设计并领导开发_Python全栈开发之路 【第七篇】:面向对象编程设计与开发(1)...

    本节内容 一.编程范式 编程指的是写程序.敲代码,就是指程序员用特定的语法.数据结构和算法编写的代码,目的是来告诉计算机如何执行任务的. 在编程的世界里最常见的两大流派是:面向过程与面向对象.&quo ...

  4. python全栈开发优势_Python全栈开发多少钱?学Python价格贵吗?

    Python全栈开发培训多少钱?学习Python是大家进入编程世界的理想之选,而且Python也是一门非常受欢迎的编程,可以从事的领域有很多. 从目前市场上的行情来说,一般情况下Python培训的费用 ...

  5. python全栈开发下载_python全栈开发神器 - 『精品软件区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn...

    将安卓手机打造成你的python全栈开发利器 超神利器- 相信多数安卓用户都使用过Qpython这款移动端的Python编辑器吧?之前我也研究过一阵子这个工具,但因为一次简单的爬虫让我对它失望之极.Q ...

  6. python全栈开发百度云_Python全栈开发9期视频

    Python全栈开发9期视频 获取教程链接的步骤 2. 用微博或QQ登录编程资源库网站 3.点击兑换按钮,兑换百度云链接 教程要积分! 声明 教程由粉丝投稿,仅供学习和交流,侵删 以下凑字数!请自行忽 ...

  7. python全栈开发实践入门_Python全栈开发实践入门

    Python全栈开发实践入门 编辑 锁定 讨论 上传视频 <Python全栈开发实践入门>是2017年10月电子工业出版社出版的图书,作者是谢瑛俊. 书 名 Python全栈开发实践入门 ...

  8. python全栈开发网络_Python 全栈开发:网络编程

    一 socket 1.什么是socket 看一看图中socket的位置 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把 ...

  9. python个人网站开发_python 全栈开发,Day81(博客系统个人主页,文章详情页)

    一.个人主页 随笔分类 需求:查询当前站点每一个分类的名称以及对应的文章数 完成这个需求,就可以展示左侧的分类 它需要利用分组查询,那么必须要会基于双下划线的查询. 基于双下划线的查询,简单来讲,就是 ...

最新文章

  1. OpenCV-Java版学习(1.在IDEA中使用OpenCV)
  2. 使用antd报less的错误
  3. java算法编程题_【java题目】考验你编程能力和算法的时候到了
  4. 在ASP.NET Atlas中调用Web Service——创建Mashup调用远端Web Service(基础知识以及简单示例)...
  5. 传统云纹祥云素材,稳妥传承中国味!
  6. AI 芯片崛起!FPGA 工程师的核心竞争力在哪里?
  7. python 股票 因子分析_因子分析1.-Python数据科学技术详解与商业项目实战精讲 - Python学习网...
  8. php规范PSR-3(日志接口)
  9. 我今天学习的技术,明天会不会一钱不值
  10. Java对二维数组排序
  11. 上海工程技术大学c语言商店存货管理系统,商店存货管理系统.docx
  12. 基于华为SMProxy开发cmpp2.0(跳坑版)
  13. 在Android应用中集成YouTube视频播放功能
  14. 银行贷款,求每月等额还款金额
  15. mysql mmm优缺点_mysql之MMM总结
  16. linux系统查看IP地址,不显示IP地址或者只显示127.0.0.1
  17. CP必读:经典RPG游戏的7个要素
  18. 第8天:布局翘楚 - Grid 布局概述
  19. 使用队列 模拟跳舞舞伴Java实现
  20. ByteV打造智慧充电桩运行可视化平台

热门文章

  1. solidworks的openGL选项是灰色的处理方法
  2. QT的.Pro文件在哪儿找帮助手册
  3. cve-2019-0708漏洞复现
  4. ds数据与mysql_比较CCDS数据库和R包内置数据集的差异
  5. java计算机毕业设计医院住院部信息管理系统源程序+mysql+系统+lw文档+远程调试
  6. 机器人视觉系统的构成
  7. 【Unity大气散射】GAMES104:3A中如何实现大气散射
  8. 趣味三角——第2章——弦
  9. pwn libc找偏移的在线网站
  10. Python实现输出手写体图片