Browse Source

替换agent

dev_des
1054425342@qq.com 1 month ago
parent
commit
3cc7deb10d
  1. BIN
      components/GPT/.DS_Store
  2. 25
      components/GPT/index.vue
  3. BIN
      components/GPT/utils/.DS_Store
  4. 247
      components/GPT/utils/audio2.js
  5. 37
      components/GPT/utils/pcm-player.js
  6. 13
      components/GPT/utils/util.js
  7. 15
      subPackages/other/ipPoster.vue

BIN
components/GPT/.DS_Store

Binary file not shown.

25
components/GPT/index.vue

@ -90,10 +90,8 @@
<script>
import Socket from './utils/socket'
import Audio from './utils/audio'
import PCMPlayer from './utils/pcm-player'
import { splitTextForTTS } from './utils/util'
import {
getHistroyMsg,
setMsgData
@ -404,6 +402,8 @@ export default {
}
this.player && this.player.destroy()
// this.audioOBJ.emit('send', txt)
// return
uni.request({
method: "post",
data: {
@ -636,6 +636,25 @@ export default {
this.recorderManager = null
},
inputSend() {
// const params = new FormData();
// params.append('tts_text', '使')
// params.append('spk_id', '')
// params.append('speed', '1.0')
// wx.uploadFile({
// url: 'http://110.42.225.206:8100/inference_sft_file',
// method: 'POST',
// // data: params,
// header: { 'content-type': 'multipart/form-data' },
// formData: {
// tts_text: '使',
// spk_id: '',
// speed: '1.0'
// },
// success: (res) => {
// console.log(111111, res)
// },
// })
// return
console.log('【inputSend------>】',);
this.onSendQuestion(this.inputValue)
this.scrollToBottom()
@ -767,7 +786,7 @@ export default {
flex-direction: column;
width: 100%;
height: 100%;
min-height: 700px;
min-height: 400px;
overflow: hidden;
background: #f8f8f8;
border-radius: 12px;

BIN
components/GPT/utils/.DS_Store

Binary file not shown.

247
components/GPT/utils/audio2.js

@ -0,0 +1,247 @@
// 心跳间隔
const HEART_BEAT_TIME = 15000;
// 心跳最大失败次数(超过此次数重连)
const HEART_BEAT_FAIL_NUM = 1;
// 重连间隔
const RECONNECT_TIME = 3000;
import { generateRequestId1 } from "./util";
export default class Audio {
constructor(option) {
this._options = option;
this.socket = null;
this.session_id = null;
this.selfCloseStatus = false
this.connectSocketTimeOut = null
this.appkey = 'hi93syrOZPxi7AZr';
this.token = '66df6ddcb4b643f08450cdf77d3de768';
}
getToken() {
return new Promise((resolve, reject) => {
console.log("-----开始请求token-----");
uni.request({
method: "GET",
dataType: "json",
// url: `http://192.168.124.118:8083/xcx/framework/agent/${this._options.agentId}`,
url: `https://des.js-dyyj.com/getDemoToken?id=${this._options.agentId}`,
success: (res) => {
console.log("请求token成功", res);
resolve(res);
},
fail: (err) => {
wx.showToast({
title: "创建失败",
icon: "none",
});
console.log("请求token失败", err);
reject();
},
});
});
}
async init() {
return this.createSocket();
}
async createSocket(options) {
console.log("开始创建socket", options);
return new Promise(async (resolve, reject) => {
const origin = `wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1?token=${this.token}`;
// 建立连接
const socket = wx.connectSocket({
url: `${origin}`,
binaryType: 'arraybuffer',
success: (e) => {
console.log("创建语音长链接成功", e);
},
complete: (e) => {
console.log("socket - complete", e);
},
});
this.socket = socket;
socket.onOpen((e) => {
console.log("socket.onOpen", e);
// 监听发送
options && options.complete && options.complete();
const socketParams = {
header: {
name: 'StartSynthesis',
appkey: this.appkey,
message_id: '1c17d4f8e7894a20aecb9f774b54ba06', //generateRequestId1(),
task_id: '1c17d4f8e7894a20aecb9f774b54ba06',//generateRequestId1(),
namespace: 'FlowingSpeechSynthesizer'
},
payload: {
voice: 'xiaoyun',
format: 'pcm',
sample_rate: 16000
}
};
this.send({ data: JSON.stringify(socketParams) }, 'txt');
});
socket.onMessage((e) => {
const { data } = e;
if (data instanceof ArrayBuffer) {
this._options.onMessage && this._options.onMessage(data);
} else {
if ( Object.prototype.toString.call(data) === "[object String]" ) {
const tmp = JSON.parse(data);
if (Object.prototype.toString.call(tmp.type) === "[object Number]") {
this._options.onMessage && this._options.onMessage(tmp);
} else {
if (!this.session_id) {
this.session_id = tmp.data
}
}
}
}
// this.on(type, e);
this.createInter();
resolve();
});
// 失败
socket.onError((e) => {
console.log("websocket error 创建语音长链接报错", e);
//
});
// 关闭
socket.onClose((e) => {
console.log("websocket close 语音长链接关闭", e);
this.connectSocketTimeOut && clearTimeout(this.connectSocketTimeOut);
//非自动关闭重连
if (e.code != 1000) {
this.doConnectTimeout();
}
});
});
}
doConnectTimeout() {
if (this.selfCloseStatus){
// 主动退出 不在重连
return
}
// 重连一次
console.log("websocket 异常关闭 开始重连");
this.connectSocketTimeOut = setTimeout(() => {
this.createSocket({
complete: function (res) {
// this.reconnectLock = false;
},
});
}, RECONNECT_TIME);
}
send(e, t) {
console.log("开始请求 websocket send", e);
this.socket && this.socket.send(e);
}
getMsgData(e) {
if (e && typeof e == "string") {
const status = e.indexOf("42");
const index = e.indexOf("[");
if (status > -1 && index > -1) {
const txt = e.substring(index);
const item = JSON.parse(txt);
const [type, obj] = item;
const payload = obj.payload ? obj.payload : {};
const params = {
chatId: this._options.agentId,
type,
contentType: "text", //默认文字
timestamp: new Date().getTime(),
...payload,
};
// 缓存聊天记录
return params;
}
}
return null;
}
emit(type, text, contentType) {
console.log("emit", type, text, generateRequestId1());
switch (type) {
case "send":
// 发送消息
// 发送消息
// const socketParams = {
// request_id: generateRequestId1()
// };
const socketParams = {
header: {
name: 'RunSynthesis',
appkey: this.appkey,
namespace: 'FlowingSpeechSynthesizer',
message_id: '1c17d4f8e7894a20aecb9f774b54ba06',
task_id: '1c17d4f8e7894a20aecb9f774b54ba06', // generateRequestId1(),
},
payload: {
text: text
}
// action: "ACTION_SYNTHESIS",
// data: text,
};
this.send({ data: JSON.stringify(socketParams) }, contentType);
break;
}
}
// 监听
on(type, params) {
switch (type) {
case "reply":
// 回复结束
const tmpParams = {
...params,
name: this.robotObj.name,
headImage: this.robotObj.headImage,
};
if (
params &&
params.type === "reply" &&
!params.is_from_self &&
params.can_rating
) {
// 回复消息
console.log("reply回复内容", tmpParams.content, tmpParams);
this._options.onMessage && this._options.onMessage(tmpParams);
}
if (!params.is_from_self && params.is_final) {
if (this.failMsg[tmpParams.request_id]) {
this.failMsg[tmpParams.request_id].status = true;
// 已回复 状态为true
}
// 回复结束 写入缓存
// setMsgData(tmpParams);
}
// 回复
break;
}
}
createInter() {
if (this.timeoutObj) {
clearTimeout(this.timeoutObj);
}
this.timeoutObj = setTimeout(() => {
console.log(111111, this.socket)
this.socket && this.socket.send && this.socket.send({ data: 3 });
}, HEART_BEAT_TIME);
}
// 关闭socket
destroy() {
if (this.socket && this.socket.readyState == 1) {
this.socket && this.socket.close();
this.socket = null;
}
}
}

37
components/GPT/utils/pcm-player.js

@ -4,26 +4,55 @@ export default class PcmPlayer {
this.audioCtx = null;
this.rate = this._options.rate ?? 16000;
this.ch = this._options.ch ?? 1;
this.samplesPerFrame = (16000 * 20) / 1000;
this.fadeMs = this._options.fadeMs ?? 20;
this.fadeSamples = (this.rate * this.fadeMs) / 1000;
this.queue = [];
this.isPlaying = false;
this.startTime = 0;
this._t = null;
this.AllTexts = [];
this.totalLen = 0
}
feed(data) {
if (!this.audioCtx) {
this.audioCtx = wx.createWebAudioContext();
}
this.queue.push(new Int16Array(data));
if (!this.isPlaying) this._play();
}
loadAudio = (url) => {
return new Promise((resolve) => {
wx.request({
url,
responseType: "arraybuffer",
success: (res) => {
console.log("res.data", res.data);
audioCtx.decodeAudioData(
res.data,
(buffer) => {
resolve(buffer);
},
(err) => {
console.error("decodeAudioData fail", err);
reject();
}
);
},
fail: (res) => {
console.error("request fail", res);
reject();
},
});
});
};
async _play() {
this.isPlaying = true;
if (!this.audioCtx) {
return
return;
}
// 开始播放
this.startTime = this.audioCtx.currentTime ?? 0;
@ -45,7 +74,7 @@ export default class PcmPlayer {
}
// 2. 帧边界淡入淡出(防不连续滋滋)
const fadeSamples = Math.min(80, len); // 5ms@16kHz
const fadeSamples = Math.min(this.fadeSamples, len); // 5ms@16kHz
const data = buf.getChannelData(0);
for (let j = 0; j < fadeSamples; j++) {
const gain = j / fadeSamples;
@ -69,7 +98,7 @@ export default class PcmPlayer {
syncLoop() {
const loop = () => {
if (!this.audioCtx) {
return
return;
}
const now = this.audioCtx.currentTime - this.startTime;
// 找当前字幕

13
components/GPT/utils/util.js

@ -53,6 +53,19 @@ export const arrayUnique = (arr, replaceKey, holdKey) => {
}, []);
};
export const generateRequestId1 = (length = 32) => {
const data =
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
let nums = '';
for (let i = 0; i < length; i++) {
const r = parseInt(Math.random() * 61, 10);
nums += data[r];
}
return nums //+ '-' + parseInt(Math.random() * 10000000000, 10);
};
export const generateRequestId = (length = 10) => {
const data =
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',

15
subPackages/other/ipPoster.vue

@ -14,9 +14,9 @@
<view class="" v-if="index==3">
<image class="bannerImg" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/4f5581b4-e354-4a2b-8f41-5d37fcd3904b.png"> </image>
<view class="action-box">
<image @click="toPath" class="action-img" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/df01e337-22bb-4056-8144-68f064b31323.png"> </image>
<image @click="toNone" class="action-img" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/e09bdd6f-bd6c-4845-a049-ccb1acc58924.png"> </image>
<image @click="toNone" class="action-img" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/11/19cca72c-b980-4a51-a855-1632a886bfc5.png"> </image>
<image @click="toPath" class="action-img" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/15/0f60d3fa-fe52-4b79-aeb5-22c707fc06b2.png"> </image>
<image @click="toNone" class="action-img" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/15/855a0a1a-0685-407a-b833-24f473308b00.png"> </image>
<image @click="toNone" class="action-img" mode="aspectFill" src="https://des.js-dyyj.com/data/2025/09/15/02d41295-048b-4523-a09f-0401df0381f9.png"> </image>
</view>
</view>
</view>
@ -79,14 +79,9 @@
}
.action-box{
position: absolute;
top: 0;
z-index: 9;
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
bottom: 170rpx;
left: 123rpx;
}
.action-img{

Loading…
Cancel
Save