预设兼容:按真实抓包对齐装配与包装层,补上声明式工具与预设正则。
- 装配只认 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:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user