Files
aio-01d4-stu/Last3Mon/72/LAB-02-A-OPTIMIZE-FLOW.md
T

9.6 KiB
Raw Blame History

Lab 02 · 규칙 먼저, 캐시, LLM 한 번

강사용 정답본 · 학생 저장소에 올리지 않습니다. 학생용 문제는 LAB-02-Q-OPTIMIZE-FLOW.md. 요청문은 예시이며 CLI 에이전트로 보내 재지는 않았습니다. 결과 숫자는 정답 워크플로우를 2026-10-18에 1회씩 실행한 값입니다 (강사 Mac, gpt-4.1-mini, bench는 n=5). 10/24에 실습을 5개로 늘리며 정답을 학생 순서대로 다시 돌렸습니다 (45단계). 명령 · -v 출력 전부와 codex 프롬프트: answers/LAB-TEST-RESULT.md. 10/24 점수: 예제 1 lab02 7/9 (캐시 케이스 · 접수 답에서 검토 LLM이 "처리 중"을 바꿈), 나머지는 모두 기대대로.

예제 1 · 요청문 예

my-work/helpdesk.json 의 순서를 바꿔 줘: Has question? → Start clock → Search FAQ → Get ticket → After data → Rule classify(Code) → Known?(If).
Rule classify: 질문에 T-1234 같은 번호(/T-?\d{4}/i)가 있으면 ticket, FAQ 결과가 1개 이상이면 faq, 아니면 unknown. {category, by:'rule'}.
Known? true → Answer, false → Classify → Parse category → After classify → Answer. Answer 는 $json.category 로 분류를 읽는다.
Build result: 분류는 Parse category 가 실행됐으면 그것, 아니면 Rule classify. steps 에 rule 또는 classify.
나머지(답, 검토, timings)는 그대로. 기대 결과 cases/lab02.json 앞 네 케이스.

빈칸 답 (Q 문서 ▶ 빈칸 채우기 ____①~____④)

빈칸 답 왜
① /T-?\d{4}/i 하이픈 있어도 없어도, 대소문자 무시, 숫자 네 자리 (T-1002 · t1002)
② 1개 이상 /faq의 results가 비어 있지 않으면 FAQ로 답할 수 있음
③ Parse category LLM 분류 길에서 분류 결과를 만드는 마지막 노드
④ rule 규칙 길을 지났다는 steps 이름 (AGENTS.md 3절)

정답: reference/lab02-example1-rules.json

수업 준비 때 결과
cases/lab02.json 7/9 (예제 2의 "같은 질문" 캐시 케이스와, 답 문장이 기대 표현과 달랐던 "없는 접수 번호" 실패. 10/23~24에는 "없는 접수 번호"가 통과해 8/9)
cases/lab01.json 4/4
규칙 질문 시간 접수 1.92.3초 (예제 2 timings 상태에서 2.42.8초)
  • 처음 쓴 "없는 접수 번호" 기대(찾지 못)가 틀렸습니다: 검토 LLM이 "확인되지 않습니다"로 바꿔 말함. 기대를 "없다는 여러 표현 + 상태를 지어내지 않음(not_contains 처리 중 등)"으로 고쳤습니다 (71일차 "모른다의 여러 모양"과 같음).

예제 2 · 요청문 예

