판단을 소프트웨어 프리미티브로 — TypeSafe Jev와 System One 모델

목차

  1. 문제 설정 — LLM은 사람이 읽을 글을 만든다
  2. RLCD — 세 번째 학습 경로
  3. 세 가지 프리미티브
  4. 병렬 평가와 투기적 질문
  5. confidence — 불확실성을 코드로 다루기
  6. AI-powered software라는 구조
  7. jev-1.13의 한계
  8. 스펙과 제약, 그리고 한국어
  9. 요약

이 글은 2026년 9월 기준 jev-1.13 의 공식 문서를 읽고 정리한 것이다. 제조사가 버전별로 한계 문서를 따로 두고 별칭이 새 버전으로 옮겨간다고 밝히므로, 다른 버전을 쓴다면 해당 버전 문서를 다시 확인하는 편이 좋다. 성능·비용 수치는 모두 제조사 자체 측정치이며 독립 벤치마크는 아직 없다.

출시일(2026년 9월 15일)은 웹 검색으로 얻은 값이고 공식 문서에는 나오지 않는다. 문서에서 확인되는 시점은 한계 문서의 최종 검토일인 2026년 9월 17일뿐이다.

1. 문제 설정 — LLM은 사람이 읽을 글을 만든다

LLM으로 판단을 시킬 때 우리는 대체로 이런 왕복을 거친다.

프롬프트 → (텍스트 생성) → JSON 파싱 → 검증 → 코드가 분기

텍스트 생성 시스템을 구조화된 판단에 억지로 끼워 맞춘 뒤, 그 결과를 다시 코드가 쓸 수 있는 형태로 되돌리는 구조다. 스키마를 강제해도 파싱은 여전히 실패할 수 있고, 모델이 스스로 얼마나 확신하는지는 알 방법이 없다.

TypeSafe의 주장은 그 왕복 자체가 불필요하다는 것이다. Jev는 state(평가 대상)와 타입이 정해진 question(질문)을 받아 타입이 확정된 값과 확률 분포를 바로 반환한다. 문자열 생성 단계가 아예 없다.

회사가 깔고 있는 전제는 이렇다. 대규모 자동화는 기계-기계 상호작용이 99%, 사람 대화가 1%가 될 것이므로 채팅 인터페이스보다 기계 인터페이스가 중요하다. 이걸 “Machine Native Intelligence”라 부르고, 구조·신뢰성·관측 가능성·테스트 가능성·속도·일관성·저비용이라는 소프트웨어의 성질을 AI에 요구한다.

2. RLCD — 세 번째 학습 경로

사전학습 모델을 실제로 쓸 수 있게 만드는 후처리 학습은 그동안 두 갈래였다. TypeSafe는 세 번째를 주장한다.

방식 만들어낸 것 최적화 목표
RLHF 챗봇 (InstructGPT, ChatGPT) 사람이 선호하는 응답
RLVR 추론 모델 검증 가능한 정답. 강하지만 느리고 비쌈
RLCD Jev 결정과 보정된(calibrated) 확률

RLCD는 Reinforcement Learning for Calibrated Decisions의 약어다. 보정의 정의는 명확하다.

확률 0.2를 부여한 결과는 실제로 약 20% 발생해야 하고, 0.8을 부여한 결과는 약 80% 발생해야 한다.

다만 이건 예측 집단에 대한 성질이지 개별 답변의 정답 보장이 아니다. 문서가 이 점을 여러 곳에서 반복해 못 박는다. confidence 1.0은 “모델이 확률을 한 곳에 몰아줬다”는 뜻이지 “정답”이라는 뜻이 아니다.

RLHF에 대한 비판 지점도 명시적이다. 사람 선호를 최적화하면 아첨과 그럴듯한 환각이 보상받고, 특정 스타일로 분포가 쏠리는 mode dropping이 일어난다. 사람에게 설득력 있는 출력과 자동화에 믿고 맡길 수 있는 출력은 다른 목표라는 것이다.

3. 세 가지 프리미티브

모든 요청은 state 하나에 questions 여러 개다. 질문마다 ID를 직접 붙이고 같은 ID로 답이 돌아온다. 중요한 제약 하나 — 질문 ID는 모델에 전달되지 않는다. 의미는 전부 instructions에 써야 한다.

타입 묻는 것 반환 criteria
Choice 이 중 어느 것? choice, probabilities, confidence 선택지 맵 (최대 255개)
Score 어느 수준? score, legend, probabilities, confidence 순서 있는 레벨 배열 (최대 10개)
Noul 이게 참인가? noul (0~1) 선택. true/false 설명

