Commit Graph

8 Commits

Author SHA1 Message Date
ttipo 4c049d2fec feat(backend): AI 코스 평가 실행기와 후보 스냅샷, 기준선 결과 추가
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m46s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m26s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m28s
CI / Frontend (lint · type-check · test) (push) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (push) Has been cancelled
CI / Backend (lint · test · e2e · build) (push) Has been cancelled
모델과 effort 를 정하려면 같은 후보로 평가셋 62개를 돌려 목표(설계 §9)와 견줄 도구가 필요했다.
평가가 서버와 다른 길을 돌면 결과를 믿을 수 없어서, 파이프라인의 'AI 초안 → 시간표 → 다시 부르기'를
course-planning.ts 로 떼어 파이프라인 · ai:check · ai:eval 이 같은 함수를 쓰게 했다.

Haiku 5.5 와 Sonnet 5.5 기준선을 재 보니 자동 채점 실패의 3분의 2가 시간표 코드가 식당을
식사 시간대로 밀지 않아서였다. 모델 결정은 그 고치기와 프롬프트 v2 뒤로 미룬다(설계 §9.1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 22:42:42 +09:00
ttipo 4dc5be72a4 feat(backend): AI 코스 생성에 Anthropic 클라이언트와 프롬프트 v1, 조건 해석 연결
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m37s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m24s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m57s
CI / Backend (lint · test · e2e · build) (push) Successful in 12m33s
CI / Frontend (lint · type-check · test) (push) Successful in 11m12s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 11m18s
4단계까지 서버는 가짜 AI 로 코스를 만들었다. 실제 모델(기본 Haiku 5.5)을 붙여
문장에서 조건을 읽고 후보 중 코스를 고르게 한다(설계 §14 5단계).

- 구조화 출력(JSON 스키마)으로 받고, 같은 시스템 프롬프트는 캐시에 올린다
- 조건 해석은 AI 가 값만 뽑고 기본값과 되물을 것은 코드가 정한다(unknown_place 추가)
- 조건 해석 비용과 응답 뒤 실패한 호출 비용도 하루 비용 상한에 넣는다
- AI_PROVIDER(fake 로 되돌림) · effort 설정, 모델은 가격표에 있어야 기동한다
- 키로 실제 호출을 확인하는 ai:check 명령

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 17:16:00 +09:00
ttipo 09c8decb15 feat(backend): AI 코스 생성 API 골격과 생성 기록 테이블 추가
CI (Flutter) / Flutter (analyze · test) (pull_request) Successful in 20m59s
CI / Frontend (lint · type-check · test) (pull_request) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Has been cancelled
CI / Backend (lint · test · e2e · build) (pull_request) Has been cancelled
설계 4단계 — 키 없이 생성 흐름을 끝까지 돌려 볼 수 있게 API·테이블·에러 코드를
먼저 세우고, AI 자리는 가짜 클라이언트로 채웠다(5단계에서 실제 모델로 바꾼다).

- 조건 해석·생성 시작·진행 조회·취소·평가·오늘 남은 횟수 API 6개
- ai_course_generation 테이블(마이그레이션)과 에러 코드 AI_001~004
- 기기 단위 하루 횟수(결과가 나온 생성만 차감)·시도 상한·하루 비용 상한·동시 생성 막기
- 프로세스 안 실행기: 동시 5건, 작업당 45초, 취소 시 AI 호출 중단,
  기동·종료 때 끝나지 못한 작업은 실패(차감 없음)로 정리
- 후보 찾기 → 거르기·줄이기 → AI 초안 → 시간표 검증·고치기 → 결과 조립
- 요청 문장의 연락처는 저장 전에 가리고, 현재 위치는 약 100m 단위로만 남긴다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 11:37:26 +09:00
ttipo 187a99ca7f feat(backend): 기상청 단기예보와 공휴일 표 추가
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m5s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m31s
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m9s
CI / Frontend (lint · type-check · test) (push) Successful in 11m12s
CI / Backend (lint · test · e2e · build) (push) Successful in 11m46s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 11m8s
AI 코스 조건 해석·거르기(설계 §3.3)에 그날 날씨와 공휴일이 필요하다. 강수확률 40% 이상이면 실내 위주로 짜고,
공휴일·명절에 쉬는 곳은 후보에서 뺀다. 4단계(API 골격)에서 생성 작업에 연결한다.

- 공휴일 표(2026–2027): 설·추석 연휴·대체공휴일·지방선거일, 2026년부터 공휴일이 된 노동절·제헌절(대체공휴일 포함).
  대체공휴일 규칙을 테스트로 검사해 해마다 표를 갱신할 때 빠뜨린 날을 잡는다
- 공휴일 거르기를 명절 종류에 맞췄다 — 설·추석 당일 휴관인 곳을 어린이날에 빼지 않고, '공휴일' 휴관은 모든 공휴일에 뺀다
- 날씨: 위경도 → 5km 격자, 가장 최근 발표(자료가 아직 없으면 앞 발표), 시간 범위의 최고 강수확률·강수 형태·하늘·기온.
  1시간 캐시, 3초·2번 시도, 하루 1,000번, 실패하면 null(입력 화면은 '예보 없음')
- 공공데이터 공통 클라이언트에 호출 제한 시간·시도 횟수 설정을 더했다(기존 동기화는 그대로 20초·3번)
- 실제 호출 확인 명령 weather:check

2026-11-08 실제 호출: 대구 도심 격자 89,90, 14시 발표로 11-08~11-11 예보, 11-12 는 예보 없음(호출 1번).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 15:39:58 +09:00
ttipo d2cd5cd96e feat(backend): AI 코스 시간표를 짜고 검증·고치는 순수 로직 추가
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 13m30s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m28s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m56s
CI / Backend (lint · test · e2e · build) (push) Successful in 14m17s
CI / Frontend (lint · type-check · test) (push) Successful in 12m17s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 12m55s
AI 코스 생성(설계 §3.3–§3.7)에서 코드가 맡는 부분이다. AI 는 후보 번호로 장소와 머무는 시간만 고르고,
영업·이동·반려동물 조건 검증과 순서 고치기는 코드가 해야 닫힌 곳으로 보내거나 지어낸 사실이 화면에 나가지 않는다.
API·AI 연동(4·5단계) 전에 키 없이 시험할 수 있게 DB·AI 와 떨어진 순수 함수로 먼저 만든다.

- 거르기: 반경·행사 기간·공휴일 휴무·반려동물·그날 영업(최소 머무는 시간만큼)
- 줄이기: 장소와 행사를 합쳐 40곳(행사 8개까지, 분류마다 10곳), 다시 만들기면 이전 장소를 빼거나 뒤로
- 시간표·검증: 직선거리 이동 추정, 영업·마지막 주문·끝 시각·구간 이동·반려동물
- 고치기: 순서와 머무는 시간을 함께 찾고(AI 순서와 가까운 것 우선), 안 되면 바꾸기 후보로 바꾸거나 뺀다
- 비 조건 실내 비율, 바꾸기 후보를 같은 시간대로 검증, 장소별 경고

6곳 코스 고치기는 대부분 20ms 안이고 가장 나쁜 경우 약 50ms 였다(서버가 한 대라 따지는 순서를 5,000개로 제한).
구현하며 정한 기준은 설계 §3.4·§3.6·§3.7 에 적었다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 11:49:16 +09:00
ttipo f752bf28f5 fix(backend): 계절별 영업시간을 날짜의 달로 골라 영업 중 표시를 바로잡음
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m4s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 14m24s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 12m14s
CI / Backend (lint · test · e2e · build) (push) Successful in 12m25s
CI / Frontend (lint · type-check · test) (push) Successful in 11m3s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 11m25s
하절기·동절기처럼 계절마다 시간표가 다른 곳을 어느 계절인지 모른 채 읽고 있었다.
23곳은 영업 중인지 판단하지 못해 '영업시간 미확인'으로 나왔고(대구미술관·수창청춘맨숀·향촌문화관 등),
7곳은 두 계절 시간을 합쳐 읽어 닫혀 있는 시각에도 영업 중으로 보였다
(대구수목원 9~4월 아침 8시, 달성 한일우호관 11~2월 17시, 상주식당 12~3월 휴업 등).
영업시간 미확인은 AI 코스가 문화시설·식당·카페를 후보에서 빼는 기준이기도 하다(설계 §3.3).

시간표를 계절별로 따로 두고(seasons) 그날 날짜의 달에 맞는 것을 고른다. isOpenAt 은 요일 대신
날짜를 받는다. 시기별 쉬는 요일(restSeasons)과 문을 열지 않는 기간(closedPeriods)도 따로 읽는다.
달 없이 "하절기/동절기"만 적은 곳은 하절기 4~9월·동절기 12~2월만 확실하다고 보고, 3·10·11월에는
두 시간표의 답이 같을 때만 판단한다. 대구 원문의 계절 범위가 기관마다 3~10월·4~11월 등으로 달라서다.

개발 DB 1,117곳을 이전 파서와 비교(2026년 달마다 7일 × 30분)해 30곳의 판단이 바뀌었다.
닫힘에서 영업 중으로, 판단에서 미확인으로 바뀐 곳은 없고, 계절과 상관없는 곳의 해석도 그대로다.
이전 형식으로 저장된 계절 구분 값은 reparse-hours 로 다시 해석하기 전까지 지금처럼 미확인이다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 08:12:29 +09:00
ttipo 542732257c docs: AI 평가셋 검토 결과를 적고 확정함
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m24s
CI / Frontend (lint · type-check · test) (push) Successful in 11m26s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 12m36s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m15s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m51s
CI / Backend (lint · test · e2e · build) (push) Successful in 12m12s
반려동물·경계 사례를 검토하며 정한 정책을 평가셋 README 와 설계 §9 에 남긴다.
요청의 핵심을 맞출 후보가 없으면 다른 곳으로 채우지 않고 만들지 않으며, 일부만 못 맞추면 맞출 수 있는 만큼
만들고 알린다. '돈 안 쓰는 코스'는 식당·카페를 뺀다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:37:29 +09:00
ttipo 29e9611bd9 docs: AI 코스 생성 설계안 추가
MVP 의 AI 코스 생성(디자인 화면 8–10)을 만들기 전에 흐름·API·비용 보호·평가 방법을 정한다.
DB 가 후보를 고르고 AI 는 후보 번호로만 고르며, 이동 시간·영업·반려 조건 검증과 순서 고치기는 코드가 한다.
화면의 사실 값(영업시간·동반 조건·출처)은 모두 DB 에서 붙여 AI 가 지어낼 수 없게 한다.

§13 의 8가지(하루 횟수·비용 상한·영업시간 미확인·반려 엄격도·이동 시간·공연 제외·보관 기간·모델)는
2026-11-05 사용자가 추천안대로 정했다. 대구 평가셋을 만들며 찾은 것도 반영했다 — 조건 해석 issues 3개,
별칭이 가리키는 장소를 중심으로, 전시는 실내, 실내 후보가 모자라면 알림으로, 코스를 못 만들면 이유를 함께.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:23:16 +09:00