hyunsu blog

홈강좌LAYA 결정 모델 24편 중 24편째

LAYA 를 LAYA 답게 — 두 사례에서 얻은, 가장 잘 쓰는 다섯 가지 모양

목차 · 6
  1. 01LAYA 는 무엇을 잘하나
  2. 02두 사례가 준 기준
  3. 03맞는 일과 안 맞는 일
  4. 04가장 LAYA 다운 다섯 가지 모양
  5. 05시작할 때 체크리스트
  6. 06실습

이 강좌에서 LAYA 를 두 번 써 봤다. 문의를 팀에 나누는 일에서는 학습 전 0.550 이 0.815 까지 올랐다. 쇼핑 검색어를 필터로 바꾸는 일에서는 사전과 정규식으로 만든 규칙에 졌다. 같은 모델인데 결과가 갈린 이유를 정리하면 LAYA 를 어디에, 어떤 모양으로 써야 하는지가 나온다. 이 편은 그 정리다.

01 LAYA 는 무엇을 잘하나

공식 문서는 LAYA 를 "System 1 결정 엔진" 이라 부른다. 글을 한 글자씩 지어내지 않고, 입력을 한 번 읽어 정해진 답을 고른다.

  • 답의 모양이 정해져 있다. 선택지 하나(choice), 단계(score), 예/아니오(noul)다(3편).
  • 답마다 확률과 확신이 함께 나온다.
  • 작아서 노트북·CPU 에서도 돈다. 한 건에 수십~수백 ms 다(문의 분류 v2 는 맥북에서 한 건 47ms, 아래 출력).
  • 내 판단으로 다시 학습할 수 있다(7·10편).

글을 쓰거나 요약·번역하는 일은 LLM 몫이라고 문서가 분명히 적는다. LAYA 는 LLM 을 대신하는 것이 아니라, LLM 이 하던 일 가운데 "고르기" 만 떼어 맡는 모델이다.

02 두 사례가 준 기준

문의 분류(1~16편)쇼핑 검색 필터(17~23편)
답은 어디에문장 전체 — "결제하기를 누르면 화면이 하얘져요" 는 결제가 아니라 기술팀단어 하나 — "브라운" 이면 갈색
학습 효과0.550 → 0.8150.014 → 0.510, 그래도 사전(0.619)보다 낮음
더 나은 방법단어 사전으로는 풀기 어려움사전·정규식이 더 정확하고 4천 배 빠름

답이 문장 전체에 있으면 LAYA, 단어에 있으면 사전. 단어 하나로 답이 정해지는 일은 표를 찾는 일이고, 표는 모델보다 정확하다. LAYA 가 값을 하는 곳은 사람이 문장을 읽고 "이건 저 팀 일이네" 하고 판단하는 곳이다.

03 맞는 일과 안 맞는 일

LAYA 가 맞는 일다른 것이 나은 일
선택지가 정해져 있고 20개 안쪽선택지가 수십~수백 개(문서: 77개 분류에서 약함 — 먼저 좁힌다)
답이 문장의 뜻에 있다(분류·심사·급함·의도)단어 → 값 조회(사전), 금액·날짜 계산(정규식)
회사 규칙이 끼어 있어 학습으로 익혀야 한다규칙이 몇 줄로 끝난다(코드)
많이·빨리·싸게, 내 서버에서한 번뿐이고 느려도 되는 판단(LLM 이 더 쉽다)
확신을 보고 자동/사람을 나누고 싶다처음 보는 표현을 상식으로 풀어야 한다(LLM, 22편)
짧은 입력아주 긴 문서(문서: 4천 토큰을 넘으면 흔들림)
단계 점수를 정밀하게(문서: score 가 가장 약함)

04 가장 LAYA 다운 다섯 가지 모양

1. 고르기만 한다

질문과 선택지를 정해 두고 답을 받는다. 결과는 늘 정해진 값이라 JSON 이 깨질 일이 없다. 여러 질문을 한 번에 물어도 계산은 한 번이다(3편). 필터 칸 여섯 개를 한 번에 물은 17편이 그 예다.

2. 자신 없으면 넘긴다

