Skip to Content

[!TIP] 本篇章文档基于 Maybe 大佬提供的 PR 和函数~

window.callGenerate(options): Promise<GenerateResult>

为 iframe 内宿主页面提供基于酒馆底层 API 的自由度大于酒馆原生 generate()generateRaw() 的调用酒馆生成并返回生成结果的桥接 API。 以“组件列表 + 行内覆写 + 注入”为核心语义,支持预览 messages 便于可视化审阅与调试,提供高度自由的提示词构建功能。

主要功能

  • 单一入口window.callGenerate(options): Promise<GenerateResult>
  • 组件列表驱动components.list 同时决定启用集合与顺序;支持 ALL(任意位置出现即表示“启用全部”)。
  • 覆写与创建:行内覆写支持 disable/replace/order,未命中 replace 时按锚点“无则创建”。
  • 历史统一chatHistory 支持 selector/replaceAll/replace[] 的消息级替换与筛选流水线。
  • 注入:内联注入(默认 AFTER_COMPONENT,邻接历史 → IN_CHAT,首项+prev → BEFORE_PROMPT)与高级注入。
  • 预览/蓝图:可导出 messagesblueprint(组件顺序/注入/覆写)。
  • 发送:统一经 ChatCompletionService,流式/非流式;标准事件回传。

这是嵌入到消息里的 iframe 页面中使用最小示例:

// 在 iframe 宿主页面代码里直接调用 // 首先构建生成请求选项,包括提示词和各种设置 const options ={ components: { list: ['ALL_PREON'] }, // 启用酒馆预设里所有开启组件当基座 userInput: '请总结要点并给出下一步建议。', // 本次用户输入 streaming: { //流式输出设置 enabled: true, //是否启用流式 onChunk: (chunk, acc) => { // 可选:流式过程中实时拿到增量(chunk)与累计文本(acc) // console.log('[chunk]', chunk); }, debug: { enabled: true } // 开启调试预览 }; // 2) 发送请求并取得最终结果 const res = await window.callGenerate(options); /* res 的结构如下: { success: true, result: '模型最终输出的完整文本', // 例如一段 JSON 或自然语言 sessionId: 'xb1', metadata: { duration: 1234, model: 'gemini/claude/GPT...', finishReason: 'stop' } } */

window.postMessage(iframe → 宿主)

本桥接为 iframe 内的宿主页面提供对 SillyTavern 世界书(worldbook/lorebook)的读写与管理能力,语义尽量对齐 STscript,但实现基于底层 API。

  • 通信协议window.postMessage(iframe → 宿主)
  • 事件推送:宿主 → iframe(worldbookEvent

API 总览

说明中返回值如果为“字符串”,通常会把非字符串值做 toString;数组会常以 JSON 字符串或数组返回,详见各 API。

文件级(worldbook): listWorldbooks() → string[] getGlobalBooks() → string(JSON 字符串化后的数组) getChatBook({ name? }) → string(已绑定或新建文件名) getPersonaBook() → string getCharBook({ type: 'primary'|'additional'|'all', name? }) → string | string(JSON) world({ state?: 'on'|'off'|'toggle', silent?: boolean, name?: string }) → ''(空字符串) 条目(entry)基础: listEntries({ file }) → Array<{ uid, comment, key, keysecondary, position, depth, order, probability, useProbability, disable }> createEntry({ file, key?, content? }) → string(新 uid) findEntry({ file, field?: string, text: string }) → string(uid 或空字符串) getEntryField({ file, uid, field?: string }) → string(字段值) setEntryField({ file, uid, field, value }) → ''(空字符串) deleteEntry({ file, uid }) → 'ok' | ''(空字符串) 条目(entry)增强: getEntryAll({ file, uid }) → Record<field, string>(按模板字段批量返回) batchSetEntryFields({ file, uid, fields: Record<field, value> }) → 'ok' cloneEntry({ file, uid, newKey? }) → string(新 uid) moveEntry({ sourceFile, targetFile, uid }) → string(新 uid) reorderEntry({ file, uid, newOrder }) → 'ok' 计时效果(最小对齐 STscript): wiGetTimedEffect({ file, uid, effect: 'sticky'|'cooldown', format?: 'bool'|'number' }) → string wiSetTimedEffect({ file, uid, effect: 'sticky'|'cooldown', value?: 'toggle'|'true'|'false'|boolean }) → ''(空字符串) 绑定/解绑: bindWorldbookToChat({ worldbookName, autoCreate?: boolean }) → { name } unbindWorldbookFromChat() → { name: '' } bindWorldbookToCharacter({ character?, worldbookName, target: 'primary'|'additional', autoCreate?: boolean }) → { primary?: string, additional?: string[] } unbindWorldbookFromCharacter({ character?, worldbookName?, target: 'primary'|'additional'|'all' }) → { primary?: string, additional?: string[] } 导入/导出与管理: exportWorldbook({ file }) → string(JSON) importWorldbook({ name, data: JSONstring, overwrite?: boolean }) → 'ok' renameWorldbook({ oldName, newName }) → 抛出 NOT_IMPLEMENTED deleteWorldbook({ name }) → 抛出 NOT_IMPLEMENTED(需 ST 核心支持)

如何构建提示词

components.list 是一个“积木清单”,按顺序从上到下处理。支持三种元素(可混搭):

1) 字符串“引用一个组件”

  • 常见键:'ALL', 'ALL_PREON', 'chatHistory', 'worldInfoBefore', 'worldInfoAfter', 'charDescription', 'personaDescription', 'scenario'
  • 也可以用带前缀的精确引用:'id:charDescription''name:世界观'id 是指代的提示词的 identifier,而 name 就是指的你在预设里每个组件的 name。如果不带前缀的话,默认你写的是 name,如果 name 找不到则回退搜索是否有符合的条件 identifier
  • 'ALL''ALL_PREON' 的意思:以“启用全部组件”/“启用全部你在酒馆的预设里设置为启用组件”为基础条件;否则默认“只用你列出来的子集”。

