From 7d15f063904e2f67cdac139bfeca10e531a80a55 Mon Sep 17 00:00:00 2001 From: sb Date: Sun, 5 Jul 2026 15:43:44 +0900 Subject: [PATCH] =?UTF-8?q?revert(ai):=20=EC=98=88=EC=83=81=20=EC=A7=80?= =?UTF-8?q?=EC=B6=9C=EC=9D=84=20AI=EC=97=90=EC=84=9C=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=20=E2=80=94=20=EB=B9=84=EA=B2=B0=EC=A0=95=EC=84=B1=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=A7=A4=20=EC=A0=91=EC=86=8D=20=EA=B0=92=20?= =?UTF-8?q?=EB=B3=80=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AI 예상지출은 호출마다 40만~500만으로 흔들려 신뢰성 부족. 코멘트/팁만 AI 유지. 예상 지출은 프론트에서 결정적 계산으로 대체. Co-Authored-By: Claude Opus 4.8 --- .../sb/web/account/dto/AiCommentRequest.java | 2 -- .../sb/web/account/dto/AiCommentResponse.java | 2 -- .../sb/web/account/service/AiEntryParser.java | 20 +++++-------------- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/sb/web/account/dto/AiCommentRequest.java b/src/main/java/com/sb/web/account/dto/AiCommentRequest.java index 8fd4349..2e25922 100644 --- a/src/main/java/com/sb/web/account/dto/AiCommentRequest.java +++ b/src/main/java/com/sb/web/account/dto/AiCommentRequest.java @@ -17,8 +17,6 @@ public class AiCommentRequest { private long prevExpense; // 직전 달 지출 합계(대비용) private long budget; // 이번 달 예산 합계 private long spent; // 이번 달 예산 대비 소비액 - private int elapsedDays; // 이번 달 경과일(현재 달일 때만 >0, 아니면 0) - private int totalDays; // 이번 달 총일수 private List categories; // 분류별 지출 상위 @Data diff --git a/src/main/java/com/sb/web/account/dto/AiCommentResponse.java b/src/main/java/com/sb/web/account/dto/AiCommentResponse.java index 4c19c6b..0e8128f 100644 --- a/src/main/java/com/sb/web/account/dto/AiCommentResponse.java +++ b/src/main/java/com/sb/web/account/dto/AiCommentResponse.java @@ -14,6 +14,4 @@ public class AiCommentResponse { private List bullets; // 현황 관찰/코멘트 private List tips; // 절약 가이드(실행 가능한 제안) - private Long forecast; // 월말 예상 지출(원) — 일회성 큰 지출 제외 추정. 없으면 null - private String forecastNote; // 예상 지출 근거 한 문장 } diff --git a/src/main/java/com/sb/web/account/service/AiEntryParser.java b/src/main/java/com/sb/web/account/service/AiEntryParser.java index 1b75b2f..a08dd08 100644 --- a/src/main/java/com/sb/web/account/service/AiEntryParser.java +++ b/src/main/java/com/sb/web/account/service/AiEntryParser.java @@ -114,18 +114,14 @@ public class AiEntryParser { if (!enabled() || summaryJson == null || summaryJson.isBlank()) return emptyComment(); try { String system = """ - 너는 한국어 개인 가계부 코치다. 아래 사용자의 이번 달 집계(JSON, 금액 단위 원)를 보고 세 가지를 만든다. + 너는 한국어 개인 가계부 코치다. 아래 사용자의 이번 달 집계(JSON, 금액 단위 원)를 보고 두 가지를 만든다. 1) bullets: 현황 관찰 2~3개. 각 한 문장, 구체적 숫자 인용, 잔소리·과장 없이 담백하게. (예: 전월 대비 지출 증감, 예산 대비 소비 속도, 특정 분류 과다, 수입 대비 지출 비율) 2) tips: 이 사용자의 지출 패턴에 딱 맞춘 '실행 가능한' 절약 제안 2~3개. 두루뭉술한 원칙 금지, 구체적 분류·습관을 지목(예: "카페 지출이 8만원인데 주 2회로 줄이면 약 3만원 절약"). 각 한 문장, 제안형. - 3) forecast: 월말 예상 지출(원, 정수). 계산법 = '지금까지 실제 지출(expense)' + '남은 날 × 평소 하루 지출'. - 단, 노트북·가전·여행 등 '일회성 큰 지출'로 보이는 분류는 남은 날에 반복되지 않으므로 하루 지출 산정에서 제외한다. - (평소 하루 지출 ≈ (expense − 일회성 큰 지출) ÷ elapsedDays). forecastNote 에 한 문장 근거(무엇을 일회성으로 봤는지). - elapsedDays 가 0 이면(과거/미래 달) forecast=0, forecastNote="". 반드시 아래 JSON '하나만' 출력한다(마크다운/설명 금지): - {"bullets":["관찰1","관찰2"],"tips":["절약제안1","절약제안2"],"forecast":정수,"forecastNote":"근거 한 문장"} - 데이터가 빈약하면 bullets/tips 는 빈 배열, forecast=0. + {"bullets":["관찰1","관찰2"],"tips":["절약제안1","절약제안2"]} + 데이터가 빈약하면 해당 배열을 빈 배열로. """; Map reqBody = Map.of( "model", model, @@ -147,14 +143,8 @@ public class AiEntryParser { JsonNode root = om.readTree(json); List bullets = strArray(root.path("bullets")); List tips = strArray(root.path("tips")); - long forecast = Math.max(0, root.path("forecast").asLong(0)); - String forecastNote = root.path("forecastNote").asText("").trim(); - log.info("[ai-comment] 결과 — 코멘트 {}개, 절약팁 {}개, 예상지출 {}", bullets.size(), tips.size(), forecast); - return AiCommentResponse.builder() - .bullets(bullets).tips(tips) - .forecast(forecast > 0 ? forecast : null) - .forecastNote(forecast > 0 ? forecastNote : null) - .build(); + log.info("[ai-comment] 결과 — 코멘트 {}개, 절약팁 {}개", bullets.size(), tips.size()); + return AiCommentResponse.builder().bullets(bullets).tips(tips).build(); } catch (Exception e) { log.warn("[ai-comment] 실패: {}", e.toString()); return emptyComment();