Choice

"department": {
  "type": "choice",
  "choice": "returns",
  "confidence": 0.42,
  "probabilities": { "returns": 0.61, "billing": 0.35, "shipping": 0.04 }
}

choice는 최고 확률 옵션일 뿐이고, 정보량은 probabilities에 있다. 위 응답은 “사이즈가 잘못 왔는데 결제도 두 번 됐다”는 티켓에서 나온 것이다. 반품 팀과 결제 팀에 확률이 갈렸고 그래서 confidence가 0.42로 떨어졌다.

공식 예제 코드는 이 분포를 이렇게 쓴다.

# 2순위 옵션도 확률이 0.25를 넘으면 해당 팀에 사본을 보낸다
for team, probability in department.probabilities.items():
    if team != department.choice and probability > 0.25:
        notify(ticket, team=team)

단일 라벨만 뱉는 분류기로는 못 하는 처리다.

Score

레벨은 배열이고 인덱스가 곧 번호(0부터)다. score는 확률 가중 평균이다.

probabilities = { "0": 0.0, "1": 0.57, "2": 0.43 }
score = 0×0.0 + 1×0.57 + 2×0.43 = 1.43

여기 함정이 두 개 있다.

첫째, 서로 다른 분포가 같은 score를 만든다. score 1.0은 “전부 레벨 1”일 수도 있고 “레벨 0과 2에 반반”일 수도 있다. score만 보고 분기하면 이 둘을 구분하지 못한다. probabilities와 confidence를 같이 읽어야 한다.

둘째, score는 위치지 양이 아니다. 위 예에서 1.43은 “고객의 43%에게 우회 방법이 없다”는 뜻이 아니다. 단지 레벨 1과 2 사이의 위치일 뿐이다.

문서가 금지하는 범위는 정확히 하나다 — 레벨 사이를 보간해서 정확한 수치를 복원하는 것. 임계값 통과 판정, 순위 매기기, 가장 가까운 레벨로 반올림은 문서가 명시적으로 허용한다. “score는 대충만 믿어라”가 아니라 “연속적인 양으로 되돌리지는 말라”는 뜻이다.

Noul

0~1 값 하나가 전부다. “예”일 확률이며 별도의 confidence가 없다. 결과가 둘뿐이라 값 하나가 분포를 완전히 서술하기 때문이다.

가장 흔한 오용이 여기서 나온다. Noul 0.5는 “중간 정도”가 아니라 “모델이 예와 아니오를 반반으로 본다”는 뜻이다.

후보 이력서 Noul “파이썬을 잘하는가?” Score “파이썬 경험 수준”
Java/Go만 사용, 파이썬 경험 없음 0.03 0.0 (경험 없음)
가끔 작은 스크립트 0.14 1.0 (약간 익숙)
2년간 매일 사용, 데이터 파이프라인 0.81 2.05 (업무에서 상시 사용)
8년, Django 코드베이스 유지보수 0.92 2.89 (깊은 전문성)

정도를 재고 싶으면 Score, 참/거짓 판정이면 Noul이다. Noul 값에 코드에서 “0.3~0.7은 중급” 같은 구간을 만들어봐야 모델은 그 구간을 본 적이 없다. 반면 Score는 내가 쓴 레벨 설명 각각을 모델이 실제로 평가한 결과다. 답이 마음에 안 들면 레벨 문장을 고쳐 다시 돌리면 된다.

질문 작성 요령도 명확하다. 한 Noul에는 조건 하나만 담고(“화가 났고 환불을 요구하는가?”는 두 개다), 높은 값이 예가 되도록 표현한다. “개인정보가 포함되어 있는가?”는 좋고 “개인정보가 없는가?”는 나중에 코드가 반대로 읽게 만든다.

4. 병렬 평가와 투기적 질문

한 요청의 모든 질문은 같은 state에 대해 서로 독립적으로, 병렬로 평가된다. 여기서 세 가지가 따라온다.

  1. 질문을 추가해도 응답 시간이 거의 안 늘어난다. 늘어나는 건 질문 토큰 값뿐인데 100만 토큰당 $0.042라 사실상 공짜다.
  2. context rot이 없다. 질문 A의 답이 질문 B의 숨은 맥락이 되지 않는다. 질문을 넣고 빼도 나머지 답이 바뀌지 않는다.
  3. 투기적 질문(speculative)이 가능하다. 쓸지 안 쓸지 모르는 질문까지 다 던져놓고 코드가 골라 쓴다.

