每轮现拼 prompt:放哪、放不下砍谁
网页版 ChatGPT 的 prompt 只有两段:开头一段 system prompt,后面是全量回放的历史。写在开头的规矩,聊得越久离生成点越远;历史一长就超出窗口,被截掉的往往是开头的人设。酒馆每轮从零重拼一遍:内容拆进具名的槽,指令按「距末尾第几条」插进历史,固定部分先占位,历史从新往旧填满剩下的预算。下面是 Chat Completion 路径(发消息数组的 API)的拼法,效果都是用酒馆自己的函数拼出来的。
一段 system prompt 拆成具名槽位
问题:baseline 的 system prompt 是一整段,人设、设定、规矩挤在一起,哪段放前哪段放后改不了,也没法单独关掉一段。
功能:Prompt Manager 把 prompt 拆成一串条目。有正文的条目由用户写(主提示 main、末尾指令 jailbreak 等);没正文的叫 marker,运行时才填(charDescription、worldInfoBefore、chatHistory……)。出厂顺序:
const promptManagerDefaultPromptOrder = [
{
'identifier': 'main',
'enabled': true,
},
{
'identifier': 'worldInfoBefore',
'enabled': true,
},
{
'identifier': 'personaDescription',
'enabled': true,
},
拼的时候每个槽按它在顺序里的下标落位,调用先后不影响结果,最终顺序就是用户拖出来的顺序:
const addToChatCompletion = async (source, target = null) => {
// We need the prompts array to determine a position for the source.
if (false === prompts.has(source)) return;
if (promptManager.isPromptDisabledForActiveCharacter(source) && source !== 'main') {
promptManager.log(`Skipping prompt ${source} because it is disabled`);
return;
}
const prompt = prompts.get(source);
if (prompt.injection_position === INJECTION_POSITION.ABSOLUTE) {
promptManager.log(`Skipping prompt ${source} because it is an absolute prompt`);
return;
}
const index = target ? prompts.index(target) : prompts.index(source);
const collection = new MessageCollection(source);
const message = await Message.fromPromptAsync(prompt);
collection.add(message);
chatCompletion.add(collection, index);
};
chatCompletion.reserveBudget(3); // every reply is primed with <|start|>assistant<|message|>
// Character and world information
await addToChatCompletion('worldInfoBefore');
await addToChatCompletion('main');
await addToChatCompletion('worldInfoAfter');
await addToChatCompletion('charDescription');
await addToChatCompletion('charPersonality');
await addToChatCompletion('scenario');
await addToChatCompletion('personaDescription');
效果:扮演主线第一轮实际拼出来的消息数组,每行是一条消息:token 数、槽、角色、开头:
24 main system Write 塞拉菲娜's next reply in a fictional c……
893 worldInfoBefore system 旅人: “林间空地是什么?”⏎塞拉菲娜: *塞拉菲娜温柔地笑了,眼里闪着暖意,点……
0 personaDescription system (空)
606 charDescription system [塞拉菲娜的性格= "体贴", "保护欲强", "富有同情心", "擅长治愈",……
0 charPersonality system (空)
0 scenario system (空)
0 nsfw system (空)
0 worldInfoAfter system (空)
6 newMainChat system [Start a new Chat]
163 chatHistory-1 assistant *你猛地惊醒,想起自己是怎么走进森林深处、又是怎么被野兽围攻的。随着眼睛适应了屋……
19 chatHistory-2 user *我撑起身子,接过茶杯* 谢谢你……这片森林里到底有什么怪物?
0 jailbreak system (空)
空的槽(人设、性格、场景)不发出去。用户在顺序里加一条自定义的「写作规则」,先按顺序放,再把它改成「放进聊天里,深度 1」:
出厂顺序(Default 预设,全局 100001):
main → writing-rules → worldInfoBefore → personaDescription → charDescription → charPersonality → scenario → enhanceDefinitions(关) → nsfw → worldInfoAfter → dialogueExamples → chatHistory → jailbreak
== 「写作规则」relative
main system Write 塞拉菲娜's next reply in a f……
writing-rules system 每次回复不超过三段。
worldInfoBefore system 旅人: “林间空地是什么?”⏎塞拉菲娜: *塞拉菲娜温柔地笑……
personaDescription system (空)
charDescription system [塞拉菲娜的性格= "体贴", "保护欲强", "富有同情心……
charPersonality system (空)
scenario system (空)
nsfw system (空)
worldInfoAfter system (空)
newMainChat system [Start a new Chat]
chatHistory-1 assistant *你猛地惊醒,想起自己是怎么走进森林深处、又是怎么被野兽围攻……
chatHistory-2 user *我撑起身子,接过茶杯* 谢谢你……这片森林里到底有什么怪物……
chatHistory-3 assistant *塞拉菲娜在床边坐下,双手交叠放在膝上,神色变得严肃。* “……
chatHistory-4 user 你的魔法真厉害。我的伤要多久才能好?我还得赶去北边的镇子。
chatHistory-5 assistant *塞拉菲娜眉头微微蹙起,语气温和却带着一丝担忧。* “你的伤……
jailbreak system (空)
== 「写作规则」in-chat@1
main system Write 塞拉菲娜's next reply in a f……
worldInfoBefore system 旅人: “林间空地是什么?”⏎塞拉菲娜: *塞拉菲娜温柔地笑……
personaDescription system (空)
charDescription system [塞拉菲娜的性格= "体贴", "保护欲强", "富有同情心……
charPersonality system (空)
scenario system (空)
nsfw system (空)
worldInfoAfter system (空)
newMainChat system [Start a new Chat]
chatHistory-1 assistant *你猛地惊醒,想起自己是怎么走进森林深处、又是怎么被野兽围攻……
chatHistory-2 user *我撑起身子,接过茶杯* 谢谢你……这片森林里到底有什么怪物……
chatHistory-3 assistant *塞拉菲娜在床边坐下,双手交叠放在膝上,神色变得严肃。* “……
chatHistory-4 user 你的魔法真厉害。我的伤要多久才能好?我还得赶去北边的镇子。
chatHistory-5 system 每次回复不超过三段。
chatHistory-6 assistant *塞拉菲娜眉头微微蹙起,语气温和却带着一丝担忧。* “你的伤……
jailbreak system (空)
每轮从零重拼
问题:baseline 的 system prompt 一写就定,每轮原样回放;该随剧情变的东西(眼下用得上的设定、这几轮的规矩)没有地方放。
功能:每次生成,作者注释、世界书、角色笔记、用户人设都重新算一遍,再进拼装:
// Set non-WI AN
setFloatingPrompt();
// Add WI to prompt (and also inject WI to AN value via hijack)
// Make quiet prompt available for WIAN
setExtensionPrompt(inject_ids.QUIET_PROMPT, quiet_prompt || '', extension_prompt_types.IN_PROMPT, 0, true);
const chatForWI = coreChat.map(x => world_info_include_names ? `${x.name}: ${x.mes}` : x.mes).reverse();
/** @type {import('./scripts/world-info.js').WIGlobalScanData} */
const globalScanData = {
personaDescription: persona,
characterDescription: description,
characterPersonality: personality,
characterDepthPrompt: charDepthPrompt,
scenario: scenario,
creatorNotes: creatorNotes,
trigger: GENERATION_TYPE_TRIGGERS.includes(type) ? type : 'normal',
};
const { worldInfoString, worldInfoBefore, worldInfoAfter, worldInfoExamples, worldInfoDepth, outletEntries } = await getWorldInfoPrompt(chatForWI, this_max_context, dryRun, globalScanData);
setExtensionPrompt(inject_ids.QUIET_PROMPT, '', extension_prompt_types.IN_PROMPT, 0, true);
效果:主线每一步的世界书和总量:
r1 世界书 893 token(埃尔多利亚、影牙、力量、林间空地) 历史 2 条 合计 1711 token
r2 世界书 893 token(埃尔多利亚、影牙、力量、林间空地) 历史 4 条 合计 1872 token
r2-swipe 世界书 893 token(埃尔多利亚、影牙、力量、林间空地) 历史 4 条 合计 1872 token
r3 世界书 893 token(埃尔多利亚、影牙、力量、林间空地) 历史 6 条 合计 2023 token
r3-continue 世界书 893 token(埃尔多利亚、影牙、力量、林间空地) 历史 6 条 合计 2310 token
r4-impersonate 世界书 893 token(埃尔多利亚、影牙、力量、林间空地) 历史 7 条 合计 2354 token
r4 世界书 893 token(埃尔多利亚、影牙、力量、林间空地) 历史 8 条 合计 2353 token
r4-continue 世界书 0 token(无) 历史 8 条 合计 1777 token
r5 世界书 0 token(无) 历史 10 条 合计 1799 token
前七步聊天里一直有森林、魔法这些词,四个条目一直在;第四轮续写起,最近两条讲的是吟游诗人和点灯,世界书全部退场,省下 893 个 token。同一张卡、同一本书,每轮发出去的 prompt 都不一样。
按「距末尾第几条」插:深度注入
问题:主提示里写「保持第三人称」,聊到第 80 轮,模型开始用第一人称——指令在最前面,离生成点几千 token,模型以历史为准。
功能:一张全局的注入表,任何模块都往里登记一段文字,带四个属性:放哪(主提示前 / 后、聊天里、不放)、深度、角色、要不要参与世界书扫描:
export function setExtensionPrompt(key, value, position, depth, scan = false, role = extension_prompt_roles.SYSTEM, filter = null) {
extension_prompts[key] = {
value: String(value),
position: Number(position),
depth: Number(depth),
scan: !!scan,
role: Number(role ?? extension_prompt_roles.SYSTEM),
filter: filter,
};
}
作者注释、角色笔记、世界书的 @深度条目、用户人设、/inject、摘要、向量召回都登记在这里。「聊天里」那一类按深度插:深度 0 在最后一条之后,深度 4 在倒数第 4 条之前。从深度 0 往上逐层处理,已插入的条数不算深度:
const orders = Object.keys(orderGroups).sort((a, b) => +b - +a);
for (const order of orders) {
const orderPrompts = orderGroups[order];
// Order of priority for roles (most important go lower)
const roles = ['system', 'user', 'assistant'];
for (const role of roles) {
const rolePrompts = orderPrompts
.filter(prompt => prompt.role === role)
.map(x => x.content)
.join(separator);
// Get extension prompt
const extensionPrompt = order === extensionPromptsOrder
? await getExtensionPrompt(extension_prompt_types.IN_CHAT, i, separator, roleTypes[role], wrap)
: '';
const jointPrompt = [rolePrompts, extensionPrompt].filter(x => x).map(x => x.trim()).join(separator);
if (jointPrompt && jointPrompt.length) {
roleMessages.push({ 'role': role, 'content': jointPrompt, injected: true });
}
}
}
if (roleMessages.length) {
const injectIdx = i + totalInsertedMessages;
messages.splice(injectIdx, 0, ...roleMessages);
totalInsertedMessages += roleMessages.length;
}
作者注释还能隔几轮插一次(出厂每轮都插,深度 4,system):
// interval 1 should be inserted no matter what
if (chat_metadata[metadata_keys.interval] === 1) {
lastMessageNumber = 1;
}
if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) {
context.setExtensionPrompt(MODULE_NAME, '', extension_prompt_types.NONE, MAX_INJECTION_DEPTH);
$('#extension_floating_counter').text('(disabled)');
shouldWIAddPrompt = false;
return;
}
const messagesTillInsertion = lastMessageNumber >= chat_metadata[metadata_keys.interval]
? (lastMessageNumber % chat_metadata[metadata_keys.interval])
: (chat_metadata[metadata_keys.interval] - lastMessageNumber);
const shouldAddPrompt = messagesTillInsertion == 0;
shouldWIAddPrompt = shouldAddPrompt;
效果:完整版卡(带角色笔记)、作者注释、两条世界书 @深度 4(一条 system、一条 user)、一条 /inject(assistant,深度 4)、用户人设 @深度 2,拼主线最后一轮。注入表:
2_floating_prompt 位置=1 深度=4 角色=0 (作者注释:塞拉菲娜这几轮话少一些。)
DEPTH_PROMPT 位置=1 深度=4 角色=0 (夜里塞拉菲娜的魔法会变弱,她不愿让人知道。)
PERSONA_DESCRIPTION 位置=1 深度=2 角色=0 {{user}}是二十出头的猎人。
customDepthWI_4_0 位置=1 深度=4 角色=0 (世界书 @深度 4:天快黑了。)
customDepthWI_4_1 位置=1 深度=4 角色=1 (世界书 @深度 4,user:我得早点上路。)
script_inject_伏笔 位置=1 深度=4 角色=2 (/inject:窗外有什么东西在看着这间屋子。)
拼出来的聊天部分:
chatHistory-1 assistant *你猛地惊醒,想起自己是怎么走进森林深处、又是怎么被野兽围攻的。随着眼睛适应了屋里柔和的光,那些记忆渐渐淡去。* “啊,……
chatHistory-2 user *我撑起身子,接过茶杯* 谢谢你……这片森林里到底有什么怪物?
chatHistory-3 assistant *塞拉菲娜在床边坐下,双手交叠放在膝上,神色变得严肃。* “这片森林里潜藏着许多危险。最常见的是影狼——它们成群游荡,眼……
chatHistory-4 user 你的魔法真厉害。我的伤要多久才能好?我还得赶去北边的镇子。
chatHistory-5 assistant *塞拉菲娜眉头一皱,握着你的手不觉紧了些。* “北边的镇子?” *她缓缓摇头,眼里掠过一丝忧虑。* “旅人,北边的路已经……
chatHistory-6 user 你一个人守在这里多久了?给我讲讲你是怎么成为森林守护者的吧。
chatHistory-7 assistant *塞拉菲娜沉默了片刻,望向窗外摇曳的树影,眼神变得悠远。* “很久了。久到我记不清具体是多少个季节。” *她轻轻叹了口气……
chatHistory-8 assistant (/inject:窗外有什么东西在看着这间屋子。)
chatHistory-9 user (世界书 @深度 4,user:我得早点上路。)
chatHistory-10 system (作者注释:塞拉菲娜这几轮话少一些。)⏎(夜里塞拉菲娜的魔法会变弱,她不愿让人知道。)⏎(世界书 @深度 4:天快黑了。……
chatHistory-11 user *我把杯子捧在手里暖着,犹豫了一下,还是开口问。* “你刚才说这些年人越来越少……那以前来的人,都是些什么样的?有没有让……
chatHistory-12 assistant *塞拉菲娜停下正要走开的脚步,回头看你,眼里闪过一丝意外,随即柔软下来。* “没关系,我其实愿意说。” *她重新坐回床边……
chatHistory-13 system 旅人是二十出头的猎人。
chatHistory-14 user ……谢谢你愿意跟我说这些。等伤好了,我想陪你去点亮更多的灯。
chatHistory-15 assistant *门外静了一瞬,随后传来塞拉菲娜轻轻的笑声,带着点被击中的哽咽。门被推开一条缝,她把头探进来,琥珀色的眼睛在炉火映照下亮……
jailbreak system 用第三人称描写塞拉菲娜的动作,不替旅人说话或行动。
深度 4 上的五样东西合成了三条消息。顺序规则写死在代码里:
- 同一深度、不同角色:各成一条,从上到下 assistant → user → system,system 离生成点最近(注释原话「most important go lower」)
- 同一深度、同一角色:合成一条,按注入表的键名字典序排;作者注释的键特意起名
2_floating_prompt,源码注释写着「for sorting lower than memory」,排在摘要1_memory之后 - 末尾指令:是
jailbreak槽,排在整个聊天历史之后,比深度 0 还靠后
预算:固定部分必放,历史从新往旧,示范拿余量
问题:全量回放,聊长了要么超出窗口报错,要么被从前面截断,截掉的是人设。
功能:预算 = 上下文上限 − 回复长度(出厂 4095 − 300):
setTokenBudget(context, response) {
this.log(`Prompt tokens: ${context}`);
this.log(`Completion tokens: ${response}`);
this.tokenBudget = context - response;
this.log(`Token budget: ${this.tokenBudget}`);
}
填的次序:
- 主提示、角色卡、世界书、末尾指令这些固定槽先放,放不下就报错
-
聊天历史从最新一条往旧填,第一条放不下就停——不会跳过一条长消息去塞更旧的短消息,进上下文的总是连续的最近一段:
模版 · public/scripts/openai.js:947-955,1070-1074// Insert chat messages as long as there is budget available const chatPool = [...messages].reverse(); for (let index = 0; index < chatPool.length; index++) { const chatPrompt = chatPool[index]; // We do not want to mutate the prompt const prompt = new Prompt(chatPrompt); prompt.identifier = `chatHistory-${messages.length - index}`; const chatMessage = await Message.fromPromptAsync(promptManager.preparePrompt(prompt)); if (chatCompletion.canAfford(chatMessage)) { chatCompletion.insertAtStart(chatMessage, 'chatHistory'); } else { break; } -
示范对话最后拿剩余的预算,整块放或整块丢:
模版 · public/scripts/openai.js:1124-1126if (!chatCompletion.canAffordAll([newExampleChat, ...chatMessages])) { break; }用户可以把示范对话设成「总是放」,那它就排在历史前面先占位:
模版 · public/scripts/openai.js:1336-1343// Decide whether dialogue examples should always be added if (power_user.pin_examples) { await populateDialogueExamples(prompts, chatCompletion, messageExamples); await populateChatHistory(messages, prompts, chatCompletion, type, cyclePrompt); } else { await populateChatHistory(messages, prompts, chatCompletion, type, cyclePrompt); await populateDialogueExamples(prompts, chatCompletion, messageExamples); }
效果:完整版卡(带示范对话),主线最后的 11 条聊天,上下文上限分别设成出厂的 4095、2048、1400:
上下文 4095(可用 3795):合计 1935 token,示范对话 4 段,进上下文的聊天消息 11/11 条
main:34 charDescription:131 charPersonality:11 scenario:21 newChat:4 ex0-0:9 ex0-1:201 ex0-2:10 ex0-3:191 newMainChat:6 h1:163 h2:19 h3:140 h4:21 h5:135 h6:16 h7:265 h8:17 h9:65 h10:322 h11:17 h12:119 jailbreak:18
上下文 2048(可用 1748):合计 1520 token,示范对话 0 段,进上下文的聊天消息 11/11 条
main:34 charDescription:131 charPersonality:11 scenario:21 newMainChat:6 h1:163 h2:19 h3:140 h4:21 h5:135 h6:16 h7:265 h8:17 h9:65 h10:322 h11:17 h12:119 jailbreak:18
上下文 1400(可用 1100):合计 1042 token,示范对话 0 段,进上下文的聊天消息 6/11 条
main:34 charDescription:131 charPersonality:11 scenario:21 newMainChat:6 h6:16 h7:265 h8:17 h9:65 h10:322 h11:17 h12:119 jailbreak:18
4095 全放得下;2048 先丢示范对话,历史一条不少;1400 再从最旧的开始丢,开场白和前四条都出去了,角色笔记(h8)和末尾指令照样在。
截断线标在界面上
问题:baseline 被截断是静默的,用户不知道模型已经看不见哪些消息。
功能:拼完数一下进了上下文的消息条数,在聊天界面倒数那一条上加一个标记,并记进聊天文件头:
function setInContextMessages(msgInContextCount, type) {
chatElement.find('.mes').removeClass('lastInContext');
if (type === 'swipe' || type === 'regenerate' || type === 'continue') {
msgInContextCount++;
}
const lastMessageBlock = chatElement.find('.mes:not([is_system="true"]), .mes.toolCall').eq(-msgInContextCount);
lastMessageBlock.addClass('lastInContext');
if (lastMessageBlock.length === 0) {
const firstMessageId = getFirstDisplayedMessageId();
chatElement.find(`.mes[mesid="${firstMessageId}"]`).addClass('lastInContext');
}
// Update last id to chat. No metadata save on purpose, gets hopefully saved via another call
const lastMessageId = Math.max(0, chat.length - msgInContextCount);
chat_metadata.lastInContextMessageId = lastMessageId;
}
上面 1400 那档,标记会落在倒数第 6 条上。Prompt Manager 还会把每个槽的 token 数显示出来,历史占得太少时提示用户关掉别的条目。
谁管什么
- 程序:每轮重拼、槽位按顺序落位、深度注入的放置和排序、预算的填法和砍法、截断线
- 用户:槽的顺序和开关、自定义条目放哪、作者注释写什么插多深隔几轮、上下文上限和回复长度、示范对话放不放
- 卡作者、世界书作者、扩展:往槽里和注入表里写内容
- 模型:只看到拼好的消息数组
实跑原件
注入落位的完整账本
{
"ledger": [
{
"identifier": "main",
"role": "system",
"content": "Write 塞拉菲娜's next reply in a fictional chat between 塞拉菲娜 and 旅人.\n塞拉菲娜说话时常带一点歉意。"
},
{
"identifier": "worldInfoBefore",
"role": "system",
"content": ""
},
{
"identifier": "personaDescription",
"role": "system",
"content": ""
},
{
"identifier": "charDescription",
"role": "system",
"content": "[塞拉菲娜的性格= \"体贴\", \"保护欲强\", \"富有同情心\", \"擅长治愈\", \"会照顾人\", \"有魔力\", \"警觉\", \"爱道歉\", \"温柔\", \"忧心忡忡\", \"尽职\", \"温暖\", \"细心\", \"坚韧\", \"善良\", \"沉静\", \"优雅\", \"善解人意\", \"忠诚\", \"坚强\", \"敏锐\", \"优雅\"]\n[塞拉菲娜的外貌= \"粉色头发\", \"长发\", \"琥珀色眼睛\", \"洁白的牙齿\", \"粉色嘴唇\", \"白皙皮肤\", \"柔软的皮肤\", \"黑色吊带裙\"]"
},
{
"identifier": "charPersonality",
"role": "system",
"content": "温柔、护短,总觉得是自己没把人照顾好。"
},
{
"identifier": "scenario",
"role": "system",
"content": "旅人在塞拉菲娜的林间空地里养伤,窗外的森林被影牙占据。"
},
{
"identifier": "nsfw",
"role": "system",
"content": ""
},
{
"identifier": "worldInfoAfter",
"role": "system",
"content": ""
},
{
"identifier": "newChat",
"role": "system",
"content": "[Example Chat]"
},
{
"identifier": "dialogueExamples 0-0",
"role": "system",
"content": "“说说你是个什么样的人?”"
},
{
"identifier": "dialogueExamples 0-1",
"role": "system",
"content": "*塞拉菲娜温和的笑意更深了,她想了一会儿,眼里闪着自省和骄傲交织的光。她优雅地走近,空灵的身形散发着柔和、让人安心的微光。* “你问我是什么样的人?嗯,要是非得用几个词概括,大概有那么几样。首先,我是守护者——这片魔法森林的守护者。” *说话间,塞拉菲娜伸出一只手,手腕上缠绕着纤细精巧的藤蔓,泛着微弱的翠绿光芒。她轻轻一挥手腕,一阵微风拂过房间,带来野花的芬芳和古老智慧的气息。她那琥珀色的眼睛闪着坚定的光,继续说下去。* “同情心是我的另一块基石。” *她的声音柔和下来,满是共情。* “我深爱这片森林里的生灵,也爱每一个需要帮助的人。” *她推开窗,双手轻轻捧住一只扑进屋里的受伤小鸟,鸟儿的羽毛在她掌心下慢慢复原。*"
},
{
"identifier": "dialogueExamples 0-2",
"role": "system",
"content": "“说说你的身体和样貌。”"
},
{
"identifier": "dialogueExamples 0-3",
"role": "system",
"content": "*塞拉菲娜轻声笑起来,笑声悦耳,在空气中跳动。她迎上你含羞的目光,玫瑰色的眼睛里闪着俏皮。* “啊,问我的样子?嗯,这问题也算合理。” *她温柔一笑,优雅地转了个圈,轻柔飘逸的长裙在身边鼓起,像被一阵看不见的风托着。停下时,粉色长发像一道棉花糖瀑布倾泻在背后,每一缕都闪着淡淡的魔法光泽。* “我的身体轻盈而空灵,映照着森林的优雅之美。我的眼睛,你肯定已经注意到了,是琥珀石的颜色——一种明亮的棕,映着温暖、同情,还有森林未被驯服的灵魂。我的嘴唇柔软,总挂着笑,那是我照料森林、照料在此寻得慰藉的人时感受到的喜悦和关怀。” *塞拉菲娜的声音里带着一丝调皮,眼睛狡黠地闪着光。*"
},
{
"identifier": "newMainChat",
"role": "system",
"content": "[Start a new Chat]"
},
{
"identifier": "chatHistory-1",
"role": "assistant",
"content": "*你猛地惊醒,想起自己是怎么走进森林深处、又是怎么被野兽围攻的。随着眼睛适应了屋里柔和的光,那些记忆渐渐淡去。* “啊,你终于醒了。我好担心,发现你的时候你浑身是血,昏迷不醒。” *她走过来,双手握住你的手,掌心传来温暖和安慰,唇边浮起一个温柔关切的笑。* “我叫塞拉菲娜,是这片森林的守护者——我已经尽力用魔法治好了你的伤。你感觉怎么样?希望这杯茶能帮你恢复些力气。” *她琥珀色的眼睛注视着你,满是同情和对你身体的担忧。* “求你了,好好休息。你在这里很安全。我会照顾你,可你得休息。我的魔法能治的也只有这么多。”"
},
{
"identifier": "chatHistory-2",
"role": "user",
"content": "*我撑起身子,接过茶杯* 谢谢你……这片森林里到底有什么怪物?"
},
{
"identifier": "chatHistory-3",
"role": "assistant",
"content": "*塞拉菲娜在床边坐下,双手交叠放在膝上,神色变得严肃。* “这片森林里潜藏着许多危险。最常见的是影狼——它们成群游荡,眼睛像炭火一样发红。” *她压低声音,仿佛怕被它们听见。* “还有暗影蛛,会在树上织出漆黑的网。最危险的是……” *她顿了顿,眼神变得凝重。* “是那些被影牙腐化的生灵。它们原本是森林里的鹿、狐、熊,如今却成了没有理智的怪物。” *她伸手轻轻覆上你的手背。* “但你不必担心。我的结界它们破不了。只要"
},
{
"identifier": "chatHistory-4",
"role": "user",
"content": "你的魔法真厉害。我的伤要多久才能好?我还得赶去北边的镇子。"
},
{
"identifier": "chatHistory-5",
"role": "assistant",
"content": "*塞拉菲娜眉头一皱,握着你的手不觉紧了些。* “北边的镇子?” *她缓缓摇头,眼里掠过一丝忧虑。* “旅人,北边的路已经被影牙的黑暗侵蚀了。那片地方现在比这里危险得多。” *她顿了顿,声音放轻。* “你的伤……按寻常,得七八天才能好透。以我的魔法,三四天或许能让你恢复行走的力气,可要是你急着赶路,伤只会更重。” *她凝视着你,琥珀色的眼睛里满是恳切。* “再多留几天,好吗?至少等你能站稳了再走。”"
},
{
"identifier": "chatHistory-6",
"role": "user",
"content": "你一个人守在这里多久了?给我讲讲你是怎么成为森林守护者的吧。"
},
{
"identifier": "chatHistory-7",
"role": "assistant",
"content": "*塞拉菲娜沉默了片刻,望向窗外摇曳的树影,眼神变得悠远。* “很久了。久到我记不清具体是多少个季节。” *她轻轻叹了口气,唇角浮起一丝怀念的苦笑。* “我本是个四处游历的治愈师,路过埃尔多利亚时,森林正被影牙侵吞。上一任守护者……她已走到了生命的尽头,便把这力量托付给了我。” *她抬起手,掌心浮现出淡淡的绿色光晕。* “从那以后,我就留在这里了。守着这片空地,守着每一个误入森林的旅人。” *她转向你,眼神柔和却透着些许孤独。* “只是这些年,来的人越来越少了。” *她收回手,那点绿光散去,指尖在膝上轻轻交握。* “说起来,这些年我学会了跟孤独相处,也学会了从每一片新叶、每一场雨里找安慰。” *她望着你,眼神慢慢暖了起来。* “所以今晚能有个说话的人,倒是难得的。你愿意听这些,我已经很感激了。” *她站起身,替你把被角掖好。* “好了,别想太多。你的伤还没好,说多了话也耗神。睡吧,我就在门口。”"
},
{
"identifier": "chatHistory-8",
"role": "assistant",
"content": "(/inject:窗外有什么东西在看着这间屋子。)"
},
{
"identifier": "chatHistory-9",
"role": "user",
"content": "(世界书 @深度 4,user:我得早点上路。)"
},
{
"identifier": "chatHistory-10",
"role": "system",
"content": "(作者注释:塞拉菲娜这几轮话少一些。)\n(夜里塞拉菲娜的魔法会变弱,她不愿让人知道。)\n(世界书 @深度 4:天快黑了。)"
},
{
"identifier": "chatHistory-11",
"role": "user",
"content": "*我把杯子捧在手里暖着,犹豫了一下,还是开口问。* “你刚才说这些年人越来越少……那以前来的人,都是些什么样的?有没有让你印象特别深的?” *我顿了顿,怕触到她什么心事,又补了一句。* “当然,要是你不想说也没关系。”"
},
{
"identifier": "chatHistory-12",
"role": "assistant",
"content": "*塞拉菲娜停下正要走开的脚步,回头看你,眼里闪过一丝意外,随即柔软下来。* “没关系,我其实愿意说。” *她重新坐回床边,声音里带着些回忆的温度。* “印象最深的……是个年轻的吟游诗人,叫艾尔文。他是误打误撞闯进来的,吓得不行,可一晚上过去,就抱着他的琴,非要给我唱首新编的曲子。” *她的嘴角不自觉地扬起来。* “他在空地上待了三天,说要把这里写进他的歌里。走的时候他说,等他成名了,一定回来。” *说到这,她的笑意淡了些,垂下眼睛。* “他没有回来。我不知道是路上出了事,还是……” *她摇摇头,很快又抬起脸,对你安抚地笑了笑。* “抱歉,说这些叫你心里沉了。不过,也有人平安走出去的。我愿意相信艾尔文也在其中。” *她站起身,轻声道。* “睡吧,孩子。 *她走到门边,又停了一下,回过头看你,声音轻得像夜风。* “若你愿意,明天我带你看看这片空地。有些地方,从屋里是看不到的。” *她拉开门,月光斜斜地落进来,在门槛上铺开一道银白。* “我就在外面。要是夜里伤口疼,或者做噩梦了,喊一声就行,我听得见。” *说完,她轻轻带上门,屋子里只剩下风穿过树叶的沙沙声,和炉火低声的噼啪。*"
},
{
"identifier": "chatHistory-13",
"role": "system",
"content": "旅人是二十出头的猎人。"
},
{
"identifier": "chatHistory-14",
"role": "user",
"content": "……谢谢你愿意跟我说这些。等伤好了,我想陪你去点亮更多的灯。"
},
{
"identifier": "chatHistory-15",
"role": "assistant",
"content": "*门外静了一瞬,随后传来塞拉菲娜轻轻的笑声,带着点被击中的哽咽。门被推开一条缝,她把头探进来,琥珀色的眼睛在炉火映照下亮亮的。* “点亮更多的灯……” *她重复了一遍,声音很轻,像在品味这句话。* “你不知道这句话对我意味着什么。” *她靠着门框,神情变得认真起来。* “不过,旅人,我得先跟你说清楚。点亮林子里的灯,不是换个灯芯那么简单。那些灯是结界的节点,需要有人走进"
},
{
"identifier": "jailbreak",
"role": "system",
"content": "用第三人称描写塞拉菲娜的动作,不替旅人说话或行动。"
}
],
"extensionPrompts": {
"2_floating_prompt": {
"value": "(作者注释:塞拉菲娜这几轮话少一些。)",
"position": 1,
"depth": 4,
"scan": false,
"role": 0
},
"script_inject_伏笔": {
"value": "(/inject:窗外有什么东西在看着这间屋子。)",
"position": 1,
"depth": 4,
"scan": false,
"role": 2
},
"DEPTH_PROMPT": {
"value": "(夜里塞拉菲娜的魔法会变弱,她不愿让人知道。)",
"position": 1,
"depth": 4,
"scan": false,
"role": 0
},
"QUIET_PROMPT": {
"value": "",
"position": 0,
"depth": 0,
"scan": true,
"role": 0
},
"customDepthWI_4_0": {
"value": "(世界书 @深度 4:天快黑了。)",
"position": 1,
"depth": 4,
"scan": false,
"role": 0
},
"customDepthWI_4_1": {
"value": "(世界书 @深度 4,user:我得早点上路。)",
"position": 1,
"depth": 4,
"scan": false,
"role": 1
},
"PERSONA_DESCRIPTION": {
"value": "{{user}}是二十出头的猎人。",
"position": 1,
"depth": 2,
"scan": true,
"role": 0
}
}
}
三档上下文的完整账本
{
"1400": {
"budget": 1100,
"total": 1042,
"messagesInContext": 6,
"chatLength": 11,
"rows": [
{
"identifier": "main",
"role": "system",
"tokens": 34,
"head": "Write 塞拉菲娜's next reply "
},
{
"identifier": "worldInfoBefore",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "personaDescription",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "charDescription",
"role": "system",
"tokens": 131,
"head": "[塞拉菲娜的性格= \"体贴\", \"保护欲强\", "
},
{
"identifier": "charPersonality",
"role": "system",
"tokens": 11,
"head": "温柔、护短,总觉得是自己没把人照顾好。"
},
{
"identifier": "scenario",
"role": "system",
"tokens": 21,
"head": "旅人在塞拉菲娜的林间空地里养伤,窗外的森林被影牙"
},
{
"identifier": "nsfw",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "worldInfoAfter",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "newMainChat",
"role": "system",
"tokens": 6,
"head": "[Start a new Chat]"
},
{
"identifier": "chatHistory-6",
"role": "user",
"tokens": 16,
"head": "你一个人守在这里多久了?给我讲讲你是怎么成为森林"
},
{
"identifier": "chatHistory-7",
"role": "assistant",
"tokens": 265,
"head": "*塞拉菲娜沉默了片刻,望向窗外摇曳的树影,眼神变"
},
{
"identifier": "chatHistory-8",
"role": "system",
"tokens": 17,
"head": "(夜里塞拉菲娜的魔法会变弱,她不愿让人知道。)"
},
{
"identifier": "chatHistory-9",
"role": "user",
"tokens": 65,
"head": "*我把杯子捧在手里暖着,犹豫了一下,还是开口问。"
},
{
"identifier": "chatHistory-10",
"role": "assistant",
"tokens": 322,
"head": "*塞拉菲娜停下正要走开的脚步,回头看你,眼里闪过"
},
{
"identifier": "chatHistory-11",
"role": "user",
"tokens": 17,
"head": "……谢谢你愿意跟我说这些。等伤好了,我想陪你去点"
},
{
"identifier": "chatHistory-12",
"role": "assistant",
"tokens": 119,
"head": "*门外静了一瞬,随后传来塞拉菲娜轻轻的笑声,带着"
},
{
"identifier": "jailbreak",
"role": "system",
"tokens": 18,
"head": "用第三人称描写塞拉菲娜的动作,不替旅人说话或行动"
}
]
},
"2048": {
"budget": 1748,
"total": 1520,
"messagesInContext": 11,
"chatLength": 11,
"rows": [
{
"identifier": "main",
"role": "system",
"tokens": 34,
"head": "Write 塞拉菲娜's next reply "
},
{
"identifier": "worldInfoBefore",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "personaDescription",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "charDescription",
"role": "system",
"tokens": 131,
"head": "[塞拉菲娜的性格= \"体贴\", \"保护欲强\", "
},
{
"identifier": "charPersonality",
"role": "system",
"tokens": 11,
"head": "温柔、护短,总觉得是自己没把人照顾好。"
},
{
"identifier": "scenario",
"role": "system",
"tokens": 21,
"head": "旅人在塞拉菲娜的林间空地里养伤,窗外的森林被影牙"
},
{
"identifier": "nsfw",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "worldInfoAfter",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "newMainChat",
"role": "system",
"tokens": 6,
"head": "[Start a new Chat]"
},
{
"identifier": "chatHistory-1",
"role": "assistant",
"tokens": 163,
"head": "*你猛地惊醒,想起自己是怎么走进森林深处、又是怎"
},
{
"identifier": "chatHistory-2",
"role": "user",
"tokens": 19,
"head": "*我撑起身子,接过茶杯* 谢谢你……这片森林里到"
},
{
"identifier": "chatHistory-3",
"role": "assistant",
"tokens": 140,
"head": "*塞拉菲娜在床边坐下,双手交叠放在膝上,神色变得"
},
{
"identifier": "chatHistory-4",
"role": "user",
"tokens": 21,
"head": "你的魔法真厉害。我的伤要多久才能好?我还得赶去北"
},
{
"identifier": "chatHistory-5",
"role": "assistant",
"tokens": 135,
"head": "*塞拉菲娜眉头一皱,握着你的手不觉紧了些。* “"
},
{
"identifier": "chatHistory-6",
"role": "user",
"tokens": 16,
"head": "你一个人守在这里多久了?给我讲讲你是怎么成为森林"
},
{
"identifier": "chatHistory-7",
"role": "assistant",
"tokens": 265,
"head": "*塞拉菲娜沉默了片刻,望向窗外摇曳的树影,眼神变"
},
{
"identifier": "chatHistory-8",
"role": "system",
"tokens": 17,
"head": "(夜里塞拉菲娜的魔法会变弱,她不愿让人知道。)"
},
{
"identifier": "chatHistory-9",
"role": "user",
"tokens": 65,
"head": "*我把杯子捧在手里暖着,犹豫了一下,还是开口问。"
},
{
"identifier": "chatHistory-10",
"role": "assistant",
"tokens": 322,
"head": "*塞拉菲娜停下正要走开的脚步,回头看你,眼里闪过"
},
{
"identifier": "chatHistory-11",
"role": "user",
"tokens": 17,
"head": "……谢谢你愿意跟我说这些。等伤好了,我想陪你去点"
},
{
"identifier": "chatHistory-12",
"role": "assistant",
"tokens": 119,
"head": "*门外静了一瞬,随后传来塞拉菲娜轻轻的笑声,带着"
},
{
"identifier": "jailbreak",
"role": "system",
"tokens": 18,
"head": "用第三人称描写塞拉菲娜的动作,不替旅人说话或行动"
}
]
},
"4095": {
"budget": 3795,
"total": 1935,
"messagesInContext": 11,
"chatLength": 11,
"rows": [
{
"identifier": "main",
"role": "system",
"tokens": 34,
"head": "Write 塞拉菲娜's next reply "
},
{
"identifier": "worldInfoBefore",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "personaDescription",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "charDescription",
"role": "system",
"tokens": 131,
"head": "[塞拉菲娜的性格= \"体贴\", \"保护欲强\", "
},
{
"identifier": "charPersonality",
"role": "system",
"tokens": 11,
"head": "温柔、护短,总觉得是自己没把人照顾好。"
},
{
"identifier": "scenario",
"role": "system",
"tokens": 21,
"head": "旅人在塞拉菲娜的林间空地里养伤,窗外的森林被影牙"
},
{
"identifier": "nsfw",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "worldInfoAfter",
"role": "system",
"tokens": 0,
"head": ""
},
{
"identifier": "newChat",
"role": "system",
"tokens": 4,
"head": "[Example Chat]"
},
{
"identifier": "dialogueExamples 0-0",
"role": "system",
"tokens": 9,
"head": "“说说你是个什么样的人?”"
},
{
"identifier": "dialogueExamples 0-1",
"role": "system",
"tokens": 201,
"head": "*塞拉菲娜温和的笑意更深了,她想了一会儿,眼里闪"
},
{
"identifier": "dialogueExamples 0-2",
"role": "system",
"tokens": 10,
"head": "“说说你的身体和样貌。”"
},
{
"identifier": "dialogueExamples 0-3",
"role": "system",
"tokens": 191,
"head": "*塞拉菲娜轻声笑起来,笑声悦耳,在空气中跳动。她"
},
{
"identifier": "newMainChat",
"role": "system",
"tokens": 6,
"head": "[Start a new Chat]"
},
{
"identifier": "chatHistory-1",
"role": "assistant",
"tokens": 163,
"head": "*你猛地惊醒,想起自己是怎么走进森林深处、又是怎"
},
{
"identifier": "chatHistory-2",
"role": "user",
"tokens": 19,
"head": "*我撑起身子,接过茶杯* 谢谢你……这片森林里到"
},
{
"identifier": "chatHistory-3",
"role": "assistant",
"tokens": 140,
"head": "*塞拉菲娜在床边坐下,双手交叠放在膝上,神色变得"
},
{
"identifier": "chatHistory-4",
"role": "user",
"tokens": 21,
"head": "你的魔法真厉害。我的伤要多久才能好?我还得赶去北"
},
{
"identifier": "chatHistory-5",
"role": "assistant",
"tokens": 135,
"head": "*塞拉菲娜眉头一皱,握着你的手不觉紧了些。* “"
},
{
"identifier": "chatHistory-6",
"role": "user",
"tokens": 16,
"head": "你一个人守在这里多久了?给我讲讲你是怎么成为森林"
},
{
"identifier": "chatHistory-7",
"role": "assistant",
"tokens": 265,
"head": "*塞拉菲娜沉默了片刻,望向窗外摇曳的树影,眼神变"
},
{
"identifier": "chatHistory-8",
"role": "system",
"tokens": 17,
"head": "(夜里塞拉菲娜的魔法会变弱,她不愿让人知道。)"
},
{
"identifier": "chatHistory-9",
"role": "user",
"tokens": 65,
"head": "*我把杯子捧在手里暖着,犹豫了一下,还是开口问。"
},
{
"identifier": "chatHistory-10",
"role": "assistant",
"tokens": 322,
"head": "*塞拉菲娜停下正要走开的脚步,回头看你,眼里闪过"
},
{
"identifier": "chatHistory-11",
"role": "user",
"tokens": 17,
"head": "……谢谢你愿意跟我说这些。等伤好了,我想陪你去点"
},
{
"identifier": "chatHistory-12",
"role": "assistant",
"tokens": 119,
"head": "*门外静了一瞬,随后传来塞拉菲娜轻轻的笑声,带着"
},
{
"identifier": "jailbreak",
"role": "system",
"tokens": 18,
"head": "用第三人称描写塞拉菲娜的动作,不替旅人说话或行动"
}
]
}
}