Skip to content

Commit 60d61f9

Browse files
committed
hotfix: gpt prompt 수정
1 parent 62c7a88 commit 60d61f9

File tree

4 files changed

+60
-6
lines changed

4 files changed

+60
-6
lines changed

src/main/java/com/haru/api/domain/moodTracker/service/MoodTrackerReportServiceImpl.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,59 @@ public void generateReport(Long moodTrackerId) {
125125

126126
}
127127

128+
/* ========================= 헬퍼들 ========================= */
129+
130+
@SuppressWarnings("unchecked")
131+
private String extractContentSafely(Map<String, Object> responseBody) {
132+
Object choicesObj = responseBody.get("choices");
133+
if (!(choicesObj instanceof List<?> choices) || choices.isEmpty())
134+
throw new MoodTrackerHandler(ErrorStatus.GPT_FAILED);
135+
136+
Object first = choices.get(0);
137+
if (!(first instanceof Map<?, ?> firstMap))
138+
throw new MoodTrackerHandler(ErrorStatus.GPT_FAILED);
139+
140+
Object messageObj = firstMap.get("message");
141+
if (messageObj instanceof Map<?, ?> messageMap) {
142+
Object contentObj = messageMap.get("content");
143+
if (contentObj instanceof String s) return s;
144+
}
145+
Object textObj = firstMap.get("text");
146+
if (textObj instanceof String s) return s;
147+
148+
throw new MoodTrackerHandler(ErrorStatus.GPT_FAILED);
149+
}
150+
151+
/** ```json ... ``` 형태여도 첫 번째 JSON 오브젝트만 추출 */
152+
private String extractFirstJsonObject(String content) {
153+
if (content == null || content.isBlank())
154+
throw new MoodTrackerHandler(ErrorStatus.GPT_FAILED);
155+
156+
String cleaned = content
157+
.replaceAll("(?s)```json\\s*", "")
158+
.replaceAll("(?s)```\\s*", "")
159+
.trim();
160+
161+
int start = cleaned.indexOf('{');
162+
int end = findMatchingBrace(cleaned, start);
163+
if (start >= 0 && end > start) return cleaned.substring(start, end + 1);
164+
return cleaned; // 순수 JSON일 수도 있음
165+
}
166+
167+
private int findMatchingBrace(String s, int start) {
168+
if (start < 0) return -1;
169+
int depth = 0;
170+
for (int i = start; i < s.length(); i++) {
171+
char c = s.charAt(i);
172+
if (c == '{') depth++;
173+
else if (c == '}') {
174+
depth--;
175+
if (depth == 0) return i;
176+
}
177+
}
178+
return -1;
179+
}
180+
128181
private String buildPrompt(String title,
129182
List<SurveyQuestion> questions,
130183
Map<Long, List<SubjectiveAnswer>> subjectiveMap,

src/main/java/com/haru/api/global/apiPayload/code/status/ErrorStatus.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ public enum ErrorStatus implements BaseErrorCode {
7272
MAIL_SEND_FAIL(HttpStatus.INTERNAL_SERVER_ERROR, "MAIL500", "이메일 전송에 실패했습니다. (존재하지 않는 이메일일 수 있습니다)"),
7373
MAIL_INVALID_FORMAT(HttpStatus.BAD_REQUEST, "MAIL400", "이메일 형식이 잘못되었습니다."),
7474

75+
// GPT 에러
76+
GPT_FAILED(HttpStatus.SERVICE_UNAVAILABLE, "GPT500", "GPT 에러입니다."),
77+
7578
// SNS 이벤트 관련 에러
7679
SNS_EVENT_NOT_FOUND(HttpStatus.BAD_REQUEST, "SNSEVENT4001", "SNS 이벤트가 존재하지 않습니다."),
7780
SNS_EVENT_LINK_NOT_FOUND(HttpStatus.BAD_REQUEST, "SNS_EVENT4002", "잘못된 인스타그램 게시물 링크 형식입니다."),

src/main/java/com/haru/api/infra/api/client/ChatGPTClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public Mono<SurveyReportResponse> getMoodTrackerReport(String userMessageContent
155155
sb.append("### 3. 자유 응답 기반 주요 키워드 정리\n");
156156
sb.append(" - 예: 잦힌 (37건), 말은 덜 불분명 (29건) 등\n\n");
157157

158-
sb.append("응답은 반드시 다음 JSON 형식으로 해줘. 형식만 따르고, 값은 생성한 값을 넣어줘야해. 질문에 대한 제안은 입력받은 질문 Id와 해당 질문에 매칭되는 제안 내용을 넣어줘. : \n");
158+
sb.append("응답은 반드시 다음 JSON 형식으로 해줘. 벡틱(`)과 json 표시는 제외하고 본문만 출력해줘야해. 형식만 따르고, 값은 생성한 값을 넣어줘야해. 질문에 대한 제안은 입력받은 질문 Id와 해당 질문에 매칭되는 제안 내용을 넣어줘. : \n");
159159
sb.append("{\n");
160160
sb.append(" \"report\": \"전체 리포트 마크다운 텍스트\",\n");
161161
sb.append(" \"suggestionsByQuestionId\": {\n");

src/main/java/com/haru/api/infra/redis/RedisReportConsumer.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
@RequiredArgsConstructor
1818
public class RedisReportConsumer {
1919

20+
private final MoodTrackerReportService reportService;
2021
private final StringRedisTemplate redisTemplate;
2122

2223
@Value("${queue-name}")
@@ -75,13 +76,10 @@ public void pollFailedQueueEvery1Minutes() {
7576

7677
for (String id : failedIds) {
7778
try {
78-
// 다시 워커 큐로 push
79-
redisTemplate.opsForList().leftPush("REPORT_WORKER_QUEUE", id);
80-
log.info("[RedisReportConsumer] 실패 큐 재실행 → {}", id);
79+
reportService.generateAndUploadReportFileAndThumbnail(Long.valueOf(id));
8180

8281
// 실패 큐에서 제거
83-
redisTemplate.opsForZSet().remove("REPORT_FAILED_QUEUE", id);
84-
82+
redisTemplate.opsForZSet().remove(FAILED_QUEUE, id);
8583
} catch (Exception e) {
8684
log.error("[RedisReportConsumer] 실패 큐 재실행 중 에러 → {}", id, e);
8785
}

0 commit comments

Comments
 (0)