import json import logging from openai import AsyncOpenAI from app.config import settings from app.models import Movie from app.services.llm.base import SYSTEM_PROMPT, LLMProvider, build_user_message logger = logging.getLogger("movie-night.llm.ollama") class OllamaProvider(LLMProvider): def __init__(self): base_url = settings.llm_base_url or "http://localhost:11434/v1" self.client = AsyncOpenAI(api_key="ollama", base_url=base_url) self.model = settings.llm_model or "llama3" async def get_recommendations(self, mood: str, candidates: list[Movie], max_results: int = 6) -> list[dict]: system = SYSTEM_PROMPT.format(max_results=max_results) user_msg = build_user_message(mood, candidates) logger.info(f"Calling Ollama ({self.model}) with {len(candidates)} candidates") response = await self.client.chat.completions.create( model=self.model, max_tokens=2048, messages=[ {"role": "system", "content": system}, {"role": "user", "content": user_msg}, ], ) text = response.choices[0].message.content.strip() try: data = json.loads(text) return data.get("recommendations", []) except json.JSONDecodeError: # Try to extract JSON from response start = text.find("{") end = text.rfind("}") + 1 if start >= 0 and end > start: try: data = json.loads(text[start:end]) return data.get("recommendations", []) except json.JSONDecodeError: pass logger.error(f"Failed to parse Ollama response: {text[:200]}") return []