문서의 측정치로는 질문 13개를 한 요청에 묶으면 13번 호출 대비 11.5배 저렴하고 9.6배 빠르며, 답은 동일하다.

그래서 권장 설계가 이렇게 된다. 티켓 분류라면 부서·반품 사유·배송 문제·요청 해결책·고객 어조를 한 번에 다 묻고, 부서가 returns로 나오면 배송 문제 답은 그냥 버린다.

if department.choice == "returns":
    assign(ticket, team="returns", issue=answers["return_reason"].choice)
elif department.choice == "shipping":
    assign(ticket, team="shipping", issue=answers["shipping_issue"].choice)

요청은 한 번, 답은 다섯 개, 라우팅 로직은 평범한 if 문이다. 나중에 “고객 언어”가 필요해지면 질문을 하나 더 넣으면 되고 요청 수는 그대로 1이다.

두 번 호출해야 하는 경우는 예외다. 첫 답이 있어야 두 번째 요청을 구성할 수 있을 때만 그렇다. 다음 질문의 선택지를 정해야 하거나, 추가 데이터를 가져와야 하거나, state 자체가 첫 답에서 만들어질 때. 그 외에는 전부 한 번에 묶으라고 한다.

5. confidence — 불확실성을 코드로 다루기

confidence는 probabilities 분포가 얼마나 한 점에 뾰족한가를 0~1로 요약한 값이다. 분포가 평평하면 낮고 한 곳에 몰리면 높다. 계산식을 공개하지는 않지만 “우리 정의에 묶이지 않도록 전체 확률 분포를 그대로 준다”고 명시한다.

여기서 헷갈리기 쉬운 지점을 먼저 짚어야겠다. 2장의 보정(calibration)과 이 confidence는 같은 것이 아니다. 보정은 모델이 내놓는 확률에 대한 학습 목표이고, confidence는 그 확률 분포에서 파생된 별도의 통계량이다. 그래서 “confidence 0.9 = 90% 정확”으로 읽을 근거는 문서 어디에도 없다. 문서 역시 임계값을 정하려면 자기 데이터에서 confidence와 실제 정확도의 관계를 직접 확인하라고 안내한다. 나도 처음 읽을 때 이 둘을 붙여서 이해했다가 다시 잡았다.

Choice에서 confidence가 낮다는 건 대개 어느 옵션도 확실한 우위가 없다는 뜻이고, Score에서 낮다는 건 레벨이 모호하거나, 질문이 여러 가지를 한꺼번에 재고 있거나, state에 판단 근거가 부족하다는 뜻이다.

문서가 내세우는 철학은 이렇다.

사람이든 기계든, 지능을 갖춘 시스템이 정직한 불확실성을 표현하지 못하면 그 시스템은 신뢰할 수 없다.

기본 패턴은 3구간 분기다.

  • 높음 → 자동 처리
  • 중간 → 사용자 확인, 검토 플래그, 추가 정보 수집
  • 낮음 → 사람에게 이관하거나 다른 시스템으로 폴백

그리고 중요한 지점 — 임계값은 하나가 아니다. 행동의 위험도마다 다르게 잡는다.

action = response.answers["action"]
confidence = action.confidence

if confidence < 0.5:
    # 모델이 모르겠다고 말하는 구간. 추측하지 않는다
    route_to_human(user_message)

elif action.choice == "check_balance":
    # 읽기 전용. 틀려도 복구 가능
    show_balance(account_id)

elif action.choice == "approve_transfer":
    if confidence > 0.9:
        confirm_then_execute(account_id)
    else:
        # 고위험인데 확신이 어중간하면 먼저 확인받는다
        ask_user_to_confirm(account_id)

같은 모델 응답인데 송금 승인과 잔액 조회의 통과 기준이 다르다. 위험 감수 수준을 프롬프트가 아니라 코드가 소유한다. 이게 개인적으로 이 모델에서 가장 실용적이라고 느낀 부분이다. 우리가 LLM 응답을 다룰 때 늘 아쉬웠던 건 “이 답을 믿어도 되나”를 판단할 재료가 없다는 점이었다.

6. AI-powered software라는 구조

문서는 세 가지 구조를 대비시킨다.

구조 제어권 특징
전통적 소프트웨어 코드 신뢰할 수 있는 프리미티브의 조합
LLM 에이전트 모델 루프마다 이탈 가능성이 쌓인다. 사람 감시가 전제
AI-powered software 코드 모델은 “프로그래밍 가능한 상식”이 필요한 지점에만 등장