LAYA 다움의 핵심이다. 답과 함께 나오는 확신으로 자동으로 처리할 것과 사람(또는 LLM)에게 넘길 것을 나눈다. 문의 분류 v2 로 문턱마다 잰다.

python
"""LAYA 답게 — 고르기만 하고, 자신 없으면 넘긴다.

문의 분류 v2 가 팀을 고르고, 확신이 문턱을 넘는 것만 자동으로 보낸다. 나머지는 사람(또는 LLM) 줄로 간다.
문턱마다 자동 처리 비율 · 자동 처리분의 정확도 · 넘긴 건수 · 한 건 시간을 잰다.
"""
import json
import time

import laya

agent = laya.load("checkpoints/v2")
cases = [json.loads(line) for line in open("tickets-eval.jsonl", encoding="utf-8")]

start = time.time()
answers = [agent.predict(c["state"], c["questions"])["answers"]["team"] for c in cases]
ms = (time.time() - start) / len(cases) * 1000
rows = [(a["answer_confidence"], a["choice"] == c["expected"]["team"]) for a, c in zip(answers, cases)]

print(f"cases {len(cases)} · all answered: accuracy {sum(ok for _, ok in rows) / len(rows):.3f} · {ms:.0f} ms per case")
print(f"{'threshold':>9}{'auto':>7}{'auto %':>8}{'auto accuracy':>15}{'to people':>11}")
for t in (0.5, 0.9, 0.99, 0.999):
    auto = [ok for conf, ok in rows if conf >= t]
    acc = sum(auto) / len(auto) if auto else float("nan")
    print(f"{t:>9}{len(auto):>7}{len(auto) / len(rows):>8.0%}{acc:>15.3f}{len(rows) - len(auto):>11}")
bash
python gate.py
text
cases 200 · all answered: accuracy 0.815 · 47 ms per case
threshold   auto  auto %  auto accuracy  to people
      0.5    200    100%          0.815          0
      0.9    171     86%          0.889         29
     0.99    141     70%          0.950         59
    0.999    131     66%          0.985         69
그림 1.확신 문턱별 — 자동으로 보낸 것의 정확도
0.50.60.70.80.91.00.5 · 자동 100%0.9 · 자동 86%0.99 · 자동 70%0.999 · 자동 66%0.5 · 자동 100%: 0.8150.9 · 자동 86%: 0.8890.99 · 자동 70%: 0.9500.999 · 자동 66%: 0.9850.8150.8890.9500.9850.50.60.70.80.91.00.5 · 자동 100%0.9 · 자동 86%0.99 · 자동 70%0.999 · 자동 66%0.5 · 자동 100%: 0.8150.9 · 자동 86%: 0.8890.99 · 자동 70%: 0.9500.999 · 자동 66%: 0.9850.8150.8890.9500.985

문의 200건, 문의 분류 v2. 문턱 아래는 사람(또는 LLM) 줄로 간다

숫자로 보기
항목자동 처리분 정확도
0.5 · 자동 100%0.815
0.9 · 자동 86%0.889
0.99 · 자동 70%0.950
0.999 · 자동 66%0.985
  • 모두 자동으로 보내면 0.815 다. 다섯 건에 한 건쯤 엉뚱한 팀으로 간다.
  • 문턱 0.99 에서는 70% 를 자동으로 보내고, 그 정확도가 0.950 이다. 나머지 59건만 사람이 본다.
  • 0.999 로 올리면 자동 처리분은 0.985 지만 사람 몫이 69건으로 는다.

같은 모델로 "얼마나 맞히나" 를 "어디까지 맡기나" 로 바꿀 수 있다. 0.815 짜리 모델도 문턱을 두면 0.95 짜리 자동화와 사람 몫 30% 가 된다. 문턱은 틀린 자동 처리 한 건의 비용과 사람이 하루에 볼 수 있는 건수로 정한다. 다만 문턱은 반드시 내 평가 데이터로 다시 재서 정한다. 쇼핑 검색 v2 는 처음 보는 단어에 확신 1.00 으로 틀렸다(20편). 확신은 순서일 뿐 정답의 보증이 아니다.

