预设兼容:按真实抓包对齐装配与包装层,补上声明式工具与预设正则。

- 装配只认 prompt_order.enabled;squash_system_messages 只合并相邻 system(新增 system 档,连接符按酒馆用单换行)
- 包装层:new_chat_prompt、示例对话(new_example_chat_prompt + <START> 切段 + name)、角色卡三块与 personality_format/scenario_format、{{user}}/{{char}} 取值、任务契约并进预设条目
- 工具协议:按 ToolBindings / 伪工具协议数据声明真 tools(presetToolPolicy=preset),工具描述用到的条目不再重复作为消息发出
- 正则:promptOnly 作用于对话历史(含 depth 过滤)、写入时脚本改写回复;{{//}} 注释按配平扫描
- tools/st-request-diff:真假上游抓包对比工具、三份预设的机制结论与实测报告
This commit is contained in:
2026-10-23 00:13:08 +08:00
parent ed09e5c831
commit 9dc927282f
94 changed files with 11558 additions and 413 deletions
+69
View File
@@ -0,0 +1,69 @@
import type { ChatMessage } from "../llm/client.js";
/** 酒馆给示例对话消息打的 name(不是角色名)。 */
export const EXAMPLE_USER_NAME = "example_user";
export const EXAMPLE_ASSISTANT_NAME = "example_assistant";
/**
* 把酒馆 `mes_example` 切成示例消息(对应 `openai.js` 的 `setOpenAIMessageExamples` +
* `parseExampleIntoIndividual`):
* - 按 `<START>` 分块;
* - 块内以 `用户名:` / `角色名:` 开头的行切换说话人,其余行算续行;
* - 每条消息 role 都是 system,name 是 example_user / example_assistant,
* 正文去掉 `名字:` 前缀。
* 传进来的 text 应该已经展开过宏(`{{user}}` / `{{char}}`),否则名字对不上。
*/
export function parseExampleDialogue(params: {
text: string;
userName: string;
charName: string;
}): ChatMessage[][] {
const text = (params.text ?? "").replace(/\r/g, "");
if (!text.trim()) return [];
const userName = params.userName.trim();
const charName = params.charName.trim();
const blocks = text
.split(/<START>/i)
.map((block) => block.trim())
.filter(Boolean);
const source = blocks.length > 0 ? blocks : [text.trim()];
const out: ChatMessage[][] = [];
for (const block of source) {
const messages: ChatMessage[] = [];
let speaker: "user" | "assistant" | null = null;
let lines: string[] = [];
const flush = () => {
const content = lines.join("\n").trim();
if (speaker && content) {
messages.push({
role: "system",
content,
name: speaker === "user" ? EXAMPLE_USER_NAME : EXAMPLE_ASSISTANT_NAME,
});
}
lines = [];
};
for (const rawLine of block.split("\n")) {
const line = rawLine.replace(/\r$/, "");
if (userName && line.startsWith(`${userName}:`)) {
flush();
speaker = "user";
lines.push(line.slice(userName.length + 1));
continue;
}
if (charName && line.startsWith(`${charName}:`)) {
flush();
speaker = "assistant";
lines.push(line.slice(charName.length + 1));
continue;
}
lines.push(line);
}
flush();
if (messages.length > 0) out.push(messages);
}
return out;
}