"""LLM 어댑터 — openai SDK 직접 호출 (langchain 미사용). provider 로 OpenAI / Azure OpenAI 분기. 무거운 import 는 호출 시점에 한다. chat_complete: messages → 응답 텍스트. json_mode 면 JSON 객체 강제(response_format). """ import json from typing import List, Optional from negotiation.profiling.config import LlmCredentials def _client(creds: LlmCredentials): if creds.provider == "azure": from openai import AzureOpenAI return AzureOpenAI(api_key=creds.api_key, azure_endpoint=creds.azure_endpoint, api_version=creds.api_version or "2024-06-01") from openai import OpenAI kwargs = {"api_key": creds.api_key} if creds.base_url: kwargs["base_url"] = creds.base_url return OpenAI(**kwargs) def chat_complete(messages: List[dict], creds: Optional[LlmCredentials] = None, json_mode: bool = False, temperature: float = 0.7, max_tokens: int = 1024) -> str: """OpenAI(또는 Azure) chat completion 호출 → 응답 텍스트. Args: messages: [{"role": "system"|"user"|"assistant", "content": "..."}] creds: 자격증명(없으면 OpenAIConfig 전역값). json_mode: True 면 JSON 객체 응답 강제. """ if creds is None: creds = LlmCredentials.from_config() if not creds.is_configured(): raise RuntimeError("LLM 미설정 (OpenAIConfig.api_key/model 확인)") client = _client(creds) kwargs = {"model": creds.model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens} if json_mode: kwargs["response_format"] = {"type": "json_object"} resp = client.chat.completions.create(**kwargs) return resp.choices[0].message.content or "" def chat_json(messages: List[dict], creds: Optional[LlmCredentials] = None, **kw) -> dict: """JSON 응답을 파싱해 dict 로 반환.""" text = chat_complete(messages, creds=creds, json_mode=True, **kw) return json.loads(text)