feat: web switch for her inner voice (Dolphin/3090 | Qwen-32B/MI50 | Off)
Her introspection (reflect/think) voice is now switchable live from the web settings, read each cycle by the dream loop — so Brian can flip it off the 3090 before gaming without touching config or restarting. - memory: runtime key/value settings table + get_setting/set_setting. - self_state: INTROSPECTION_MODES (dolphin=local/dolphin3:8b, mi50=Qwen-32B, off=paused) + introspection_target()/set_introspection_mode(); default "dolphin". reflect() resolves from the live setting and SKIPS entirely when off. - thoughts.think(): same resolution + skip-when-off. - server: GET/POST /settings/introspection. - index.html: "Inner Voice (introspection)" selector in Settings, applies instantly. - tests: routing (dolphin/mi50), off-skip for think + reflect. Suite 77, ruff clean. Default = Dolphin on the 3090 (richer voice). Flip to MI50 or Off in Settings before gaming — that was the GPU-contention culprit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -243,6 +243,21 @@ def create_app() -> FastAPI:
|
||||
async def journal_data(limit: int = 300) -> dict:
|
||||
return {"entries": memory.list_journal(limit=limit)}
|
||||
|
||||
@app.get("/settings/introspection")
|
||||
async def get_introspection() -> dict:
|
||||
"""Current introspection (her inner voice) routing + the available options."""
|
||||
tgt = self_state.introspection_target()
|
||||
return {"mode": tgt["mode"],
|
||||
"options": [{"key": k, "label": v["label"]}
|
||||
for k, v in self_state.INTROSPECTION_MODES.items()]}
|
||||
|
||||
@app.post("/settings/introspection")
|
||||
async def set_introspection(request: Request) -> dict:
|
||||
"""Switch her inner voice: dolphin (3090) | mi50 (gaming-safe) | off."""
|
||||
b = await request.json()
|
||||
ok = await asyncio.to_thread(self_state.set_introspection_mode, b.get("mode", ""))
|
||||
return {"ok": ok, "mode": self_state.introspection_target()["mode"]}
|
||||
|
||||
@app.get("/thoughts")
|
||||
async def thoughts_page() -> FileResponse:
|
||||
"""Lyra's thought loop — threads she's been turning over, and a place to reply."""
|
||||
|
||||
@@ -169,6 +169,17 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-section" style="margin-top: 24px;">
|
||||
<h4>Inner Voice (introspection)</h4>
|
||||
<p class="settings-desc">Which model runs her reflections & thoughts (her dream loop).
|
||||
Dolphin is richer but shares the 3090 — switch to MI50 or Off before gaming.</p>
|
||||
<select id="introspectionMode">
|
||||
<option value="dolphin">Dolphin · 3090 (richer voice)</option>
|
||||
<option value="mi50">Qwen-32B · MI50 (gaming-safe)</option>
|
||||
<option value="off">Off (pause her thinking)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-section" style="margin-top: 24px;">
|
||||
<h4>Session Management</h4>
|
||||
<p class="settings-desc">Manage your saved chat sessions:</p>
|
||||
@@ -979,10 +990,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Inner-voice (introspection) switch — applies instantly, read live by the dream loop.
|
||||
const introspectionSel = document.getElementById("introspectionMode");
|
||||
async function loadIntrospection() {
|
||||
try {
|
||||
const r = await fetch("/settings/introspection", { cache: "no-store" });
|
||||
const d = await r.json();
|
||||
if (d.mode) introspectionSel.value = d.mode;
|
||||
} catch (e) {}
|
||||
}
|
||||
if (introspectionSel) {
|
||||
introspectionSel.addEventListener("change", async () => {
|
||||
try {
|
||||
await fetch("/settings/introspection", {
|
||||
method: "POST", headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ mode: introspectionSel.value })
|
||||
});
|
||||
} catch (e) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Show modal and load session list
|
||||
settingsBtn.addEventListener("click", () => {
|
||||
settingsModal.classList.add("show");
|
||||
loadSessionList(); // Refresh session list when opening settings
|
||||
loadIntrospection(); // reflect the current inner-voice setting
|
||||
});
|
||||
|
||||
// Sidebar "Settings" from another page navigates here with ?settings=1.
|
||||
|
||||
Reference in New Issue
Block a user