my-work/helpdesk.json 에 캐시를 더해 줘 (AGENTS.md 2절 데이터 API, 3절 캐시 규칙).
Start clock 다음: Cache key(Code: question 을 trim·소문자·연속 공백 하나, use_cache = body.no_cache !== true)
→ Cache lookup(GET http://data-api:8800/cache/<encodeURIComponent(key)>, neverError) → Cached?(value 있고 use_cache)
  true → Cached result(route·category·answer·sources + llm_calls 0, cached true, steps ['cache'], timings.total_ms) → Send cached
  false → 지금 흐름(Search FAQ ...).
Build result 뒤: Cache it?(category faq 이고 use_cache) true → Store in cache(POST /cache/<key> {value:{route,category,answer,sources}, ttl 600}) → Send result.
접수(ticket)는 저장하지 않는다. 기대 결과 cases/lab02.json 전체, lab01 도 통과.

빈칸 답 (Q 문서 ▶ 빈칸 채우기 ____①~____④)

빈칸 답 왜
① trim · 소문자 · 연속 공백 하나 띄어쓰기 · 대소문자만 다른 질문을 같은 키로 (AGENTS.md 3절)
② body.no_cache !== true 본문 no_cache가 true가 아닐 때만 캐시 사용
③ neverError 캐시에 없을 때의 404에서 멈추지 않게 (AGENTS.md 5절)
④ 접수(ticket) 상태가 바뀌는 답은 캐시하지 않음 (AGENTS.md 3절 굵은 줄)

정답: reference/lab02-example2-cache.json

수업 준비 때 결과
cases/lab02.json 9/9 · 같은 질문(띄어쓰기·대소문자 다름) 0.1초, llm_calls: 0
cases/lab01.json · lab03.json 4/4 · 2/4 (3단계 전)
캐시 없이 (faq-vpn-nocache) bench p50 2.01초 · p95 2.23초
  • 처음에는 "규칙으로 모르는 질문"(회의실 화면 공유)이 LLM 분류로 faq가 되어 캐시에 들어갔고, 다음 테스트에서 0.1초로 나와 llm_calls 기대가 깨졌습니다. 그 케이스에 no_cache: true를 넣었습니다 → 수업 이야기 거리: "캐시는 테스트도 바꾼다".

예제 3 · 결과 (에이전트 없이, 10/24)

예제 2 정답(reference/lab02-example2-cache.json), 캐시를 비운 뒤.

재기 첫 호출 p50 max
캐시 씀 (faq-vpn × 5) 2.07초 (LLM 2번) 0.05초 2.07초
캐시 안 씀 (faq-vpn-nocache × 5) 1.99초 1.99초 2.24초
  • /cache-stats 뒤: entries 1 · hits 9 · misses 1. no_cache 요청도 캐시를 조회는 하므로 hits로 셉니다 (쓰지는 않음). 학생이 "적중 9번?"이라고 하면 이 이야기를 합니다.
  • 적중률 어림 (0.05초 · 2.0초): 10% → 1.81초, 30% → 1.42초, 60% → 0.83초.

과제 1 · 요청문 예

my-work/helpdesk.json 에서 Review(검토 LLM)와 Review model 을 지우고, 그 자리에 Review check(Code)를 둬:
Answer 의 output 을 trim, 비었으면 empty, 한글이 없으면 not_korean, 400자 넘으면 자르고 too_long 을 review_problems 에.
Answer 지시문에 "합니다체, 3문장 이내"가 이미 있는지 확인. steps 에는 review 대신 check, llm_calls 는 검토를 세지 않는다.
나머지는 그대로. cases/lab02-challenge.json, lab02.json, lab01.json 모두 통과.

빈칸 답 (Q 문서 ▶ 빈칸 채우기 ____①~____④)

빈칸 답 왜
① 400 답 길이 상한 (교안 2단계 6절 검사 표)
② 합니다체, 3문장 이내 검토 LLM이 하던 말투 · 길이 다듬기를 지시문으로
③ check 검토 대신 코드 검사를 지났다는 단계 이름 (다른 짧은 이름도 됨)
④ 검토를 세지 않는다 지운 Review는 빼고 셈: 규칙 길 1, LLM 분류 길 2

정답: answers/72-lab02-challenge-fast.json

수업 준비 때 결과
cases/lab02-challenge.json 5/5 (VPN 1.2초 · 비밀번호 1.1초 · 접수 1.3초) · 캐시 단계 상태 1/5
cases/lab02.json · lab01.json 9/9 · 4/4
캐시 없이 bench p50 2.01 → 1.15초 · p95 2.23 → 1.16초
  • 처음 쓴 lab01 · lab02 기대에 llm_calls: 3, steps에 review 같은 구조가 들어 있어, 과제로 정당하게 빨라진 워크플로우가 실패했습니다. 품질 테스트는 답의 내용만 보게 고쳤습니다 (구조 기대는 그 단계의 테스트에만) → 이야기 거리: "최적화하면 깨지는 테스트는 무엇을 재고 있었나".

10/24 다시 돌린 결과: 고치기 전 lab02-challenge 1/5, bench p50 2.22 · p95 2.45초 → 고친 뒤 15/15 (--repeat 3, 0.9~1.6초), lab02 9/9, lab01 4/4, bench p50 1.12 · p95 1.32초.

과제 2 · 요청문 예

my-work/helpdesk.json 에 FAQ 번호 캐시를 더해 줘 (AGENTS.md 3절 캐시 키 표).
Rule classify 다음: FAQ cache key(Code: category 가 faq 이고 use_cache 이고 FAQ 결과가 있으면 faq_key = 'faq-' + 첫 FAQ id, 아니면 'none')
→ FAQ cache lookup(GET /cache/<faq_key>, neverError) → FAQ cached?(value 있고 faq_key 가 'none' 아님)
  true → FAQ cached result(llm_calls 0, cached true, cache_by 'faq', steps ['faq', 'rule', 'cache']) → Send
  false → Back to rule(Code: Rule classify 의 결과를 그대로) → Known?
Store in cache 뒤에 Store by FAQ(POST /cache/<faq_key>, 같은 value, ttl 600) → Result again.
질문 캐시의 Cached result 에는 cache_by 'question', Build result 에는 cache_by null.
기대 결과 cases/lab02-challenge2.json, lab02-challenge.json, lab02.json 도 통과.

빈칸 답 (Q 문서 ▶ 빈칸 채우기 ____①~____④)

빈칸 답 왜
① faq- 캐시 키 표 둘째 줄: faq-<FAQ id>
② faq FAQ 번호 키로 찾았을 때 (AGENTS.md 3절 Lab 02 과제 2)
③ 600 질문 캐시와 같은 ttl (초)
④ question ②와 짝. 질문 키로 찾았을 때

정답: answers/72-lab02-challenge2-faqcache.json (과제 1 정답에 노드 7개: FAQ cache key · FAQ cache lookup · FAQ cached? · FAQ cached result · Send FAQ cached · Back to rule · Store by FAQ)

10/24 결과 (cases/lab02-challenge2.json) 고치기 전 (과제 1 정답) 고친 뒤
처음 묻는 VPN ✔ 1.1초 ✔ 2.5초 (push 직후)
다른 말 VPN ✘ cached: false, LLM 1번, 1.2초 ✔ cache_by: faq, LLM 0번, 0.1초
같은 말 ✘ cache_by 칸 없음 (캐시는 맞음, 0.1초) ✔ cache_by: question, 0.0초
no_cache ✔ ✔ 1.2초
프린터 처음 · 접수 현황 ✔ ✔
합 4/6 6/6, lab02-challenge 5/5, lab02 9/9
  • Back to rule이 없으면 Known?이 캐시 응답을 읽어 분류가 사라집니다. 학생이 가장 많이 막힐 곳으로 예상합니다 (수업 준비 때 예상).
  • 풀이 때 "잃는 것": FAQ-003에 묶인 질문은 모두 처음 질문에 맞춘 답을 받습니다.