diff --git a/lyra/chat.py b/lyra/chat.py index 02a987b..d9ba75b 100644 --- a/lyra/chat.py +++ b/lyra/chat.py @@ -113,14 +113,21 @@ def build_messages(session_id: str, user_msg: str) -> list[Message]: return messages -def respond(session_id: str, user_msg: str, backend: Backend = "cloud") -> str: - """Produce Lyra's reply to a single user message and persist the exchange.""" +def respond(session_id: str, user_msg: str, backend: Backend = "cloud", + model_override: str | None = None) -> str: + """Produce Lyra's reply to a single user message and persist the exchange. + + `model_override` (from the UI's cloud-model picker) only applies on the cloud + backend; local/mi50 keep their own configured models. + """ cfg = config.load() # Live chat uses the stronger chat_model on cloud (bulk consolidation keeps # cloud_model). local/mi50 use their own configured model. model = {"local": cfg.local_model, "cloud": cfg.chat_model, "mi50": cfg.mi50_model}.get( backend, backend ) + if model_override and backend == "cloud": + model = model_override logbus.log( "info", "chat request", session=session_id, backend=backend, model=model, embed=cfg.embed_backend, diff --git a/lyra/web/server.py b/lyra/web/server.py index f2a3b1c..87a478b 100644 --- a/lyra/web/server.py +++ b/lyra/web/server.py @@ -92,9 +92,10 @@ def create_app() -> FastAPI: backend = _backend_for(body.get("backend")) user_msg = _last_user_message(body.get("messages", [])) + model_override = body.get("model") or None memory.ensure_session(session_id) try: - reply = await asyncio.to_thread(chat.respond, session_id, user_msg, backend) + reply = await asyncio.to_thread(chat.respond, session_id, user_msg, backend, model_override) except Exception as exc: logbus.log("error", "chat failed", session=session_id, error=str(exc)) reply = f"[error] {exc}" diff --git a/lyra/web/static/index.html b/lyra/web/static/index.html index 5ad59ac..fafc32f 100644 --- a/lyra/web/static/index.html +++ b/lyra/web/static/index.html @@ -143,6 +143,19 @@ +
+

Chat Model (Cloud)

+

Which OpenAI model answers on the Cloud backend. Tools (poker, equity, journaling) require Cloud.

+ +
+

Session Management

Manage your saved chat sessions:

@@ -283,6 +296,12 @@ body.backend = backend; } + // Cloud chat-model override (ignored server-side unless backend is cloud) + const cloudModel = localStorage.getItem("cloudModel"); + if (cloudModel) { + body.model = cloudModel; + } + try { const resp = await fetch(API_URL, { method: "POST", @@ -571,6 +590,10 @@ const initialRadio = document.querySelector(`input[name="backend"][value="${savedBackend}"]`); if (initialRadio) initialRadio.checked = true; + // Restore saved cloud-model choice + const savedModelSel = document.getElementById("cloudModel"); + if (savedModelSel) savedModelSel.value = localStorage.getItem("cloudModel") || ""; + // Session management functions async function loadSessionList() { try { @@ -679,7 +702,11 @@ const backendValue = selectedRadio ? selectedRadio.value : "local"; localStorage.setItem("standardModeBackend", backendValue); - addMessage("system", `Backend changed to: ${backendValue}`); + const modelSel = document.getElementById("cloudModel"); + const modelValue = modelSel ? modelSel.value : ""; + localStorage.setItem("cloudModel", modelValue); + const modelLabel = modelValue || "default (gpt-4o)"; + addMessage("system", `Backend: ${backendValue} ยท cloud model: ${modelLabel}`); hideModal(); });