설계 원칙은 다섯 줄로 요약된다.

  • 제어 흐름, 결정론적 규칙, 부수 효과는 코드가 소유한다
  • 넓은 판단은 좁고 타입이 정해진 질문들로 분해한다
  • 각 질문에 필요한 맥락만 준다
  • 확률과 confidence로 실행·검토·이관을 결정한다
  • 독립적인 질문은 한 번에 묶고, 답은 코드에서 조합한다

분해의 실익이 여기서 나온다. “이 스타트업 피칭을 평가해줘” 대신 시장 규모·기술 실현성·차별성을 각각 묻고 코드에서 가중치로 합친다. 우선순위가 바뀌면 프롬프트를 다시 쓰는 게 아니라 계수 하나를 고친다. 프롬프트 엔지니어링이 일반적인 리팩토링 대상으로 내려오는 셈이다.

공식 문서가 정리한 패턴은 네 가지다.

패턴 내용 이득
Speculative Fan-Out 투기적 질문까지 한 번에 던지고 코드가 선별 비용, 속도
Confidence-Gated Routing confidence를 두 번째 결정 축으로 사용 안정성, 안전성
Composite Scoring 여러 차원의 점수를 하나로 합성 비용, 안정성, 속도
Intent Routing 의도를 분류해 핸들러로 분배 비용, 속도

7. jev-1.13의 한계

공식 문서에 jev-1.13 jaggedness라는 페이지가 따로 있다. 제조사가 자기 모델의 실패 모드를 9개로 공개해둔 문서인데, 이 글에서 가장 값진 부분이라고 생각한다.

  1. 문자 그대로 읽는다. 의도가 아니라 쓴 문장을 답한다. 한정어와 부정문이 액면가로 처리된다. → 틀린 답을 보고 “내 말은 그게 아니라”라고 설명하게 된다면, 그 설명이 빠진 절반이다.
  2. 수학과 숫자. 계산기가 아니다. 세기(counting)도 부정확하고 대상이 커질수록 오차가 커진다. 16진수 색상값보다 색 이름이, 어셈블리보다 고수준 언어가 잘 나온다. → 산술은 코드에서.
  3. 날짜·시간 비교. 날짜를 순서 있는 양이 아니라 텍스트로 읽는다. → 추출은 모델에게(월·일·연도를 열거된 Choice로), 비교와 기간 계산은 코드가.
  4. 간접 참조. 이중 부정, “속성의 속성” 같은 다단계 추론에서 정확도가 떨어진다.
  5. 불필요하게 큰 state. 무관한 내용이 방해 요소로 작동한다. Jev도 context rot을 겪는다. → 코드에서 먼저 걸러 보낸다.
  6. 적대적 입력. state를 적대적으로 취급하지 않는다. 프롬프트 주입에 답이 흔들릴 수 있다.
  7. instructions와 criteria의 모순. 예컨대 Noul에서 true가 “아니오”를 뜻하게 매핑하면 성능이 떨어진다.
  8. 구조적 불변식이 성립하지 않는다.
  9. 생성. 텍스트 생성 모델이 아니다. Choice를 엮어 억지로 시킬 수는 있지만 느리고 결과도 나쁘다.

8번을 좀 더

같은 질문을 Noul과 예/아니오 Choice로 각각 물었을 때 나온 실제 값이다.

Noul noul Choice yes Choice no Choice confidence
0.22 0.01 0.99 0.97

같은 질문과 그 부정문을 각각 Noul로 물었을 때는 이렇다.

refund not_refund 합
0.72 0.47 1.19

P(X) + P(¬X) = 1이 성립하지 않는다. 실무 규칙 두 가지가 여기서 나온다.

  • Noul로 튜닝한 임계값을 Choice로 옮기지 말 것
  • 별개의 질문들 사이에 산술적 항등식을 기대하지 말 것

이유는 두 프리미티브가 다른 질문을 하고 있기 때문이다. Choice는 상대적이다 — 어느 쪽이 더 맞는지를 가린다. Noul은 절대적이다 — 이게 참인지를 본다. 그래서 모든 옵션에 대해 Noul이 전부 낮게 나올 수 있다. 문서는 둘을 같이 쓰는 예를 든다. Choice로 어느 것을 추천할지 고르고, Noul로 애초에 추천할 게 있기는 한지를 판정한다.

