"""Cliente OpenAI compartilhado. Um único OpenAI() reusado em toda a aplicação. Cobre tanto LLM quanto juiz. """ from functools import lru_cache from openai import OpenAI from src.config import get_settings @lru_cache def get_openai_client() -> OpenAI: """Singleton do cliente OpenAI.""" settings = get_settings() return OpenAI(api_key=settings.openai_api_key) def chat_completion( messages: list[dict], model: str | None = None, tools: list[dict] | None = None, tool_choice: str | dict = "auto", temperature: float = 0.7, response_format: dict | None = None, ) -> dict: """Wrapper sobre chat.completions.create com defaults sensatos. Retorna o primeiro `choice.message` como dict (já serializado). """ client = get_openai_client() settings = get_settings() kwargs: dict = { "model": model or settings.openai_model, "messages": messages, "temperature": temperature, } if tools: kwargs["tools"] = tools kwargs["tool_choice"] = tool_choice if response_format: kwargs["response_format"] = response_format response = client.chat.completions.create(**kwargs) message = response.choices[0].message return message.model_dump()