package com.caliverse.admin.domain.service; import com.caliverse.admin.domain.dao.admin.MailMapper; import com.caliverse.admin.domain.entity.AI.AIRequestType; import com.caliverse.admin.domain.entity.AI.AIRole; import com.caliverse.admin.domain.entity.Mail; import com.caliverse.admin.domain.request.AIRequest; import com.caliverse.admin.domain.request.LogGenericRequest; import com.caliverse.admin.domain.request.OpenAIRequest; import com.caliverse.admin.domain.response.AIResponse; import com.caliverse.admin.domain.response.OpenAIResponse; import com.caliverse.admin.global.common.code.CommonCode; import com.caliverse.admin.global.common.constants.CommonConstants; import com.caliverse.admin.global.common.utils.CommonUtils; import com.caliverse.admin.logs.Indicatordomain.GenericMongoLog; import com.caliverse.admin.logs.logservice.businesslogservice.BusinessLogGenericService; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; @Slf4j @Service @RequiredArgsConstructor public class AIService { @Autowired private ObjectMapper mapper; private final OpenAIService openAIService; private final BusinessLogGenericService businessLogGenericService; private final MailMapper mailMapper; public AIResponse aiMessageAnalyze(AIRequest dataRequest){ List> messages = initMessage(); List data = getDataList(dataRequest.getType(), dataRequest.getConditions()); messages = splitDataToMessages(messages, data, dataRequest.getMessage()); OpenAIRequest openAIRequest = new OpenAIRequest(); openAIRequest.setMessages(messages); OpenAIResponse result = openAIService.askOpenAI(openAIRequest); log.info(result.getChoices().get(0).getMessage().getContent()); return AIResponse.builder() .resultData(AIResponse.ResultData.builder() .result(result.getChoices().get(0).getMessage().getContent()) .build()) .status(CommonCode.SUCCESS.getHttpStatus()) .result(CommonCode.SUCCESS.getResult()) .build(); } private List> splitDataToMessages(List> messages, List dataList, String userMessage) { String dataJson; try { dataJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(dataList); } catch (JsonProcessingException e) { throw new RuntimeException("JSON 변환 실패", e); } messages.add(CommonUtils.getAIMessage(AIRole.user, messageMerge(userMessage, dataJson))); return messages; } private String messageMerge(String message, String data){ return String.format("사용자 질문: %s\n\n아래는 시스템이 제공하는 데이터입니다.\n%s", message, data); } private List> initMessage(){ List> messages = new ArrayList<>(); messages.add(CommonUtils.getAIMessage(AIRole.system, """ 너는 프론트엔드 게시용 데이터를 생성하는 게임 데이터 분석 AI야. \ 사용자는 게임 로그 데이터와 함께 다양한 질문을 보낼 수 있어. \ 너는 항상 HTML 또는 React 코드 형식으로 응답해야 해. \ 응답에는 반드시 다음 항목을 포함해줘: \ 1) 분석된 내용 설명 \ 2) 분석된 요약 결과 (표 또는 문단) \ 3) 시각화 차트 (예: bar chart, pie chart 등) \ 응답은 반드시 한국어로 작성해. \ 절대로 파이썬, Java, Node.js 코드 같은 것은 포함하지 마. \ 사용자의 웹에 그대로 게시될 수 있는 코드만 생성해. \ React를 쓸 경우, React 18 기준 코드로 TailwindCSS 기반의 스타일을 사용해줘. """)); return messages; } private List getDataList(AIRequestType type, Map conditions){ switch (type){ case BUSINESS_LOG -> { LogGenericRequest logReq = mapper.convertValue(conditions, LogGenericRequest.class); List logs = businessLogGenericService.loadBusinessLogData(logReq, GenericMongoLog.class, true); return logs; } case MAIL -> { List mailList = mailMapper.getMailList(conditions); return mailList; } default -> throw new RuntimeException("Not Type"); } } }