Issues / #738

#738 Configurable system prompt in the web GUI

open · @RobinMeyer · 1 comments · View on GitHub

Server & API

Description

At first, thanks for the great program!
A system prompt can change the output dramatically, especially for story telling etc.
Please add a system prompt text edit in the preferences of the web GUI. Here is a proposal:
```
--- a/serve/web/app.js
+++ b/serve/web/app.js
@@ -461,7 +461,7 @@
 
 // ------------------------------------------------------------------ Chat
-const DEFAULTS = {thinking: "high", temperature: 0.6, top_p: 0.95, top_k: 20, max: "", seed: "", show: true, esp: true, mcp: true};
+const DEFAULTS = {thinking: "high", temperature: 0.6, top_p: 0.95, top_k: 20, max: "", seed: "", show: true, esp: true, mcp: true, system_prompt: ""};
 let settings = {...DEFAULTS, ...store.get("sampling", {})};
 let messages = store.get("chat", []);
 let attachments = [];                 // {name, url}
@@ -625,6 +625,8 @@
     if (d.open && body.dataset.pending) { body.textContent = messages[+d.closest(".st-msg").dataset.i].reasoning; delete body.dataset.pending; }
 }, true);
 
+// The optional browser-local instruction is prepended to every chat request.
+// It is deliberately not saved in the chat transcript or sent to shared API defaults.
 function apiMessages() {
   const out = [];
   for (const m of messages) {
@@ -637,7 +639,9 @@
       out.push(...assistantMessages(m));
     }
   }
-  return out;
+  const systemPrompt = (settings.system_prompt || "").trim();
+  return systemPrompt ? [{role: "system", content: systemPrompt}, ...out] : out;
 }
 // An answer that used MCP tools goes back as the model wrote it: per round the text before the calls, the calls and
 // their results (as the model read them), then the rest - so the next question can build on what the tools found.
@@ -877,6 +881,22 @@
 
 // ------------------------------------------------------------------ the sampling drawer
+function ensureSystemPromptField() {
+  if ($("s-system-prompt")) return;
+
+  const field = document.createElement("div");
+  field.className = "st-field";
+  field.innerHTML =
+    `<label class="st-label" for="s-system-prompt">System prompt</label>` +
+    `<textarea class="st-input" id="s-system-prompt" rows="5" ` +
+    `placeholder="Optional instructions for every message in this chat"></textarea>` +
+    `<span class="muted small">Stored only in this browser; it is sent as the first system message.</span>`;
+
+  $("s-seed").closest(".st-field").insertAdjacentElement("afterend", field);
+}
+
 function openDrawer(open) {
   $("drawer").dataset.open = String(open);
   $("drawer").setAttribute("aria-hidden", String(!open));
@@ -884,10 +904,12 @@
   if (open) { loadDrawer(); loadShared(); loadMcp(); }
 }
 function loadDrawer(s = settings) {
+  ensureSystemPromptField();
   for (const b of $("s-thinking").children) b.setAttribute("aria-checked", String(b.dataset.v === s.thinking));
   $("s-temp").value = s.temperature; $("s-topp").value = s.top_p; $("s-topk").value = s.top_k;
   $("s-max").value = s.max; $("s-seed").value = s.seed;
+  $("s-system-prompt").value = s.system_prompt || "";
   $("s-show").setAttribute("aria-checked", String(!!s.show));
   $("s-esp").setAttribute("aria-checked", String(s.esp !== false));
   $("esp-row").hidden = !projectionLoaded();
@@ -946,10 +968,11 @@
   const sel = [...$("s-thinking").children].find((b) => b.getAttribute("aria-checked") === "true");
   settings = {thinking: sel ? sel.dataset.v : "high", temperature: +$("s-temp").value, top_p: +$("s-topp").value,
               top_k: +$("s-topk").value, max: $("s-max").value.trim(), seed: $("s-seed").value.trim(),
+              system_prompt: $("s-system-prompt").value,
               show: $("s-show").getAttribute("aria-checked") === "true",
               esp: $("s-esp").getAttribute("aria-checked") === "true",
               mcp: $("s-mcp").getAttribute("aria-checked") === "true"};
   store.set("sampling", settings);```

Related on strata.com

Editorial links to help you install, pick models, or read release notes — not part of the upstream thread.