Files
writing-agent/tools/st-request-diff/README.md
T

68 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 真实请求对比(酒馆 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")
1. 假上游 `capture-server.mjs`:实现够用的 OpenAI 兼容端点,把收到的**原始请求体**原样写进 `captures/`,并回一句固定文本。
2. 酒馆侧:起 ST → 起 headless 浏览器 → CDP 进页面 → 用页面上的「导入预设」文件输入把 json 丢进去(等于人手点导入)→ 选预设 → 连接指向假上游 → 选探针角色 `ProbeCard` → 清空历史 → `ctx.generate("normal")` 真发一轮。
3. 本仓库侧:起 `src/server/web-server.ts`(独立数据目录)→ `POST /api/presets/import` → `POST /api/direct-chat/ephemeral/complete` 真发一轮。
4. `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,纯文本 |
## 已确认的差距(按优先级)
1. **脚本/正则层**(最贵):本仓库导入时明确不执行 ST 正则与前端脚本;linux_1.3 的 tools 升格、Reborn2.4 的 `game_content` 都在这层。
2. **`prompts[].enabled` 双闸**(确定 bug):酒馆只用 `prompt_order.enabled`(`openai.js` 从不读 `prompts[].enabled`),本仓库要求两者都开 → linux_1.3 少发 `<世界设定与背景>`、`作者简介 古典武侠`、`结尾` 共约 1 万字。
3. **`squash_system_messages` 语义**(确定 bug):酒馆只合并**相邻 system**(跳过带 `name` 的、跳过 `newMainChat/newChat/groupNudge`),本仓库按"同角色合并"把 `结尾(框架闭合)`、`/历史记录`、`你好` 三条 user 合成一条。
4. **角色卡插槽 + 格式模板**:`charDescription/charPersonality/scenario` 及 `personality_format/scenario_format` 包装(如 `<character_personality>…</character_personality>`)。
5. **示例对话**:`new_example_chat_prompt` 打头,`mes_example` 按 `<START>` 切段成多条 system,并带 `name=example_user/example_assistant`。
6. **`new_chat_prompt`**:空聊天时插一条 `[Start a new Chat]` / `[NVWA chat history begins below.]`。
7. 本仓库多发的:`姓名:玩家`(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']` 等硬编码决定),不是位置规则;当前三份抓包里两边位置一致 → 不是当前核心差距。