真实请求对比(酒馆 vs 本仓库)
目的:让本机真酒馆和本仓库用同一个预设发一次真实请求,把两边真正发到上游的 JSON 落盘,再逐字段、逐条消息对齐,弄清"预设兼容"还差在哪。
不猜、不看内部对象,只看线上真实请求体。
前提
- 酒馆源码在
D:/game/sillytavern,能node server.js起来(版本 1.18)。 - Node 22+(用到内置
WebSocket)、本机有 Edge 或 Chrome(headless 也行)。 - 不改你
D:/game/sillytavern/data里的任何东西:两边都用独立数据目录 (酒馆--dataRoot ./.st-data,本仓库WRITING_AGENT_DATA_DIR=./.wa-data)。
链路(两边都走"纯导入 json")
- 假上游
capture-server.mjs:实现够用的 OpenAI 兼容端点,把收到的原始请求体原样写进captures/,并回一句固定文本。 - 酒馆侧:起 ST → 起 headless 浏览器 → CDP 进页面 → 用页面上的「导入预设」文件输入把 json 丢进去(等于人手点导入)→ 选预设 → 连接指向假上游 → 选探针角色
ProbeCard→ 清空历史 →ctx.generate("normal")真发一轮。 - 本仓库侧:起
src/server/web-server.ts(独立数据目录)→POST /api/presets/import→POST /api/direct-chat/ephemeral/complete真发一轮。 diff.mjs对齐两份请求体,出captures/report-<预设名>.md。
用法
全自动(两个预设、两边、报告):
node run-all.mjs
node run-all.mjs --only st --preset "C:/Users/zed/Downloads/linux_1.3.json"
node run-all.mjs --only wa|diff
手动挡(我起环境、你点发送、我只监控):
node manual-st.mjs --preset "C:/Users/zed/Downloads/NVWA-Galaxia-ST.json"
# 浏览器窗口打开后,你在里面写内容点发送即可;抓到会打出来
配套小工具(都对着已开着的页面,不动浏览器):
node attach-preset.mjs --preset <json> # 往活页面里再导入一个预设并选中
node attach-clear.mjs --preset <名字> # 切预设 + 清空历史 + 打印当前生效参数
node attach-send.mjs --preset <名字> --text 你好
node inspect-capture.mjs captures/st-001-xxx.json [--full 3]
node inspect-prompt-order.mjs <preset.json> # 看 order/开关/marker/system_prompt/注入位置
node peek-preset-flags.mjs <preset.json> # 看 function_calling / squash / extensions
node peek-gen-fields.mjs <preset.json> # 看采样参数字段类型
node inspect-wa-assembly.mjs <preset.json> # 用本仓库的装配代码看会拼出什么(不发请求)
已确认的机制差异(2026-10 实测)
| 预设 | 酒馆侧机制 | 证据 |
|---|---|---|
linux_1.3 |
预设里是纯文本的伪工具协议(6 条 【ToolCall引导】…),运行期被 tavern_helper 脚本抽 description/fields 动态注册成真 tool |
4 条消息 + tools(1)=dispatch_stream_payload_xxx、tool_choice:auto |
Reborn2.4 |
预设自带 function_calling:true、tool_call_recurse_limit:5、extensions.ToolBindings.game_content,提示词要求必须调用 game_content → 设计上就是真 function calling |
两次抓包都是 33 条、无 tools → 绑定没注册上,退化成纯文本 |
NVWA-Galaxia-ST |
无任何工具痕迹(无 tool 条目、无 function_calling) |
14 条、无 tools,纯文本 |
已确认的差距(按优先级)
- 脚本/正则层(最贵):本仓库导入时明确不执行 ST 正则与前端脚本;linux_1.3 的 tools 升格、Reborn2.4 的
game_content都在这层。 prompts[].enabled双闸(确定 bug):酒馆只用prompt_order.enabled(openai.js从不读prompts[].enabled),本仓库要求两者都开 → linux_1.3 少发<世界设定与背景>、作者简介 古典武侠、结尾共约 1 万字。squash_system_messages语义(确定 bug):酒馆只合并相邻 system(跳过带name的、跳过newMainChat/newChat/groupNudge),本仓库按"同角色合并"把结尾(框架闭合)、/历史记录、你好三条 user 合成一条。- 角色卡插槽 + 格式模板:
charDescription/charPersonality/scenario及personality_format/scenario_format包装(如<character_personality>…</character_personality>)。 - 示例对话:
new_example_chat_prompt打头,mes_example按<START>切段成多条 system,并带name=example_user/example_assistant。 new_chat_prompt:空聊天时插一条[Start a new Chat]/[NVWA chat history begins below.]。- 本仓库多发的:
姓名:玩家(persona 无描述时的兜底)、### 任务契约 …、stream_options:{include_usage:true}。
决策记录
- 采样参数跟默认走:预设缺
temperature/top_p/max_tokens时,本仓库回落到 API 配置默认即可(酒馆是"缺就不改,沿用上次的值",不做对齐)。所以NVWA-Galaxia-ST报告里那行参数差异算已知取舍。 names_behavior(NONE:-1/DEFAULT:0/COMPLETION:1/CONTENT:2)只影响聊天历史是否加名字:前缀,三个预设都是 0,单角色下无效果 → 暂不实现。system_prompt:true标的是 ST 的内置槽位(不可删/不在用户列表/不参与深度注入,落位由openai.js里systemPrompts=['nsfw','jailbreak']等硬编码决定),不是位置规则;当前三份抓包里两边位置一致 → 不是当前核心差距。