统一在预设包装层做提示词夹心,并修正探针实际发信路径。
让所有模型请求与界面预览共用同一套夹心,避免探针与运行时行为分叉。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -51,9 +51,11 @@ describe("assemblePlayWorkerMessages", () => {
|
||||
});
|
||||
|
||||
expect(messages.map((m) => [m.role, m.content])).toEqual([
|
||||
["system", "SKILL"],
|
||||
["system", "MAIN"],
|
||||
["system", "### 舞台\n\n古镇夜雨"],
|
||||
[
|
||||
"system",
|
||||
"### 任务契约\n\nSKILL\n\n### 舞台\n\n古镇夜雨",
|
||||
],
|
||||
["system", "用户:昨天来过"],
|
||||
["system", "### 变量\n\nHP 3"],
|
||||
["user", "我推门"],
|
||||
@@ -62,6 +64,57 @@ describe("assemblePlayWorkerMessages", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("does not emit any message before the first preset order entry", () => {
|
||||
const report = importSillyTavernPreset({
|
||||
prompts: [
|
||||
{
|
||||
identifier: "wb-head",
|
||||
name: "世界书首",
|
||||
role: "system",
|
||||
content: "<世界书>",
|
||||
},
|
||||
{
|
||||
identifier: "chatHistory",
|
||||
name: "History",
|
||||
role: "system",
|
||||
marker: true,
|
||||
},
|
||||
{
|
||||
identifier: "wb-tail",
|
||||
name: "世界书尾",
|
||||
role: "system",
|
||||
content: "</世界书>",
|
||||
},
|
||||
],
|
||||
prompt_order: [
|
||||
{
|
||||
character_id: 1,
|
||||
order: [
|
||||
{ identifier: "wb-head", enabled: true },
|
||||
{ identifier: "chatHistory", enabled: true },
|
||||
{ identifier: "wb-tail", enabled: true },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
const messages = assemblePlayWorkerMessages({
|
||||
systemPrompt: "创作步骤契约",
|
||||
preset: report.preset,
|
||||
pack: {
|
||||
worldBookBefore: [{ id: "lore", name: "设定", content: "港口" }],
|
||||
history: "昨日对话",
|
||||
worldBookAfter: [],
|
||||
turn: "本轮",
|
||||
postTurn: [],
|
||||
},
|
||||
});
|
||||
expect(messages[0]).toEqual({ role: "system", content: "<世界书>" });
|
||||
expect(messages.some((m) => m.content === "创作步骤契约")).toBe(false);
|
||||
expect(
|
||||
messages.some((m) => m.content.includes("### 任务契约\n\n创作步骤契约")),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("does not fill ST charDescription even if resolver returns content", () => {
|
||||
const report = importSillyTavernPreset({
|
||||
prompts: [
|
||||
|
||||
@@ -46,9 +46,11 @@ describe("assemblePresetProbe", () => {
|
||||
});
|
||||
|
||||
expect(messages.map((m) => [m.role, m.content])).toEqual([
|
||||
["system", PROBE_SYSTEM_PROMPT],
|
||||
["system", "MAIN"],
|
||||
["system", `### 试跑设定\n\n${DEFAULT_PROBE_CONTEXT.loreBefore}`],
|
||||
[
|
||||
"system",
|
||||
`### 任务契约\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", "我推开门。"],
|
||||
@@ -66,8 +68,8 @@ describe("assemblePresetProbe", () => {
|
||||
});
|
||||
|
||||
expect(messages.map((m) => m.content)).toEqual([
|
||||
PROBE_SYSTEM_PROMPT,
|
||||
"MAIN",
|
||||
`### 任务契约\n\n${PROBE_SYSTEM_PROMPT}`,
|
||||
"你好",
|
||||
"PHI",
|
||||
]);
|
||||
|
||||
@@ -53,7 +53,7 @@ function recordingProvider(): {
|
||||
}
|
||||
|
||||
describe("wrapLlmForSession", () => {
|
||||
it("context trace matches the exact messages and generation sent to the inner LLM", async () => {
|
||||
it("frames task messages with preset prompt_order and merges generation", async () => {
|
||||
const { provider, received } = recordingProvider();
|
||||
const ctx: LlmTrackingContext = {};
|
||||
const llm = wrapLlmForSession(provider, { current: ctx }, () => samplePreset);
|
||||
@@ -64,14 +64,15 @@ describe("wrapLlmForSession", () => {
|
||||
);
|
||||
|
||||
expect(received).toHaveLength(1);
|
||||
expect(received[0].messages).toEqual([{ role: "user", content: "TASK" }]);
|
||||
expect(received[0].messages.map((m) => [m.role, m.content])).toEqual([
|
||||
["system", "PRESET_RULES"],
|
||||
["user", "TASK"],
|
||||
]);
|
||||
expect(received[0].generation).toMatchObject({
|
||||
temperature: 0.91,
|
||||
maxOutputTokens: 1234,
|
||||
});
|
||||
expect(ctx.pendingContextTrace?.messages).toEqual([
|
||||
{ role: "user", content: "TASK" },
|
||||
]);
|
||||
expect(ctx.pendingContextTrace?.messages).toEqual(received[0].messages);
|
||||
expect(ctx.pendingContextTrace?.generation).toMatchObject({
|
||||
temperature: 0.91,
|
||||
maxOutputTokens: 1234,
|
||||
@@ -80,7 +81,44 @@ describe("wrapLlmForSession", () => {
|
||||
expect(ctx.pendingContextTrace?.model).toBe("rec-model");
|
||||
});
|
||||
|
||||
it("completeStream also records the merged request", async () => {
|
||||
it("puts task system inside worldBookBefore, not before the preset shell", async () => {
|
||||
const { provider, received } = recordingProvider();
|
||||
const llm = wrapLlmForSession(provider, undefined, () => samplePreset);
|
||||
|
||||
await llm.completeWithTools(
|
||||
[
|
||||
{ role: "system", content: "SKILL" },
|
||||
{ role: "user", content: "do it" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: null,
|
||||
tool_calls: [
|
||||
{
|
||||
id: "1",
|
||||
type: "function",
|
||||
function: { name: "t", arguments: "{}" },
|
||||
},
|
||||
],
|
||||
},
|
||||
{ role: "tool", content: "{}", tool_call_id: "1" },
|
||||
],
|
||||
{ tools: [], caller: "dictate_agent" },
|
||||
);
|
||||
|
||||
expect(received[0].messages[0].content).toBe("PRESET_RULES");
|
||||
expect(
|
||||
received[0].messages.some(
|
||||
(m) => m.content === "### 任务契约\n\nSKILL",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(received[0].messages.some((m) => m.content === "do it")).toBe(true);
|
||||
expect(received[0].messages.map((m) => m.role).slice(-2)).toEqual([
|
||||
"assistant",
|
||||
"tool",
|
||||
]);
|
||||
});
|
||||
|
||||
it("completeStream also records the framed request", async () => {
|
||||
const { provider, received } = recordingProvider();
|
||||
const ctx: LlmTrackingContext = {};
|
||||
const llm = wrapLlmForSession(provider, { current: ctx }, () => samplePreset);
|
||||
@@ -93,7 +131,9 @@ describe("wrapLlmForSession", () => {
|
||||
);
|
||||
|
||||
expect(chunks.join("")).toBe("ok");
|
||||
expect(received[0].messages).toEqual([{ role: "user", content: "TASK" }]);
|
||||
expect(received[0].messages.some((m) => m.content === "PRESET_RULES")).toBe(
|
||||
true,
|
||||
);
|
||||
expect(ctx.pendingContextTrace?.messages).toEqual(received[0].messages);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user