预设装配注入人设与身份宏,并支持编辑采样参数。

让游玩提示词能吃到当前用户角色,同时在设置里可调 generation。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-14 01:14:32 +08:00
co-authored by Cursor
parent 8a22cdc37c
commit 16f66ffd5e
10 changed files with 233 additions and 11 deletions
+51
View File
@@ -48,6 +48,7 @@ describe("assemblePlayWorkerMessages", () => {
systemPrompt: "SKILL",
preset: report.preset,
pack,
persona: null,
});
expect(messages.map((m) => [m.role, m.content])).toEqual([
@@ -107,6 +108,7 @@ describe("assemblePlayWorkerMessages", () => {
turn: "本轮",
postTurn: [],
},
persona: null,
});
expect(messages[0]).toEqual({ role: "system", content: "<世界书>" });
expect(messages.some((m) => m.content === "创作步骤契约")).toBe(false);
@@ -148,4 +150,53 @@ describe("assemblePlayWorkerMessages", () => {
});
expect(messages.map((m) => m.content)).toEqual(["HIST"]);
});
it("fills personaDescription and expands @玩家 with the given persona", () => {
const report = importSillyTavernPreset({
prompts: [
{
identifier: "personaDescription",
name: "Persona",
role: "system",
marker: true,
},
{
identifier: "main",
name: "Main",
role: "system",
content: "对 @玩家 说话",
},
{
identifier: "chatHistory",
name: "History",
role: "system",
marker: true,
},
],
prompt_order: [
{
character_id: 1,
order: [
{ identifier: "personaDescription", enabled: true },
{ identifier: "main", enabled: true },
{ identifier: "chatHistory", enabled: true },
],
},
],
});
const messages = assemblePlayWorkerMessages({
systemPrompt: "SKILL",
preset: report.preset,
pack: {
worldBookBefore: [],
history: "昨日",
worldBookAfter: [],
turn: "本轮",
postTurn: [],
},
persona: { name: "@玩家", description: "占位人设" },
});
expect(messages.some((m) => m.content === "占位人设")).toBe(true);
expect(messages.some((m) => m.content === "对 @玩家 说话")).toBe(true);
});
});
-1
View File
@@ -52,7 +52,6 @@ describe("assemblePresetProbe", () => {
`### 任务契约\n\n${PROBE_SYSTEM_PROMPT}\n\n### 试跑设定\n\n${DEFAULT_PROBE_CONTEXT.loreBefore}`,
],
["system", DEFAULT_PROBE_CONTEXT.history],
["system", `### 本轮状态\n\n${DEFAULT_PROBE_CONTEXT.loreAfter}`],
["user", "我推开门。"],
["system", "PHI"],
]);
+36
View File
@@ -6,6 +6,10 @@ import {
listAllPresetEntries,
listEnabledPresetEntries,
} from "../src/preset/entries.js";
import {
applyPresetGeneration,
normalizeGeneration,
} from "../src/preset/generation.js";
import { importSillyTavernPreset } from "../src/preset/importer.js";
const samplePreset = {
@@ -170,3 +174,35 @@ describe("applyPresetEntryPatches", () => {
).toBe(true);
});
});
describe("normalizeGeneration / applyPresetGeneration", () => {
it("keeps finite numbers and clears empty fields on replace", () => {
expect(
normalizeGeneration({
temperature: "0.9",
topP: "",
maxOutputTokens: 4096,
reasoningEffort: " high ",
verbosity: " ",
stream: true,
seed: "not-a-number",
}),
).toEqual({
temperature: 0.9,
maxOutputTokens: 4096,
reasoningEffort: "high",
stream: true,
});
});
it("replaces preset generation wholesale", () => {
const report = importSillyTavernPreset(samplePreset);
expect(report.preset.generation.temperature).toBe(1);
const next = applyPresetGeneration(report.preset, {
topP: 0.8,
maxOutputTokens: 2048,
});
expect(next.generation).toEqual({ topP: 0.8, maxOutputTokens: 2048 });
expect(next.prompts).toBe(report.preset.prompts);
});
});