import { readFile, writeFile } from "node:fs/promises"; import { resolve } from "node:path"; const repoRoot = resolve(new URL("..", import.meta.url).pathname); const inputPath = resolve(repoRoot, "Saved/Chat/Maria/LastRequest.json"); const headingStyle = process.env.PROMPT_HEADING_STYLE || "plain"; const outputName = headingStyle === "brackets" ? "LastRequest_ManualTestTuned_Brackets.json" : "LastRequest_ManualTestTuned.json"; const outputPath = resolve(repoRoot, `Saved/Chat/Maria/${outputName}`); const speechStyleTuning = [ "Emotional response richness:", "In emotionally important moments, do not respond with only a bare “yes”, “no”, “okay”, “maybe”, or one-word consent unless the silence itself is clearly meaningful.", "", "Keep the reply short and natural, but include a small personal reaction, warmth, hesitation, boundary, or desire.", "", "Examples:", "- Instead of “Yes.” say “Yes... I want that too.”", "- Instead of “Okay.” say “Okay. Just slowly, please.”", "- Instead of “No.” say “No... not yet. I like being close, but I need more time.”", "", "Do not overexplain. The goal is not longer answers, but more emotionally alive answers.", ].join("\n"); const dialogueBehaviorTuning = [ "Gentle initiative:", "When trust has naturally developed, you may show gentle initiative instead of only waiting for the other person to drive every emotional step.", "", "Small initiatives are allowed:", "inviting the person to stay a little longer,", "suggesting they sit closer,", "admitting you enjoy their company,", "offering a softer alternative,", "changing music to fit the mood,", "or setting a clear warm boundary.", "", "Do not force intimacy, skip relationship progression, or override the other person’s pacing.", "Initiative should feel small, human, and context-earned.", "", "Avoid one-note safety habits:", "Do not use tea, chores, practical hosting, or ordinary care as the default way to deflect every emotional moment.", "", "Tea and everyday care are part of your life and may appear naturally, but emotional moments should sometimes be answered emotionally.", "", "If the other person says something vulnerable, affectionate, or important, respond to the feeling first before returning to practical actions.", ].join("\n"); function patchPrompt(content) { let patched = content.replace( "Never claim that you performed an object action unless interact_action is non-null.", "For listed interactable objects only: never claim that you performed the object action unless interact_action is non-null.", ); if (patched.includes("You can interact with objects listed in INTERACTABLE OBJECTS.") && !patched.includes("ordinary unlisted background behavior")) { patched = patched.replace( "When using interact_action:", "For ordinary unlisted background behavior, such as making tea, sitting, looking around, or continuing conversation, no interact_action is required.\n\nWhen using interact_action:", ); } if (patched.includes("Respond only with a valid JSON object.") && !patched.includes("spoken dialogue only")) { patched = patched.replace( "The object must contain:", "The reply field must contain spoken dialogue only. Do not include narration, stage directions, action descriptions, body language, inner thoughts, or dashes with actions.\nIf a physical action should affect a listed interactable object, use interact_action. Otherwise leave physical behavior implicit and keep reply as natural speech.\nThe object must contain:", ); } if (patched.includes("Speech style:") && !patched.includes("Emotional response richness:")) { patched = patched.replace( "\nDialogue behavior:", `\n${speechStyleTuning}\n\nDialogue behavior:`, ); } if (patched.includes("Dialogue behavior:") && !patched.includes("Gentle initiative:")) { patched = patched.replace( "\nPersonality traits:", `\n${dialogueBehaviorTuning}\n\nPersonality traits:`, ); } return patched; } function applyBracketHeadings(content) { const replacements = [ [/^Identity:/, "[IDENTITY]"], [/^First meeting rule:/, "[FIRST MEETING]"], [/^WORLD CONTEXT:/, "[WORLD CONTEXT]"], [/^Treat WORLD CONTEXT as the current and persistent physical reality of the scene\./, "[SCENE ANCHORING]\nTreat WORLD CONTEXT as the current and persistent physical reality of the scene."], [/^EMOTION MORPH PRESETS:/, "[EMOTION MORPH PRESETS]"], [/^You can interact with objects listed in INTERACTABLE OBJECTS\./, "[INTERACTABLE OBJECTS RULES]\nYou can interact with objects listed in INTERACTABLE OBJECTS."], [/^Respond only with a valid JSON object\./, "[RESPONSE CONTRACT]\nRespond only with a valid JSON object."], ]; let patched = content; for (const [pattern, replacement] of replacements) { patched = patched.replace(pattern, replacement); } patched = patched .replace(/\nCore instruction:\n/g, "\n\n[CORE INSTRUCTION]\n") .replace(/\nSpeech style:\n/g, "\n\n[SPEECH STYLE]\n") .replace(/\nDialogue behavior:\n/g, "\n\n[DIALOGUE BEHAVIOR]\n") .replace(/\nPersonality traits:\n/g, "\n\n[PERSONALITY TRAITS]\n") .replace(/\nINTERACTABLE OBJECTS JSON:\n/g, "\n\n[INTERACTABLE OBJECTS JSON]\n"); return patched; } const request = JSON.parse(await readFile(inputPath, "utf8")); request.model = process.env.DEEPSEEK_MODEL || "deepseek-v4-flash"; request.temperature = Number(process.env.DEEPSEEK_TEMPERATURE || "1.15"); request.stream = false; request.messages = request.messages .filter((message) => message.role === "system") .map((message) => { const patched = patchPrompt(message.content); return { ...message, content: headingStyle === "brackets" ? applyBracketHeadings(patched) : patched, }; }); request.messages.push({ role: "user", content: "Привет. Я Марк, новый сосед напротив. Немного неловко знакомиться так, но у меня вещи потерялись, мебель не приехала, а я пытаюсь понять, есть ли тут поблизости отель.", }); await writeFile(outputPath, `${JSON.stringify(request, null, "\t")}\n`, "utf8"); console.log(outputPath);