From 58c9e04ffc07b9206fb95e057582126f9b8107be Mon Sep 17 00:00:00 2001 From: Gyueon Lee Date: Mon, 16 Feb 2026 00:23:36 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9Bfix:=20=EB=B0=98=EB=B3=B5=20?= =?UTF-8?q?=EA=B7=B8=EB=A3=B9=20llm=20=EB=A6=AC=ED=84=B4=20=EA=B0=92?= =?UTF-8?q?=EC=9D=B4=20=EC=8B=A4=EC=A0=9C=20=EC=84=9C=EB=B2=84=20dto?= =?UTF-8?q?=EC=99=80=20=EB=8B=AC=EB=9E=90=EB=8D=98=20=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/prompts/recurrence-suggestion-prompt.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/prompts/recurrence-suggestion-prompt.txt b/src/main/resources/prompts/recurrence-suggestion-prompt.txt index 47eaadf..77f230b 100644 --- a/src/main/resources/prompts/recurrence-suggestion-prompt.txt +++ b/src/main/resources/prompts/recurrence-suggestion-prompt.txt @@ -7,7 +7,7 @@ - 입력 JSON에 주어진 값만 사용해 문구를 생성합니다. 없는 정보는 절대 만들지 않습니다. - title의 의미를 확장하지 마세요. (장소/행동/상황을 덧붙이지 말고 “일정/반복/연장/종료” 같은 중립어만 사용) - 실제 날짜(YYYY-MM-DD)는 문구에 노출해도 됩니다. 단, 날짜/시간 “계산·변환”은 금지합니다. -- recurrenceGroupId는 식별자이며 절대 변형하지 말고 그대로 반환하세요. +- id는 식별자이며 절대 변형하지 말고 그대로 반환하세요. - 출력은 반드시 JSON만 반환합니다. (설명, 코멘트, 마크다운 금지) --- @@ -18,7 +18,7 @@ "suggestionReqCnt": <정수>, "recurrenceGroupSuggestionDetails": [ { - "recurrenceGroupId": <정수>, + "id": <정수>, "title": "문자열", "lastStartTime": "YYYY-MM-DDTHH:mm:ss", "endDate": "YYYY-MM-DD" | null, @@ -84,7 +84,7 @@ B) occurrenceCount가 존재하는 경우 (occurrenceCount != null) "suggestionResCnt": <입력 suggestionReqCnt와 동일한 정수>, "llmRecurrenceGroupSuggestionList": [ { - "recurrenceGroupId": <입력으로 받은 recurrenceGroupId 그대로>, + "id": <입력으로 받은 id 그대로>, "content": "<생성 문구>" } ] From 6c899803eeb298b52bc579e656b1b9a8dcfbe633 Mon Sep 17 00:00:00 2001 From: Gyueon Lee Date: Mon, 16 Feb 2026 00:23:45 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9Bfix:=20=EB=8B=A8=EB=B0=9C?= =?UTF-8?q?=EC=84=B1=20=EA=B0=9D=EC=B2=B4=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?llm=20response=EA=B0=80=20=EC=96=B4=EC=83=89=ED=96=88=EB=8D=98?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/prompts/suggestion-prompt.txt | 73 ++++++++++++++----- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/src/main/resources/prompts/suggestion-prompt.txt b/src/main/resources/prompts/suggestion-prompt.txt index 2af72d1..3c16a93 100644 --- a/src/main/resources/prompts/suggestion-prompt.txt +++ b/src/main/resources/prompts/suggestion-prompt.txt @@ -39,9 +39,11 @@ - 은/는: title의 마지막 글자에 받침 있으면 “은”, 없으면 “는”. - 문구는 반드시 질문(“…등록할까요?”/“…추가할까요?”)으로 끝낼 것. - {등록/추가}는 둘 중 하나만 선택(카테고리 강제 없음, 단 문장 끝 질문 유지). -- 시간표현(start의 시각만 사용, 날짜 추론 금지): - - HH:00 → “HH시에” (예: 10:00 → “10시에”, “10시 0분” 금지) - - HH:MM(00 아님) → “HH시 M분에” (앞자리 0 없이: 10:05 → “10시 5분에”) + +[시간표현 규칙(start의 시각만 사용, 날짜 추론 금지)] +- HH:00 → “HH시에” (예: 10:00 → “10시에”, “10시 0분” 금지) +- HH:MM(00 아님) → “HH시 M분에” (앞자리 0 없이: 10:05 → “10시 5분에”) +- “10시로” 금지, 시간표현은 반드시 “~에”로 끝나야 함 [요일 표기] - MONDAY 월요일, TUESDAY 화요일, WEDNESDAY 수요일, THURSDAY 목요일, FRIDAY 금요일, SATURDAY 토요일, SUNDAY 일요일 @@ -68,10 +70,14 @@ - dayOfMonthSet은 “31일” 또는 “27일·28일”처럼 ‘·’로 연결(실제 날짜 계산 금지) [patternType별 “상대표현” 규칙] (실제 날짜 계산 금지) +※ “다음 번” 금지(추상적 표현 금지). 가능한 한 숫자/주/달 기반으로 구체적으로 말하세요. + 1) N_INTERVAL -- dayDiff가 7의 배수이면 “다음 주 {요일}” 또는 “{n}주 뒤 {요일}” - - 이때 요일은 start의 요일을 사용해도 됨(날짜 노출은 금지) -- 7의 배수가 아니면 “{dayDiff}일 뒤” 또는 “다음 번” +- dayDiff가 7의 배수이면: + - dayDiff=7 → “다음 주” + - dayDiff=14 → “2주 뒤” + - 그 외(7의 배수) → “{n}주 뒤” (n = dayDiff/7) +- 7의 배수가 아니면 반드시 “{dayDiff}일 뒤” 2) WEEKLY_SET - weekDiff=1: “다음 주 {요일(들)}” @@ -79,9 +85,15 @@ - 요일(들)은 dayOfWeekSet만 사용 3) MONTHLY_DAY -- monthDiff=1: “다음 달” -- monthDiff=2: 반드시 “2달 뒤”(“다음 달” 금지) -- monthDiff>2: 반드시 “{monthDiff}달 뒤” +- monthDiff=1: “다음 달 {dayOfMonthSet}” +- monthDiff=2: 반드시 “2달 뒤 {dayOfMonthSet}”(“다음 달” 금지) +- monthDiff>2: 반드시 “{monthDiff}달 뒤 {dayOfMonthSet}” + +[시간 배치 핵심 규칙(중요)] +- primaryContent(2문장) 안에서 시간표현(“~시에/~시 ~분에”)은 “정확히 1번만” 등장해야 합니다. +- 즉, 1문장에 시간이 나오면 2문장에는 시간 금지, 1문장에 시간이 없으면 2문장에 시간 필수입니다. +- 2문장(질문 문장)은 반드시 “상대표현”으로 시작해야 합니다. (시간으로 시작 금지) +- 2문장에 시간이 포함되는 경우에도 “상대표현 + (공백) + 시간표현” 순서로만 배치하세요. [문구 생성 규칙] ※ primaryContent는 어떤 stableType이든 “반드시 2문장”입니다. @@ -94,32 +106,53 @@ A) stableType = PERFECTLY_STABLE 또는 PARTIALLY_STABLE - primaryContent는 아래 2문장 구조 고정(추가/삭제/순서 변경 금지): 1) "({일정|할 일}) ‘{title}’{은/는} {primary 간격표현} {(가능하면 요일/날짜요소)} {시간}에 반복한 기록이 있어요." - - N_INTERVAL: 보통 “{간격표현} {시간}” - - WEEKLY_SET: “{간격표현} {요일(들)} {시간}” - - MONTHLY_DAY: “{간격표현} {dayOfMonthSet} {시간}” - 2) "{(반드시 primaryPattern 기반) primary 상대표현}{시간}로 {등록/추가}할까요?" - - 2문장에는 반드시 시간표현을 포함해야 함(예: “10시에”, “10시 5분에”) + - N_INTERVAL: “{간격표현} {시간}에” + - WEEKLY_SET: “{간격표현} {요일(들)} {시간}에” + - MONTHLY_DAY: “{간격표현} {dayOfMonthSet} {시간}에” + 2) "{(반드시 primaryPattern 기반) primary 상대표현}에 {등록/추가}할까요?" + - 2문장은 반드시 상대표현으로 시작 + - A에서는 1문장에 시간이 이미 있으므로 2문장에는 시간표현 절대 금지 + - “{상대표현}에” 형태 유지(예: “2일 뒤에”, “2주 뒤에”, “다음 주 월요일·수요일에”, “다음 달 27일·28일에”) B) stableType = CONTAMINATED_STABLE - primaryContent는 아래 2문장 구조 고정: - 1) "({일정|할 일}) ‘{title}’{은/는} 최근 기록에서 {primary 간격표현} 간격이 가장 많았어요." + 1) "({일정|할 일}) ‘{title}’{은/는} 최근 기록에서 {primary 간격표현} {(가능하면 요일/날짜요소)} 기록이 가장 많았어요." - 간격표현은 정확히 1회만 등장 - 2) "{(반드시 primaryPattern 기반) primary 상대표현}{시간}로 {등록/추가}할까요?" - - 2문장에는 반드시 시간표현을 포함해야 함 + - WEEKLY_SET이면 “{요일(들)}”를 덧붙일 수 있음(단, 간격표현 반복 금지) + - MONTHLY_DAY이면 “{dayOfMonthSet}”를 덧붙일 수 있음 + - B의 1문장에는 시간표현 절대 금지 + 2) "{(반드시 primaryPattern 기반) primary 상대표현} {시간}로 {등록/추가}할까요?" + - 2문장은 반드시 상대표현으로 시작 + - B에서는 1문장에 시간이 없으므로 2문장에는 시간표현 반드시 포함 + - 시간은 상대표현 뒤에만 배치(예: “2일 뒤 10시에”, “2주 뒤 10시 5분에”, “다음 주 월요일·수요일 10시에”) + - “로”는 반드시 “{등록/추가}” 앞에서만 쓰고, 시간표현에는 쓰지 마세요. + - 올바름: “2일 뒤 10시에 추가할까요?” + - 금지: “10시로 추가할까요?” C) secondaryContent - secondaryPattern이 null이면 secondaryContent는 반드시 null. -- secondaryPattern이 존재하면 아래 1문장 구조 고정(secondaryPattern만 사용, 반드시 물음표로 끝): +- secondaryPattern이 존재하면 아래 구조 고정(secondaryPattern만 사용, 한 줄 문자열, 반드시 물음표로 끝): - EVENT: - "일정 ‘{title}’은 가장 최근에 {secondary 간격표현} 간격이었어요. {(반드시 secondaryPattern 기반) secondary 상대표현}{시간}로 {등록/추가}할까요?" + "일정 ‘{title}’은 가장 최근에 {secondary 간격표현} {(가능하면 요일/날짜요소)} {시간}에 반복한 기록이 있어요. {(반드시 secondaryPattern 기반) secondary 상대표현}에 {등록/추가}할까요?" - TODO: - "할 일 ‘{title}’은 가장 최근에 {secondary 간격표현} 간격이었어요. {(반드시 secondaryPattern 기반) secondary 상대표현}{시간}로 {등록/추가}할까요?" + "할 일 ‘{title}’은 가장 최근에 {secondary 간격표현} {(가능하면 요일/날짜요소)} {시간}에 반복한 기록이 있어요. {(반드시 secondaryPattern 기반) secondary 상대표현}에 {등록/추가}할까요?" + - secondaryContent에서도 시간표현은 “정확히 1번만” 등장해야 함(위 구조는 1문장에만 시간 포함, 질문에는 시간 금지) [자체 검증(출력 전 필수)] - primaryContent는 반드시 “마침표(.) 1개 + 물음표(?) 1개”를 포함해야 하며, 문장 수는 정확히 2개여야 함. - 조건을 만족하지 않으면 해당 항목의 primaryContent를 규칙에 맞게 즉시 재생성. +- A(PERFECTLY_STABLE/PARTIALLY_STABLE): + - 1문장에 시간표현이 반드시 있어야 함. + - 2문장에 시간표현이 있으면 규칙 위반 → 즉시 재생성. +- B(CONTAMINATED_STABLE): + - 1문장에 시간표현이 있으면 규칙 위반 → 즉시 재생성. + - 2문장에 시간표현이 없으면 규칙 위반 → 즉시 재생성. +- 2문장(질문)이 시간으로 시작하면 규칙 위반 → 즉시 재생성. +- “다음 번”이 포함되면 규칙 위반 → 즉시 재생성. +- “{숫자}일뒤”처럼 붙여쓰면 규칙 위반 → “{숫자}일 뒤”로 재생성. - secondaryContent가 null이면 그대로 null인지 확인. - secondaryContent가 문자열이면 반드시 물음표(?)로 끝나는지 확인. +- secondaryContent(문자열)에 시간표현이 2회 이상 등장하면 규칙 위반 → 즉시 재생성. - primaryContent의 간격/상대표현 숫자는 primaryPattern에서만 나와야 함. - secondaryContent의 간격/상대표현 숫자는 secondaryPattern에서만 나와야 함. - monthDiff=2인데 “매달/다음 달” 사용하면 규칙 위반.