87 lines
3.5 KiB
JavaScript
87 lines
3.5 KiB
JavaScript
// 从「酒馆真实抓包」直接复刻出一个预设:messages 原样搬,tools.description 搬成 system 块。
|
||
// 用法: node build-clone-from-capture.mjs <capture.json> <输出名>
|
||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||
import path from "node:path";
|
||
|
||
const captureFile = process.argv[2];
|
||
const name = process.argv[3] || "wa-clone";
|
||
const OUT = "D:/progarm/my/writing-agent/tools/st-request-diff/presets/" + name + ".json";
|
||
mkdirSync(path.dirname(OUT), { recursive: true });
|
||
|
||
const outer = JSON.parse(readFileSync(captureFile, "utf8"));
|
||
const body = JSON.parse(outer.body);
|
||
const msgs = body.messages || [];
|
||
|
||
const toolDescs = (body.tools || []).map((t) => {
|
||
const fn = t.function || t;
|
||
return "# [工具声明] " + (fn.name || "") + "\n" + String(fn.description || "");
|
||
});
|
||
|
||
const blocks = [];
|
||
msgs.forEach((m, i) => {
|
||
const content = String(m.content ?? "");
|
||
if (!content.trim()) return;
|
||
blocks.push({
|
||
identifier: "clone_" + String(i).padStart(2, "0"),
|
||
name: "复刻消息 " + i + "(" + m.role + ")",
|
||
role: ["system", "user", "assistant"].includes(m.role) ? m.role : "system",
|
||
content,
|
||
});
|
||
});
|
||
toolDescs.forEach((d, i) => {
|
||
blocks.push({ identifier: "clone_tool_" + i, name: "复刻工具声明 " + i, role: "system", content: d });
|
||
});
|
||
|
||
const markers = [
|
||
["worldInfoBefore", "World Info (before)"],
|
||
["personaDescription", "Persona Description"],
|
||
["charDescription", "Char Description"],
|
||
["charPersonality", "Char Personality"],
|
||
["scenario", "Scenario"],
|
||
["worldInfoAfter", "World Info (after)"],
|
||
["dialogueExamples", "Chat Examples"],
|
||
["chatHistory", "Chat History"],
|
||
].map(([identifier, nm]) => ({
|
||
identifier, name: nm, marker: true, system_prompt: true, role: "system", content: "",
|
||
injection_position: 0, injection_depth: 4, injection_order: 100, enabled: true,
|
||
}));
|
||
|
||
const prompts = [
|
||
...markers,
|
||
...blocks.map((b) => ({
|
||
identifier: b.identifier, name: b.name, enabled: true, role: b.role,
|
||
content: b.content, injection_position: 0, injection_depth: 4, injection_order: 100,
|
||
system_prompt: false, marker: false, forbid_overrides: false,
|
||
})),
|
||
];
|
||
|
||
const prompt_order = [
|
||
{
|
||
character_id: 100001,
|
||
order: [
|
||
...blocks.map((b) => b.identifier),
|
||
"worldInfoBefore", "personaDescription", "charDescription", "charPersonality", "scenario", "worldInfoAfter",
|
||
"dialogueExamples", "chatHistory",
|
||
].map((identifier) => ({ identifier, enabled: true })),
|
||
},
|
||
];
|
||
|
||
const preset = {
|
||
name,
|
||
temperature: 1, frequency_penalty: 0, presence_penalty: 0, top_p: 0.99, top_k: 60,
|
||
max_context_unlocked: true, openai_max_context: 200000, openai_max_tokens: 3000,
|
||
names_behavior: 0, send_if_empty: "",
|
||
new_chat_prompt: "[chat Start]", new_example_chat_prompt: "{{mesExamples}}",
|
||
continue_nudge_prompt: "[继续]",
|
||
wi_format: "{0}", scenario_format: "{{scenario}}", personality_format: "{{personality}}",
|
||
stream_openai: true, use_sysprompt: true, squash_system_messages: true,
|
||
function_calling: false, reasoning_effort: "low", seed: -1, n: 1,
|
||
prompts, prompt_order,
|
||
};
|
||
|
||
writeFileSync(OUT, JSON.stringify(preset, null, 2), "utf8");
|
||
console.log("已写入 " + OUT);
|
||
console.log("消息 " + msgs.length + " 条(原样搬 " + blocks.filter((b) => b.name.startsWith("复刻消息")).length + " 条)、工具声明 " + toolDescs.length + " 段");
|
||
console.log("正文合计 " + prompts.reduce((n, p) => n + String(p.content || "").length, 0) + " 字");
|
||
console.log("来源抓包: " + path.basename(captureFile) + " receivedAt=" + outer.receivedAt);
|