2) 覆写一个组件(开关/替换/排序参与)

  • 语法:{ '<ref>': { ...配置 } }<ref> 用法同上(如 'id:scenario''dialogueExamples'
  • 常用字段:
    • disable: true 关掉该组件
    • replace: '新的文本' 替换该组件内容(即便该组件没有内容也会将你设置的文本填入进去)
    • order: false'ALL' 基座下,表示“不参与重排”,保持原位
  • 特别的 chatHistory(聊天历史)还能做“选择/替换”:
    • selector 选历史子集(按角色/包含词/范围等)
    • replaceAllreplace 用你的消息替换全部或者指定历史段

3) 内联“插一条自定义消息”

  • 语法:{ role: 'system'|'assistant'|'user', content: '...', position?: 'BEFORE_PROMPT'|'IN_PROMPT'|'IN_CHAT', depth?: number }
  • 放在 list 的哪个位置,就会影响它贴近谁(有时会自动判定“插在某组件后面”)
  • 常用位置:
    • BEFORE_PROMPT:放最前面当“总前言”
    • IN_PROMPT:放在“历史对话之前”,当系统规则/背景
    • IN_CHAT:插到历史附近(depth: 0 表示插入在最底层;大于 0 表示在更浅的位置)

如何构建一个 list

1) 先决定基座

  • 要“继承酒馆所有组件” → 用 'ALL'
  • 要“只继承酒馆所有预设里设置为启用组件” → 用 'ALL_PREON'
  • 要“只用若干关键组件” → 不写 'ALL' 或者 'ALL_PREON',按需求列出它们(子集模式)

2) 需要强调顺序的组件写成字符串按顺序列出来

  • 'ALL' 或者 'ALL_PREON' 下,你列出来的这些会被按照你 list 里的顺序进行重新列排列(未列出的保持原位)
  • 不想被重排的,给它 { '<ref>': { order: false } }

3) 用覆写对象做开关/替换

  • 关掉:{ 'id:scenario': { disable: true } }
  • 替换:{ 'id:authorsNote': { replace: '注意简洁、可执行。' } }
  • 历史选择与替换:{ 'id:chatHistory': { selector: {...}, replace: [...] } }

4) 用内联注入插“自定义规则/提示”

  • 开场总规则:{ role: 'system', content: '...', position: 'BEFORE_PROMPT' }
  • 体系化要求:{ role: 'system', content: '输出包含摘要/清单/下一步', position: 'IN_PROMPT' }
  • 历史附近提醒:{ role: 'assistant', content: '...', position: 'IN_CHAT', depth: 0 }

模板示例 1:ALL 基座 + 关掉场景 + 替换作者注 + 注入总规则

