支持websocket协议

This commit is contained in:
linghaihui 2023-03-26 23:05:16 +08:00
parent af7c4ebc2f
commit ded224588e
4 changed files with 245 additions and 93 deletions

View File

@ -2,22 +2,20 @@
"pages": [
"pages/index/index"
],
"useExtendedLib": {
"weui":true
},
"usingComponents": {
"chat-box":"components/chatbox/index"
"chat-box": "components/chatbox/index"
},
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTitleText": "New Bing Bot 🤖",
"navigationBarTextStyle": "black"
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json",
"networkTimeout": {
"request": 1800000
},
"resizable": true,
"lazyCodeLoading": "requiredComponents"
"request": 900000,
"connectSocket": 900000
},
"resizable": true,
"lazyCodeLoading": "requiredComponents"
}

View File

@ -1,4 +1,5 @@
const SERVER_HOST = "https://example.com";
const SERVER_WSS_HOST = "wss://example.com";
function doRequest(url, method = "GET", data = {}) {
return new Promise((resolve, reject) => {
@ -20,5 +21,6 @@ function doRequest(url, method = "GET", data = {}) {
}
export {
doRequest,
SERVER_HOST
SERVER_HOST,
SERVER_WSS_HOST
}

View File

@ -1,5 +1,6 @@
import {
doRequest
doRequest,
SERVER_WSS_HOST
} from "../../config";
const systemInfo = wx.getSystemInfoSync()
@ -49,9 +50,14 @@ Page({
data: {
InputBottom: initHeight,
content: "",
lastContent: "",
systemInfo: systemInfo,
textareaFocus: false,
searching: false,
socket: {
socket: null,
isOpen: false,
},
},
InputFocus(e) {
if (inputPop()) {
@ -62,12 +68,12 @@ Page({
},
InputBlur(e) {
this.setData({
InputBottom: initHeight,
textareaFocus: false,
InputBottom: initHeight,
textareaFocus: false,
});
},
processContent(content) {
return content.replace(/\\n/g, "\n");
return content.replace(/\\n/g, "\n").replace(/\[\^\d+\^\]/g, "");
},
resetConversation: function (callback) {
app.getSid(sid => {
@ -89,6 +95,77 @@ Page({
}
},
onLoad() {},
processData: function (data, suggests, content) {
var robContent = data["data"]["status"];
if (robContent == "Success") {
robContent = data["data"]["text"];
suggests.push(...data["data"]["suggests"]);
if (robContent.indexOf("New topic") != -1) {
robContent += "\n\n发送“重新对话”开始新的对话";
suggests.push("重新对话!");
suggests.push(content);
}
} else {
if (robContent == "Throttled") {
robContent = "这真是愉快,但你已达到每日限制。是否明天再聊?";
suggests.push("重新对话!");
suggests.push(content);
} else {
var msg = data["data"]["message"];
if (msg.indexOf("has expired") != -1) {
this.resetConversation();
robContent = "本轮对话已过期,请重新开始。";
suggests.push(content);
} else {
robContent = "抱歉😭,发生错误:" + msg + ",请重试";
suggests.push(content);
}
}
}
return robContent
},
sendWSRequest: function (content) {
var that = this
app.getSid(sid => {
that.sendSocketMessage({
"q": content,
"sid": sid,
"t": new Date().getTime()
})
})
},
sendHttpRequest: function (content) {
var that = this
const cht = app.globalData.cht;
app.getSid(sid => {
doRequest("/chat", "POST", {
q: content,
sid: sid,
}).then(res => {
try {
var robContent = ""
var suggests = []
var num_in_conversation = -1
if (res.statusCode != 200) {
robContent =
"抱歉😭,网络异常,请稍后重试 [" + res.statusCode + "]";
suggests.push(content);
} else {
robContent = that.processData(res.data, suggests, content)
num_in_conversation = res.data["data"]["num_in_conversation"];
}
that.pushStorageMessage(cht, robContent, "rob", suggests, false, true, num_in_conversation)
} catch (error) {
wx.showToast({
title: "fatal error",
});
that.pushStorageMessage(cht, "发生致命错误😱", "rob", [], false, true)
}
}).catch(e => {
that.pushStorageMessage(cht, e.errMsg, "rob", [], false, true)
})
})
},
submitContent: function (content) {
if (this.data.searching) {
wx.showToast({
@ -106,6 +183,7 @@ Page({
that.pushStorageMessage(cht, content, "man", [], false)
that.setData({
content: "",
lastContent: content,
});
if (content == "重新对话!") {
that.resetConversation(() => {
@ -115,61 +193,10 @@ Page({
} else {
that.pushStorageMessage(cht, "搜索中🔍...", "rob", [], true)
}
app.getSid(sid => {
doRequest("/chat", "POST", {
q: content,
sid: sid,
}).then(res => {
try {
var robContent = ""
var suggests = []
var num_in_conversation = -1
if (res.statusCode != 200) {
robContent =
"抱歉😭,网络异常,请稍后重试 [" + res.statusCode + "]";
suggests.push(content);
} else {
robContent = res.data["data"]["status"];
if (robContent == "Success") {
robContent = res.data["data"]["text"];
suggests = res.data["data"]["suggests"];
if (robContent.indexOf("New topic") != -1) {
robContent += "\n\n发送“重新对话”开始新的对话";
suggests.push("重新对话!");
suggests.push(content);
}
num_in_conversation = res.data["data"]["num_in_conversation"];
} else {
if (robContent == "Throttled") {
robContent = "这真是愉快,但你已达到每日限制。是否明天再聊?";
suggests.push("重新对话!");
suggests.push(content);
} else {
var msg = res.data["data"]["message"];
if (msg.indexOf("has expired") != -1) {
that.resetConversation();
robContent = "本轮对话已过期,请重新开始。";
suggests.push(content);
} else {
robContent = "抱歉😭,发生错误:" + msg + ",请重试";
suggests.push(content);
}
}
}
}
that.pushStorageMessage(cht, robContent, "rob", suggests, false, true, num_in_conversation)
} catch (error) {
wx.showToast({
title: "fatal error",
});
that.pushStorageMessage(cht, "发生致命错误😱", "rob", [], false, true)
}
}).catch(e => {
that.pushStorageMessage(cht, e.errMsg, "rob", [], false, true)
})
})
// that.sendHttpRequest(content)
that.sendWSRequest(content)
},
pushStorageMessage: function (cht, content, role, suggests, blink, pop, num_in_conversation = -1) {
pushStorageMessage: function (cht, content, role, suggests, blink, pop, num_in_conversation = -1, final = true) {
if (pop) {
cht.data.chatList.pop();
}
@ -185,7 +212,7 @@ Page({
cht.setData({
chatList: cht.data.chatList,
});
if (role == "rob" && !blink) {
if (role == "rob" && !blink && final) {
this.setData({
searching: false
})
@ -221,5 +248,97 @@ Page({
this.setData({
textareaFocus: true
})
},
openSocket(callback) {
if (this.data.socket.isOpen) {
return
}
var that = this
const socket = wx.connectSocket({
url: SERVER_WSS_HOST + "/chat",
fail: function () {
wx.showToast({
title: '打开websocket失败',
})
}
})
socket.onOpen(() => {
that.setData({
socket: {
socket: socket,
isOpen: true
}
})
setTimeout(() => {
if (callback) {
callback()
}
}, 50)
})
socket.onClose((code, reason) => {
console.log('Socket onClose', code, reason)
that.setData({
socket: {
socket: null,
isOpen: false
}
})
})
socket.onError(msg => {
console.log('Socket onError', msg)
that.setData({
socket: {
socket: null,
isOpen: false
}
})
})
socket.onMessage(data => {
const cht = app.globalData.cht;
var data = JSON.parse(data.data)
var suggests = []
var robContent = ''
var num_in_conversation = -1
if (!data['final']) {
robContent = data['data']
} else {
robContent = that.processData(data['data'], suggests, that.data.lastContent)
num_in_conversation = data['data']['data']['num_in_conversation']
}
that.pushStorageMessage(cht, robContent, "rob", suggests, false, true, num_in_conversation, data['final'])
})
},
sendSocketMessage: function (data) {
if (!this.data.socket.isOpen) {
this.openSocket(() => {
this.data.socket.socket.send({
data: JSON.stringify(data),
fail: err => {
console.log(err)
wx.showToast({
title: '消息发送失败',
})
}
})
})
} else {
this.data.socket.socket.send({
data: JSON.stringify(data),
fail: err => {
console.log(err)
wx.showToast({
title: '消息发送失败',
})
}
})
}
},
onUnload: function () {
if (this.data.socket.isOpen) {
this.data.socket.socket.close({
code: 1000,
reason: "Page Unload"
})
}
}
});
});

View File

@ -1,5 +1,6 @@
# coding=utf-8
import json as raw_json
import logging
import os
import re
@ -12,6 +13,7 @@ from sanic.response import json
from EdgeGPT import Chatbot, ConversationStyle
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
APPID = os.environ.get('WXAPPID')
APPSECRET = os.environ.get('WXAPPSECRET')
@ -23,6 +25,13 @@ BAK_COOKIE1 = os.environ.get('COOKIE_FILE2', '')
LOCK = threading.Lock()
BOT_LOCK = threading.Lock()
bots = {}
app = Sanic('new-bing')
app.config.REQUEST_TIMEOUT = 900
app.config.RESPONSE_TIMEOUT = 900
app.config.WEBSOCKET_PING_INTERVAL = 15
app.config.WEBSOCKET_PING_TIMEOUT = 15
def reset_cookie():
@ -40,10 +49,30 @@ def reset_cookie():
LOCK.release()
app = Sanic('new-bing')
app.config.REQUEST_TIMEOUT = 900
app.config.RESPONSE_TIMEOUT = 900
bots = {}
@app.websocket('/chat')
async def ws_chat(request, ws):
while True:
data = raw_json.loads(await ws.recv())
logger.warn('Receive data: %s', data)
sid = data['sid']
q = data['q']
async for response in get_bot(sid).ask_stream(q, conversation_style=ConversationStyle.creative):
final, res = response
if final:
processed_data = await process_data(res, q, sid, auto_reset=1)
if processed_data['data']['status'] == 'Throttled':
reset_cookie()
await get_bot(sid).reset()
processed_data['data']['suggests'].append(q)
await ws.send(raw_json.dumps({
'final': final,
'data': processed_data
}))
else:
await ws.send(raw_json.dumps({
'final': final,
'data': res
}))
def get_bot(sid):
@ -58,24 +87,16 @@ def get_bot(sid):
async def do_chat(request):
logger.warn('Request payload: %s', request.json)
return await get_bot(request.json.get('sid')).ask(
request.json.get('q'), conversation_style=ConversationStyle.creative
)
@app.post('/chat')
async def chat(request):
res = await do_chat(request)
auto_reset = request.json.get('auto_reset', '')
sid = request.json.get('sid')
status = res['item']['result']['value']
if status == 'Throttled':
reset_cookie()
await get_bot(sid).reset()
res = await do_chat(request)
status = res['item']['result']['value']
async def process_data(res, q, sid, auto_reset=None):
text = ''
suggests = []
status = res['item']['result']['value']
if status == 'Success':
item = res['item']['messages']
if len(item) >= 2:
@ -89,18 +110,16 @@ async def chat(request):
text = re.sub(r'\[\^\d+\^\]', '', text)
suggests = [x['text'] for x in item[1]['suggestedResponses']] if 'suggestedResponses' in item[1] else []
else:
text = '抱歉,未搜索到结果,请重试'
text = '抱歉,未搜索到结果'
logger.error('响应异常:%s', res)
suggests = [request.json.get('q')]
# 结束本轮对话
suggests = [q]
if res['type'] == 2:
await get_bot(sid).reset()
text = '抱歉,未搜索到结果,已结束本轮对话。'
text += '\n\n已结束本轮对话。'
msg = res['item']['result']['message'] if 'message' in res['item']['result'] else ''
# 自动reset
if auto_reset and ('New topic' in text or 'has expired' in msg):
await get_bot(sid).reset()
return json({
return {
'data': {
'status': status,
'text': text,
@ -109,8 +128,22 @@ async def chat(request):
'num_in_conversation': res['item']['throttling']['numUserMessagesInConversation']
if 'throttling' in res['item'] else -1,
},
'cookie': os.environ.get('COOKIE_FILE')
})
'cookie': os.environ.get('COOKIE_FILE'),
}
@app.post('/chat')
async def chat(request):
res = await do_chat(request)
auto_reset = request.json.get('auto_reset', '')
sid = request.json.get('sid')
data = await process_data(res, request.json.get('q'), sid, auto_reset)
if data['data']['status'] == 'Throttled':
reset_cookie()
await get_bot(sid).reset()
res = await do_chat(request)
data = await process_data(res, request.json.get('q'), sid, auto_reset)
return json(data)
@app.route('/reset')