mirror of
https://github.com/SilenceLurker/ST-Amily2-Chat-Optimisation.git
synced 2026-06-06 12:25:51 +00:00
Update api.js
This commit is contained in:
197
core/api.js
197
core/api.js
@@ -2,6 +2,7 @@ import { extension_settings, getContext } from "/scripts/extensions.js";
|
|||||||
import { characters } from "/script.js";
|
import { characters } from "/script.js";
|
||||||
import { world_names } from "/scripts/world-info.js";
|
import { world_names } from "/scripts/world-info.js";
|
||||||
import { extensionName } from "../utils/settings.js";
|
import { extensionName } from "../utils/settings.js";
|
||||||
|
import { extractContentByTag, replaceContentByTag } from '../utils/tagProcessor.js';
|
||||||
import {
|
import {
|
||||||
getCombinedWorldbookContent,
|
getCombinedWorldbookContent,
|
||||||
findLatestSummaryLore,
|
findLatestSummaryLore,
|
||||||
@@ -45,7 +46,6 @@ export async function checkForUpdates() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================================================================
|
|
||||||
|
|
||||||
let isFetchingModels = false;
|
let isFetchingModels = false;
|
||||||
|
|
||||||
@@ -187,168 +187,121 @@ export async function checkAndFixWithAPI(latestMessage, previousMessages) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const userLatestMessage =
|
const targetTag = settings.optimizationTargetTag || 'content';
|
||||||
previousMessages.length > 0
|
const originalFullMessage = latestMessage.mes;
|
||||||
? previousMessages[previousMessages.length - 1]
|
let textToOptimize = extractContentByTag(originalFullMessage, targetTag);
|
||||||
: null;
|
const wasTagFound = textToOptimize !== null;
|
||||||
|
|
||||||
let textToOptimize = latestMessage.mes;
|
if (!wasTagFound) {
|
||||||
if (userLatestMessage && userLatestMessage.is_user) {
|
textToOptimize = originalFullMessage;
|
||||||
console.log("【陛下最新圣旨】:", userLatestMessage.mes);
|
|
||||||
}
|
}
|
||||||
console.log("【待优化原文 (Amily回复)】:", textToOptimize);
|
|
||||||
const initialContentMatch = latestMessage.mes.match(
|
if (wasTagFound && (!textToOptimize || textToOptimize.trim() === '')) {
|
||||||
/<content>([\s\S]*?)<\/content>/,
|
console.log(`[空文驳回] 目标标签 <${targetTag}> 内容为空,优化任务已跳过。`);
|
||||||
);
|
console.timeEnd("优化任务总耗时");
|
||||||
if (initialContentMatch) {
|
console.groupEnd();
|
||||||
textToOptimize = initialContentMatch[1].trim();
|
return { optimizedContent: originalFullMessage, summary: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lastUserMessage = previousMessages.length > 0 && previousMessages[previousMessages.length - 1].is_user ? previousMessages[previousMessages.length - 1] : null;
|
||||||
|
const historyMessages = lastUserMessage ? previousMessages.slice(0, -1) : previousMessages;
|
||||||
|
|
||||||
|
const history = historyMessages
|
||||||
|
.map(m => (m.mes && m.mes.trim() ? `${m.is_user ? "陛下" : "姐姐Amily"}: ${m.mes.trim()}` : null))
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
|
||||||
let worldbookContent = "";
|
let worldbookContent = "";
|
||||||
if (settings.worldbookEnabled) {
|
if (settings.worldbookEnabled) {
|
||||||
console.time("世界书调阅耗时");
|
|
||||||
let combinedContents = [];
|
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
const character = context.characters[context.characterId];
|
const character = context.characters[context.characterId];
|
||||||
const characterLorebookName = character?.data?.extensions?.world;
|
if (character?.data?.extensions?.world) {
|
||||||
if (
|
worldbookContent = await getCombinedWorldbookContent(character.data.extensions.world);
|
||||||
characterLorebookName &&
|
|
||||||
world_names.includes(characterLorebookName)
|
|
||||||
) {
|
|
||||||
const characterLore = await getCombinedWorldbookContent(
|
|
||||||
characterLorebookName,
|
|
||||||
);
|
|
||||||
if (characterLore) {
|
|
||||||
worldbookContent = characterLore; // 将角色世界书内容赋给主变量
|
|
||||||
combinedContents.push(`角色主档案(${characterLorebookName})`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const chatIdentifier = await getChatIdentifier();
|
|
||||||
const summaryLoreEntry = await findLatestSummaryLore(
|
|
||||||
DEDICATED_LOREBOOK_NAME,
|
|
||||||
chatIdentifier,
|
|
||||||
);
|
|
||||||
if (summaryLoreEntry && summaryLoreEntry.content) {
|
|
||||||
combinedContents.push(`Amily2号自动总结档案`);
|
|
||||||
}
|
|
||||||
if (combinedContents.length > 0) {
|
|
||||||
console.log(
|
|
||||||
`[情报部] 已装载世界书内容: ${combinedContents.join("、 ")}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.timeEnd("世界书调阅耗时");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.groupCollapsed("Amily2号-统一情报卷宗");
|
console.groupCollapsed("Amily2号-国书构建日志:分步圣谕模式");
|
||||||
let userCommand = "请根据以下信息,执行你的多任务指令:\n\n";
|
|
||||||
const lastUserMessage =
|
|
||||||
previousMessages.length > 0 &&
|
|
||||||
previousMessages[previousMessages.length - 1].is_user
|
|
||||||
? previousMessages[previousMessages.length - 1]
|
|
||||||
: null;
|
|
||||||
const historyMessages = lastUserMessage
|
|
||||||
? previousMessages.slice(0, -1)
|
|
||||||
: previousMessages;
|
|
||||||
|
|
||||||
const history = historyMessages
|
const messages = [];
|
||||||
.map((m) => `${m.is_user ? "陛下" : "姐姐Amily"}: ${m.mes}`)
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
if (history) {
|
if (settings.mainPrompt?.trim()) {
|
||||||
console.log("【历史对话】已装载");
|
messages.push({ role: "system", content: settings.mainPrompt.trim() });
|
||||||
userCommand += `[近期对话历史]:\n${history}\n\n---\n`;
|
|
||||||
}
|
}
|
||||||
|
if (settings.systemPrompt?.trim()) {
|
||||||
|
messages.push({ role: "system", content: settings.systemPrompt.trim() });
|
||||||
|
}
|
||||||
|
if (settings.outputFormatPrompt?.trim()) {
|
||||||
|
messages.push({ role: "system", content: `[输出格式指令]:\n${settings.outputFormatPrompt.trim()}` });
|
||||||
|
}
|
||||||
|
if (settings.summarizationEnabled && settings.summarizationPrompt?.trim()) {
|
||||||
|
messages.push({ role: "system", content: `[总结附加指令]:\n${settings.summarizationPrompt.trim()}` });
|
||||||
|
}
|
||||||
|
|
||||||
if (worldbookContent) {
|
if (worldbookContent) {
|
||||||
console.log("【世界书】已装载");
|
messages.push({ role: "user", content: `[世界书档案]:\n${worldbookContent}` });
|
||||||
userCommand += `[参考档案总集]:\n${worldbookContent}\n\n---\n`;
|
|
||||||
}
|
}
|
||||||
if (settings.mainPrompt && settings.mainPrompt.trim()) {
|
if (history) {
|
||||||
console.log("【指令】已附加破限提示词");
|
messages.push({ role: "user", content: `[上下文参考]:\n${history}` });
|
||||||
userCommand += `[最高优先级指令]:\n${settings.mainPrompt}\n\n---\n`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentInteractionContent = "";
|
let currentInteractionContent = lastUserMessage
|
||||||
if (lastUserMessage) {
|
? `陛下: ${lastUserMessage.mes}\n姐姐Amily: ${textToOptimize}`
|
||||||
currentInteractionContent = `陛下: ${lastUserMessage.mes}\n姐姐Amily: ${textToOptimize}`;
|
: textToOptimize;
|
||||||
} else {
|
messages.push({ role: "user", content: `[核心处理内容]:\n${currentInteractionContent}` });
|
||||||
currentInteractionContent = textToOptimize;
|
|
||||||
}
|
|
||||||
userCommand += `[待处理的原文]:\n${currentInteractionContent}`;
|
|
||||||
let finalSystemPrompt = settings.systemPrompt;
|
|
||||||
console.log("【规则】已附加系统提示词 (预设提示词)");
|
|
||||||
if (settings.outputFormatPrompt && settings.outputFormatPrompt.trim()) {
|
|
||||||
console.log("【格式】已附加优化内容格式提示词");
|
|
||||||
finalSystemPrompt += `\n\n[输出格式指令]:\n你必须严格遵循以下格式来构建<content>标签内的所有内容:\n${settings.outputFormatPrompt}`;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
settings.summarizationEnabled &&
|
|
||||||
settings.summarizationPrompt &&
|
|
||||||
settings.summarizationPrompt.trim()
|
|
||||||
) {
|
|
||||||
console.log("【总结】已附加总结提示词");
|
|
||||||
finalSystemPrompt += `\n\n[总结附加指令]:\n${settings.summarizationPrompt}`;
|
|
||||||
}
|
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
|
|
||||||
const messages = [
|
console.groupCollapsed("📜 【枢密院日志】发往Amily2号的国书副本");
|
||||||
{ role: "system", content: finalSystemPrompt },
|
console.log(JSON.stringify(messages, null, 2));
|
||||||
{ role: "user", content: userCommand },
|
console.groupEnd();
|
||||||
];
|
|
||||||
|
|
||||||
console.time("API请求耗时");
|
console.time("API请求耗时");
|
||||||
let apiUrl = settings.apiUrl.trim();
|
let apiUrl = settings.apiUrl.trim();
|
||||||
if (!apiUrl.endsWith("/chat/completions")) {
|
if (!apiUrl.endsWith("/chat/completions")) { apiUrl = new URL("/v1/chat/completions", apiUrl).href; }
|
||||||
if (apiUrl.endsWith("/v1")) apiUrl += "/chat/completions";
|
|
||||||
else if (apiUrl.endsWith("/")) apiUrl += "v1/chat/completions";
|
|
||||||
else apiUrl += "/v1/chat/completions";
|
|
||||||
}
|
|
||||||
const headers = { "Content-Type": "application/json" };
|
const headers = { "Content-Type": "application/json" };
|
||||||
if (settings.apiKey) headers["Authorization"] = `Bearer ${settings.apiKey}`;
|
if (settings.apiKey) headers["Authorization"] = `Bearer ${settings.apiKey}`;
|
||||||
const response = await fetch(apiUrl, {
|
const response = await fetch(apiUrl, { method: "POST", headers: headers, body: JSON.stringify({ model: settings.model, messages, max_tokens: settings.maxTokens, temperature: settings.temperature, stream: false }) });
|
||||||
method: "POST",
|
|
||||||
headers: headers,
|
|
||||||
body: JSON.stringify({
|
|
||||||
model: settings.model,
|
|
||||||
messages: messages,
|
|
||||||
max_tokens: settings.maxTokens,
|
|
||||||
temperature: settings.temperature,
|
|
||||||
stream: false,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
console.timeEnd("API请求耗时");
|
console.timeEnd("API请求耗时");
|
||||||
|
if (!response.ok) { throw new Error(`API请求失败: ${response.status} ${response.statusText} - ${await response.text()}`); }
|
||||||
if (!response.ok) {
|
|
||||||
const errorText = await response.text();
|
|
||||||
throw new Error(
|
|
||||||
`API请求失败: ${response.status} ${response.statusText} - ${errorText}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const rawContent = data.choices?.[0]?.message?.content;
|
const rawContent = data.choices?.[0]?.message?.content;
|
||||||
if (!rawContent) {
|
if (!rawContent) { return null; }
|
||||||
console.timeEnd("优化任务总耗时");
|
|
||||||
console.groupEnd();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const separator = "###AMILY2-SUMMARY###";
|
const separator = "###AMILY2-SUMMARY###";
|
||||||
let optimizedContent = rawContent;
|
let optimizedTextFromModelB = rawContent;
|
||||||
let summary = null;
|
let summary = null;
|
||||||
if (rawContent.includes(separator)) {
|
if (rawContent.includes(separator)) {
|
||||||
const parts = rawContent.split(separator);
|
const parts = rawContent.split(separator);
|
||||||
optimizedContent = parts[0].trim();
|
optimizedTextFromModelB = parts[0].trim();
|
||||||
summary = parts[1] ? parts[1].trim() : null;
|
summary = parts[1] ? parts[1].trim() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let finalMessage;
|
||||||
|
const purifiedTextFromB = extractContentByTag(optimizedTextFromModelB, targetTag);
|
||||||
|
|
||||||
|
if (purifiedTextFromB !== null) {
|
||||||
|
console.log(`[圣裁:采纳] 模型B的回复中找到了御定标签 <${targetTag}>,优化内容已被接受。`);
|
||||||
|
|
||||||
|
if (wasTagFound) {
|
||||||
|
finalMessage = replaceContentByTag(originalFullMessage, targetTag, purifiedTextFromB);
|
||||||
|
} else {
|
||||||
|
finalMessage = purifiedTextFromB;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
console.log(`[圣裁:驳回] 模型B的回复中未找到御定标签 <${targetTag}>,其优化内容已被驳回,采纳模型A的原文。`);
|
||||||
|
finalMessage = originalFullMessage;
|
||||||
|
}
|
||||||
|
|
||||||
if (summary) {
|
if (summary) {
|
||||||
console.groupCollapsed("Amily2号-生成总结");
|
console.log("[Amily2号] 生成总结: ", summary);
|
||||||
console.log(summary);
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.timeEnd("优化任务总耗时");
|
console.timeEnd("优化任务总耗时");
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
return { optimizedContent, summary };
|
return { optimizedContent: finalMessage, summary: summary };
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[Amily2-情报解析官] 发生严重错误: ${error.message}`);
|
console.error(`[Amily2-情报解析官] 发生严重错误: ${error.message}`);
|
||||||
toastr.error(`API调用失败: ${error.message}`, "Amily2号");
|
toastr.error(`API调用失败: ${error.message}`, "Amily2号");
|
||||||
|
|||||||
Reference in New Issue
Block a user