넘긴 쪽을 LLM 이 맡게 해도 된다. 이때 LAYA 는 LLM 호출을 30% 로 줄이는 앞단 필터가 된다. 4번 모양이 이것이다.

3. 판단과 실행을 나눈다

공식 문서의 "단계적 도입" 은 한 문장으로 시작한다. LAYA 가 돌려주는 것은 판단이지 실행 허가가 아니다. 실행은 늘 애플리케이션이 쥔다.

  1. 그림자 — 지금 방식이 그대로 결정하고, LAYA 는 옆에서 답만 기록한다(15편).
  2. 비교 — 같은 요청에서 둘이 다른 것을 본다. 다르다고 LAYA 가 틀린 것은 아니다.
  3. 정책 — 내 데이터로 확신 문턱을 정하고 기록한다(판·질문 판·문턱·평가셋).
  4. 좁은 범위만 승격 — 되돌릴 수 있는 일, 평가한 언어·질문만, 처음엔 일부 트래픽만. 되돌릴 조건을 미리 적는다.

확신이 아무리 높아도 되돌릴 수 없는 일(환불 실행, 계정 정지)은 사람 확인 뒤에 둔다.

4. LLM 앞의 문지기

문서의 첫 번째 사용 사례는 "Smart Ingress Gateway" 다. LAYA 가 요청의 종류와 난이도를 먼저 고르고, 간단하고 확신 높은 것은 로컬에서 끝내고, 복잡하거나 자신 없는 것만 LLM 으로 보낸다. 같은 결로 문서는 에이전트의 도구 고르기를 LAYA 로 하는 길도 낸다. 문서에 적힌 시간은 GPU 에서 30~40ms, Apple Silicon 에서 중앙값 126ms 로, LLM 의 도구 호출(1~2.5초)보다 한참 짧다(정확도는 문서에 없다).

쇼핑 검색에 대입하면 LAYA 의 자리는 필터 칸이 아니라 입구다. "이 검색어는 키워드 검색으로 충분한가, 상품 비교·추천을 해 줄 대화형 도우미로 보낼 것인가, 주문·배송 문의인가" 를 고르는 일은 답이 문장 전체에 있다. 이것은 이 강좌에서 재지 않았다.

5. 넘긴 것으로 다시 학습한다

2번에서 사람에게 넘긴 것은 버리는 일이 아니다. 사람이 내린 판단이 다음 판의 정답이 된다. 16편의 순서 그대로다. 정답을 모으고, 바탕 모델에서 누적 데이터로 처음부터 다시 학습하고, 고정 평가 세트로 승격을 판정한다. 넘기는 문턱이 곧 학습 데이터를 모으는 장치다.

05 시작할 때 체크리스트

  1. 답이 단어에 있나, 문장에 있나 — 단어에 있으면 사전부터. 문장에 있으면 LAYA 후보.
  2. 선택지를 20개 안쪽으로 — 많으면 단계를 나누거나 먼저 좁힌다.
  3. 학습 전 모델로 먼저 잰다(5편) — 이 숫자가 출발점이다.
  4. 평가 세트를 먼저 고정한다(16편) — 학습 데이터와 다른 표현, 200건 이상.
  5. 문턱은 내 데이터로 정한다 — 배포된 체크포인트는 지나치게 자신 있는 편이다(문서). 학습 뒤 다시 잰다.
  6. 그림자로 시작한다 — 실행 권한은 마지막에, 좁게.
  7. 넘긴 것을 정답으로 모은다 — 그리고 처음부터 다시 학습한다.

06 실습

  1. gate.py 의 문턱에 0.95 를 더해, 사람이 하루에 볼 수 있는 건수에 맞는 문턱을 골라 본다. 하루 문의 1000건, 사람이 볼 수 있는 것이 100건이라면 어디인가.
  2. 내 서비스의 판단 셋을 적고, 체크리스트 1·2번으로 LAYA 후보인지 가려 본다.
  3. 쇼핑 검색의 "입구 고르기" 질문(키워드 검색 · 대화형 도우미 · 주문 문의)을 choice 하나로 설계해 학습 전 모델에 물어 본다(17편의 first_query.py 를 고쳐서).