From 9a07a270011ed37df3d50728af74f7ab5414c97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 5 Jun 2026 13:56:06 +0200 Subject: [PATCH] fix(insights): default to current full-size AI models for the headline feature The OpenAI BYOK + admin-shared fallback defaulted to a small model and Anthropic to a 2024 Sonnet, so a user on the operator's shared key got the weakest model for the Insights assessments. Bump the OpenAI default to gpt-4o and the Anthropic default to claude-sonnet-4-6; both stay overridable by user config. Sync the provider docs. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/integrations/ai-providers.md | 31 ++++++++++++++++--------------- src/lib/ai/provider.ts | 12 ++++++------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/docs/integrations/ai-providers.md b/docs/integrations/ai-providers.md index c24679214..547364392 100644 --- a/docs/integrations/ai-providers.md +++ b/docs/integrations/ai-providers.md @@ -11,8 +11,8 @@ Ollama endpoint can fall back from one to the other automatically. | Provider | Key acquisition | Default model | Endpoint | Privacy stance | | -------- | ---------------- | ------------- | -------- | -------------- | -| `OPENAI` | | `gpt-4o-mini` | `https://api.openai.com/v1` | Measurement context sent to OpenAI | -| `ANTHROPIC` | | `claude-3-5-sonnet-latest` | Anthropic SDK default | Measurement context sent to Anthropic | +| `OPENAI` | | `gpt-4o` | `https://api.openai.com/v1` | Measurement context sent to OpenAI | +| `ANTHROPIC` | | `claude-sonnet-4-6` | Anthropic SDK default | Measurement context sent to Anthropic | | `LOCAL` | None (your endpoint) | `local-model` | OpenAI-compatible URL you control | Stays on your network | | `CHATGPT_OAUTH` | Sign in with your ChatGPT account | Codex-routed | `chatgpt.com/backend-api/codex/responses` | Routed via your ChatGPT subscription | @@ -71,16 +71,17 @@ the default rather than 500-ing. 4. In HealthLog, open `/settings/ai`. Set provider to **OpenAI**, paste the key, optionally override the model. -The default model is `gpt-4o-mini` (`src/lib/ai/provider.ts:80`) — -cheap, fast, and grounded enough for the structured-output Coach -prompts. Override to `gpt-4o` or `gpt-4.1` if you want more reasoning -headroom and accept the per-token cost. +The default model is `gpt-4o` (`src/lib/ai/provider.ts:80`) — a +full-size model that keeps the headline Insights assessments grounded +and well-reasoned out of the box. Override to a lighter model such as +`gpt-4o-mini` if you want to trade some reasoning headroom for a lower +per-token cost. **Cost expectation.** A daily briefing for an active account runs at -roughly 4–8k input tokens + ~1k output. At gpt-4o-mini's published -rates that is well under a US cent per briefing; a heavy user -generating multiple Coach turns plus a weekly report typically spends -a few dollars per month. +roughly 4–8k input tokens + ~1k output. At gpt-4o's published rates +that is a fraction of a US cent per briefing; a heavy user generating +multiple Coach turns plus a weekly report typically spends a few +dollars per month. A lighter override drops this further. ## Anthropic setup @@ -91,16 +92,16 @@ a few dollars per month. 4. In HealthLog, open `/settings/ai`. Set provider to **Anthropic**, paste the key, optionally override the model. -The default model is `claude-3-5-sonnet-latest` (`src/lib/ai/provider.ts:55`). +The default model is `claude-sonnet-4-6` (`src/lib/ai/provider.ts`). The Anthropic client refuses to forward an Anthropic key to a stale `aiBaseUrl` even if one is parked in the shared column — Anthropic has no per-tenant base URL the UI exposes; the SDK default is the only correct endpoint. -**Cost expectation.** Claude 3.5 Sonnet runs roughly 5x the per-token -cost of `gpt-4o-mini` but produces noticeably stronger reasoning on -the more structured Coach prompts. Most BYOK users on Claude spend -in the low single digits per month. +**Cost expectation.** A current Sonnet runs at a higher per-token +cost than a lightweight OpenAI model but produces noticeably stronger +reasoning on the more structured Coach prompts. Most BYOK users on +Claude spend in the low single digits per month. ## Local endpoints (Ollama, LM Studio, vLLM) diff --git a/src/lib/ai/provider.ts b/src/lib/ai/provider.ts index 26e1a10ae..e695f3058 100644 --- a/src/lib/ai/provider.ts +++ b/src/lib/ai/provider.ts @@ -70,14 +70,14 @@ function buildUserProvider(row: UserAIRow): AIProvider | null { // to the admin key if the user hasn't supplied their own. The // model-default mirrors the admin path for consistency so a saved // user "OPENAI" without an explicit model still produces an - // OpenAIClient with `gpt-4o-mini`. + // OpenAIClient with the current full-size default `gpt-4o`. // Belt-and-braces: ignore any persisted `aiBaseUrl`. The column is // shared with LOCAL, so a stale LAN URL there would otherwise // redirect the user's OpenAI key to a private host. if (!row.aiOpenaiKeyEncrypted) return null; return new OpenAIClient({ apiKey: decrypt(row.aiOpenaiKeyEncrypted), - model: row.aiModel ?? "gpt-4o-mini", + model: row.aiModel ?? "gpt-4o", baseUrl: "https://api.openai.com/v1", }); } @@ -97,7 +97,7 @@ async function resolveAdminProvider(): Promise { if (settings?.adminAiKeyEncrypted) { return new OpenAIClient({ apiKey: decrypt(settings.adminAiKeyEncrypted), - model: settings.adminAiModel ?? "gpt-4o-mini", + model: settings.adminAiModel ?? "gpt-4o", baseUrl: settings.adminAiBaseUrl ?? "https://api.openai.com/v1", }); } @@ -339,7 +339,7 @@ async function resolveProviderForType( if (!enc) return null; return new OpenAIClient({ apiKey: decrypt(enc), - model: ctx.userRow?.aiModel ?? "gpt-4o-mini", + model: ctx.userRow?.aiModel ?? "gpt-4o", baseUrl: "https://api.openai.com/v1", }); } @@ -348,7 +348,7 @@ async function resolveProviderForType( if (!enc) return null; return new AnthropicClient({ apiKey: decrypt(enc), - model: ctx.userRow?.aiModel ?? "claude-3-5-sonnet-latest", + model: ctx.userRow?.aiModel ?? "claude-sonnet-4-6", }); } case "local": { @@ -501,7 +501,7 @@ export async function resolveProviderForTest( if (userKey) { return new OpenAIClient({ apiKey: userKey, - model: model || "gpt-4o-mini", + model: model || "gpt-4o", baseUrl: "https://api.openai.com/v1", }); }