Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions src/AI/AI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,25 @@ export class AI {
await ai.context.addMessage(ctx, msg, ai, content, images, 'user', transformMsgId(msg.rawId));
}

async reply(ctx: seal.MsgContext, msg: seal.Message, contextArray: string[], replyArray: string[], images: Image[]) {
async reply(ctx: seal.MsgContext, msg: seal.Message, contextArray: string[], replyArray: string[], images: Image[], options: { withNonStreamDelay?: boolean } = {}) {
const { withNonStreamDelay = false } = options;
const { nonStreamSegmentDelayEnabled, nonStreamSegmentDelayMs, nonStreamSegmentImageExtraDelayMs } = ConfigManager.reply;

for (let i = 0; i < contextArray.length; i++) {
const content = contextArray[i];
const reply = replyArray[i];

// 非流式延迟
if (withNonStreamDelay && nonStreamSegmentDelayEnabled && i > 0) {
let delayMs = Math.max(0, nonStreamSegmentDelayMs);
if (/\[CQ:image(?:,[^\]]*)?\]/.test(reply)) {
delayMs += Math.max(0, nonStreamSegmentImageExtraDelayMs);
}
if (delayMs > 0) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}

const msgId = await replyToSender(ctx, msg, this, reply);
await this.context.addMessage(ctx, msg, this, content, images, 'assistant', msgId);
}
Expand Down Expand Up @@ -186,7 +201,7 @@ export class AI {
logger.info(`触发工具调用`);
// 先给他回复了再说
const { contextArray, replyArray, images } = result;
await this.reply(ctx, msg, contextArray, replyArray, images);
await this.reply(ctx, msg, contextArray, replyArray, images, { withNonStreamDelay: true });

await this.context.addMessage(ctx, msg, this, match[0], [], "assistant", '');
try {
Expand All @@ -202,7 +217,7 @@ export class AI {
logger.info(`触发工具调用`);
// 先给他回复了再说
const { contextArray, replyArray, images } = result;
await this.reply(ctx, msg, contextArray, replyArray, images);
await this.reply(ctx, msg, contextArray, replyArray, images, { withNonStreamDelay: true });

this.context.addToolCallsMessage(tool_calls);
try {
Expand Down Expand Up @@ -233,7 +248,7 @@ export class AI {
}

const { contextArray, replyArray, images } = result;
await this.reply(ctx, msg, contextArray, replyArray, images);
await this.reply(ctx, msg, contextArray, replyArray, images, { withNonStreamDelay: true });
AIManager.saveAI(this.id);
}

Expand Down Expand Up @@ -584,4 +599,4 @@ export class AIManager {

return usage;
}
}
}
8 changes: 7 additions & 1 deletion src/config/config_reply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export class ReplyConfig {
"\n{{{match.[1]}}}"
], "替换匹配到的文本,与上面正则表达式序号对应");
seal.ext.registerBoolConfig(ReplyConfig.ext, "回复文本是否去除首尾空白字符", true, "");
seal.ext.registerBoolConfig(ReplyConfig.ext, "非流式分段发送延时", true, "仅非流式生效,消息间隔是否开启延时防止乱序");
seal.ext.registerIntConfig(ReplyConfig.ext, "非流式分段发送基础延时/ms", 350, "仅非流式生效,从第二条消息开始每条发送前等待的毫秒数");
seal.ext.registerIntConfig(ReplyConfig.ext, "非流式分段发送含图额外延时/ms", 250, "仅非流式生效,当消息包含图片时额外增加的等待毫秒数");
}

static get() {
Expand All @@ -50,7 +53,10 @@ export class ReplyConfig {
filterRegexes: ConfigManager.getRegexesConfig(ReplyConfig.ext, "回复消息过滤正则表达式"),
contextTemplates: ConfigManager.getHandlebarsTemplatesConfig(ReplyConfig.ext, "正则处理上下文消息模板"),
replyTemplates: ConfigManager.getHandlebarsTemplatesConfig(ReplyConfig.ext, "正则处理回复消息模板"),
isTrim: seal.ext.getBoolConfig(ReplyConfig.ext, "回复文本是否去除首尾空白字符")
isTrim: seal.ext.getBoolConfig(ReplyConfig.ext, "回复文本是否去除首尾空白字符"),
nonStreamSegmentDelayEnabled: seal.ext.getBoolConfig(ReplyConfig.ext, "非流式分段发送延时"),
nonStreamSegmentDelayMs: seal.ext.getIntConfig(ReplyConfig.ext, "非流式分段发送基础延时/ms"),
nonStreamSegmentImageExtraDelayMs: seal.ext.getIntConfig(ReplyConfig.ext, "非流式分段发送含图额外延时/ms")
}
}
}