diff --git a/bingchat/app.json b/bingchat/app.json index 5236657..60057ae 100644 --- a/bingchat/app.json +++ b/bingchat/app.json @@ -8,7 +8,7 @@ "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#ffffff", - "navigationBarTitleText": "New Bing Bot 🤖", + "navigationBarTitleText": "New Bing 🤖", "navigationBarTextStyle": "black" }, "sitemapLocation": "sitemap.json", diff --git a/bingchat/components/chatbox/index.js b/bingchat/components/chatbox/index.js index b699ce3..cff7fd2 100644 --- a/bingchat/components/chatbox/index.js +++ b/bingchat/components/chatbox/index.js @@ -14,7 +14,12 @@ Component({ addGlobalClass: true, multipleSlots: true, }, - properties: {}, + properties: { + chatType: { + type: String, + value: "bing" + } + }, pageLifetimes: { show: function () { this.initMessageHistory() @@ -146,63 +151,6 @@ Component({ "cancelReceive", {}, {} ) }, - deleteAllChat: function () { - var that = this - wx.showModal({ - content: "是否删除全部聊天?", - complete: (res) => { - if (res.confirm) { - that.setData({ - chatList: [], - }) - wx.setStorage({ - key: "chatList", - data: [], - }) - } - }, - }) - }, - longPress: function (e) { - var that = this - wx.showActionSheet({ - itemList: ["删除全部聊天记录", "切换聊天接口方式", that.data.closeShareOnCopy ? "打开复制后分享" : "关闭复制后分享"], - success(res) { - if (res.tapIndex == 0) { - that.deleteAllChat() - } else if (res.tapIndex == 1) { - that.triggerEvent( - "switchRequestMethod", {}, {} - ) - } else if (res.tapIndex == 2) { - if (that.data.closeShareOnCopy) { - that.setData({ - closeShareOnCopy: false, - }) - wx.showToast({ - title: "已打开复制后分享", - icon: "none" - }) - wx.removeStorage({ - key: "closeShareOnCopy", - }) - } else { - that.setData({ - closeShareOnCopy: true, - }) - wx.showToast({ - title: "已关闭复制后分享", - icon: "none" - }) - wx.setStorage({ - key: "closeShareOnCopy", - data: 1, - }) - } - } - } - }) - }, showOriginContent: function (e) { var index = e.currentTarget.dataset.index var data = this.data.chatList[index] @@ -218,7 +166,7 @@ Component({ onPopButtonClick: function (e) { if (e.detail.t !== "confirm") { wx.removeStorage({ - key: 'shareContent', + key: "shareContent", }) } this.setData({ diff --git a/bingchat/components/chatbox/index.wxml b/bingchat/components/chatbox/index.wxml index f79fb85..430b5a7 100644 --- a/bingchat/components/chatbox/index.wxml +++ b/bingchat/components/chatbox/index.wxml @@ -1,34 +1,32 @@ - - 输入问题开始和New Bing聊天吧~ - - - - - - {{item.dt}} - {{item.num_in_conversation}} - - - - {{item.originContent}} - - - - {{suggest}} +输入问题开始和{{chatType == "bing" ? "New Bing" : "ChatGPT"}}聊天吧~ + + + + + + {{item.dt}} + {{item.num_in_conversation}} + + + + {{item.originContent}} - - - - {{item.dt}} - {{item.originContent}} + + {{suggest}} - - - - - + + + {{item.dt}} + {{item.originContent}} + + + + + + + \ No newline at end of file diff --git a/bingchat/components/popup/popup.wxss b/bingchat/components/popup/popup.wxss index a656bb4..137b9e3 100644 --- a/bingchat/components/popup/popup.wxss +++ b/bingchat/components/popup/popup.wxss @@ -9,7 +9,7 @@ padding: 20rpx 30rpx 20rpx 30rpx; box-sizing: border-box; z-index: 10000; - border: 1rpx dashed; + border: 1px dashed; } .bt { diff --git a/bingchat/image/chatgpt.png b/bingchat/image/chatgpt.png new file mode 100644 index 0000000..7cefa94 Binary files /dev/null and b/bingchat/image/chatgpt.png differ diff --git a/bingchat/image/chatgpt_share.png b/bingchat/image/chatgpt_share.png new file mode 100644 index 0000000..676679c Binary files /dev/null and b/bingchat/image/chatgpt_share.png differ diff --git a/bingchat/pages/index/index.js b/bingchat/pages/index/index.js index 5a58db0..3cb3870 100644 --- a/bingchat/pages/index/index.js +++ b/bingchat/pages/index/index.js @@ -24,6 +24,16 @@ function inputPop() { // 自增对话 var autoIncrConversation = 0 +// 默认采用new bing +var chatType = "bing" +try { + if (wx.getStorageSync("usechatgpt")) { + chatType = "chatgpt" + } +} catch (e) { + chatType = "bing" +} + Date.prototype.format = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 @@ -74,6 +84,7 @@ Page({ useWebsocket: useWebsocket, showSearchPop: false, searchPopMessage: "", + chatType: chatType, }, inputFocus(e) { if (inputPop()) { @@ -120,10 +131,19 @@ Page({ var options = this.getOptions() if (options && options["q"]) { var q = decodeURIComponent(options["q"]) + var chatType = this.data.chatType + if (options["chatType"]) { + chatType = options["chatType"] + // 聊天方式不同,关闭websocket + if (chatType != this.data.chatType) { + this.onCancelReceive() + } + } this.setData({ searchPopMessage: "即将搜索“" + q + "”", showSearchPop: true, q: q, + chatType: chatType, }) } const cht = app.globalData.cht @@ -132,6 +152,19 @@ Page({ scrollId: "item" + (cht.data.chatList.length - 2), }) } + // 切换title + this.switchTitle() + }, + switchTitle: function () { + if (this.data.chatType == "bing") { + wx.setNavigationBarTitle({ + title: "New Bing 🤖️", + }) + } else { + wx.setNavigationBarTitle({ + title: "ChatGPT 🤖️", + }) + } }, onLoad() {}, processData: function (data, suggests, content) { @@ -139,7 +172,7 @@ Page({ if (robContent == "Success") { robContent = data["data"]["text"] suggests.push(...data["data"]["suggests"]) - if (robContent.indexOf("New topic") != -1) { + if (robContent.indexOf("New topic") != -1 && this.data.chatType == "bing") { robContent += "\n发送“重新对话!”开始新的对话" suggests.push("重新对话!") suggests.push(content) @@ -157,7 +190,9 @@ Page({ suggests.push(content) } else { robContent = "抱歉😭,发生错误:" + msg - suggests.push("重新对话!") + if (this.data.chatType == "bing") { + suggests.push("重新对话!") + } suggests.push(content) } } @@ -177,8 +212,9 @@ Page({ sendHttpRequest: function (content) { var that = this const cht = app.globalData.cht + var api = that.data.chatType == "bing" ? "/chat" : "/openai_chat" app.getSid(sid => { - doRequest("/chat", "POST", { + doRequest(api, "POST", { q: content, sid: sid_prefix + sid, }).then(res => { @@ -226,7 +262,7 @@ Page({ content: "", lastContent: content, }) - if (content == "重新对话!") { + if (content == "重新对话!" && that.data.chatType == "bing") { that.resetConversation(() => { that.pushStorageMessage(cht, "现在我们可以开始新的对话😊", "rob", [], false) }) @@ -244,9 +280,10 @@ Page({ if (pop) { cht.data.chatList.pop() } + var rAvatar = this.data.chatType == "bing" ? robAvatar : "../../image/chatgpt.png" cht.data.chatList.push({ type: role, - avatarUrl: role == "rob" ? robAvatar : personAvatar, + avatarUrl: role == "rob" ? rAvatar : personAvatar, dt: getNow(), originContent: this.processContent(content), suggests: suggests, @@ -281,7 +318,7 @@ Page({ this.submitContent(content) }, onShareAppMessage() { - var title = "New Bing Bot 🤖" + var title = this.data.chatType == "bing" ? "New Bing 🤖" : "ChatGPT 🤖️" var content = this.data.content.trim() if (content.length > 0) { title = content @@ -299,8 +336,8 @@ Page({ } return { title: title, - path: "/pages/index/index?q=" + encodeURIComponent(content), - imageUrl: "../../image/newBing.png" + path: "/pages/index/index?q=" + encodeURIComponent(content) + "&chatType=" + this.data.chatType, + imageUrl: this.data.chatType == "bing" ? "../../image/newBing.png" : "../../image/chatgpt_share.png" } }, onSuggestSubmit: function (e) { @@ -318,8 +355,9 @@ Page({ } var that = this const cht = app.globalData.cht + var apiPath = that.data.chatType == "bing" ? "/chat" : "/ws_openai_chat" const socket = wx.connectSocket({ - url: SERVER_WSS_HOST + "/chat", + url: SERVER_WSS_HOST + apiPath, fail: function () { wx.showToast({ title: "打开websocket失败", @@ -380,7 +418,11 @@ Page({ var robContent = "" var num_in_conversation = -1 if (!data["final"]) { - robContent = data["data"] + " ..." + if (data["data"]["data"]) { + robContent = data["data"]["data"]["text"] + " ..." + } else { + robContent = data["data"] + " ..." + } cht.setData({ receiveData: true }) @@ -485,5 +527,91 @@ Page({ } }) } - } + }, + deleteAllChat: function () { + const cht = app.globalData.cht + wx.showModal({ + content: "是否删除全部聊天?", + complete: (res) => { + if (res.confirm) { + cht.setData({ + chatList: [], + }) + wx.setStorage({ + key: "chatList", + data: [], + }) + } + }, + }) + }, + longPress: function (e) { + var that = this + const cht = app.globalData.cht + wx.showActionSheet({ + itemList: ["删除全部聊天记录", "切换聊天接口方式", that.data.chatType == "bing" ? "切换成ChatGPT" : "切换成New Bing", cht.data.closeShareOnCopy ? "打开复制后分享" : "关闭复制后分享"], + success(res) { + if (res.tapIndex == 0) { + that.deleteAllChat() + } else if (res.tapIndex == 1) { + that.switchRequestMethod() + } else if (res.tapIndex == 3) { + if (cht.data.closeShareOnCopy) { + cht.setData({ + closeShareOnCopy: false, + }) + wx.showToast({ + title: "已打开复制后分享", + icon: "none" + }) + wx.removeStorage({ + key: "closeShareOnCopy", + }) + } else { + cht.setData({ + closeShareOnCopy: true, + }) + wx.showToast({ + title: "已关闭复制后分享", + icon: "none" + }) + wx.setStorage({ + key: "closeShareOnCopy", + data: 1, + }) + } + } else if (res.tapIndex == 2) { + if (that.data.chatType == "chatgpt") { + wx.removeStorage({ + key: "usechatgpt", + }) + that.setData({ + chatType: "bing", + }) + wx.showToast({ + title: "已切换成New Bing", + icon: "none" + }) + } else { + wx.setStorage({ + key: "usechatgpt", + data: 1, + }) + that.setData({ + chatType: "chatgpt", + }) + wx.showToast({ + title: "已切换成ChatGPT", + icon: "none" + }) + } + } + // 关闭websocket + that.onCancelReceive() + setTimeout(() => { + that.switchTitle() + }, 100) + } + }) + }, }) diff --git a/bingchat/pages/index/index.wxml b/bingchat/pages/index/index.wxml index c25cb77..a155cb4 100644 --- a/bingchat/pages/index/index.wxml +++ b/bingchat/pages/index/index.wxml @@ -1,5 +1,5 @@ - - + + 发送 diff --git a/new-bing/app.py b/new-bing/app.py index 76ef726..9ea921c 100644 --- a/new-bing/app.py +++ b/new-bing/app.py @@ -4,8 +4,10 @@ import json as raw_json import os import re import threading +from collections import defaultdict from datetime import datetime, timedelta +import openai import requests from sanic import Sanic from sanic.log import logger @@ -38,6 +40,9 @@ app.config.RESPONSE_TIMEOUT = 900 app.config.WEBSOCKET_PING_INTERVAL = 15 app.config.WEBSOCKET_PING_TIMEOUT = 30 +# openai conversation +OPENAI_CONVERSATION = defaultdict(lambda: []) + def reset_cookie(): if not LOCK.acquire(blocking=False): @@ -191,5 +196,92 @@ async def openid(request): return json({'data': requests.get(url).json()}) +# #########################################以下是openid接口################################## + + +@app.websocket('/ws_openai_chat') +async def ws_openai_chat(_, ws): + while True: + try: + data = raw_json.loads(await ws.recv()) + logger.info('Websocket receive data: %s', data) + sid = data['sid'] + q = data['q'] + # 保存30个对话 + history_conversation = OPENAI_CONVERSATION[sid][-30:] + history_conversation.append({ + 'role': 'user', + 'content': q, + }) + response = openai.ChatCompletion.create( + model='gpt-3.5-turbo', + messages=history_conversation, + temperature=1.2, + stream=True, + ) + chunks = [] + for chunk in response: + chunk_message = chunk['choices'][0]['delta'] + if chunk_message: + if 'content' in chunk_message: + chunks.append(chunk_message['content']) + await ws.send( + raw_json.dumps({ + 'final': False, + 'data': make_response_data('Success', ''.join(chunks), [], '') + }) + ) + else: + OPENAI_CONVERSATION[sid].append({ + 'role': 'assistant', + 'content': ''.join(chunks) + }) + await ws.send( + raw_json.dumps({ + 'final': True, + 'data': make_response_data('Success', ''.join(chunks), [], '') + }) + ) + except Exception as e: + logger.error(e) + await ws.send(raw_json.dumps({ + 'final': True, + 'data': make_response_data('Error', str(e), [], str(e)) + })) + + +@app.post('/openai_chat') +async def openai_chat(request): + try: + sid = request.json.get('sid') + q = request.json.get('q') + history_conversation = OPENAI_CONVERSATION[sid][-30:] + history_conversation.append({ + 'role': 'user', + 'content': q, + }) + response = openai.ChatCompletion.create( + model='gpt-3.5-turbo', + messages=history_conversation, + temperature=1.2, + stream=True, + ) + chunks = [] + for chunk in response: + chunk_message = chunk['choices'][0]['delta'] + if chunk_message: + if 'content' in chunk_message: + chunks.append(chunk_message['content']) + else: + OPENAI_CONVERSATION[sid].append({ + 'role': 'assistant', + 'content': ''.join(chunks) + }) + return json(make_response_data('Success', ''.join(chunks), [], '')) + except Exception as e: + logger.error(e) + return json(make_response_data('Error', str(e), [], str(e))) + + if __name__ == '__main__': app.run(host='0.0.0.0', port=8000) diff --git a/new-bing/env.example b/new-bing/env.example index bc30727..ad8df90 100644 --- a/new-bing/env.example +++ b/new-bing/env.example @@ -5,3 +5,4 @@ COOKIE_FILE1=/sanic/cookies/cookie1.json # 备用cookie1, 没有可以删掉 COOKIE_FILE2=/sanic/cookies/cookie2.json # 备用cookie2, 没有可以删掉 COOKIE_FILES=["/sanic/cookies/cookie.json", "/sanic/cookies/cookie1.json", "/sanic/cookies/cookie2.json"] #cookie列表,配置了此环境变量,会优先使用此变量,直接忽略上面的3个环境变量 https_proxy=http://127.0.0.1:1080 # 目前中国大陆的IP会返回404,所以最好能加个代理 +OPENAI_API_KEY= diff --git a/new-bing/requirements.txt b/new-bing/requirements.txt index 8ca718d..0fe308c 100644 --- a/new-bing/requirements.txt +++ b/new-bing/requirements.txt @@ -3,3 +3,4 @@ requests==2.28.2 asyncio==3.4.3 websockets==10.4 httpx==0.23.3 +openai==0.27.2