테마 전환
Laya 실전 ④: 호출 비용의 진실과 신뢰도 게이트
"한 번의 호출이 얼마냐"는 질문에 예제 16–19는 재현 가능한 답을 줍니다: 로드는 초 단위, 첫 호출은 준비 비용, 정상 호출은 밀리초 단위. 그리고 이 숫자들을 서비스 로직으로 잇는 두 기둥이 질문 배칭과 answer_confidence 게이트입니다.
질문 13개도 순전파 한 번 (예제 16)
실제 트리아주는 한 메시지에 대해 열 가지 이상을 묻습니다. choice 5개·score 3개·noul 5개, 합쳐서 13개 질문을 predict() 호출 하나로 답하면 — usage["input_tokens"]는 호출 전체의 배치 합계입니다. 질문을 두 호출로 쪼개면 토큰 수가 정확히 같은 합으로 다시 나눠지고, 지연 시간은 질문 수에 거의 비례하지 않습니다. 인코더 실행이 비용의 본문이고, 그 배치 전체가 한 묶음이기 때문입니다.
정직하게 재는 법 (예제 17)
perf_counter() 하나로 predict()를 재면 세 가지가 섞입니다: 체크포인트 빌드(프로세스당 한 번, 초 단위), 차가운 첫 호출(MPS에서는 Metal 커널 컴파일 ~13초 등 준비 비용), 정상 추론(호출당 밀리초). 예제 17의 처방은 단순합니다. 로드는 별도로, 첫 호출은 별도로, 그리고 웜업 한 번을 버린 뒤 여러 번의 중앙값으로 정상을 재세요. 절대 밀리초는 머신 부하에 흔들리니 비율을 읽으라는 단서도 붙어 있습니다.
질문은 배칭, 상태는 루프 (예제 19)
predict(state, questions)는 상태를 정확히 하나만 받습니다. 상태를 스물 개 묶는 인자는 없고, 그럴 필요도 없습니다. 이미 predict 자체가 한 상태에 대한 질문의 배치이기 때문입니다. 규칙은 이렇습니다:
📥 질문은 배칭
한 상태에 궁금한 게 열 개면, 그 상태의 호출 하나에 열 개를 다 담습니다. 추가 질문은 거의 공짜로 따라옵니다.
🔁 상태는 루프
상태가 스물 개면 호출 스물 개의 루프가 바른 모양입니다. 순전파가 상태 단위의 비용이고, 새 시퀀스 길이는 워밍업 비용을 새로 지불하게 만듭니다.
신뢰도 게이트: answer_confidence에 선을 긋는다 (예제 18)
예측→
answer_confidence ≥ 0.85?→
자동 라우팅/
사람에게 에스컬레이션
게이트가 재는 것은 확신이지 정확성이 아닙니다. 기대한 라벨이 나왔어도 확률이 낮으면 에스컬레이션됩니다 — 그 trade-off를 THRESHOLD로 조정하는 겁니다.
정직한 경고가 두 개 달려 있습니다. shipped 분포의 평균 ECE는 0.466이고, 홀드아웃 데이터로 (질문 타입, 옵션 수) 버킷당 temperature를 다시 맞추면 0.081까지 내려갑니다 — 두 체크포인트 모두 기본값은 과신 상태입니다. 따라서 문서의 0.85는 "그 분포에 대한 정책"일 뿐, 자기 데이터로 검증한 기준이 아닙니다. 예제 18은 각 질문의 확률이 실제로 어떤 temperature로 스케일링됐는지 체크포인트에서 다시 읽어 출력합니다.
결정은 캐시된다 (예제 40)
def cache_key(state, questions):
# 답을 결정하는 입력만 해시한다: 상태와 질문 정의
payload = json.dumps({"state": state, "questions": questions},
sort_keys=True, default=str)
return hashlib.sha256(payload.encode()).hexdigest()[:12]
모델은 상태 없고 결정적입니다: 같은 상태 + 같은 질문 정의는 항상 같은 답. 입력의 정렬된 JSON 해시를 키로 answers를 캐시하면 순전파를 한 번만 지불합니다. 예제 40은 여기에 배치 답변을 auto/review/escalate로 나누는 컨피던스 모니터를 붙이고, 각 숫자가 실제로 어떤 스케일을 통과했는지 출력합니다.
다음 편: 체크포인트 세 개 중 무엇을 쓸지, 모델을 돌리지 않고 마이크로초 만에 결정하는 라우팅 (예제 20–24).