先下載github代碼,下面的操做,都是基於這個版原本的!javascript
https://github.com/987334176/Intelligent_toy/archive/v1.6.zipphp
注意:因爲涉及到版權問題,此附件沒有圖片和音樂。請參考連接,手動採集一下!html
請參考連接:前端
http://www.javashuo.com/article/p-splctlzd-t.htmlhtml5
以前實現了App發送語音消息給web端玩具,web端有消息提醒。如今app端,也須要消息提醒!java
那麼在後端,須要判斷。這個消息是人仍是玩具發送的消息。加一個user_typepython
修改玩具表toys。這裏的小魚,表示用戶!jquery
增長user_typeandroid
toys表的其餘記錄,也須要一併修改ios
務必保證 friend_list裏面的每一條記錄。都有user_type字段!
務必保證,每個玩具都有2個好友。一個是主人,一個是除本身以外的玩具。
修改用戶表
修改第一個好友,增長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" } ] }
務必保證 friend_list裏面的每一條記錄。都有user_type字段!
進入flask項目,修改 serv--> friend.py,增長user_type
from flask import Blueprint, request, jsonify from setting import MONGO_DB from setting import RET from bson import ObjectId 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_list return jsonify(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"] = {} return jsonify(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 in enumerate(reqs): reqs[index]["_id"] = str(req.get("_id")) RET["code"] = 0 RET["msg"] = "" RET["data"] = reqs return jsonify(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_info return jsonify(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 else user_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}}) return jsonify(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)
修改 serv--> devices.py,增長user_type
from flask import Blueprint, request, jsonify from setting import MONGO_DB from setting import RET from bson import ObjectId 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 not toy_info: RET["code"] = 0 RET["msg"] = "感謝購買本公司產品" RET["data"] = {} # 若是被綁定加好友邏輯開啓 if toy_info: RET["code"] = 1 RET["msg"] = "添加好友" RET["data"] = {"toy_id": str(toy_info.get("_id"))} else: RET["code"] = 2 RET["msg"] = "二貨,這不是本公司設備,快去買正版!" RET["data"] = {} return jsonify(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)
修改 utils-->baidu_ai.py,增長user_type
from aip import AipSpeech import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 項目根目錄 import sys sys.path.append(BASE_DIR) # 加入到系統環境變量中 import setting # 導入setting from uuid import uuid4 # from setting import MONGO_DB # import setting import os from bson import ObjectId client = AipSpeech(setting.APP_ID,setting.API_KEY,setting.SECRET_KEY) def text2audio(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) return file_name def get_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: return fp.read() def audio2text(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: return res # text2audio("你好") def my_nlp(q,toy_id): # 1. 假設玩具說:q = 我要給爸爸發消息 print(q,"百度q") if "發消息" in q: 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") in q : 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") } return send_str if "我要聽" in q or "我想聽" in q or "唱一首" in q: sources = setting.MONGO_DB.sources.find({}) for i in sources: if i.get("title") in q: send_str = { "code": 0, "from_user": toy_id, "msg_type": "music", "data": i.get("audio") } return send_str res = text2audio("對不起,我沒明白你的意思") send_str = { "code": 0, "from_user": toy_id, "msg_type": "chat", "data": res } return send_str
修改 im_serv.py,增長user_type
from flask import Flask, request from geventwebsocket.websocket import WebSocket from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer import json, os from uuid import uuid4 from setting import AUDIO_FILE,CHAT_FILE from serv import content from utils import baidu_ai from utils import chat_redis import setting from bson import ObjectId import time app = Flask(__name__) user_socket_dict = {} # 空字典,用來存放用戶名和發送消息 @app.route("/toy/<tid>") def toy(tid): # 玩具鏈接 # 獲取請求的WebSocket對象 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket if user_socket: # 設置鍵值對 user_socket_dict[tid] = user_socket print(user_socket_dict) # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>} file_name = "" to_user = "" # 循環,接收消息 while True: 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 and file_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/<uid>") def user_app(uid): # 手機app鏈接 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket if user_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 } if other_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}}) return res if __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 # 歌曲名 } '''
修改 templates-->index.html,增長user_type
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <audio src="" autoplay="autoplay" controls id="player"></audio> <br> <input type="text" id="device_id"/> <button onclick="start_toy()">玩具開機鍵</button> <br> <button onclick="start_reco()">開始廢話</button> <br> <button onclick="stop_reco()">發送語音</button> <br> <button onclick="start_reco()">錄製消息</button> <span id="to_user"></span> <span id="user_type"></span> <br> <button onclick="send_reco()">發送語音消息</button> <br> <button onclick="recv_msg()">收取消息</button> </body> <script src="/static/recorder.js"></script> <script src="/static/jquery.min.js"></script> <script type="application/javascript"> var serv = "http://127.0.0.1:9527"; 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.onended = function () { // 若是長度大於0,也就是有1條或者多條時 if(data.data.length > 0){ //修改audio標籤src屬性,有多條時,會輪詢觸發 player.src = get_chat + data.data.shift().msg; }else{ return null; } } }, "json" ) } </script> </html>
重啓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" } ] }
修改 用戶表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" } ] }
修改 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" ] }
進入左邊網頁,點擊 開始廢話,說: 發消息給 小豆芽 。再點擊發送語音!
網頁會說:能夠按消息鍵,給 小豆芽 發消息了!
這裏會出現 toy,表示給玩具發消息。左邊的id,就是 小豆芽的id
點擊 錄製消息,說:你好, 我是小甜甜!
點擊 發送語音消息
這個時候,網頁會有提示: 你有來自 小甜甜 的消息
切換到第二個網頁,會出現設備id,這個是 小甜甜的。
點擊 收取消息
會播放: 你好, 我是小甜甜!
這樣,就實現了,玩具之間的通訊了!
jieba分詞,徹底開源,有集成的python庫,簡單易用。
jieba分詞是基於前綴詞典實現高效的詞圖掃描,生成句子中漢字全部可能成詞狀況所構成的有向無環圖 (DAG),動態規劃查找最大機率路徑, 找出基於詞頻的最大切分組合
pip install gensim
因爲包很大,若是安裝比較慢,可使用國內更新源安裝
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba
咱們一般把這個庫叫作 結巴分詞 確實是結巴分詞,並且這個詞庫是 made in china , 基本用一下這個結巴分詞:
import jieba key_word = "個人媽媽真偉大" # 定義一句話,基於這句話進行分詞 cut_word = jieba.cut(key_word) # 使用結巴分詞中的cut方法對"個人媽媽真偉大" 進行分詞 print(cut_word) # <generator object Tokenizer.cut at 0x03676390> 不懂生成器的話,就忽略這裏 cut_word_list = list(cut_word) # 若是不明白生成器的話,這裏要記得把生成器對象作成列表 print(cut_word_list) # ['我', '的', '媽媽', '真', '偉大']
測試代碼就很明顯了,它很清晰的把我們的中文字符串轉爲列表存儲起來了
若是須要將 "真偉大" 變成一個詞,須要添加詞庫,使用add_word
import jieba key_word = "個人媽媽真偉大" # 定義一句話,基於這句話進行分詞 jieba.add_word("真偉大") # 添加詞庫 cut_word = jieba.cut(key_word) # 使用結巴分詞中的cut方法對"個人媽媽真偉大" 進行分詞 cut_word_list = list(cut_word) # 若是不明白生成器的話,這裏要記得把生成器對象作成列表 print(cut_word_list) # ['我', '的', '媽媽', '真偉大']
將漢字轉爲拼音。能夠用於漢字註音、排序、檢索(Russian translation) 。
pip install pypinyin
from pypinyin import lazy_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 import lazy_pinyin,TONE2 key_word = "貝貝蓓蓓背背" # 定義一句話 res = lazy_pinyin(key_word,style=TONE2) # 設置拼音風格 print(res) # ['be4i', 'be4i', 'be4i', 'be4i', 'be4i', 'be4i']
Gensim是一款開源的第三方Python工具包,用於從原始的非結構化的文本中,無監督地學習到文本隱層的主題向量表達。
它支持包括TF-IDF,LSA,LDA,和word2vec在內的多種主題模型算法,
支持流式訓練,並提供了諸如類似度計算,信息檢索等一些經常使用任務的API接口
語料(Corpus):一組原始文本的集合,用於無監督地訓練文本主題的隱層結構。語料中不須要人工標註的附加信息。在Gensim中,Corpus一般是一個可迭代的對象(好比列表)。每一次迭代返回一個可用於表達文本對象的稀疏向量。
向量(Vector):由一組文本特徵構成的列表。是一段文本在Gensim中的內部表達。
稀疏向量(SparseVector):一般,咱們能夠略去向量中多餘的0元素。此時,向量中的每個元素是一個(key, value)的元組
模型(Model):是一個抽象的術語。定義了兩個向量空間的變換(即從文本的一種向量表達變換爲另外一種向量表達)。
pip install jieba
這個訓練庫很厲害, 裏面封裝不少機器學習的算法, 是目前人工智能的主流應用庫,這個不是很好理解, 須要必定的Python數據處理的功底
import jieba import gensim from gensim import corpora from gensim import models from gensim import similarities l1 = ["你的名字是什麼", "你今年幾歲了", "你有多高你心情怎麼樣", "你心情怎麼樣"] a = "你今年多大了" # 製做語料庫 all_doc_list = [] for doc in l1: doc_list = [word for word in jieba.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 in jieba.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 in all_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)
執行輸出:
[['你', '的', '名字', '是', '什麼'], ['你', '今年', '幾歲', '了'], ['你', '有', '多', '高', '你', '心情', '怎麼樣'], ['你', '心情', '怎麼樣']] token2id {'什麼': 0, '你': 1, '名字': 2, '是': 3, '的': 4, '了': 5, '今年': 6, '幾歲': 7, '多': 8, '心情': 9, '怎麼樣': 10, '有': 11, '高': 12} dictionary Dictionary(13 unique tokens: ['什麼', '你', '名字', '是', '的']...) <class 'gensim.corpora.dictionary.Dictionary'> 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)]] <class 'list'> doc_test_vec [(1, 1), (5, 1), (6, 1)] <class 'list'> lsi LsiModel(num_terms=13, num_topics=200, decay=1.0, chunksize=20000) <class 'gensim.models.lsimodel.LsiModel'> lsi[corpus] <gensim.interfaces.TransformedCorpus object at 0x00000260DA2DAF28> lsi[doc_test_vec] [(0, 0.900230201263672), (1, 0.3426436202483724), (2, -1.1659919622685817)] index <gensim.similarities.docsim.SparseMatrixSimilarity object at 0x00000260DA2F3048> <class 'gensim.similarities.docsim.SparseMatrixSimilarity'> sim [0.2956978 0.99180055 0.44080025 0.38174424] <class 'numpy.ndarray'> [(1, 0.99180055), (2, 0.44080025), (3, 0.38174424), (0, 0.2956978)] 你今年多大了 你今年幾歲了
噼裏啪啦寫了這一堆代碼,到底幹了啥喲?看了一臉懵逼!
大概意思就是。我拋出了一個問題,就是變量a
你今年多大了
在問題庫裏面,有這些問題
["你的名字是什麼", "你今年幾歲了", "你有多高你心情怎麼樣", "你心情怎麼樣"]
通過 矩陣類似度計算以後,獲得一個最優的結果
你今年幾歲了
也就是說,我問:你今年多大了,機器認爲個人問題是:你今天幾歲了
這2句話,實際上是一個意思!
進入flask項目,進入utils目錄,新建文件lowB_plus.py
import jieba import setting from gensim import corpora from gensim import models from gensim import similarities l1 = [] for i in setting.MONGO_DB.sources.find({}): l1.append(i.get("title")) def my_nlp(text): # 製做語料庫 all_doc_list = [] for doc in l1: doc_list = [word for word in jieba.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 in jieba.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 in all_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
因爲還不夠智能,因此叫 lowB_plus
修改 utils-->baidu_ai.py,使用 lowB_plus
from aip import AipSpeech import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 項目根目錄 import sys sys.path.append(BASE_DIR) # 加入到系統環境變量中 import setting # 導入setting from uuid import uuid4 # from setting import MONGO_DB # import setting import os from bson import ObjectId from utils import lowB_plus from pypinyin import lazy_pinyin, TONE2 client = AipSpeech(setting.APP_ID,setting.API_KEY,setting.SECRET_KEY) def text2audio(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) return file_name def get_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: return fp.read() def audio2text(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: return res # text2audio("你好") def my_nlp(q,toy_id): # 1. 假設玩具說:q = 我要給爸爸發消息 if "發消息" in q: 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 in q: 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") } return send_str if "我要聽" in q or "我想聽" in q or "唱一首" in q: 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 in sources: if i.get("title") in q: send_str = { "code": 0, "from_user": toy_id, "msg_type": "music", "data": i.get("audio") } return send_str res = text2audio("對不起,我沒明白你的意思") send_str = { "code": 0, "from_user": toy_id, "msg_type": "chat", "data": res } return send_str
重啓 manager.py和im_serv.py
從新訪問網頁,讓2個玩具開機。左邊是小甜甜,右邊是小豆芽
使用 小甜甜給小豆芽發送消息。注意:說話的時候,可使用兒化音。
好比:發消息 給 小豆芽兒
查看Pycharm控制檯輸出:
發消息給小豆芽兒
fa1xia1oxi1ge3ixia3odo4uya2e2r
第二個網頁,小豆芽,也能夠接收消息!
打開玩具表toys,找到 小甜甜的記錄,將小豆芽,改爲曉逗牙
再次測試發送語音給 小豆芽
小豆芽,同樣也能夠收到消息!
注意:儘量避免多音字。不然會沒法匹配到!
若是說別的話,好比:今每天氣怎麼樣?網頁會提示: 對不起,我沒明白你的意思
這樣用戶體驗很差,那麼這種匹配不到的問題,扔給圖靈來處理就能夠了!
修改 setting.py,增長圖靈配置
import pymongo import os import redis # 數據庫配置 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" } }
進入utils目錄,新建文件 tuling.py
import requests import json from setting import TL_URL as tuling_url from setting import TL_DATA as data def to_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
修改 utils-->baidu_ai.py,接入圖靈
from aip import AipSpeech import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 項目根目錄 import sys sys.path.append(BASE_DIR) # 加入到系統環境變量中 import setting # 導入setting from uuid import uuid4 # from setting import MONGO_DB # import setting import os from bson import ObjectId from utils import lowB_plus from pypinyin import lazy_pinyin, TONE2 from utils import tuling client = AipSpeech(setting.APP_ID,setting.API_KEY,setting.SECRET_KEY) def text2audio(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) return file_name def get_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: return fp.read() def audio2text(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: return res # text2audio("你好") def my_nlp(q,toy_id): # 1. 假設玩具說:q = 我要給爸爸發消息 if "發消息" in q: 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 in q: 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") } return send_str if "我要聽" in q or "我想聽" in q or "唱一首" in q: 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 in sources: if i.get("title") in q: send_str = { "code": 0, "from_user": toy_id, "msg_type": "music", "data": i.get("audio") } return send_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
重啓 manager.py和im_serv.py
讓2個玩具開機,說一段話: 上海的天氣怎麼樣
網頁會播放: 上海:週四,多雲轉陰 東北風4-5級,最低氣溫22度,最高氣溫27度
查看Pycharm控制檯輸出:
上海的天氣怎麼樣
上海:週四,多雲轉陰 東北風4-5級,最低氣溫22度,最高氣溫27度
單擊打原生安裝包
必需要登陸帳號才行
注意:默認是使用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 magicString 5.手機app是怎麼作的(使用什麼方式): mui + html5plus 6.談談你對人工智能的理解(說出人工智能技術的關鍵字至少5個): 語音類 : 語音識別 語音合成 圖像類 : 圖像識別 文字識別 人臉識別 視頻審覈 語言類 : 天然語言處理 機器翻譯 詞法分析 依存句法分析 文本糾錯 對話情緒識別 詞向量表示 短文本類似度 詞義類似度 情感傾向分析 7.mongodb相關: 1.修改器: $push $set $pull $inc $pop 2.說說你對 $ 的理解 : $ 個人理解就是代指符號,代指所查詢到的數據或索引位置 3.Mongodb中的數據類型 : ObjectID String Boolean Integer Double Arrays Object(Dict) Null Timestamp Date 4.mongodb的比較符 : $lt $gt $lte $gte ":" 8.公司組織架構: 1.綜合人力財務行政:1個小姐姐 2.營銷部:老張 3.產品部:老李 + UI小姐姐 4.軟件部:閆帥 + 前端小姐姐 + 我 5.硬件部:江老師 9.項目不作底層,只使用三方的緣由: 製做底層大量佔用人力,公司資金不足以支撐底層研發 將大量成本投入到硬件研發中 10. 項目中,涉及到的技術 智能語音識別 - 第三方百度ai 開機提示 天然語言處理(nlp) 點歌 :內容點播 開啓消息發送 基於通信錄的即時通信(IM) websocket 不用第三方的緣由 保護隱私 管理玩具的功能: 1.經過掃描二維碼 綁定玩具 2.玩具通信錄管理
完整終極代碼,請參考github:
https://github.com/987334176/Intelligent_toy/archive/v1.7.zip
附帶項目須要的全部文件,包括音頻,圖片,數據庫等等