힐링페이퍼(강남언니)
경력근거: 운영 중인 고객 예약 웹·상담센터 어드민·파트너 포털의 프론트엔드·백엔드·데이터베이스를 개발하고 운영해요.
※ 실제 산출물이 아닌 AI 예측 시안입니다.
공고는 신규 사업 스쿼드가 '미용의료 시술을 위해 한국을 방문하는 글로벌 고객을 대상으로, 온라인 서비스와 오프라인 운영을 연결하는 사업' 을 운영한다고 적고, 주요업무로 '운영 중인 고객 예약 웹·상담센터 어드민·파트너 포털' 의 개발·운영, '여러 언어권의 고객을 위한 다국어 환경 구축', '비정형 데이터 구조화' 를 듭니다. 한국에 머무는 기간이 정해진 고객의 예약을 다루는 곳이라 고객이 말한 날짜와 시술 일정을 견주는 일이 상담센터 어드민 안에서 생기고, 그 말이 여러 언어로 들어옵니다. 이 자리의 FDE 는 '운영 현장과 오피스를 오가며 사용자의 요구와 업무 맥락을 파악' 하므로 이 화면의 사용자도 외부 고객사가 아니라 사내 상담센터 코디네이터와 운영 담당자입니다. 공고에는 입국·출국·재방문이라는 말이 나오지 않습니다. 한국을 방문하는 고객이라는 공고의 사실에서 이 주제를 골랐고, 실제 상담센터가 방문 일정을 어떻게 다루는지는 면접에서 물어 맞춥니다. 이 포트폴리오는 다국어 대화에서 날짜 근거를 뽑아 예약과 견주는 풀스택 구현을 보여줍니다. 시술 후 재방문 시기 같은 의료 판단이나 출입국 절차의 전문성은 주장하지 않습니다.
신규 사업 스쿼드는 미용의료 시술을 위해 한국을 방문하는 글로벌 고객을 대상으로 온라인 서비스와 오프라인 운영을 연결하는 사업을 운영합니다. 예약은 온라인에서 잡히고 시술은 한국의 병원에서 받으니, 고객이 머무는 기간과 예약 일정이 맞는지가 운영의 일이 됩니다.
주요업무 첫 줄이 고객 예약 웹·상담센터 어드민·파트너 포털의 프론트엔드·백엔드·데이터베이스 개발과 운영이고, 이어서 여러 언어권 고객을 위한 다국어 환경 구축이 나옵니다. 판정 화면은 상담센터 어드민 안에 들어가고, 근거는 고객이 쓴 언어의 원문 그대로 보입니다.
AI 활용 항목에 도메인 지식과 문맥을 반영한 비정형 데이터 구조화·분석 기능, 그리고 평가 데이터와 오류 분석으로 정확성과 일관성을 높이는 일이 적혀 있습니다. 메신저 대화에서 입국·출국 날짜를 고르는 일이 비정형 데이터 구조화이고, 손으로 단 정답과 맞대는 2주차가 오류 분석입니다.
힐링페이퍼(강남언니) 신규 사업 스쿼드가 쓰는 상담센터 어드민 안의 판정 화면입니다. 방한 외국인 고객의 병원 예약을 잡는 코디네이터와 통역 동행 일정을 짜는 운영 담당자가 예약 목록을 열면, 고객이 메신저 대화에서 말한 입국·출국 날짜와 병원이 올린 시술 소요 시간·재방문 일수를 예약 시각과 견줘 예약마다 다섯 판정 가운데 하나와 그 근거를 보여줍니다. 날짜는 고객이 쓴 언어의 원문 표기를 근거로 남기고, 원문에 표기가 없는 날짜는 쓰지 않습니다.
상담센터에서 방한 외국인 고객의 병원 예약을 잡는 코디네이터와 통역 동행 일정을 짜는 운영 담당자. 매일 같은 상담센터 어드민 화면에서 입출국 일정과 어긋난 예약을 보고, 고객에게 고객의 언어로 일정 변경을 안내한다
코디네이터는 고객이 처음 말한 입국·출국 날짜를 보고 예약을 잡습니다. 그런데 고객은 항공편이 바뀌면 메신저에 새 날짜를 다시 쓰고, 그 문장은 일본어·태국어·중국어·영어로 옵니다. 대화에서 가장 늦게 말한 날짜를 원문 표기에서 다시 읽어 예약 시각·재방문일·병원 사이 이동 시간과 견주면, 코디네이터가 재방문을 못 하고 귀국하게 될 예약과 입국 전에 잡힌 예약을 고객이 오기 전에 바로잡습니다.
코디네이터가 상담센터 어드민의 판정 화면을 열면 이번 주 예약이 다섯 판정으로 나뉘고, 예약을 펼치면 대화 원문의 날짜 표기, 입국 시각에 3시간을 더한 시각, 재방문일, 필요한 이동 시간이 나옵니다. 대화·예약·시술·병원·이동 계수 다섯 표는 더미로 시작하고, 날짜는 Claude Haiku 가 고른 표기를 규칙이 원문에서 다시 읽어 같을 때만 씁니다.
작성자가 입국·출국 날짜를 손으로 단 대화 60건으로 추출과 판정을 돌려, 맞은 건수와 틀린 대화를 언어별로 리포트합니다. 틀린 대화는 추출 실패 모음에 쌓아 프롬프트를 바꿀 때마다 같은 세트로 다시 돌립니다.
걸린 예약마다 고객이 쓴 언어로 일정 변경 안내 초안을 내고, 코디네이터가 고쳐 직접 보냅니다. 시술 정보가 든 대화 원문은 역할별로만 열고 누가 언제 열었는지 감사 로그에 남깁니다.
코디네이터가 판정 화면을 열면 이번 주 예약이 다섯 판정으로 나뉘고, BK-5520 을 펼치면 LINE 원문 '10月11日 13:20着' 과 그 시각에 3시간을 더한 16:20 이 예약 시각 10:00 옆에 나옵니다.
항공편을 바꿔 입국 날짜를 다시 말한 대화, 요일로만 말해 날짜 표기가 없는 대화, 입국 시각 없이 날짜만 말한 대화, 출국일과 같은 날 재방문인 예약을 섞어도 판정이 판정식대로 나오고, 모델이 원문에 없는 날짜를 내면 그 날짜는 판정에 들지 않습니다.
예약 시각 칸이 글자로 깨진 줄, 위도·경도가 숫자가 아닌 병원 줄처럼 형식이 깨진 입력 20종을 넣어도 화면이 멈추지 않고, 어느 예약을 왜 뺐는지 표 위 알림에 남습니다.
손으로 입국·출국 날짜를 단 대화 60건으로 날짜 추출과 판정이 정답과 맞은 건수를 셉니다. 단, 대화와 정답을 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건에서의 동작입니다.
위 수치는 작성자가 쓴 대화의 자가채점이며, 날짜 추출이 실제로 맞는 비율은 힐링페이퍼 상담센터의 실제 메신저 대화와 코디네이터의 확인이 있어야 잽니다. 이 포트폴리오는 그 측정을 바로 돌릴 수 있는 상태까지 만듭니다.
대화 60건과 그 정답 날짜를 모두 제가 썼으니 일치 수는 성능 증명이 아닙니다. 제가 쓴 문장에는 제가 아는 날짜 표기만 들어 있어, 실제 고객이 쓰는 표기가 얼마나 다양한지는 이 수치로 알 수 없습니다.
Yui·Emily·Sora 세 고객의 예약이 판정을 가르는 자리입니다. Yui 는 항공편이 바뀌어 입국 시각을 두 번 말했고, Emily 는 요일로만 일정을 말했으며, Sora 는 출국 당일에 실밥 제거가 잡혀 있습니다. 먼저 말한 입국 시각을 쓰면 BK-5520 이, 모델이 'next Friday' 에 붙인 날짜를 믿으면 BK-5540 이, 재방문일이 출국일과 같은 날도 걸린다고 보면 BK-5550 이 판정을 바꿉니다.
재방문 일수는 병원이 파트너 포털에 올린 값이라고 가정하고 그대로 씁니다. 실밥 제거를 앞당겨도 되는지 같은 의료 판단은 병원이 하고, 이 화면은 그 값과 출국일을 견주는 데서 멈춥니다. 의료 판단이나 출입국 절차에 대한 전문성은 주장하지 않습니다.
입국 시각을 말하지 않은 고객은 그날 00:00 으로 보므로, 입국 당일 오후 예약은 판정식으로 걸리지 않습니다. 이런 예약에는 메모를 남겨 코디네이터가 항공편 시각을 묻게 합니다.
공고는 한국을 방문하는 글로벌 고객과 상담센터 어드민을 말하지만 입국·출국·재방문이라는 말은 쓰지 않습니다. 실제 도입에서는 메신저마다 대화를 내보내는 형식과 상담센터가 방문 일정을 기록하는 방식부터 맞춰야 하고, 3시간과 시간대 속도 계수도 실제 이동 기록으로 다시 잡습니다. 형식 맞추기와 계수 재설정은 실제 도입 단계의 일로 둡니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
상담센터가 메신저로 주고받은 방한 고객 대화를 고객별로 내보낸 표입니다. 고객 메시지와 코디네이터 메시지가 섞여 있고 text 는 고객이 쓴 언어 그대로입니다. 항공편을 바꿔 입국 날짜를 다시 말한 대화, 요일로만 말해 날짜 표기가 없는 대화, 코디네이터가 시술 날짜를 되짚는 메시지를 일부러 넣었습니다.
| message_id | customer_id | sent_at | channel | sender | text |
|---|---|---|---|---|---|
| M-7001 | C-3101 | 2026-10-01T21:14:00+09:00 | LINE | customer | Hi! I'm planning double eyelid surgery… |
| M-7002 | C-3101 | 2026-10-02T10:03:00+09:00 | LINE | customer | Also, I fly back on Oct 15, so please … |
| M-7003 | C-3101 | 2026-10-02T10:20:00+09:00 | LINE | coordinator | Got it, Mei! Surgery on Oct 12 at 2 PM… |
| M-7004 | C-3102 | 2026-10-03T13:40:00+09:00 | LINE | customer | 10月10日 21:40着の便で行きます。翌日の午前中に施術できますか? |
| M-7005 | C-3102 | 2026-10-06T08:12:00+09:00 | LINE | customer | すみません、便が変わって10月11日 13:20着になりました。帰国は10月… |
아래 JSON Schema 를 그대로 만족하는 상담 메시지를 고객 20명 분량으로 더 만들어 주세요. {"type":"object","properties":{"message_id":{"type":"string"},"customer_id":{"type":"string"},"sent_at":{"type":"string","description":"ISO 8601, +09:00 입니다. 같은 고객의 메시지는 이 값 순서로 읽습니다"},"channel":{"type":"string","enum":["LINE","WhatsApp","WeChat"]},"sender":{"type":"string","enum":["customer","coordinator"]},"text":{"type":"string","description":"보낸 언어 그대로의 원문입니다"}},"required":["message_id","customer_id","sent_at","channel","sender","text"]} 고객마다 메시지 2~5개를 sent_at 순으로 쓰고, text 는 고객 나라의 언어(일본어·태국어·중국어 간체와 번체·영어)로 쓰세요. 입국·출국 날짜는 그 언어에서 흔히 쓰는 꼴(10月11日 13:20着, 9 ต.ค., Oct 15, 10月13日回国)로 적으세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 항공편을 바꿔 나중 메시지에서 입국 날짜나 시각을 다시 말한 고객, (2) 'next Friday' 처럼 요일·상대 표현으로만 말해 날짜 표기가 없는 고객, (3) 입국 날짜만 말하고 시각은 말하지 않은 고객, (4) 코디네이터가 시술 예약 날짜를 되짚는 메시지(입출국 날짜가 아닌 날짜), (5) 입국과 출국을 한 메시지에 함께 말한 고객. 생성한 행은 반드시 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도(sent_at 이 날짜가 아닌 문자열, channel 이 목록 밖)는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"message_id":{"type":"string"},"customer_id":{"type":"string"},"sent_at":{"type":"string","description":"ISO 8601, +09:00 입니다. 같은 고객의 메시지는 이 값 순서로 읽습니다"},"channel":{"type":"string","enum":["LINE","WhatsApp","WeChat"]},"sender":{"type":"string","enum":["customer","coordinator"]},"text":{"type":"string","description":"보낸 언어 그대로의 원문입니다"}},"required":["message_id","customer_id","sent_at","channel","sender","text"]}코디네이터가 상담센터 어드민에서 잡은 병원 예약입니다. 한 고객이 같은 날 두 병원을 잇달아 잡은 예약과, 고객이 처음 말한 입국 날짜를 보고 잡은 예약이 들어 있습니다.
| booking_id | customer_id | customer_name | country | hospital_id | procedure_id | visit_at | interpreter_escort |
|---|---|---|---|---|---|---|---|
| BK-5512 | C-3101 | Mei | TW | H-01 | PR-101 | 2026-10-12T14:00:00+09:00 | true |
| BK-5513 | C-3101 | Mei | TW | H-03 | PR-302 | 2026-10-09T15:00:00+09:00 | false |
| BK-5520 | C-3102 | Yui | JP | H-02 | PR-201 | 2026-10-11T10:00:00+09:00 | true |
| BK-5521 | C-3102 | Yui | JP | H-02 | PR-203 | 2026-10-12T11:00:00+09:00 | false |
| BK-5531 | C-3103 | Nok | TH | H-02 | PR-202 | 2026-10-10T09:30:00+09:00 | true |
아래 JSON Schema 를 그대로 만족하는 예약을 30건 더 만들어 주세요. {"type":"object","properties":{"booking_id":{"type":"string"},"customer_id":{"type":"string"},"customer_name":{"type":"string"},"country":{"type":"string","description":"ISO 3166-1 alpha-2 국가 코드입니다"},"hospital_id":{"type":"string"},"procedure_id":{"type":"string"},"visit_at":{"type":"string","description":"ISO 8601, +09:00 입니다"},"interpreter_escort":{"type":"boolean","description":"통역사가 병원에 동행하는 예약인지입니다"}},"required":["booking_id","customer_id","customer_name","country","hospital_id","procedure_id","visit_at","interpreter_escort"]} customer_id 는 함께 주는 대화 표의 고객을, hospital_id·procedure_id 는 시술 표에서 같은 병원의 시술을 쓰세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 고객이 처음 말한 입국 시각으로는 맞지만 나중에 바꾼 입국 시각보다 이른 예약, (2) 재방문일이 출국일을 하루 넘기는 예약과 출국일과 같은 날인 예약, (3) 한 고객이 같은 날 서로 먼 두 병원을 20분 간격으로 잡은 예약과, 같은 병원에서 이어지는 예약, (4) 날짜를 말하지 않은 고객의 예약. 생성한 행은 반드시 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도(visit_at 에 시간대가 빠진 값)는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"booking_id":{"type":"string"},"customer_id":{"type":"string"},"customer_name":{"type":"string"},"country":{"type":"string","description":"ISO 3166-1 alpha-2 국가 코드입니다"},"hospital_id":{"type":"string"},"procedure_id":{"type":"string"},"visit_at":{"type":"string","description":"ISO 8601, +09:00 입니다"},"interpreter_escort":{"type":"boolean","description":"통역사가 병원에 동행하는 예약인지입니다"}},"required":["booking_id","customer_id","customer_name","country","hospital_id","procedure_id","visit_at","interpreter_escort"]}병원이 파트너 포털에 올린다고 가정한 시술 정보입니다. 소요 시간과 재방문(실밥 제거·경과 확인)까지의 일수가 있고, 재방문이 없는 시술은 revisit_after_days 가 null 입니다.
| procedure_id | hospital_id | procedure_name | duration_min | revisit_after_days | revisit_reason |
|---|---|---|---|---|---|
| PR-101 | H-01 | 쌍꺼풀 절개 | 120 | 6 | 실밥 제거 |
| PR-102 | H-01 | 눈밑 지방 재배치 | 90 | 5 | 실밥 제거 |
| PR-201 | H-02 | 울쎄라 리프팅 | 60 | — | — |
| PR-202 | H-02 | 보톡스 | 20 | — | — |
| PR-203 | H-02 | 리쥬란 주사 | 40 | — | — |
아래 JSON Schema 를 그대로 만족하는 시술 정보를 15건 더 만들어 주세요. {"type":"object","properties":{"procedure_id":{"type":"string"},"hospital_id":{"type":"string"},"procedure_name":{"type":"string"},"duration_min":{"type":"integer","minimum":5},"revisit_after_days":{"type":["integer","null"],"minimum":1,"description":"시술일로부터 재방문(실밥 제거·경과 확인)까지의 일수입니다. 재방문이 없는 시술은 null 입니다"},"revisit_reason":{"type":["string","null"],"enum":["실밥 제거","경과 확인",null]}},"required":["procedure_id","hospital_id","procedure_name","duration_min","revisit_after_days","revisit_reason"]} 병원 표의 hospital_id 마다 시술을 2~3개 두고, 피부과 시술은 대개 재방문이 없게, 절개가 있는 성형 시술은 실밥 제거 재방문이 있게 하세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) revisit_after_days 가 null 인 시술, (2) 재방문이 실밥 제거가 아니라 경과 확인인 시술, (3) duration_min 이 150분을 넘는 긴 시술. 생성한 행은 반드시 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도(duration_min 이 '1시간' 같은 문자열)는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"procedure_id":{"type":"string"},"hospital_id":{"type":"string"},"procedure_name":{"type":"string"},"duration_min":{"type":"integer","minimum":5},"revisit_after_days":{"type":["integer","null"],"minimum":1,"description":"시술일로부터 재방문(실밥 제거·경과 확인)까지의 일수입니다. 재방문이 없는 시술은 null 입니다"},"revisit_reason":{"type":["string","null"],"enum":["실밥 제거","경과 확인",null]}},"required":["procedure_id","hospital_id","procedure_name","duration_min","revisit_after_days","revisit_reason"]}제휴 병원의 위치입니다. 같은 날 두 병원 사이 이동 시간을 내는 데 lat·lng 를 씁니다. 병원 이름은 작성자가 지은 더미입니다.
| hospital_id | hospital_name | area | lat | lng |
|---|---|---|---|---|
| H-01 | 신사 A성형외과 | 신사동 | 37.521 | 127.023 |
| H-02 | 압구정 B피부과 | 압구정동 | 37.527 | 127.029 |
| H-03 | 강남역 C피부과 | 역삼동 | 37.498 | 127.028 |
| H-04 | 청담 D의원 | 청담동 | 37.525 | 127.049 |
| H-05 | 명동 E피부과 | 명동 | 37.564 | 126.985 |
아래 JSON Schema 를 그대로 만족하는 제휴 병원을 10곳 더 만들어 주세요. {"type":"object","properties":{"hospital_id":{"type":"string"},"hospital_name":{"type":"string"},"area":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"}},"required":["hospital_id","hospital_name","area","lat","lng"]} 서울에서 미용의료 병원이 모인 동네에 두고, lat·lng 는 그 동네 안의 좌표로 쓰세요. 병원 이름은 실제 병원과 겹치지 않게 '<동네> <알파벳><진료과>' 꼴로 지으세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 같은 건물에 있어 좌표가 거의 같은 두 병원, (2) 강남과 강북처럼 직선거리로 8km 넘게 떨어진 두 병원. 생성한 행은 반드시 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도(lat·lng 가 뒤바뀐 행)는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"hospital_id":{"type":"string"},"hospital_name":{"type":"string"},"area":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"}},"required":["hospital_id","hospital_name","area","lat","lng"]}병원 사이 이동 시간을 내는 계수표입니다. 앞 예약이 끝나는 시각의 시마다 도심 평균 속도를 두고, 직선거리를 도로 거리로 늘리는 우회 계수와 통역사와 함께 병원을 나서는 준비 시간을 둡니다. 작성자가 정한 합성 계수입니다.
| hour | speed_kmh | detour_factor | buffer_min |
|---|---|---|---|
| 9 | 18 | 1.3 | 10 |
| 10 | 21 | 1.3 | 10 |
| 11 | 22 | 1.3 | 10 |
| 12 | 20 | 1.3 | 10 |
| 13 | 21 | 1.3 | 10 |
아래 JSON Schema 를 그대로 만족하는 시간대 계수를 견줘 볼 한 벌(12행) 더 만들어 주세요. {"type":"object","properties":{"hour":{"type":"integer","minimum":9,"maximum":20,"description":"앞 예약이 끝나는 시각의 시입니다"},"speed_kmh":{"type":"number","description":"그 시간대 도심 평균 이동 속도입니다"},"detour_factor":{"type":"number","description":"직선거리를 도로 거리로 늘리는 계수입니다"},"buffer_min":{"type":"integer","description":"통역사와 병원을 나서 차를 타기까지의 준비 시간입니다"}},"required":["hour","speed_kmh","detour_factor","buffer_min"]} hour 는 9~20 을 한 번씩 쓰고, speed_kmh 는 서울 도심처럼 출퇴근 시간대에 낮게 두세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) speed_kmh 가 15 아래로 떨어지는 시간대, (2) buffer_min 이 다른 시간대보다 긴 점심 시간대. 생성한 행은 반드시 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도(hour 가 24 를 넘는 행)는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"hour":{"type":"integer","minimum":9,"maximum":20,"description":"앞 예약이 끝나는 시각의 시입니다"},"speed_kmh":{"type":"number","description":"그 시간대 도심 평균 이동 속도입니다"},"detour_factor":{"type":"number","description":"직선거리를 도로 거리로 늘리는 계수입니다"},"buffer_min":{"type":"integer","description":"통역사와 병원을 나서 차를 타기까지의 준비 시간입니다"}},"required":["hour","speed_kmh","detour_factor","buffer_min"]}| LLM | Claude Haiku 가 메신저 대화에서 입국·출국 날짜 표기를 원문 그대로 고르고 어느 쪽인지 정합니다. 고른 표기는 규칙이 다시 읽어 같을 때만 판정에 씁니다. |
| TypeScript | 언어별 날짜 읽기 규칙, 입국 시각·재방문일·이동 시간 계산, 판정 우선순위를 씁니다. |
| Next.js | 상담센터 어드민의 판정 화면과 서버 쪽 판정 실행을 맡습니다. |
| PostgreSQL | 다섯 표를 담고 마이그레이션으로 스키마를 올립니다. 예약·시술·병원은 키로 잇고 대화는 고객별 sent_at 순으로 읽습니다. |
| 다국어 | 근거는 고객이 쓴 언어의 원문 표기 그대로 두고 화면 라벨은 한국어로 둡니다. 3주차 안내 초안은 고객의 언어로 냅니다. |
| 평가 데이터·오류 분석 | 2주차에 손으로 단 정답 60건으로 추출과 판정을 맞대고, 틀린 대화를 언어별로 모읍니다. |
| 테스트 | 판정식의 '이르면'·'넘으면'·'짧으면' 마다 같은 값 사례를 테스트로 둡니다. 출국일과 같은 날 재방문인 BK-5550 이 그 사례입니다. |
| 접근 권한·감사 로그 | 3주차에 시술 정보가 든 대화 원문을 역할별로만 열고 열람 기록을 남깁니다. |
✗ fail → 첫 메시지의 21:40 으로 판정하면 sent_at 순 선택부터 고칩니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우려면 손으로 단 정답으로 날짜 추출이 맞는지 세는 단계로 갑니다.
✓ pass → 여기까지도 완결입니다. 더 키우려면 고객 언어 안내 초안과 대화 열람 기록으로 넓힙니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
verdict사유 라벨 · booking_id + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
일정에 맞는 예약일정에 맞음입국하기 전으로 잡힌 예약입국 전 예약출국 전에 재방문을 못 마침재방문 불가다음 병원까지 이동 시간이 모자람이동 시간 부족대화에서 입출국 날짜를 못 찾음입출국 날짜 없음예약 하나에 입출국 일정 판정 하나와 그 근거(대화 원문의 날짜 표기, 계산한 시각·날짜·이동 시간)를 남기는 형식입니다.
{"type":"object","properties":{"booking_id":{"type":"string"},"customer_id":{"type":"string"},"customer_name":{"type":"string"},"country":{"type":"string"},"procedure_id":{"type":"string"},"procedure_name":{"type":"string"},"hospital_id":{"type":"string"},"visit_at":{"type":"string"},"verdict":{"type":"string","enum":["일정에 맞는 예약","입국하기 전으로 잡힌 예약","출국 전에 재방문을 못 마침","다음 병원까지 이동 시간이 모자람","대화에서 입출국 날짜를 못 찾음"],"description":"걸린 판정이 여럿이면 입국하기 전으로 잡힌 예약, 출국 전에 재방문을 못 마침, 다음 병원까지 이동 시간이 모자람, 대화에서 입출국 날짜를 못 찾음 순으로 앞선 하나입니다. 하나도 걸리지 않으면 일정에 맞는 예약입니다"},"also_found":{"type":"array","items":{"type":"string","enum":["입국하기 전으로 잡힌 예약","출국 전에 재방문을 못 마침","다음 병원까지 이동 시간이 모자람","대화에서 입출국 날짜를 못 찾음"]}},"arrival":{"type":["object","null"],"properties":{"date":{"type":"string"},"time":{"type":["string","null"]},"message_id":{"type":"string"},"sent_at":{"type":"string"},"quote":{"type":"string"}},"description":"원문 검사를 통과한 입국 표기 가운데 sent_at 이 가장 늦은 것입니다. 없으면 null 입니다"},"departure":{"type":["object","null"],"properties":{"date":{"type":"string"},"time":{"type":["string","null"]},"message_id":{"type":"string"},"sent_at":{"type":"string"},"quote":{"type":"string"}},"description":"원문 검사를 통과한 출국 표기 가운데 sent_at 이 가장 늦은 것입니다. 없으면 null 입니다"},"earliest_visit_at":{"type":["string","null"],"description":"정적 계산값입니다. arrival 의 날짜·시각(시각이 없으면 00:00)에 180분을 더한 값이고, 입국 수속·이동 3시간은 확정 카드가 정한 고정값입니다"},"revisit_date":{"type":["string","null"],"description":"정적 계산값입니다. visit_at 날짜에 procedures.revisit_after_days 를 더한 날이고, 재방문이 없는 시술이면 null 입니다"},"next_booking_id":{"type":["string","null"],"description":"같은 고객·같은 날 visit_at 순으로 바로 다음 예약입니다"},"interval_min":{"type":["integer","null"],"description":"정적 계산값입니다. 다음 예약 visit_at 에서 이 예약 visit_at 과 duration_min 의 합을 뺀 분입니다"},"distance_km":{"type":["number","null"],"minimum":0,"description":"정적 계산값입니다. 두 병원 lat·lng 의 하버사인 거리(지구 반지름 6,371km, 소수 둘째 자리 반올림)이고 같은 병원이면 0 입니다"},"travel_min":{"type":["integer","null"],"minimum":0,"description":"정적 계산값입니다. 두 병원이 같으면 0, 다르면 올림(distance_km × detour_factor ÷ speed_kmh × 60) + buffer_min 이고, 계수는 이 예약이 끝나는 시각의 시(hour) 행을 travel_speed_by_hour 에서 씁니다"},"evidence":{"type":"array","items":{"type":"object","properties":{"table":{"type":"string","enum":["chat_messages","bookings","procedures","hospitals","travel_speed_by_hour"]},"row":{"type":["string","null"],"description":"그 표의 키 값입니다. agg 항목이면 null 입니다"},"field":{"type":"string"},"value":{"type":["string","integer","number","null"]},"quote":{"type":"string","description":"text 원문에서 그대로 딴 날짜 표기입니다"},"agg":{"type":"string","enum":["count","sum","avg","min","max"]}},"required":["table","row","field"]}},"notes":{"type":"array","items":{"type":"string"},"description":"판정에 들지 않았지만 코디네이터가 확인할 사실입니다"},"summary":{"type":"string"}},"required":["booking_id","customer_id","customer_name","country","procedure_id","procedure_name","hospital_id","visit_at","verdict","also_found","arrival","departure","earliest_visit_at","revisit_date","next_booking_id","interval_min","distance_km","travel_min","evidence","notes","summary"]}[
{
"booking_id": "BK-5520",
"customer_id": "C-3102",
"customer_name": "Yui",
"country": "JP",
"procedure_id": "PR-201",
"procedure_name": "울쎄라 리프팅",
"hospital_id": "H-02",
"visit_at": "2026-10-11T10:00:00+09:00",
"verdict": "입국하기 전으로 잡힌 예약",
"also_found": [],
"arrival": {
"date": "2026-10-11",
"time": "13:20",
"message_id": "M-7005",
"sent_at": "2026-10-06T08:12:00+09:00",
"quote": "10月11日 13:20着"
},
"departure": {
"date": "2026-10-14",
"time": null,
"message_id": "M-7005",
"sent_at": "2026-10-06T08:12:00+09:00",
"quote": "帰国は10月14日"
},
"earliest_visit_at": "2026-10-11T16:20:00+09:00",
"revisit_date": null,
"next_booking_id": null,
"interval_min": null,
"distance_km": null,
"travel_min": null,
"evidence": [
{
"table": "bookings",
"row": "BK-5520",
"field": "visit_at",
"value": "2026-10-11T10:00:00+09:00"
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "text",
"quote": "10月11日 13:20着"
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "sent_at",
"value": "2026-10-06T08:12:00+09:00"
},
{
"table": "procedures",
"row": "PR-201",
"field": "revisit_after_days",
"value": null
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "text",
"quote": "帰国は10月14日"
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "sent_at",
"value": "2026-10-06T08:12:00+09:00"
}
],
"notes": [
"10월 3일 메시지의 '10月10日 21:40着' 대신 sent_at 이 더 늦은 10월 6일 메시지의 '10月11日 13:20着' 을 입국 시각으로 씁니다."
],
"summary": "고객이 10월 6일 LINE 에서 바꿔 말한 입국 시각 10월 11일 13:20 에 3시간을 더하면 16:20 인데, 울쎄라 리프팅 예약은 그날 10:00 입니다."
},
{
"booking_id": "BK-5512",
"customer_id": "C-3101",
"customer_name": "Mei",
"country": "TW",
"procedure_id": "PR-101",
"procedure_name": "쌍꺼풀 절개",
"hospital_id": "H-01",
"visit_at": "2026-10-12T14:00:00+09:00",
"verdict": "출국 전에 재방문을 못 마침",
"also_found": [],
"arrival": {
"date": "2026-10-08",
"time": null,
"message_id": "M-7001",
"sent_at": "2026-10-01T21:14:00+09:00",
"quote": "Oct 8"
},
"departure": {
"date": "2026-10-15",
"time": null,
"message_id": "M-7002",
"sent_at": "2026-10-02T10:03:00+09:00",
"quote": "Oct 15"
},
"earliest_visit_at": "2026-10-08T03:00:00+09:00",
"revisit_date": "2026-10-18",
"next_booking_id": null,
"interval_min": null,
"distance_km": null,
"travel_min": null,
"evidence": [
{
"table": "bookings",
"row": "BK-5512",
"field": "visit_at",
"value": "2026-10-12T14:00:00+09:00"
},
{
"table": "chat_messages",
"row": "M-7001",
"field": "text",
"quote": "Oct 8"
},
{
"table": "chat_messages",
"row": "M-7001",
"field": "sent_at",
"value": "2026-10-01T21:14:00+09:00"
},
{
"table": "procedures",
"row": "PR-101",
"field": "revisit_after_days",
"value": 6
},
{
"table": "chat_messages",
"row": "M-7002",
"field": "text",
"quote": "Oct 15"
},
{
"table": "chat_messages",
"row": "M-7002",
"field": "sent_at",
"value": "2026-10-02T10:03:00+09:00"
}
],
"notes": [],
"summary": "쌍꺼풀 절개 뒤 6일째인 실밥 제거일이 10월 18일인데, 고객이 10월 2일 LINE 에서 말한 출국일은 10월 15일입니다."
},
{
"booking_id": "BK-5531",
"customer_id": "C-3103",
"customer_name": "Nok",
"country": "TH",
"procedure_id": "PR-202",
"procedure_name": "보톡스",
"hospital_id": "H-02",
"visit_at": "2026-10-10T09:30:00+09:00",
"verdict": "다음 병원까지 이동 시간이 모자람",
"also_found": [],
"arrival": {
"date": "2026-10-09",
"time": "07:40",
"message_id": "M-7006",
"sent_at": "2026-10-02T16:25:00+09:00",
"quote": "9 ต.ค. 07:40"
},
"departure": {
"date": "2026-10-14",
"time": null,
"message_id": "M-7007",
"sent_at": "2026-10-02T16:26:00+09:00",
"quote": "14 ต.ค."
},
"earliest_visit_at": "2026-10-09T10:40:00+09:00",
"revisit_date": null,
"next_booking_id": "BK-5532",
"interval_min": 20,
"distance_km": 5.6,
"travel_min": 35,
"evidence": [
{
"table": "bookings",
"row": "BK-5531",
"field": "visit_at",
"value": "2026-10-10T09:30:00+09:00"
},
{
"table": "chat_messages",
"row": "M-7006",
"field": "text",
"quote": "9 ต.ค. 07:40"
},
{
"table": "chat_messages",
"row": "M-7006",
"field": "sent_at",
"value": "2026-10-02T16:25:00+09:00"
},
{
"table": "procedures",
"row": "PR-202",
"field": "revisit_after_days",
"value": null
},
{
"table": "chat_messages",
"row": "M-7007",
"field": "text",
"quote": "14 ต.ค."
},
{
"table": "chat_messages",
"row": "M-7007",
"field": "sent_at",
"value": "2026-10-02T16:26:00+09:00"
},
{
"table": "procedures",
"row": "PR-202",
"field": "duration_min",
"value": 20
},
{
"table": "bookings",
"row": "BK-5532",
"field": "visit_at",
"value": "2026-10-10T10:10:00+09:00"
},
{
"table": "hospitals",
"row": "H-02",
"field": "lat",
"value": 37.527
},
{
"table": "hospitals",
"row": "H-02",
"field": "lng",
"value": 127.0286
},
{
"table": "hospitals",
"row": "H-05",
"field": "lat",
"value": 37.5636
},
{
"table": "hospitals",
"row": "H-05",
"field": "lng",
"value": 126.985
},
{
"table": "travel_speed_by_hour",
"row": "9",
"field": "speed_kmh",
"value": 18
},
{
"table": "travel_speed_by_hour",
"row": "9",
"field": "detour_factor",
"value": 1.3
},
{
"table": "travel_speed_by_hour",
"row": "9",
"field": "buffer_min",
"value": 10
}
],
"notes": [],
"summary": "압구정 B피부과 보톡스가 09:50 에 끝나고 다음 예약인 명동 E피부과 피코 레이저가 10:10 이라 간격은 20분인데, 두 병원 사이 이동에는 35분이 필요합니다."
},
{
"booking_id": "BK-5540",
"customer_id": "C-3104",
"customer_name": "Emily",
"country": "US",
"procedure_id": "PR-301",
"procedure_name": "레이저 토닝",
"hospital_id": "H-03",
"visit_at": "2026-10-17T11:00:00+09:00",
"verdict": "대화에서 입출국 날짜를 못 찾음",
"also_found": [],
"arrival": null,
"departure": null,
"earliest_visit_at": null,
"revisit_date": null,
"next_booking_id": null,
"interval_min": null,
"distance_km": null,
"travel_min": null,
"evidence": [
{
"table": "bookings",
"row": "BK-5540",
"field": "visit_at",
"value": "2026-10-17T11:00:00+09:00"
},
{
"table": "procedures",
"row": "PR-301",
"field": "revisit_after_days",
"value": null
},
{
"table": "chat_messages",
"row": null,
"field": "message_id",
"agg": "count",
"value": 3
},
{
"table": "chat_messages",
"row": "M-7008",
"field": "text",
"quote": "next Friday morning"
},
{
"table": "chat_messages",
"row": "M-7008",
"field": "text",
"quote": "the Sunday after"
}
],
"notes": [
"모델이 'next Friday morning'·'the Sunday after' 를 날짜로 냈지만 원문에 날짜 표기가 없어 버렸습니다."
],
"summary": "Emily 의 WhatsApp 메시지 세 개에는 'next Friday morning' 처럼 요일로 말한 표현만 있어 입국일·출국일로 쓸 날짜가 없습니다."
},
{
"booking_id": "BK-5513",
"customer_id": "C-3101",
"customer_name": "Mei",
"country": "TW",
"procedure_id": "PR-302",
"procedure_name": "스킨 부스터",
"hospital_id": "H-03",
"visit_at": "2026-10-09T15:00:00+09:00",
"verdict": "일정에 맞는 예약",
"also_found": [],
"arrival": {
"date": "2026-10-08",
"time": null,
"message_id": "M-7001",
"sent_at": "2026-10-01T21:14:00+09:00",
"quote": "Oct 8"
},
"departure": {
"date": "2026-10-15",
"time": null,
"message_id": "M-7002",
"sent_at": "2026-10-02T10:03:00+09:00",
"quote": "Oct 15"
},
"earliest_visit_at": "2026-10-08T03:00:00+09:00",
"revisit_date": null,
"next_booking_id": null,
"interval_min": null,
"distance_km": null,
"travel_min": null,
"evidence": [
{
"table": "bookings",
"row": "BK-5513",
"field": "visit_at",
"value": "2026-10-09T15:00:00+09:00"
},
{
"table": "chat_messages",
"row": "M-7001",
"field": "text",
"quote": "Oct 8"
},
{
"table": "chat_messages",
"row": "M-7001",
"field": "sent_at",
"value": "2026-10-01T21:14:00+09:00"
},
{
"table": "procedures",
"row": "PR-302",
"field": "revisit_after_days",
"value": null
},
{
"table": "chat_messages",
"row": "M-7002",
"field": "text",
"quote": "Oct 15"
},
{
"table": "chat_messages",
"row": "M-7002",
"field": "sent_at",
"value": "2026-10-02T10:03:00+09:00"
}
],
"notes": [],
"summary": "입국일 10월 8일 다음 날 오후 예약이고 재방문이 없는 시술이라 출국일 10월 15일 안에 끝납니다."
},
{
"booking_id": "BK-5521",
"customer_id": "C-3102",
"customer_name": "Yui",
"country": "JP",
"procedure_id": "PR-203",
"procedure_name": "리쥬란 주사",
"hospital_id": "H-02",
"visit_at": "2026-10-12T11:00:00+09:00",
"verdict": "일정에 맞는 예약",
"also_found": [],
"arrival": {
"date": "2026-10-11",
"time": "13:20",
"message_id": "M-7005",
"sent_at": "2026-10-06T08:12:00+09:00",
"quote": "10月11日 13:20着"
},
"departure": {
"date": "2026-10-14",
"time": null,
"message_id": "M-7005",
"sent_at": "2026-10-06T08:12:00+09:00",
"quote": "帰国は10月14日"
},
"earliest_visit_at": "2026-10-11T16:20:00+09:00",
"revisit_date": null,
"next_booking_id": null,
"interval_min": null,
"distance_km": null,
"travel_min": null,
"evidence": [
{
"table": "bookings",
"row": "BK-5521",
"field": "visit_at",
"value": "2026-10-12T11:00:00+09:00"
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "text",
"quote": "10月11日 13:20着"
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "sent_at",
"value": "2026-10-06T08:12:00+09:00"
},
{
"table": "procedures",
"row": "PR-203",
"field": "revisit_after_days",
"value": null
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "text",
"quote": "帰国は10月14日"
},
{
"table": "chat_messages",
"row": "M-7005",
"field": "sent_at",
"value": "2026-10-06T08:12:00+09:00"
}
],
"notes": [
"10월 3일 메시지의 '10月10日 21:40着' 대신 sent_at 이 더 늦은 10월 6일 메시지의 '10月11日 13:20着' 을 입국 시각으로 씁니다."
],
"summary": "입국 다음 날 오전 리쥬란 주사 예약이고 재방문이 없는 시술이라 출국일 10월 14일 안에 끝납니다."
},
{
"booking_id": "BK-5550",
"customer_id": "C-3106",
"customer_name": "Sora",
"country": "JP",
"procedure_id": "PR-101",
"procedure_name": "쌍꺼풀 절개",
"hospital_id": "H-01",
"visit_at": "2026-10-10T10:00:00+09:00",
"verdict": "일정에 맞는 예약",
"also_found": [],
"arrival": {
"date": "2026-10-09",
"time": "11:05",
"message_id": "M-7012",
"sent_at": "2026-10-04T12:30:00+09:00",
"quote": "10月9日 11:05着"
},
"departure": {
"date": "2026-10-16",
"time": "18:30",
"message_id": "M-7012",
"sent_at": "2026-10-04T12:30:00+09:00",
"quote": "10月16日 18:30発"
},
"earliest_visit_at": "2026-10-09T14:05:00+09:00",
"revisit_date": "2026-10-16",
"next_booking_id": null,
"interval_min": null,
"distance_km": null,
"travel_min": null,
"evidence": [
{
"table": "bookings",
"row": "BK-5550",
"field": "visit_at",
"value": "2026-10-10T10:00:00+09:00"
},
{
"table": "chat_messages",
"row": "M-7012",
"field": "text",
"quote": "10月9日 11:05着"
},
{
"table": "chat_messages",
"row": "M-7012",
"field": "sent_at",
"value": "2026-10-04T12:30:00+09:00"
},
{
"table": "procedures",
"row": "PR-101",
"field": "revisit_after_days",
"value": 6
},
{
"table": "chat_messages",
"row": "M-7012",
"field": "text",
"quote": "10月16日 18:30発"
},
{
"table": "chat_messages",
"row": "M-7012",
"field": "sent_at",
"value": "2026-10-04T12:30:00+09:00"
}
],
"notes": [
"실밥 제거일 10월 16일이 출국일과 같은 날입니다. 원문 '10月16日 18:30発' 의 출발 전에 실밥 제거를 마칠 수 있는지 확인합니다."
],
"summary": "실밥 제거일 10월 16일이 출국일과 같은 날이라 판정식으로는 걸리지 않습니다."
},
{
"booking_id": "BK-5545",
"customer_id": "C-3105",
"customer_name": "Lin",
"country": "CN",
"procedure_id": "PR-401",
"procedure_name": "코 필러",
"hospital_id": "H-04",
"visit_at": "2026-10-07T15:00:00+09:00",
"verdict": "일정에 맞는 예약",
"also_found": [],
"arrival": {
"date": "2026-10-07",
"time": null,
"message_id": "M-7011",
"sent_at": "2026-10-03T19:48:00+09:00",
"quote": "10月7日上午到仁川"
},
"departure": {
"date": "2026-10-13",
"time": null,
"message_id": "M-7011",
"sent_at": "2026-10-03T19:48:00+09:00",
"quote": "10月13日回国"
},
"earliest_visit_at": "2026-10-07T03:00:00+09:00",
"revisit_date": null,
"next_booking_id": "BK-5546",
"interval_min": 30,
"distance_km": 0,
"travel_min": 0,
"evidence": [
{
"table": "bookings",
"row": "BK-5545",
"field": "visit_at",
"value": "2026-10-07T15:00:00+09:00"
},
{
"table": "chat_messages",
"row": "M-7011",
"field": "text",
"quote": "10月7日上午到仁川"
},
{
"table": "chat_messages",
"row": "M-7011",
"field": "sent_at",
"value": "2026-10-03T19:48:00+09:00"
},
{
"table": "procedures",
"row": "PR-401",
"field": "revisit_after_days",
"value": null
},
{
"table": "chat_messages",
"row": "M-7011",
"field": "text",
"quote": "10月13日回国"
},
{
"table": "chat_messages",
"row": "M-7011",
"field": "sent_at",
"value": "2026-10-03T19:48:00+09:00"
},
{
"table": "procedures",
"row": "PR-401",
"field": "duration_min",
"value": 30
},
{
"table": "bookings",
"row": "BK-5546",
"field": "visit_at",
"value": "2026-10-07T16:00:00+09:00"
},
{
"table": "bookings",
"row": "BK-5545",
"field": "hospital_id",
"value": "H-04"
},
{
"table": "bookings",
"row": "BK-5546",
"field": "hospital_id",
"value": "H-04"
}
],
"notes": [
"입국 시각을 말하지 않아 10월 7일 00:00 으로 봤습니다. 원문 '10月7日上午到仁川' 만으로는 같은 날 15:00 예약에 맞춰 올 수 있는지 알 수 없어 항공편 시각을 확인합니다."
],
"summary": "입국 당일 오후 코 필러 예약이고, 다음 예약이 같은 병원에서 30분 뒤라 이동 시간이 들지 않습니다."
}
][자동 검증 · 코드가 판정합니다] 1. verdict 가 일정에 맞는 예약·입국하기 전으로 잡힌 예약·출국 전에 재방문을 못 마침·다음 병원까지 이동 시간이 모자람·대화에서 입출국 날짜를 못 찾음 다섯 값 중 하나인지, also_found 가 일정에 맞는 예약을 뺀 네 값 중 하나인지 확인합니다. 2. 필수 필드 booking_id·customer_id·customer_name·country·procedure_id·procedure_name·hospital_id·visit_at·verdict·also_found·arrival·departure·earliest_visit_at·revisit_date·next_booking_id·interval_min·distance_km·travel_min·evidence·notes·summary 가 모두 존재하는지 확인합니다. 3. arrival·departure 의 quote 가 그 message_id 의 chat_messages.text 원문에 글자 그대로 있는지, quote 를 언어별 날짜 읽기 규칙으로 다시 읽은 월·일(시각이 있으면 시각)이 date·time 과 같은지 확인합니다. 둘 중 하나라도 어긋난 모델 출력은 버리므로 원문에 날짜 표기가 없는 날짜는 판정에 들지 않습니다. 4. 입국하기 전으로 잡힌 예약: 같은 customer_id 의 chat_messages 를 sent_at 순으로 보고, 3번을 통과한 입국 표기 가운데 sent_at 이 가장 늦은 표기를 arrival 로 씁니다. 시각이 없으면 그날 00:00 으로 봅니다. earliest_visit_at 이 arrival 에 180분을 더한 값인지 다시 계산하고, visit_at 이 earliest_visit_at 보다 이르면 이 판정이 걸립니다. C-3102 는 10月10日 21:40着 뒤에 10月11日 13:20着 을 말해 13:20 이 arrival 이고, 16:20 보다 이른 BK-5520(10:00)이 걸립니다. 시각 없이 10月7日 만 말한 C-3105 의 BK-5545(10월 7일 15:00)는 03:00 보다 늦어 걸리지 않습니다. 5. 출국 전에 재방문을 못 마침: revisit_after_days 가 null 이 아니면 revisit_date 가 visit_at 날짜에 그 일수를 더한 날인지 다시 계산합니다. revisit_date 가 3번을 통과한 출국 표기 가운데 sent_at 이 가장 늦은 메시지의 날짜(departure.date)보다 늦으면 걸리고, 같은 날이면 걸리지 않습니다. BK-5512 는 10월 18일이 10월 15일보다 늦어 걸리고, BK-5550 은 10월 16일이 출국일과 같아 걸리지 않습니다. 6. 다음 병원까지 이동 시간이 모자람: 같은 customer_id·같은 날짜의 bookings 를 visit_at 순으로 보고, interval_min 이 다음 예약 visit_at 에서 이 예약 visit_at 과 duration_min 의 합을 뺀 분인지 다시 계산합니다. distance_km 는 두 병원 lat·lng 의 하버사인 거리(지구 반지름 6,371km, 소수 둘째 자리 반올림)이고, travel_min 은 두 병원이 같으면 0, 다르면 올림(distance_km × detour_factor ÷ speed_kmh × 60) + buffer_min 입니다. 계수는 이 예약이 끝나는 시각의 시(hour) 행을 travel_speed_by_hour 에서 씁니다. interval_min 이 travel_min 보다 짧으면 앞 예약에 이 판정이 걸립니다. BK-5531 은 20분이 35분보다 짧아 걸리고, 같은 병원에서 30분 뒤 예약이 이어지는 BK-5545 는 걸리지 않습니다. 7. 대화에서 입출국 날짜를 못 찾음: 같은 customer_id 의 대화에서 3번을 통과한 입국 표기와 출국 표기 가운데 하나라도 없으면 걸리는지 다시 계산합니다. 'next Friday morning'·'the Sunday after' 처럼 요일로만 말한 C-3104 의 BK-5540 이 이 경우입니다. 8. 한 예약에 여러 판정이 걸리면 입국하기 전으로 잡힌 예약, 출국 전에 재방문을 못 마침, 다음 병원까지 이동 시간이 모자람, 대화에서 입출국 날짜를 못 찾음 순으로 앞선 하나가 verdict 이고 나머지는 also_found 입니다. 하나도 걸리지 않으면 일정에 맞는 예약입니다. 이 순서로 정해졌는지 다시 계산합니다. 9. evidence 의 table·field 가 chat_messages·bookings·procedures·hospitals·travel_speed_by_hour 에 실재하는 컬럼인지 대조합니다. 10. evidence 의 quote 가 그 row 의 text 원문 substring 인지, agg 가 없는 value 가 그 row 의 그 컬럼 값과 같은지 확인합니다. agg 가 count 인 값은 그 고객의 메시지 수입니다. 11. summary 가 존댓말로 끝나는지 확인합니다. [수동 검증 · 사람이 봅니다] 1. 입국 시각을 말하지 않은 고객의 입국 당일 예약은 판정식으로 걸리지 않습니다. notes 에 남은 그런 예약은 코디네이터가 고객에게 항공편 시각을 물어 확인합니다. 2. 출국일과 같은 날 재방문인 예약도 판정식으로 걸리지 않으므로, 재방문 시각과 출발 시각 사이가 넉넉한지 코디네이터가 봅니다. 3. 재방문 일수를 앞당겨도 되는지는 병원이 정합니다. 이 화면은 병원이 올린 값을 바꾸지 않습니다. 4. 걸린 예약을 옮길지, 고객에게 항공편을 다시 물을지는 코디네이터와 운영 담당자가 정합니다. [평가 러너 · 2주차] 1. 작성자가 입국·출국 날짜를 손으로 단 대화 60건에서, 모델 추출과 3번 검사를 거친 날짜가 정답과 같은 건수를 언어별로 셉니다. 2. 같은 60건에 딸린 예약의 verdict 가 손으로 낸 판정과 같은 건수를 셉니다. [판정식에 더한 정의 · 오너 확인 항목] 1. 이동 시간 계산에 쓰는 시간대별 속도·우회 계수·준비 시간은 카드 inputs 에 없던 travel_speed_by_hour 표로 선언했습니다. 작성자가 정한 합성 계수입니다. 2. 이동 시간 판정은 두 예약 가운데 앞 예약의 판정으로 두고 next_booking_id 로 다음 예약을 가리킵니다. 3. 입국 시각이 없는 날짜 표기는 그날 00:00 으로 보고, 같은 병원에서 이어지는 예약은 이동 시간을 0분으로 봅니다. 4. 날짜 표기를 고르는 일은 Claude Haiku 가 하고, 고른 표기의 날짜 값은 규칙이 원문에서 다시 읽습니다.