perf: 优化轮询请求错误重试策略

This commit is contained in:
WJG 2024-06-14 09:29:01 +08:00
parent 4aed353487
commit 42d2e51b60
No known key found for this signature in database
GPG Key ID: 258474EF8590014A
4 changed files with 56 additions and 20 deletions

View File

@ -4,18 +4,19 @@
## ✨ 新功能
- ✅ 开放自定义 System Prompt 能力
- ✅ 新增自定义系统 Prompt 功能
- 登录凭证过期后自动刷新 token https://github.com/idootop/mi-gpt/issues/76
- 支持火山引擎 TTS 和音色切换能力(微软 TTS、OpenAI TTS 待定)
## 💪 优化
- 优化网络请求错误重试策略(消息/播放状态轮询)
- ✅ 优化网络请求错误重试策略(消息/播放状态轮询)
- 移除 TTS 不发音字符emoji
- 【待定】使用通知事件获取最新消息和设备播放状态
## 📚 文档
- ✅ 添加 System Prompt 模板字符串变量的说明
- ✅ 添加系统 Prompt 模板字符串变量的说明
- ✅ DAN 模式,猫娘等整活 prompt 的演示示例
- ✅ Awesome prompt 征集
- ✅ 添加更新人设 Prompt 的使用说明(你是 xxx你喜欢 xxx

View File

@ -9,6 +9,7 @@ import { clamp, jsonEncode, sleep } from "../../utils/base";
import { Logger } from "../../utils/log";
import { StreamResponse } from "./stream";
import { kAreYouOK } from "../../utils/string";
import { fastRetry } from "../../utils/retry";
export type TTSProvider = "xiaoai" | "doubao";
@ -337,24 +338,23 @@ export class BaseSpeaker {
// 等待一段时间,确保本地设备状态已更新
await sleep(this.checkTTSStatusAfter * 1000);
// 等待回答播放完毕
const retry = fastRetry(this, "设备状态");
while (true) {
// 检测设备播放状态
let playing: any = { status: "idle" };
if (this.playingCommand) {
const res = await this.MiIOT!.getProperty(
this.playingCommand[0],
this.playingCommand[1]
);
if (this.debug) {
this.logger.debug(jsonEncode({ playState: res ?? "undefined" }));
}
if (res === this.playingCommand[2]) {
playing = { status: "playing" };
}
} else {
const res = await this.MiNA!.getStatus();
if (this.debug) {
this.logger.debug(jsonEncode({ playState: res ?? "undefined" }));
}
let res = this.playingCommand
? await this.MiIOT!.getProperty(
this.playingCommand[0],
this.playingCommand[1]
)
: await this.MiNA!.getStatus();
if (this.debug) {
this.logger.debug(jsonEncode({ playState: res ?? "undefined" }));
}
if (this.playingCommand && res === this.playingCommand[2]) {
playing = { status: "playing" };
}
if (!this.playingCommand) {
playing = { ...playing, ...res };
}
if (
@ -365,7 +365,11 @@ export class BaseSpeaker {
// 响应被中断
return "break";
}
if (playing.status !== "playing") {
const isOk = retry.onResponse(res);
if (isOk === "break") {
break; // 获取设备状态异常
}
if (res && playing.status !== "playing") {
break;
}
await sleep(this.checkInterval);

View File

@ -1,4 +1,5 @@
import { clamp, firstOf, lastOf, sleep } from "../../utils/base";
import { fastRetry } from "../../utils/retry";
import { kAreYouOK } from "../../utils/string";
import { BaseSpeaker, BaseSpeakerConfig } from "./base";
import { StreamResponse } from "./stream";
@ -76,8 +77,13 @@ export class Speaker extends BaseSpeaker {
}
this.logger.success("服务已启动...");
this.activeKeepAliveMode();
const retry = fastRetry(this, "消息列表");
while (this.status === "running") {
const nextMsg = await this.fetchNextMessage();
const isOk = retry.onResponse(this._lastConversation);
if (isOk === "break") {
process.exit(1); // 退出应用
}
if (nextMsg) {
this.responding = false;
this.logger.log("🔥 " + nextMsg.text);
@ -275,6 +281,7 @@ export class Speaker extends BaseSpeaker {
}
}
private _lastConversation: any;
async getMessages(options?: {
limit?: number;
timestamp?: number;
@ -282,6 +289,7 @@ export class Speaker extends BaseSpeaker {
}): Promise<QueryMessage[]> {
const filterTTS = options?.filterTTS ?? true;
const conversation = await this.MiNA!.getConversations(options);
this._lastConversation = conversation;
let records = conversation?.records ?? [];
if (filterTTS) {
// 过滤有小爱回答的消息

23
src/utils/retry.ts Normal file
View File

@ -0,0 +1,23 @@
import { BaseSpeaker } from "../services/speaker/base";
export const fastRetry = (speaker: BaseSpeaker, tag: string, maxRetry = 10) => {
let failed = 0;
return {
onResponse(resp: any) {
if (resp == null) {
failed += 1;
if (failed > maxRetry) {
speaker.logger.error(`获取${tag}异常`);
return "break";
}
if (speaker.debug) {
speaker.logger.error(`获取${tag}失败,正在重试: ${failed}`);
}
return "retry";
} else {
failed = 0;
}
return "continue";
},
};
};