o2o-negosium-original/agent/negotiation/profiling/infra/llm_adapter.py

52 lines
2.0 KiB
Python

"""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)