package com.erp.ai.client; import com.erp.ai.exception.LlmClientException; import com.erp.ai.mapper.AiLlmProviderMapper; import com.erp.ai.model.AiLlmProvider; import com.erp.ai.util.AesGcmCipher; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.client.RestClient; import org.springframework.web.client.RestClientResponseException; import java.util.Map; /** * OpenAI LLM 클라이언트 (DeepSeek 등 OpenAI 호환 프로바이더 포함). */ @Slf4j @Component @RequiredArgsConstructor public class OpenAiLlmClient implements LlmClient { private static final String DEFAULT_BASE_URL = "https://api.openai.com"; @Qualifier("llmRestClient") private final RestClient httpClient; private final AiLlmProviderMapper providerMapper; private final AesGcmCipher cipher; @Override public boolean supports(String model) { return model != null && (model.startsWith("gpt-") || model.startsWith("o1-") || model.startsWith("o3-")); } @Override public String providerName() { return "openai"; } @Override @SuppressWarnings("unchecked") public Map chat(Map request) { AiLlmProvider provider = providerMapper.getByName("openai"); if (provider == null || !Boolean.TRUE.equals(provider.getIs_active())) { throw new LlmClientException("OpenAI 프로바이더가 활성화되지 않았습니다."); } String apiKey = cipher.decrypt(provider.getApi_key_encrypted()); String baseUrl = provider.getEndpoint() != null ? provider.getEndpoint() : DEFAULT_BASE_URL; try { return httpClient.post() .uri(baseUrl + "/v1/chat/completions") .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + apiKey) .body(request) .retrieve() .body(Map.class); } catch (RestClientResponseException e) { log.error("OpenAI API 오류 {}: {}", e.getStatusCode().value(), e.getResponseBodyAsString()); throw new LlmClientException("OpenAI API 오류: " + e.getMessage(), e.getStatusCode().value()); } catch (Exception e) { throw new LlmClientException("OpenAI 호출 실패: " + e.getMessage(), e); } } }