다만 자기 일관성(self-consistency)에 대해서는 “의미적으로 유사한 입력에는 양적으로 유사한 출력을 기대할 수 있다”, “반복 평가에서 안정적인 답을 반환하도록 설계되었다”고 말한다. 보장(guarantee)이라는 단어는 쓰지 않는다. 회귀 테스트의 근거로 삼을 만하다고 보지만, 그건 문서의 주장이 아니라 내 판단이다.

8. 스펙과 제약, 그리고 한국어

항목 값
엔드포인트 POST https://api.typesafe.ai/v1/systemone
가격 입력 100만 토큰당 $0.042 / 출력 무료
레이트 리밋 250,000 토큰/초, 1,200 요청/분 (초과 시 429)
컨텍스트 요청당 64k. state + 가장 긴 질문 하나는 32k
입력 텍스트 전용. 문자열, JSON 객체, 텍스트 배열. 이미지·음성·영상 불가
별칭 jev-latest, jev-preview (현재 둘 다 jev-1.13.0)

운영 관점에서 짚어둘 것들.

  • 고객 데이터로 파인튜닝하거나 LoRA를 붙이지 않는다. 원문은 not fine-tuned or LoRA-adapted with customer data로, “고객 데이터로”라는 한정어가 문장의 핵심이다. 모든 계정이 같은 가중치를 쓰며, 도메인 적응은 오직 state, instructions, criteria, 그리고 코드에서의 조합으로만 한다. 프롬프트가 곧 설정이다.
  • 별칭은 움직인다. confidence 임계값을 특정 버전에 맞춰 튜닝했다면 jev-1.13.0처럼 버전을 고정해야 한다. 응답의 model 필드에 실제 응답한 버전이 찍히므로 로깅해두는 편이 좋다.
  • 레이트 리밋은 “예고 없이 바뀔 수 있다”는 경고가 붙어 있다.
  • 고객 요청·응답으로 학습하지 않으며 엔터프라이즈는 무보존(ZDR) 옵션이 있다.

그리고 우리 입장에서 가장 큰 제약은 언어다. 문서가 직접 이렇게 쓴다.

영어가 주 학습 언어이며 정확도가 가장 좋은 곳이다. CJK를 포함한 다른 언어도 처리되지만 동등하지 않다. 비영어 작업에 의존하기 전에 자신의 데이터로 직접 테스트하고, 라우팅할 때 confidence에 각별히 주의하라.

한국어 고객 문의 분류 같은 데 바로 투입하기에는 검증이 먼저다. 다만 낮은 confidence를 사람에게 넘기는 구조로 감싸면 위험을 어느 정도 통제할 수는 있다. 단 이 구조가 실제로 작동하려면 자기 데이터에서 confidence와 정확도의 관계를 먼저 재봐야 한다 — 그 관계를 모른 채 임계값만 걸어두는 건 아무것도 막지 못한다.

반대로 언어 의존이 낮은 용도 — 코드·로그·구조화된 레코드에 대한 판정, 다른 LLM 출력의 검증, 모델 라우팅 — 은 부담이 상대적으로 적다.

9. 요약

  • Jev는 “LLM을 더 똑똑하게”가 아니라 “판단을 소프트웨어 프리미티브로 강등시키는” 방향의 베팅이다. 텍스트 생성을 포기하는 대신 타입 안전성, 확률 분포, 속도, 비용을 가져간다.
  • 프리미티브는 Choice / Score / Noul 셋. 각각 “어느 것”, “어느 수준”, “참인가”에 대응하고 반환 형태가 다르다.
  • 한 요청의 질문들은 독립·병렬로 평가된다. 그래서 질문을 아끼지 말고 투기적으로 다 던진 뒤 코드가 고르는 게 권장 설계다.
  • confidence가 설계의 핵심이다. 위험도가 다른 동작에 다른 임계값을 걸어, 불확실성 처리 정책을 코드가 소유한다.
  • 한계는 제조사가 문서로 공개해뒀다. 산술·날짜 비교·다단계 추론·생성은 맡기지 않는다. 서로 다른 질문 사이의 확률 항등식도 기대하지 않는다.
  • 성능 수치는 자체 측정치이고 한국어 정확도는 검증되지 않았다. 도입한다면 자기 데이터로 재보는 것이 문서가 권하는 첫 단계다.

넓은 판단을 원자적 질문으로 쪼개 병렬로 던지고, 확률과 confidence를 코드가 받아 위험도별로 분기하는 것 — 이 조립 방식 자체가 제품의 본체이고 모델은 그중 한 부품이다. 모델을 도입하지 않더라도, 이 조립 방식은 지금 쓰는 LLM 파이프라인에 그대로 적용해볼 만하다.


참고