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.openai") class OpenAIProvider(LLMProvider): def __init__(self): kwargs = {"api_key": settings.llm_api_key} if settings.llm_base_url: kwargs["base_url"] = settings.llm_base_url self.client = AsyncOpenAI(**kwargs) self.model = settings.llm_model or "gpt-4o" 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 OpenAI ({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}, ], response_format={"type": "json_object"}, ) text = response.choices[0].message.content.strip() try: data = json.loads(text) return data.get("recommendations", []) except json.JSONDecodeError: logger.error(f"Failed to parse LLM response: {text[:200]}") return []