啊
This commit is contained in:
@@ -41,6 +41,10 @@ Output:
|
|||||||
userTemplate: `
|
userTemplate: `
|
||||||
这是你要配图的场景的背景知识设定(世界观/人设/场景设定),用于你理解背景:
|
这是你要配图的场景的背景知识设定(世界观/人设/场景设定),用于你理解背景:
|
||||||
<worldInfo>
|
<worldInfo>
|
||||||
|
用户设定:
|
||||||
|
{{persona}}
|
||||||
|
---
|
||||||
|
世界/场景:
|
||||||
{{description}}
|
{{description}}
|
||||||
---
|
---
|
||||||
{$worldInfo}
|
{$worldInfo}
|
||||||
@@ -206,92 +210,75 @@ export async function generateScenePlan(options) {
|
|||||||
presentCharacters = [],
|
presentCharacters = [],
|
||||||
llmApi = {},
|
llmApi = {},
|
||||||
useStream = false,
|
useStream = false,
|
||||||
useWorldInfo = false, // 新增:默认不使用世界书
|
useWorldInfo = false,
|
||||||
timeout = 120000
|
timeout = 120000
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
if (!messageText?.trim()) {
|
if (!messageText?.trim()) {
|
||||||
throw new LLMServiceError('消息内容为空', 'EMPTY_MESSAGE');
|
throw new LLMServiceError('消息内容为空', 'EMPTY_MESSAGE');
|
||||||
}
|
}
|
||||||
|
|
||||||
const charInfo = buildCharacterInfoForLLM(presentCharacters);
|
const charInfo = buildCharacterInfoForLLM(presentCharacters);
|
||||||
|
|
||||||
// msg1: systemPrompt (硬编码)
|
// msg1: systemPrompt
|
||||||
const msg1 = LLM_PROMPT_CONFIG.systemPrompt;
|
const msg1 = LLM_PROMPT_CONFIG.systemPrompt;
|
||||||
|
|
||||||
// msg2: assistantAck + TAG编写指南注入
|
// msg2: assistantAck + TAG编写指南
|
||||||
let msg2 = LLM_PROMPT_CONFIG.assistantAck;
|
let msg2 = LLM_PROMPT_CONFIG.assistantAck;
|
||||||
if (tagGuideContent) {
|
if (tagGuideContent) {
|
||||||
msg2 = msg2.replace('{$tagGuide}', tagGuideContent);
|
msg2 = msg2.replace('{$tagGuide}', tagGuideContent);
|
||||||
} else {
|
} else {
|
||||||
msg2 = msg2.replace(/我已查阅以下.*?\n\s*\{\$tagGuide\}\s*\n/g, '');
|
msg2 = msg2.replace(/我已查阅以下.*?\n\s*\{\$tagGuide\}\s*\n/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
// msg3: userTemplate
|
// msg3: userTemplate
|
||||||
let msg3 = LLM_PROMPT_CONFIG.userTemplate
|
let msg3 = LLM_PROMPT_CONFIG.userTemplate
|
||||||
.replace('{{lastMessage}}', messageText)
|
.replace('{{lastMessage}}', messageText)
|
||||||
.replace('{{characterInfo}}', charInfo);
|
.replace('{{characterInfo}}', charInfo);
|
||||||
|
|
||||||
// 根据 useWorldInfo 决定是否保留 {$worldInfo} 占位符
|
// 不用世界书时:只清空占位符
|
||||||
if (!useWorldInfo) {
|
if (!useWorldInfo) {
|
||||||
// 不使用世界书时,清空占位符
|
|
||||||
msg3 = msg3.replace(/\{\$worldInfo\}/gi, '');
|
msg3 = msg3.replace(/\{\$worldInfo\}/gi, '');
|
||||||
// 清理多余的空行和分隔线
|
|
||||||
msg3 = msg3.replace(/---\s*\n\s*(?=<\/worldInfo>)/g, '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// msg4: assistantPrefix
|
// msg4: assistantPrefix
|
||||||
const msg4 = LLM_PROMPT_CONFIG.assistantPrefix;
|
const msg4 = LLM_PROMPT_CONFIG.assistantPrefix;
|
||||||
|
|
||||||
const messages = [
|
// 只把 msg1+msg2 放到 top
|
||||||
|
const topMessages = [
|
||||||
{ role: 'user', content: msg1 },
|
{ role: 'user', content: msg1 },
|
||||||
{ role: 'assistant', content: msg2 },
|
{ role: 'assistant', content: msg2 },
|
||||||
{ role: 'user', content: msg3 },
|
|
||||||
{ role: 'assistant', content: msg4 }
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const streamingMod = getStreamingModule();
|
const streamingMod = getStreamingModule();
|
||||||
if (!streamingMod) {
|
if (!streamingMod) {
|
||||||
throw new LLMServiceError('xbgenraw 模块不可用', 'MODULE_UNAVAILABLE');
|
throw new LLMServiceError('xbgenraw 模块不可用', 'MODULE_UNAVAILABLE');
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
as: 'user',
|
as: 'user',
|
||||||
nonstream: useStream ? 'false' : 'true',
|
nonstream: useStream ? 'false' : 'true',
|
||||||
top64: b64UrlEncode(JSON.stringify(messages)),
|
top64: b64UrlEncode(JSON.stringify(topMessages)),
|
||||||
|
bottomassistant: msg4,
|
||||||
id: 'xb_nd_scene_plan'
|
id: 'xb_nd_scene_plan'
|
||||||
};
|
};
|
||||||
|
|
||||||
if (useWorldInfo) {
|
|
||||||
args.addon = 'worldInfo';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 渠道配置
|
|
||||||
const provider = String(llmApi.provider || '').toLowerCase();
|
|
||||||
const mappedApi = PROVIDER_MAP[provider];
|
|
||||||
if (mappedApi && provider !== 'st') {
|
|
||||||
args.api = mappedApi;
|
|
||||||
if (llmApi.url) args.apiurl = llmApi.url;
|
|
||||||
if (llmApi.key) args.apipassword = llmApi.key;
|
|
||||||
if (llmApi.model) args.model = llmApi.model;
|
|
||||||
}
|
|
||||||
|
|
||||||
let rawOutput;
|
let rawOutput;
|
||||||
try {
|
try {
|
||||||
if (useStream) {
|
if (useStream) {
|
||||||
const sessionId = await streamingMod.xbgenrawCommand(args, '');
|
const sessionId = await streamingMod.xbgenrawCommand(args, msg3);
|
||||||
rawOutput = await waitForStreamingComplete(sessionId, streamingMod, timeout);
|
rawOutput = await waitForStreamingComplete(sessionId, streamingMod, timeout);
|
||||||
} else {
|
} else {
|
||||||
rawOutput = await streamingMod.xbgenrawCommand(args, '');
|
rawOutput = await streamingMod.xbgenrawCommand(args, msg3);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new LLMServiceError(`LLM 调用失败: ${e.message}`, 'CALL_FAILED');
|
throw new LLMServiceError(`LLM 调用失败: ${e.message}`, 'CALL_FAILED');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.group('%c[LLM-Service] 场景分析输出', 'color: #d4a574; font-weight: bold');
|
console.group('%c[LLM-Service] 场景分析输出', 'color: #d4a574; font-weight: bold');
|
||||||
console.log(rawOutput);
|
console.log(rawOutput);
|
||||||
console.groupEnd();
|
console.groupEnd();
|
||||||
|
|
||||||
return rawOutput;
|
return rawOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user