提示词调整

This commit is contained in:
RT15548
2026-01-01 14:45:24 +08:00
committed by GitHub
parent e00121e35d
commit 94ff286443
7 changed files with 859 additions and 132 deletions

View File

@@ -1,28 +1,99 @@
// ════════════════════════════════════════════════════════════════════════════
// 图片模块 - 缓存与生成
// 图片模块 - 缓存与生成(带队列)
// ════════════════════════════════════════════════════════════════════════════
const DB_NAME = 'xb_fourth_wall_images';
const DB_STORE = 'images';
const CACHE_TTL = 7 * 24 * 60 * 60 * 1000;
// 队列配置
const QUEUE_DELAY_MIN = 5000;
const QUEUE_DELAY_MAX = 10000;
let db = null;
/**
* 图片提示词指南 - 注入给 LLM
*/
export const IMG_GUIDELINE = `## 模拟图片
如果需要发图、照片给对方时,可以在聊天文本中穿插以下格式行,进行图片模拟:
[image: Subject, Appearance, Background, Atmosphere, Extra descriptors]
- tag必须为英文用逗号分隔使用Danbooru风格的tag5-15个tag
- 第一个tag须固定为人物数量标签如: 1girl, 1boy, 2girls, solo, etc.
- 可以多张照片: 每行一张 [image: ...]
- 当需要发送的内容尺度较大时加上nsfw相关tag
- image部分也需要在<msg>内`;
// ═══════════════════════════════════════════════════════════════════════════
// 生成队列(全局共享)
// ═══════════════════════════════════════════════════════════════════════════
// ════════════════════════════════════════════════════════════════════════════
// IndexedDB 操作
// ════════════════════════════════════════════════════════════════════════════
const generateQueue = [];
let isQueueProcessing = false;
function getRandomDelay() {
return QUEUE_DELAY_MIN + Math.random() * (QUEUE_DELAY_MAX - QUEUE_DELAY_MIN);
}
/**
* 将生成任务加入队列
* @returns {Promise<string>} base64 图片
*/
function enqueueGeneration(tags, onProgress) {
return new Promise((resolve, reject) => {
const position = generateQueue.length + 1;
onProgress?.('queued', position);
generateQueue.push({ tags, resolve, reject, onProgress });
processQueue();
});
}
async function processQueue() {
if (isQueueProcessing || generateQueue.length === 0) return;
isQueueProcessing = true;
while (generateQueue.length > 0) {
const { tags, resolve, reject, onProgress } = generateQueue.shift();
// 通知:开始生成
onProgress?.('generating', generateQueue.length);
try {
const base64 = await doGenerateImage(tags);
resolve(base64);
} catch (err) {
reject(err);
}
// 如果还有待处理的,等待冷却
if (generateQueue.length > 0) {
const delay = getRandomDelay();
// 通知所有排队中的任务
generateQueue.forEach((item, idx) => {
item.onProgress?.('waiting', idx + 1, delay);
});
await new Promise(r => setTimeout(r, delay));
}
}
isQueueProcessing = false;
}
/**
* 获取队列状态
*/
export function getQueueStatus() {
return {
pending: generateQueue.length,
isProcessing: isQueueProcessing
};
}
/**
* 清空队列
*/
export function clearQueue() {
while (generateQueue.length > 0) {
const { reject } = generateQueue.shift();
reject(new Error('队列已清空'));
}
}
// ═══════════════════════════════════════════════════════════════════════════
// IndexedDB 操作(保持不变)
// ═══════════════════════════════════════════════════════════════════════════
async function openDB() {
if (db) return db;
@@ -78,9 +149,6 @@ async function saveToCache(tags, base64) {
} catch {}
}
/**
* 清理过期缓存
*/
export async function clearExpiredCache() {
try {
const database = await openDB();
@@ -97,15 +165,67 @@ export async function clearExpiredCache() {
} catch {}
}
// ═══════════════════════════════════════════════════════════════════════════
// 图片请求处理
// ═══════════════════════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════════════════════
// 图片生成(内部函数,直接调用 NovelDraw
// ═══════════════════════════════════════════════════════════════════════════
async function doGenerateImage(tags) {
const novelDraw = window.xiaobaixNovelDraw;
if (!novelDraw) {
throw new Error('NovelDraw 模块未启用');
}
const settings = novelDraw.getSettings();
const paramsPreset = settings.paramsPresets?.find(p => p.id === settings.selectedParamsPresetId)
|| settings.paramsPresets?.[0];
if (!paramsPreset) {
throw new Error('无可用的参数预设');
}
const scene = [paramsPreset.positivePrefix, tags].filter(Boolean).join(', ');
const base64 = await novelDraw.generateNovelImage({
scene,
characterPrompts: [],
negativePrompt: paramsPreset.negativePrefix || '',
params: paramsPreset.params || {}
});
await saveToCache(tags, base64);
return base64;
}
// ═══════════════════════════════════════════════════════════════════════════
// 公开接口
// ═══════════════════════════════════════════════════════════════════════════
/**
* 处理缓存检查请求
* @param {Object} data - { requestId, tags }
* @param {Function} postToFrame - 发送消息到 iframe 的函数
* 检查缓存
*/
export async function checkImageCache(tags) {
return await getFromCache(tags);
}
/**
* 生成图片(自动排队)
* @param {string} tags - 图片标签
* @param {Function} [onProgress] - 进度回调 (status, position, delay?)
* @returns {Promise<string>} base64 图片
*/
export async function generateImage(tags, onProgress) {
// 先检查缓存
const cached = await getFromCache(tags);
if (cached) return cached;
// 加入队列生成
return enqueueGeneration(tags, onProgress);
}
// ═══════════════════════════════════════════════════════════════════════════
// postMessage 接口(用于 iframe
// ═══════════════════════════════════════════════════════════════════════════
export async function handleCheckCache(data, postToFrame) {
const { requestId, tags } = data;
@@ -123,11 +243,6 @@ export async function handleCheckCache(data, postToFrame) {
}
}
/**
* 处理图片生成请求
* @param {Object} data - { requestId, tags }
* @param {Function} postToFrame - 发送消息到 iframe 的函数
*/
export async function handleGenerate(data, postToFrame) {
const { requestId, tags } = data;
@@ -136,35 +251,30 @@ export async function handleGenerate(data, postToFrame) {
return;
}
const novelDraw = window.xiaobaixNovelDraw;
if (!novelDraw) {
postToFrame({ type: 'IMAGE_RESULT', requestId, error: 'NovelDraw 模块未启用' });
return;
}
try {
const settings = novelDraw.getSettings();
const paramsPreset = settings.paramsPresets?.find(p => p.id === settings.selectedParamsPresetId)
|| settings.paramsPresets?.[0];
if (!paramsPreset) {
postToFrame({ type: 'IMAGE_RESULT', requestId, error: '无可用的参数预设' });
return;
}
const scene = [paramsPreset.positivePrefix, tags].filter(Boolean).join(', ');
const base64 = await novelDraw.generateNovelImage({
scene,
characterPrompts: [],
negativePrompt: paramsPreset.negativePrefix || '',
params: paramsPreset.params || {}
// 使用队列生成,发送进度更新
const base64 = await generateImage(tags, (status, position, delay) => {
postToFrame({
type: 'IMAGE_PROGRESS',
requestId,
status,
position,
delay: delay ? Math.round(delay / 1000) : undefined
});
});
await saveToCache(tags, base64);
postToFrame({ type: 'IMAGE_RESULT', requestId, base64 });
} catch (e) {
postToFrame({ type: 'IMAGE_RESULT', requestId, error: e?.message || '生成失败' });
}
}
export const IMG_GUIDELINE = `## 模拟图片
如果需要发图、照片给对方时,可以在聊天文本中穿插以下格式行,进行图片模拟:
[image: Subject, Appearance, Background, Atmosphere, Extra descriptors]
- tag必须为英文用逗号分隔使用Danbooru风格的tag5-15个tag
- 第一个tag须固定为人物数量标签如: 1girl, 1boy, 2girls, solo, etc.
- 可以多张照片: 每行一张 [image: ...]
- 当需要发送的内容尺度较大时加上nsfw相关tag
- image部分也需要在<msg>内`;