const options = { components: { list: [ 'ALL', // 以“全部组件”为基座 // 需要强调顺序的几个(其余保持原位) 'charDescription', 'worldInfoBefore', 'worldInfoAfter', 'dialogueExamples', // 覆写:关掉场景;替换作者注 { 'id:scenario': { disable: true } }, { 'id:authorsNote': { replace: '简洁、结构化、可执行。' } }, // 注入:最前面加一个总规则 { role: 'system', content: '回答需包含:摘要、清单、下一步。', position: 'BEFORE_PROMPT' }, ], }, userInput: '基于当前上下文给出行动建议。', streaming: { enabled: true }, debug: { enabled: true } }; window.callGenerate(options);

模板示例 2:子集模式(只用人设 + 世界观 + 历史片段)

const options = { components: { list: [ 'charDescription', 'worldInfoBefore', { 'id:chatHistory': { selector: { roles: { include: ['user', 'assistant'] }, last: 8 // 只取最后 8 条 } } }, { role: 'system', content: '先思考再作答,最后列出下一步。', position: 'IN_PROMPT' }, ], }, userInput: '总结当前局势并给出计划。', streaming: { enabled: false }, // 不流式也可 debug: { enabled: true } }; window.callGenerate(options);

chatHistory 选择与覆写

{ 'id:chatHistory': { selector: { roles: { include: ['user', 'assistant'] }, // 角色筛选,这里就是只使用role为user和assistant的消息 filter: { contains: ['线索'], regex: 'Boss' }, // 内容筛选(或用正则) anchorWindow: { anchor: 'lastUser', before: 4, after: 2 }, // 锚点窗口 takeEvery: 1, // 每隔几条取一条 limit: { count: 12, truncateStrategy: 'even' }, // 限条数(first/middle/even/last) }, // 替换最后X条历史,这里是最后一条 replace: [ { indices: { values: [-1] }, with: [{ role: 'user', content: '(系统)聚焦新线索。' }] } ] } }

常见问答

  • 我只想快速“全套原生提示 + 自己的输入”?
    • list: ['ALL'] 或者 list: ['ALL_PREON'],加上 userInput 即可。
  • 要确保某组件有内容(没有就补上)?
    • 覆写里用 { '<ref>': { replace: '...' } },缺失时会自动“补出来”。
  • 引用名分不清?
    • 'id:xxx' 最稳(如 id:charDescriptionid:worldInfoBefore),如果是自定义组件,则需要你去查看具体 identifier,酒馆给自定义组件都是默认分配一个随机 identifier
  • 想看最终发给模型的消息?
    • debug.enabled: true,会有“提示预览/蓝图”消息。

如何对 API 进行覆写

默认行为(inherit=true

  • 不写 api 或只写 api.overrides 时,会继承酒馆里当前聊天设置(来源/模型/代理等),你只“改你写的那几项”。

关闭继承(inherit=false

  • 完全手动指定来源与模型,必要时提供 baseURL

常用字段(写在 api.overrides 里):

  • provider: 'openai' | 'claude' | 'gemini' | 'google' | 'vertexai' | 'cohere' | 'deepseek' | 'xai' | 'groq' | 'openrouter' | 'custom' 其中 custom 就是兼容 OpenAI 格式的来源
  • model: 模型名(如 'gpt-4o-mini''Gemini 2.5 pro'
  • temperature, topP, topK, frequencyPenalty, presencePenalty, repetitionPenalty
  • maxTokens: 最大输出令牌数
  • stop: 停止词数组,如 ['<END>']
  • responseFormat: 如 { type: 'json_object' }(OpenAI 风格)
  • seed: 随机种子
  • baseURL: 覆写接口地址
  • provider='custom' → 映射到 custom_url
  • 其他 provider → 映射到 reverse_proxy(OpenAI/Claude 等)

额外注意:

  • 继承模式会自动透传你在酒馆里配置的代理与自定义头(适配来源)。
  • 不支持 SSE 的端点请设 streaming.enabled=false,否则会超时。

典型用法

  1. 继承现有设置,只改模型与采样参数
window.callGenerate({ components: { list: ['ALL_PREON'] }, api: { inherit: true, overrides: { model: 'Gemini 2.5 pro', temperature: 0.7, topP: 0.9, maxTokens: 1024, stop: ['<END>'] }, }, userInput: '请总结并给出下一步。', streaming: { enabled: true }, debug: { enabled: true }, });
  1. 直连自定义 OpenAI 兼容端(CUSTOM)
window.callGenerate({ components: { list: ['ALL'] }, api: { inherit: false, // 不继承酒馆配置 provider: 'custom', model: 'my-model-name', baseURL: 'https://api.example.com/v1/chat/completions', // 映射到 custom_url overrides: { responseFormat: { type: 'json_object' }, temperature: 0.3, }, }, userInput: '请用 JSON 输出结果。', streaming: { enabled: false }, // 若端点不支持 SSE,关闭流式 debug: { enabled: true }, });

获取头像

在你的 HTML 代码块里,直接放这两个类名的 div,即可自动填充用户、角色头像:

  • 用户头像:xb-user-avatar
  • 角色头像:xb-char-avatar