diff --git a/123.py b/123.py new file mode 100644 index 0000000..c47ed39 --- /dev/null +++ b/123.py @@ -0,0 +1,22 @@ +import requests +import json + +url = "https://api.mixrai.com/v1/chat/completions" +# 'xxx' is your API key, 换成你的令牌 +api_key = "xxx" + +payload = json.dumps( + {"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "Hello!"}]} +) +headers = { + "Accept": "application/json", + "Authorization": api_key, + "User-Agent": "Apifox/1.0.0 (https://apifox.com)", + "Content-Type": "application/json", +} + +response = requests.request("POST", url, headers=headers, data=payload) + +print(response.text) +print("----下面是API Key----") +print(api_key) diff --git a/2598290917api_test.py b/2598290917api_test.py new file mode 100644 index 0000000..4448f1c --- /dev/null +++ b/2598290917api_test.py @@ -0,0 +1,25 @@ +import requests +import json + +url = "https://chatapi.midjourney-vip.cn/v1/chat/completions" + +payload = json.dumps({ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "Hello!" + } + ] +}) +headers = { + 'Accept': 'application/json', + # 'xxx' is your API key, 换成你的令牌 + 'Authorization': 'sk-QxlvoGgkYT1idnvP129595EdA4324330A84f441b58A7E478', + 'User-Agent': 'Apifox/1.0.0 (https://apifox.com)', + 'Content-Type': 'application/json' +} + +response = requests.request("POST", url, headers=headers, data=payload) + +print(response.text) \ No newline at end of file diff --git a/2818902639api_test(3).py b/2818902639api_test(3).py new file mode 100644 index 0000000..d969a7d --- /dev/null +++ b/2818902639api_test(3).py @@ -0,0 +1,36 @@ +import requests +import json + + + +def send_request(session, data): + url = "https://api.mixrai.com/v1/chat/completions" + + try: + headers = { + "Accept": "application/json", + "Authorization":"sk-QxlvoGgkYT1idnvP129595EdA4324330A84f441b58A7E478", + "User-Agent": "Apifox/1.0.0 (https://apifox.com)", + "Content-Type": "application/json", + } + + response = session.post(url, json=data, headers=headers) + response.raise_for_status() + result = response.json() + response_text = result["choices"][0]["message"]["content"] + except requests.exceptions.RequestException as e: + print(f"请求失败: {e}") + response_text = "抱歉,我现在太忙了,休息一会,请稍后再试。" + return response_text + +messages=[{"role": "system", "content": "你好"}] +data = { + "model": "gpt-3.5-turbo", + "messages": messages, + "temperature": 0.3, + "max_tokens": 2000, + "user": f"user_0" + } +session = requests.Session() +session.verify = False +print(send_request(session,data)) \ No newline at end of file diff --git a/cache_data/input.wav b/cache_data/input.wav index 20c3f23..79f0c22 100644 Binary files a/cache_data/input.wav and b/cache_data/input.wav differ diff --git a/config.json b/config.json index 716ad4c..9e1d5d0 100644 --- a/config.json +++ b/config.json @@ -29,7 +29,7 @@ "automatic_player_status": true, "automatic_player_url": "http://127.0.0.1:6000", "liveRoom": { - "enabled": false, + "enabled": true, "url": "" }, "record": { diff --git a/fay.db b/fay.db index f9ee0f9..8b3a6a4 100644 Binary files a/fay.db and b/fay.db differ diff --git a/gui/flask_server.py b/gui/flask_server.py index 44325e9..e762bcb 100644 --- a/gui/flask_server.py +++ b/gui/flask_server.py @@ -520,6 +520,10 @@ def setting(): @__app.route('/chat') def chat(): return render_template('chat.html') + +@__app.route('/chat1') +def chat1(): + return render_template('chat1.html') # 输出的音频http @__app.route('/audio/') def serve_audio(filename): diff --git a/gui/static/css/chat1.css b/gui/static/css/chat1.css new file mode 100644 index 0000000..f83ac14 --- /dev/null +++ b/gui/static/css/chat1.css @@ -0,0 +1,144 @@ +html, body { + margin: 0; + padding: 0; + height: 100%; + font-family: 'Orbitron', sans-serif; + background: linear-gradient(135deg, #0f2027, #203a43, #2c5364); + color: #fff; +} + +#chat-widget { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + flex-direction: column; + z-index: 1000; + background: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(10px); + border-radius: 15px; + margin: 20px; + box-shadow: 0 0 20px rgba(0, 255, 255, 0.2); +} + +.top_info { + font-size: 14px; + font-family: 'Orbitron', sans-serif; + color: #00f0ff; + line-height: 48px; + text-align: left; + padding: 0 20px; + margin: 10px 20px 0 20px; /* 与 chat-widget 的 padding 对齐 */ + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(0, 255, 255, 0.2); + box-shadow: 0 0 10px rgba(0, 255, 255, 0.1); + border-radius: 10px; + backdrop-filter: blur(6px); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.top_info_text { + font-size: 15px; + font-weight: bold; + color: #00ffff; +} + + +#chat-container { + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; +} + +#messages { + flex: 1; + padding: 10px; + overflow-y: auto; +} + +.message { + display: flex; + margin-bottom: 10px; +} + +.message.receiver-message { + justify-content: flex-start; + padding-right: 30%; + margin-right: auto; +} + +.message.sender-message { + justify-content: flex-end; + padding-left: 30%; + margin-left: auto; +} + +.message-content { + flex: 0 1 auto; +} + +.message-bubble { + border-radius: 10px; + padding: 12px 16px; + font-size: 15px; + background: rgba(255, 255, 255, 0.1); + color: #e0e0e0; + box-shadow: 0 0 8px rgba(0, 255, 255, 0.3); + word-break: break-word; + white-space: pre-wrap; + text-align: left; +} + +.message.sender-message .message-bubble { + text-align: right; + background: linear-gradient(135deg, #00c6ff, #0072ff); + color: white; + box-shadow: 0 0 10px rgba(0, 114, 255, 0.7); +} + +#status-indicator { + height: 20px; + text-align: center; + color: #aaa; + font-size: 14px; +} + +#input-area { + display: flex; + align-items: center; + padding: 10px; + border-top: 1px solid rgba(255, 255, 255, 0.2); + background-color: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(8px); +} + +#input-area button { + background: none; + border: none; + cursor: pointer; + margin-right: 10px; +} + +#input-area img { + width: 25px; + height: 25px; + filter: drop-shadow(0 0 5px #00ffff); +} + +#message-input { + flex: 1; + padding: 8px; + border: 1px solid #00c6ff; + border-radius: 5px; + background-color: rgba(0, 0, 0, 0.4); + color: white; +} + +#message-input:disabled { + background-color: #444; +} diff --git a/gui/static/images/Normal.ico b/gui/static/images/Normal.ico new file mode 100644 index 0000000..995b9dc Binary files /dev/null and b/gui/static/images/Normal.ico differ diff --git a/gui/static/js/chat1.js b/gui/static/js/chat1.js new file mode 100644 index 0000000..90588e9 --- /dev/null +++ b/gui/static/js/chat1.js @@ -0,0 +1,495 @@ +// chat1.js +class FayInterface { + constructor(baseWsUrl, baseApiUrl, vueInstance) { + this.baseWsUrl = baseWsUrl; + this.baseApiUrl = baseApiUrl; + this.websocket = null; + this.vueInstance = vueInstance; + } + + connectWebSocket() { + if (this.websocket) { + this.websocket.onopen = null; + this.websocket.onmessage = null; + this.websocket.onclose = null; + this.websocket.onerror = null; + } + + this.websocket = new WebSocket(this.baseWsUrl); + + this.websocket.onopen = () => { + console.log('WebSocket connection opened'); + }; + + this.websocket.onmessage = (event) => { + const data = JSON.parse(event.data); + this.handleIncomingMessage(data); + }; + + this.websocket.onclose = () => { + console.log('WebSocket connection closed. Attempting to reconnect...'); + setTimeout(() => this.connectWebSocket(), 5000); + }; + + this.websocket.onerror = (error) => { + console.error('WebSocket error:', error); + }; + } + + async fetchData(url, options = {}) { + try { + const response = await fetch(url, options); + if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`); + return await response.json(); + } catch (error) { + console.error('Error fetching data:', error); + return null; + } + } + + getVoiceList() { + return this.fetchData(`${this.baseApiUrl}/api/get-voice-list`); + } + + getAudioDeviceList() { + return this.fetchData(`${this.baseApiUrl}/api/get-audio-device-list`); + } + + submitConfig(config) { + return this.fetchData(`${this.baseApiUrl}/api/submit`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ config }) + }); + } + + controlEyes(state) { + return this.fetchData(`${this.baseApiUrl}/api/control-eyes`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ state }) + }); + } + + startLive() { + return this.fetchData(`${this.baseApiUrl}/api/start-live`, { + method: 'POST' + }); + } + + stopLive() { + return this.fetchData(`${this.baseApiUrl}/api/stop-live`, { + method: 'POST' + }); + } + + getRunStatus() { + return this.fetchData(`${this.baseApiUrl}/api/get_run_status`, { + method: 'POST' + }); + } + + getMessageHistory(username) { + return new Promise((resolve, reject) => { + const url = `${this.baseApiUrl}/api/get-msg`; + const xhr = new XMLHttpRequest(); + xhr.open("POST", url); + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + const send_data = `data=${encodeURIComponent(JSON.stringify({ username }))}`; + xhr.send(send_data); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + try { + const data = JSON.parse(xhr.responseText); + if (data && data.list) { + const combinedList = data.list.flat(); + resolve(combinedList); + } else { + resolve([]); + } + } catch (e) { + console.error('Error parsing response:', e); + reject(e); + } + } else { + reject(new Error(`Request failed with status ${xhr.status}`)); + } + } + }; + }); + } + + getUserList() { + return this.fetchData(`${this.baseApiUrl}/api/get-member-list`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' } + }); + } + + getData() { + return this.fetchData(`${this.baseApiUrl}/api/get-data`, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + } + + getTime(){ + const date = new Date(); + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始,需要+1 + const day = date.getDate().toString().padStart(2, '0'); + const hours = date.getHours().toString().padStart(2, '0'); + const minutes = date.getMinutes().toString().padStart(2, '0'); + const seconds = date.getSeconds().toString().padStart(2, '0'); + const milliseconds = date.getMilliseconds().toString().padStart(3, '0'); + const currentDateTimeWithMs = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`; + return currentDateTimeWithMs + } + + handleIncomingMessage(data) { + const vueInstance = this.vueInstance; + // console.log('Incoming message:', data); + if (data.liveState !== undefined) { + vueInstance.liveState = data.liveState; + if (data.liveState === 1) { + vueInstance.configEditable = false; + } else if (data.liveState === 0) { + vueInstance.configEditable = true; + } + } + + if (data.voiceList !== undefined) { + vueInstance.voiceList = data.voiceList.map(voice => ({ + value: voice.id, + label: voice.name + })); + } + + if (data.deviceList !== undefined) { + vueInstance.deviceList = data.deviceList.map(device => ({ + value: device, + label: device + })); + } + + if (data.panelMsg !== undefined) { + vueInstance.panelMsg = data.panelMsg; + + } + if (data.robot) { + console.log(data.robot) + vueInstance.$set(vueInstance, 'robot', data.robot); + } + if (data.panelReply !== undefined) { + vueInstance.panelReply = data.panelReply.content; + const userExists = vueInstance.userList.some(user => user[1] === data.panelReply.username); + if (!userExists) { + vueInstance.userList.push([data.panelReply.uid, data.panelReply.username]); + } + if (vueInstance.selectedUser && data.panelReply.username === vueInstance.selectedUser[1]) { + vueInstance.messages.push({ + id: data.panelReply.id, + username: data.panelReply.username, + content: data.panelReply.content, + type: data.panelReply.type, + timetext: this.getTime(), + is_adopted:0 + }); + vueInstance.$nextTick(() => { + const chatContainer = vueInstance.$el.querySelector('#messages'); + if (chatContainer) { + chatContainer.scrollTop = chatContainer.scrollHeight; + } + }); + } + } + + if (data.is_connect !== undefined) { + vueInstance.isConnected = data.is_connect; + } + + if (data.remote_audio_connect !== undefined) { + vueInstance.remoteAudioConnected = data.remote_audio_connect; + } + } + } + + new Vue({ + + el: '#chat-app', + delimiters: ["[[", "]]"], + data() { + return { + messages: [], + newMessage: '', + fayService: null, + liveState: 0, + isConnected: false, + remoteAudioConnected: false, + userList: [], + selectedUser: null, + loading: false, + chatMessages: {}, + panelMsg: '', + panelReply: '', + robot:'static/images/Normal.gif', + base_url: 'http://127.0.0.1:5000', + play_sound_enabled: false, + source_record_enabled: false, + //后加的 + /*isRecording: false,*/ + status: '',// 用于显示“聆听中...”或“思考中...” + }; + }, + created() { + this.initFayService(); + this.getData(); + /*this.startLive();//启动聊天功能*/ + //后加的 + this.initSocket(); + }, + methods: { + // 初始化 WebSocket 连接 + initSocket() { + const socket = io.connect('http://localhost:5000'); // 请根据实际 WebSocket 地址替换 + socket.on('connect', () => { + this.status = '已连接'; + }); + socket.on('message', (data) => { + this.addMessage(data); + }); + socket.on('disconnect', () => { + this.status = '连接已断开'; + }); + }, + // 切换录音状态 + /*toggleRecording() { + this.isRecording = !this.isRecording; + },*/ + // 添加消息到消息列表 + addMessage(message) { + message.timetext = new Date().toLocaleTimeString(); + this.messages.push(message); + }, + // + //index.js原有的 + initFayService() { + this.fayService = new FayInterface('ws://127.0.0.1:10003', this.base_url, this); + this.fayService.connectWebSocket(); + this.fayService.websocket.addEventListener('open', () => { + this.loadUserList(); + }); + }, + sendMessage() { + let _this = this; + let text = _this.newMessage; + if (!text) { + alert('请输入内容'); + return; + } + if (_this.selectedUser === 'others' && !_this.othersUser) { + alert('请输入自定义用户名'); + return; + } + if (this.liveState != 1) { + alert('请先开启服务'); + return; + } + let usernameToSend = _this.selectedUser === 'others' ? _this.othersUser : _this.selectedUser[1]; + + this.timer = setTimeout(() => { + let height = document.querySelector('#messages').scrollHeight; + document.querySelector('#messages').scrollTop = height; + }, 1000);//1秒后滑动到聊天底部 + _this.newMessage = ''; + let url = `${this.base_url}/api/send`; + let send_data = { + "msg": text, + "username": usernameToSend + }; + + let xhr = new XMLHttpRequest(); + xhr.open("post", url); + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + xhr.send('data=' + encodeURIComponent(JSON.stringify(send_data))); + let executed = false; + xhr.onreadystatechange = async function () { + if (!executed && xhr.status === 200) { + executed = true; + } + }; + }, + getData() { + this.fayService.getRunStatus().then((data) => { + if (data) { + if(data.status){ + this.liveState = 1; + this.configEditable = false; + }else{ + this.liveState = 0; + this.configEditable = true; + } + + } + }); + this.fayService.getData().then((data) => { + if (data) { + this.updateConfigFromData(data.config); + } + }); + }, + updateConfigFromData(config) { + + if (config.interact) { + this.play_sound_enabled = config.interact.playSound; + } + if (config.source && config.source.record) { + this.source_record_enabled = config.source.record.enabled; + } + }, + saveConfig() { + let url = `${this.base_url}/api/submit`; + let send_data = { + "config": { + "source": { + "record": { + "enabled": this.source_record_enabled, + }, + }, + "interact": { + "playSound": this.play_sound_enabled, + } + } + }; + + let xhr = new XMLHttpRequest() + xhr.open("post", url) + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded") + xhr.send('data=' + JSON.stringify(send_data)) + let executed = false + xhr.onreadystatechange = async function () { + if (!executed && xhr.status === 200) { + try { + let data = await eval('(' + xhr.responseText + ')') + executed = true + } catch (e) { + } + } + } + }, + changeRecord(){ + if(this.source_record_enabled){ + this.source_record_enabled = false + }else{ + this.source_record_enabled = true + } + this.saveConfig() + }, + changeSound(){ + if(this.play_sound_enabled){ + this.play_sound_enabled = false + }else{ + this.play_sound_enabled = true + } + this.saveConfig() + }, + loadUserList() { + this.fayService.getUserList().then((response) => { + if (response && response.list) { + if (response.list.length == 0){ + info = []; + info[0] = 1; + info[1] = 'User'; + this.userList.push(info) + this.selectUser(info); + }else{ + this.userList = response.list; + this.selectUser(this.userList[0]); + } + } + }); + }, + selectUser(user) { + this.selectedUser = user; + this.fayService.websocket.send(JSON.stringify({ "Username": user[1] })); + this.loadMessageHistory(user[1], 'common'); + }, + startLive() { + this.liveState = 2 //把这个变量持久化到会话中,实现livestate=2时刷新浏览器不要重新执行此方法 + this.fayService.startLive().then(() => { + this.sendSuccessMsg('已开启!'); + this.getData(); + }); + }, + stopLive() { + this.fayService.stopLive().then(() => { + this.liveState = 3 + this.sendSuccessMsg('已关闭!'); + }); + }, + + loadMessageHistory(username, type) { + this.fayService.getMessageHistory(username).then((response) => { + if (response) { + this.messages = response; + if(type == 'common'){ + this.$nextTick(() => { + const chatContainer = this.$el.querySelector('#messages'); + if (chatContainer) { + chatContainer.scrollTop = chatContainer.scrollHeight; + } + }); + } + } + }); + }, + sendSuccessMsg(message) { + this.$notify({ + title: '成功', + message, + type: 'success', + }); + +} , +adoptText(id) { + // 调用采纳接口 + this.fayService.fetchData(`${this.base_url}/api/adopt_msg`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ id }) // 发送采纳请求 + }) + .then((response) => { + if (response && response.status === 'success') { + // 处理成功的响应 + this.$notify({ + title: '成功', + message: response.msg, // 显示成功消息 + type: 'success', + }); + + this.loadMessageHistory(this.selectedUser[1], 'adopt'); + } else { + // 处理失败的响应 + this.$notify({ + title: '失败', + message: response ? response.msg : '请求失败', + type: 'error', + }); + } + }) + .catch((error) => { + // 处理网络错误或HTTP错误 + this.$notify({ + title: '错误', + message: error.message || '请求失败', + type: 'error', + }); + }); +} +, + } + }); diff --git a/gui/static/js/index.js b/gui/static/js/index.js index 6e97143..ec39650 100644 --- a/gui/static/js/index.js +++ b/gui/static/js/index.js @@ -390,7 +390,7 @@ class FayInterface { this.liveState = 2 this.fayService.startLive().then(() => { this.sendSuccessMsg('已开启!'); - this.getData(); + this.fayService.getData(); }); }, stopLive() { diff --git a/gui/templates/chat.html b/gui/templates/chat.html index 38222cb..aa4a939 100644 --- a/gui/templates/chat.html +++ b/gui/templates/chat.html @@ -17,7 +17,6 @@
-