fix(api): correct mana-llm path prefix and model name in vision routes

Found while smoke-testing the AI SDK refactor: both nutriphi and planta
were calling `${MANA_LLM_URL}/api/v1/chat/completions` and passing
`gemini-2.0-flash` as the model name. Both wrong:

  1. mana-llm exposes routes under /v1/, not /api/v1/. The original
     pre-refactor code had the same bug — it predates this commit and
     was apparently never noticed because the photo workflow was never
     wired into the unified app's UI until last week. /api/v1 returned
     404 against the live mana-llm container; now we hit /v1.

  2. mana-llm's router parses model strings as `provider/model`
     (services/mana-llm/src/providers/router.py:_parse_model). Without
     a prefix, `gemini-2.0-flash` was being routed as
     `ollama/gemini-2.0-flash` and only worked via the auto-fallback
     to Google when ollama failed. Be explicit: `google/gemini-2.0-flash`
     hits the Google provider directly and skips the failed-ollama
     round-trip.

VISION_MODEL env var still wins over the default, so prod overrides
remain possible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-09 18:11:43 +02:00
parent 6c0f88f5a2
commit 3ccfc3be99
2 changed files with 12 additions and 4 deletions

View file

@ -32,11 +32,17 @@ import {
import { logger, type AuthVariables } from '@mana/shared-hono';
const LLM_URL = process.env.MANA_LLM_URL || 'http://localhost:3025';
const VISION_MODEL = process.env.VISION_MODEL || 'gemini-2.0-flash';
// mana-llm parses model strings as `provider/model` (router.py:_parse_model).
// Without a prefix, it defaults to ollama/ which then falls back to Google
// only if auto_fallback_enabled + google_api_key are set. Be explicit.
const VISION_MODEL = process.env.VISION_MODEL || 'google/gemini-2.0-flash';
const llm = createOpenAICompatible({
name: 'mana-llm',
baseURL: `${LLM_URL}/api/v1`,
// mana-llm exposes /v1/chat/completions (see services/mana-llm/CLAUDE.md +
// src/main.py:125). The AI SDK's openai-compatible adapter appends
// /chat/completions to baseURL, so baseURL ends in /v1.
baseURL: `${LLM_URL}/v1`,
});
const ANALYSIS_PROMPT = `Du bist ein Ernährungsexperte. Analysiere die Mahlzeit und gib strukturierte Nährwertdaten zurück. Schätze realistische Portionsgrößen und Kalorien. Antworte auf Deutsch.`;

View file

@ -21,11 +21,13 @@ import {
import { logger, type AuthVariables } from '@mana/shared-hono';
const LLM_URL = process.env.MANA_LLM_URL || 'http://localhost:3025';
const VISION_MODEL = process.env.VISION_MODEL || 'gemini-2.0-flash';
// See nutriphi/routes.ts for the explanation of the model prefix and
// the /v1 suffix on the base URL.
const VISION_MODEL = process.env.VISION_MODEL || 'google/gemini-2.0-flash';
const llm = createOpenAICompatible({
name: 'mana-llm',
baseURL: `${LLM_URL}/api/v1`,
baseURL: `${LLM_URL}/v1`,
});
const IDENTIFICATION_PROMPT = `Du bist ein Pflanzenexperte. Analysiere das Pflanzenfoto und liefere eine strukturierte Identifikation mit lateinischem Namen, deutschen Trivialnamen, Pflegehinweisen und einer Gesundheitseinschätzung. Antworte auf Deutsch.`;