본문으로 건너뛰기
5분 AI.
TRENDSHIFT DAILY #11 딥다이브 · 2026-10-23 분석

deepopen 딥다이브
— 문장을 쓰는 AI에서 선택을 내리는 AI로

라이브러리·모델

빠른 판단

무엇
문자열·JSON·대화를 읽고 정해진 선택지·점수·참 여부를 확률로 반환하는 비자기회귀 결정 엔진
이럴 때
고객 문의·문서의 부서 분류·긴급도·조건 충족 여부를 앱에서 쓸 판단값으로 만들고 확률을 보정할 때
입력
문자열·JSON·대화 목록과 미리 정의한 판단 질문
결과
선택지 확률·점수·참 여부를 담은 Python 딕셔너리
고객 문의를 읽고 담당 부서·긴급도·환불 요청 여부를 정할 때, 긴 답변을 생성할 필요가 있을까요? deepopen은 미리 정한 질문에 선택지·점수·참일 확률로 답하는 Python 결정 엔진입니다. 커밋 57819b8의 SDK·실험 코드·CI를 바탕으로 입력 구성부터 텐서 배치, 언어별 모델 선택, 확률 보정까지 따라갑니다. Python 37개 파일·5,974줄 중 핵심 SDK는 1,436줄입니다. (deepopen-com/deepopen · ⭐2,246 · 포크 219 · Apache-2.0 · 2026-10-23 GitHub 기준)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

상태를 읽고, 정해진 형식의 판단을 돌려주는 작은 추론 라이브러리

deepopen은 문자열·JSON·대화 목록을 입력받아 여러 판단 질문에 확률 분포로 답하는 비자기회귀 결정 엔진입니다. 답변 문장을 한 토큰씩 쓰는 대신, 주어진 선택지들을 평가해 프로그램이 바로 사용할 판단값을 만듭니다.

가령 “결제가 두 번 됐으니 오늘 환불해 주세요”라는 문의 하나를 놓고 담당 부서, 긴급도, 환불 요구 여부를 함께 묻습니다. 결과는 자연어 보고서가 아니라 Python 딕셔너리입니다. 다만 출력 형식이 정해져 있다는 사실과 판단이 정확하다는 사실은 별개입니다.

한 문장 비유

장문의 답안지를 쓰는 작가보다, 항목별 접수표를 채우는 상담 창구에 가깝습니다

상담 창구는 문의를 읽고 “결제팀”, “긴급도 2”, “환불 요청 있음”에 표시합니다. 결과를 다음 담당자에게 넘기기 쉽고, 매번 문장 속에서 팀 이름을 찾아낼 필요도 없습니다.

대신 접수표에 없는 새 질문을 설명하거나, 판단 근거를 긴 글로 작성하는 일은 이 엔진의 주된 역할이 아닙니다. 접수표 자체를 잘 설계하고 실제 문의로 검증하는 일이 개발자의 몫입니다.

용어
비자기회귀와 System 1
자기회귀는 앞서 만든 토큰을 바탕으로 다음 토큰을 순서대로 생성하는 방식입니다. 여기서는 입력 전체를 인코더로 읽고 후보 점수를 한 번에 계산합니다. System 1은 빠른 직관적 판단을 빗댄 프로젝트의 표현입니다. 사람처럼 사고한다거나 복잡한 추론을 항상 해결한다는 보증은 아닙니다.

1-1. 출력은 세 종류로 제한됩니다

종류실제 반환값문의 분류 예시
choice최상위 선택지, 후보별 probabilities, confidence담당 부서를 billing·technical·other 중 선택
score단계 인덱스의 기대값, 범례, 단계별 확률긴급도를 0·1·2 단계로 정의하고 1.6처럼 반환
noulP(true)와 이진 판단 신뢰도환불을 요청했는지 0~1 사이 확률로 반환

noul은 이 프로젝트의 API 식별자입니다. 일반적인 Python 자료형 이름이 아니므로 그대로 기억하면 됩니다. 구현에서는 항상 [false, true] 두 후보를 만들고 두 번째 후보의 확률을 꺼냅니다. score도 임의의 실수를 직접 생성하지 않고 단계별 확률의 가중평균을 계산합니다.

1-2. 모델 선택과 모델 실행은 다른 작업입니다

아래는 API 사용 형태를 보여주는 예시입니다. Router.route()는 모델을 고르기만 하고, Router.predict()는 필요할 때 모델을 로드한 뒤 실제 판단을 수행합니다.

from deepopen import Router

state = {"body": "고객이 두 번 청구되어 환불을 원합니다"}
questions = {
    "department": {
        "type": "choice",
        "instructions": "어느 부서가 이 문의를 처리해야 하나요?",
        "criteria": {
            "billing": "결제, 청구, 환불",
            "technical": "오류, 장애, 연동",
            "other": "그 밖의 문의"
        }
    }
}
router = Router()
decision = router.route(state, questions)
# 코드 분기를 따르면 한글 입력은 multilingual로 선택됩니다.
# router.predict(state, questions)는 모델 로드와 추론까지 수행합니다.

소스 근거: deepopen/router.py의 Router.route()·predict(), deepopen/agent.py의 Agent.system_one().

이 글의 학습 목표
작은 SDK 안에서 추론 시스템의 경계를 배웁니다

입력 계약을 정의하고, 다양한 후보 수를 배치로 묶고, 실행할 모델을 고르고, 결과의 확률을 해석하는 과정을 배웁니다. 웹 서비스 전체를 만들기 전에도 읽어볼 수 있는 크기의 저장소입니다.

2왜 주목받는가

빠른 판단이라는 문제 설정은 매력적이지만, 화제의 원인과 성능의 조건은 구분하기

2-1. 관심을 끄는 지점은 “생성하지 않아도 되는 일”입니다

2026-10-23 TrendShift Daily #11에 선정되었으며, 같은 날 GitHub 기준 스타 2,246개·포크 219개입니다. 순위와 누적 수치만으로 관심이 늘어난 원인을 단정할 수는 없습니다. 다음은 코드와 문서로 확인되는 관심 요소입니다.

첫째, 분류·우선순위 지정처럼 짧은 결론이 필요한 업무에 초점을 맞춥니다. 둘째, 후보 확률을 반환해 후속 프로그램과 연결하기 쉽습니다. 셋째, 영어와 다국어 체크포인트를 요청마다 고르는 라우터를 제공합니다. 공개된 Python 구현에서 이 흐름을 짧게 추적할 수 있다는 점도 학습 가치입니다.

이 저장소의 장점은 모든 일을 하는 능력보다, 판단 문제의 입력과 출력을 작게 고정하는 설계에서 먼저 찾을 수 있습니다.

접근유리한 상황deepopen과 비교할 점
생성형 LLM자유로운 설명, 긴 답변, 복합 작업deepopen은 후보 점수를 계산합니다. 생성형 모델도 구조화 출력을 지원할 수 있으므로 JSON만으로 우열을 가릴 수는 없습니다.
고정 분류기항상 같은 77개·150개 라벨을 분류SDK는 질문의 후보 설명을 입력에 넣습니다. 라벨을 바꿀 수 있지만 후보 길이와 수가 입력 예산을 씁니다.
TypeSafe Jev문서에서 비교하는 결정 모델 APIdeepopen은 구현을 읽고 로컬 운영을 설계할 수 있습니다. Jev 수치는 외부 발표값이며 이 저장소에서 직접 실행한 비교가 아닙니다.
규칙 기반 분류정확한 키워드·명시적 업무 규칙모델은 문맥적 일반화를 기대할 수 있지만 틀릴 수 있습니다. 확정 규칙과 모델 판단을 함께 설계할 여지가 있습니다.

2-2. “33ms”는 어떤 측정인가

research/results/t4_colab_benchmark.json에는 Tesla T4에서 측정한 기존 laya 계열의 기록이 들어 있습니다. 메타데이터의 측정 시각은 2026-09-19입니다. 커밋 57819b8보다 앞선 측정 기록이므로 해당 커밋의 실행 성능과 구분해야 합니다.

조건영어 모델 p50다국어 모델 p50
질문 1개39.5ms32.8ms
질문 10개158.6ms / 호출72.3ms / 호출, 약 7.23ms / 질문
질문 50개771.3ms / 호출337.4ms / 호출, p95는 693.7ms

질문 10개를 넣었다고 각 질문이 7.23ms 뒤에 따로 도착하는 것은 아닙니다. 한 호출이 끝난 뒤 결과를 함께 받고, 전체 시간을 질문 수로 나눈 값입니다. 다운로드·모델 교체·웹 요청까지 포함한 서비스 지연시간과도 구분해야 합니다.

2-3. 한국어 독자가 확인할 만한 수치

research/results/cpu_51_language_sweep.json의 MASSIVE 의도 분류는 언어당 100개 예제, 질문당 후보 20개, seed 13입니다. 한국어 정확도는 영어 모델 0.11, 다국어 모델 0.45입니다. 다국어 모델이 낫지만, 이 기록만으로 한국어 업무에서 충분한 품질이라고 결론 내릴 수는 없습니다.

수치를 읽는 비유

“영어 시험보다 한국어 시험에서 점수가 올랐다”와 “한국어 상담을 맡겨도 된다”는 다른 판단입니다. 시험 문항 수, 후보 수, 실제 업무의 오답 비용을 함께 봐야 합니다.

2-4. 연구 실험의 높은 점수는 별도 모델의 결과입니다

banking77/README.md는 94.0909%를 일반 분류기의 추가 학습 대조군 결과로 설명합니다. 새 원형 분류 구조의 효과라고 쓰지 않습니다. clinc150/README.md의 97.7556%는 검증으로 고른 R-Drop 단일 모델, 98.0222%는 Laya 하나와 DeBERTa 세 개를 합친 네 모델 시스템의 결과입니다.

두 실험 모두 기본 SDK를 그대로 호출한 제로샷 성능과 다릅니다. CLINC150 결과는 알려진 150개 의도만 다루는 in-scope 평가이며, 범위 밖 질문을 거절하는 능력을 포함하지 않습니다. 저장소도 공식 외부 순위 인증을 주장하지 않는다고 명시합니다.

비교의 조건
외부 수치와 자체 측정을 한 줄의 승패로 합치지 않습니다

BENCHMARKS.md는 Jev를 직접 실행하지 않았고 표본 수와 프롬프트가 다르다고 밝힙니다. “몇 배 빠르다”, “더 정확하다”는 README의 비교는 참고값입니다. 같은 입력·장비·평가 규칙의 통제 실험으로 읽으면 안 됩니다.

확인 자료: 벤치마크의 조건과 한계, T4 원시 기록, Banking77 구조 변경 대조 실험.

3기술 스택 전체 지도

추론 SDK, 실험 도구, 패키징·CI를 나누어 의존성 읽기

3-1. 백엔드에 해당하는 것은 Python 추론 SDK입니다

저장소의 중심은 Python 추론 SDK인 deepopen/ 패키지입니다. pyproject.toml의 선언은 다음과 같습니다. >=는 설치된 버전이 아니라 허용하는 최소 버전이라는 뜻입니다.

항목선언 버전소스에서 맡는 역할
Python>=3.8패키지 메타데이터의 지원 범위. 실험 환경과 동일한 뜻은 아닙니다.
PyTorchtorch>=2.0.0nn.Module, 인코더·결정 헤드, 배치 텐서, CUDA 추론
Transformerstransformers>=4.45.0AutoTokenizer, AutoConfig, AutoModel 구성
safetensors>=0.4.0model.safetensors에서 가중치 텐서 읽기
Hub 클라이언트huggingface_hub>=0.20.0snapshot_download()로 모델 파일 확보
NumPynumpy>=1.20.0출력 확률·기대값·엔트로피 계산

common.build_model()은 인코더를 attn_implementation="sdpa"로 만듭니다. 결정 헤드는 nn.TransformerEncoderLayer와 점수 계산용 작은 신경망으로 구성합니다. 어떤 인코더를 쓸지는 외부 체크포인트의 rl_agent_config.json에 달려 있습니다.

3-2. 학습·평가 환경은 더 구체적으로 고정되어 있습니다

banking77/requirements.txt와 clinc150/requirements.txt는 아래 직접 의존성을 같은 버전으로 고정합니다. Banking77에만 datasets가 추가되고, 선택적 혼합 모델 환경에는 두 패키지가 더 필요합니다.

묶음파일의 실제 값읽을 때 주의할 점
모델 실행torch==2.9.1, transformers==4.57.6SDK의 최소 버전 선언보다 구체적입니다.
수치·평가numpy==2.5.3, scikit-learn==1.7.2, scipy==1.18.1정확도·F1·확률 평가 및 실험 분석에 사용합니다.
파일·통신huggingface-hub==0.36.2, requests==2.34.2모델·데이터 다운로드가 필요한 별도 환경입니다.
사전 출시판safetensors==0.9.0rc0, tokenizers==0.23.0rc0의존성 파일의 고정값입니다. 설치에는 해당 사전 출시판을 구할 수 있는 패키지 소스가 필요합니다.
추가 의존성Banking77: datasets==4.5.0
혼합 모델: sentencepiece==0.2.2, protobuf==7.36.2
clinc150/requirements-hybrid.txt는 기본 파일을 -r requirements.txt로 포함합니다.

T4 벤치마크 JSON에는 또 다른 환경인 torch 2.11.0+cu128·transformers 5.17.0이 기록되어 있습니다. 모든 수치가 하나의 공통 환경에서 나온 것처럼 합치지 않아야 합니다.

3-3. 프론트엔드와 서비스 인프라는 어디에 있나

커밋 57819b8에는 package.json, React·Vue 소스, TypeScript·JavaScript 앱, Dockerfile, Kubernetes 설정이 없습니다. README의 Hugging Face 데모는 외부 링크입니다. 따라서 데모 화면의 프레임워크나 서버 운영 방식을 이 저장소의 기술 스택으로 확정할 근거는 없습니다.

assets/에는 로고와 그래프가 있고, research/scripts/make_plots.py가 결과 시각화를 담당합니다. 이 시각화 코드를 웹 애플리케이션 프론트엔드로 볼 수는 없습니다.

3-4. 빌드는 setuptools, 자동화는 GitHub Actions입니다

구분설정설정 내용
빌드setuptools>=61.0setuptools.build_meta 백엔드, setup.py의 find_packages()
CI 행렬Python 3.9·3.11·3.13.github/workflows/ci.yml에 CPU PyTorch 설치, 라우터·기준값 테스트, Ruff, 패키지 빌드 선언
환경변수USE_TF=0, USE_TORCH=1추론을 PyTorch 경로에 두려는 설정. TOKENIZERS_PARALLELISM=false도 지정합니다.
보안 자동화gitleaks 8.30.1·CodeQL·pip-audit.github/workflows/security.yml에 비밀·의존성·Python 분석 단계가 선언되어 있습니다.
배포 자동화.github/workflows/release.ymlv* 태그에서 빌드·PyPI 게시·GitHub Release 생성 경로가 선언되어 있습니다.

설정 파일에 자동화가 적혀 있다는 사실은, 현재 경로와 버전으로 자동화가 성공한다는 증거가 아닙니다. .github/workflows/ci.yml은 import laya·ruff check laya/를 사용하지만 패키지 디렉토리는 deepopen/입니다. 테스트 파일의 import와 보안 검색 경로에도 이전 이름이 남아 있습니다.

이름 변경의 흔적
버전과 기본 모델 주소가 통일되어 있지 않습니다

pyproject.toml과 deepopen/__init__.py는 0.3.4, setup.py는 0.8.3.1입니다. README의 모델 링크는 convaiinnovations/deepopen이지만 SDK의 기본값은 convaiinnovations/laya입니다. 패키지 설치와 모델 다운로드에서는 이 차이에 주의해야 합니다.

의존성 근거: pyproject.toml, Banking77 버전 파일, 혼합 모델 버전 파일, CI 설정.

4아키텍처 심화 분석

공개된 핵심 SDK 1,436줄을 따라가는 입력 → 라우팅 → 추론 → 해석

시스템 경계부터 잡겠습니다. 사용자의 프로그램 안에서 라우터와 모델이 실행됩니다. 첫 모델 로드 때는 외부 Hub가 파일 공급원이 될 수 있고, 실제 예측 경로에는 별도의 HTTP 서버가 들어 있지 않습니다. 아래는 핵심 호출 관계입니다.

[사용자 프로그램: Router.predict()] state: 문자열 / dict / list questions: 질문 ID별 정의 | | +--------------+---------------+ v Router.route() [규칙만 평가] model > task > 자동 업무 감지 > lang > 문자·언어 | RouteDecision: model / reason v Router.load() [모델 LRU] 재사용 <--------+--------> 새 Agent 구성 | [로컬 경로 또는 Hugging Face Hub] config + tokenizer + safetensors | +-------------+ v Agent.system_one() 질문별 build_sequence() 반복 | collate_items(): [B, L] v DecisionModel.forward() 인코더 → 질문 유형 임베딩 → 추가 헤드(설정 시) | 후보 [MASK] 위치 gather → 후보별 logits | 온도 적용 → softmax → 유형별 반환값 구성 v answers + usage + routing → 사용자 프로그램 별도 실험 경로: banking77/ · clinc150/ → 학습·검증·시험 → 전문 분류기 research/ → 벤치마크 스크립트와 기존 결과

4-1. 패턴 ① 여러 질문 형식을 하나의 입력 계약으로 통일

Agent._to_internal()은 외부의 type / instructions / criteria를 내부의 t / ins / crit로 바꿉니다. choice 후보를 리스트로 받으면 후보 이름을 키로 하는 딕셔너리로 정규화합니다. 다음 단계는 질문 종류와 무관하게 같은 함수를 사용할 수 있습니다.

common.render_options()는 선택지 설명을 문자열 목록으로 통일합니다. 구조화된 설명은 render_criterion()에서 JSON으로 바뀝니다. 숫자 0과 불리언 False를 “없음”으로 취급하지 않는 조건도 들어 있습니다. 이런 작은 입력 규칙이 추론 SDK의 안정성을 좌우합니다.

# build_sequence()가 만드는 개념적인 입력 모양
[CLS] choice question: 질문 [SEP]
[MASK] billing: 결제와 환불
[MASK] technical: 오류와 장애
[MASK] other: 기타 [SEP]
문의의 상태를 직렬화한 텍스트 [SEP]

# 후보 시작 위치를 별도로 기억합니다.
markers = [후보0의_MASK_위치, 후보1의_MASK_위치, 후보2의_MASK_위치]

위의 후보 표시는 빈 단어를 생성하는 작업이 아닙니다. 인코더가 문맥을 읽고 만든 벡터 중 “이 후보의 대표 위치”를 찾아 점수를 매기기 위한 표시입니다. 입력 본문이나 후보 설명에 원래부터 들어 있던 mask 토큰 문자열은 공백으로 바꿔 표시와 충돌하는 일을 줄입니다.

용어
토큰 예산
모델이 한 번에 읽는 입력 길이는 유한합니다. 이 구현은 질문·후보에 쓸 head_max_len과 전체 길이 max_len을 따로 받습니다. 후보 설명을 길게 쓰면 상태 본문에 남는 공간이 줄어듭니다. 토큰 수는 글자 수나 단어 수와 같지 않습니다.

build_sequence()는 후보별 설명을 먼저 최대 48토큰으로 자르고 앞에 mask 표시 1토큰을 붙입니다. 후보 영역을 빼고 남은 예산이 16토큰 미만이면 per = max(4, (head_max_len - 16) // 후보수)에 맞춰 후보를 mask 포함 최대 per토큰으로 줄입니다. 절단 길이의 하한이 후보별 4토큰·질문 머리말 8토큰이므로, head_max_len이 항상 지켜지는 엄격한 상한은 아닙니다. 최종 전체 입력은 ids[:max_len]으로 잘립니다.

따라서 “후보가 77개면 무조건 실패”도, “설정만 늘리면 정확도가 보장됨”도 맞지 않습니다. 후보 의미가 먼저 잘릴 수 있고, 아주 많으면 표시 자체가 전체 길이 밖으로 나갈 수 있습니다. Agent.system_one()은 남은 표시 수와 원래 후보 수가 다르면 ValueError를 냅니다.

4-2. 패턴 ② 질문 유형은 달라도 후보 점수 계산기는 공유

collate_items()는 질문별 입력을 하나의 배치로 평탄화합니다. 질문 수를 B, 배치의 최대 길이를 L, 최대 후보 수를 K라고 놓으면 텐서의 역할은 아래와 같습니다.

텐서모양의미
input_ids[B, L]질문마다 상태가 포함된 토큰 ID. 짧은 행은 pad ID로 채웁니다.
attention_mask[B, L]진짜 입력은 1, 채움 영역은 0입니다.
marker_pos[B, K]각 후보 대표 벡터를 꺼낼 위치입니다.
marker_mask[B, K]해당 행에 실제로 존재하는 후보만 표시합니다.
qtype[B]choice=0, score=1, noul=2

DecisionModel.forward()는 인코더 출력에 질문 유형 임베딩을 더한 뒤, head_layers > 0이면 추가 Transformer 헤드를 통과시킵니다. torch.gather()로 후보 위치의 벡터를 모으고, LayerNorm → Linear → GELU → Linear 점수 계산기를 모든 후보에 공유합니다. 실제 후보가 아닌 칸의 점수는 -1e4로 덮습니다.

“여러 질문을 한 번에”는 질문별로 상태를 포함한 입력을 만든 뒤, 한 배치의 forward 호출로 처리한다는 뜻입니다. 상태를 단 한 번 인코딩하고 모든 질문이 그 결과를 재사용하는 구조는 아닙니다. 질문이 많아질수록 메모리와 연산도 늘어납니다.

배치의 비유

한 장의 문의를 여러 담당자가 각자 읽되, 같은 엘리베이터를 타고 한꺼번에 올라가는 방식입니다. 이동 비용을 나눌 수 있지만, 담당자가 읽을 서류 사본까지 한 장으로 줄어드는 것은 아닙니다.

별도의 act_head는 첫 토큰 벡터와 확률의 최댓값·상위 두 값 차이·정규화 엔트로피·후보 수 특징을 받아 행동 logits를 만듭니다. SDK는 그중 0번 행동의 확률을 action.act_probability로 반환할 뿐, 실제 업무 도구를 호출하거나 자동으로 사람에게 넘기지는 않습니다.

4-3. 패턴 ③ 선택 정책과 실행을 나누고, 비싼 모델은 캐시

Router.route()의 우선순위는 model → task → 자동 업무 감지 → lang → 문자·언어 감지 → 기본값입니다. 자동 업무 감지는 auto_task_detection=True일 때만 작동하며, 네 업무에 정해진 질문 ID 집합과 정확히 일치해야 합니다. 질문의 의미를 학습해 업무를 이해하는 별도 AI 분류기는 아닙니다.

lang.state_text()는 JSON 키를 버리고 문자열 값만 모읍니다. max_chars=4000으로 감지 입력을 제한하고, 중첩 수집은 깊이 6을 넘으면 멈춥니다. detect_script()는 코드포인트 범위로 문자를 세며, 라틴 문자 언어는 불용어와 악센트 문자의 휴리스틱으로 추정합니다.

한국어가 우세하면 hangul로 잡혀 다국어 모델로 갑니다. 다만 혼합 언어는 우세 문자에 영향을 받고, 짧은 라틴 입력은 언어를 못 맞힐 수 있습니다. 언어를 아는 호출자가 lang="ko"나 model="multilingual"로 덮어쓸 수 있게 한 이유입니다.

# max_loaded=2일 때 _order의 변화를 손으로 추적합니다.
load("english")          → [english]
load("multilingual")     → [english, multilingual]
load("english")          → [multilingual, english]
load("typed-decisions")  → [english, typed-decisions]
# 가장 오래 안 쓴 multilingual이 퇴출됩니다.

Router._touch()는 사용한 모델을 목록 끝으로 옮기고, _evict()는 앞에서 제거합니다. 기본 max_loaded=1에서 언어가 교대로 들어오면 매번 모델을 다시 구성할 수 있습니다. preload()는 지정한 모델 수를 수용하도록 용량도 늘리고, attach()는 이미 만든 Agent를 재사용하게 합니다.

unload()는 라우터가 가진 참조를 지웁니다. GPU 메모리가 즉시 모두 반환된다는 보장은 아닙니다. load()는 새 Agent를 구성한 뒤 기존 모델을 퇴출하므로, 교체 중에는 두 모델의 메모리가 겹칠 수 있습니다. 또한 이 클래스에는 요청 간 잠금이 보이지 않으므로, 다중 요청 서버에 붙일 때의 동시성 정책은 별도로 설계해야 합니다.

4-4. 패턴 ④ 외부 체크포인트를 검증하는 로딩 경계

Agent.__init__()는 존재하는 로컬 경로를 그대로 사용합니다. /·./·../로 시작하는 경로가 없으면 FileNotFoundError를 내고, 그 밖의 식별자는 snapshot_download()로 받습니다. 하위 모델을 지정했을 때는 allow_patterns=["하위폴더/*"]로 다운로드 범위를 제한합니다. SDK 소스와 대형 가중치가 분리되어 있는 구조입니다.

  1. _fix_tokenizer_config()가 이전 토크나이저 설정을 호환 형태로 보정합니다. 이 함수는 모델 디렉토리의 설정 파일을 실제로 다시 쓸 수 있습니다.
  2. rl_agent_config.json을 읽고 model.safetensors가 있는지 확인합니다.
  3. build_model()로 구조를 구성한 뒤 _verify_compatibility()가 필수 설정·가중치 접두사·파라미터 모양을 비교합니다.
  4. load_state_dict(weights, strict=True)로 로드하고 장치에 올립니다. CUDA·MPS를 사용할 수 없거나 비 CPU 장치에 모델을 배치하다 런타임 오류가 나면 CPU로 전환합니다. 추론 중에는 오류 메시지에 memory 또는 cuda가 포함된 비 CPU 장치 오류에서만 CPU로 재시도합니다.

필수 가중치 접두사는 encoder.·type_emb.·scorer.·act_head.입니다. 이름만 비슷한 일반 분류기 체크포인트를 받아도 된다는 뜻이 아닙니다. Banking77의 일반 분류기와 CLINC150 파생 모델은 별도의 로더가 필요한 이유가 여기에 있습니다.

4-5. 마지막 해석 단계: 확률, 점수, 신뢰도는 다릅니다

모델의 원시 점수인 logits는 아직 확률이 아닙니다. Agent.system_one()은 질문 유형·후보 수에 맞는 온도 T를 찾고, 점수를 나눈 뒤 softmax를 계산합니다. temp_bucket()의 후보 수 구간은 2 / 3-5 / 6-10 / 11+입니다.

# 구현을 수식으로 요약한 설명용 예시
z = logits / max(0.001, T)
p = exp(z - max(z)) / sum(exp(z - max(z)))

choice = 후보[argmax(p)]
score = sum(i * p[i] for i in range(k))
noul = p[1]

# 단계별 확률이 [0.1, 0.2, 0.7]이면
score = 0 * 0.1 + 1 * 0.2 + 2 * 0.7  # 1.6

choice·score의 confidence는 confidence_from_probs()의 1 − H(p) / log(k)입니다. 반면 noul의 confidence는 max(P(true), P(false))입니다. 같은 확률 [0.9, 0.1]이라도 전자는 약 0.531, 후자는 0.9가 됩니다.

확률 해석
confidence 0.9를 모든 유형의 “정답률 90%”로 읽지 않습니다

research/scripts/bench_local.py와 research/scripts/build_benchmark_nb.py의 ECE 계산은 최상위 후보 확률을 사용합니다. SDK의 엔트로피 기반 confidence와 다른 양입니다. 공개 ECE 수치를 그대로 SDK 필드의 품질 보증으로 옮길 수 없으며, 업무 데이터에서 어느 값을 평가하는지 먼저 고정해야 합니다.

핵심 소스: 입력 구성·DecisionModel·확률 도우미, 로딩 검증·유형별 결과 해석, 문자·언어 휴리스틱.

5디렉토리 구조 해부

라이브러리 코드와 실험 기록을 같은 기능으로 착각하지 않기
deepopen/ 저장소 루트 ├── deepopen/ 배포 대상 Python 패키지 │ ├── __init__.py 공개 API와 __version__ │ ├── router.py 모델 선택, LRU, preload·attach │ ├── agent.py 로딩, 추론, 결과 해석 │ ├── common.py 모델 구조, 입력·배치, 보상·지표 │ ├── lang.py 문자·언어 감지 │ ├── presets.py 업무별 질문 정의 │ └── email.py 이메일 전처리와 질문 정의 ├── tests/ 라우팅·기준값·로컬 통합 테스트 ├── banking77/ 77개 금융 의도 학습·대조 실험 ├── clinc150/ 150개 의도 학습·정규화·집계 실험 ├── research/ │ ├── scripts/ 벤치마크·그래프·노트북 생성기 │ └── results/ T4·CPU 결과 JSON 2개 ├── notebooks/ │ └── laya_finetune_typed_decisions_2xT4_kaggle.ipynb ├── assets/ 로고·실험 그래프·이미지 생성 코드 ├── .github/ CI·보안·릴리스·의존성 갱신 설정 ├── pyproject.toml 패키지 메타데이터와 빌드 선언 ├── setup.py 별도 setuptools 설정 ├── BENCHMARKS.md 과거 측정의 조건·강점·한계 └── LICENSE Apache-2.0 본문

5-1. 파일 종류별 코드 규모

커밋 57819b8의 파일을 .git/를 제외하고 집계한 물리적 줄 수입니다. 빈 줄·주석과 마지막 개행이 없는 줄도 포함합니다. 노트북 코드는 코드 셀별 줄 수를 합산하며 Python 파일 합계와 구분합니다.

범위파일 수줄 수와 해석
Python 전체375,974줄. 아래 여섯 묶음과 루트 setup.py 25줄의 합
SDK71,436줄. 먼저 읽을 핵심 경로
테스트3630줄. 현재 import 이름에 불일치가 있습니다.
Banking776531줄. 가변 후보 결정기와 고정 분류기 비교
CLINC150141,409줄. 단일 모델·추가 학습·혼합 모델 실험
연구·그림5 + 1연구 스크립트 1,802줄, assets/make_logo.py 141줄
노트북2JSON 표기 1,840줄. 코드 셀만 모으면 1,355줄이며 위 Python 합계에는 넣지 않았습니다.
그 밖의 텍스트Markdown 18 / YAML 4각각 2,476줄 / 305줄. TOML은 1개·38줄입니다.

저장소 루트에서 wc -l deepopen/*.py로 SDK의 1,436줄을 확인할 수 있습니다. 이 커밋에는 .js·.ts·.go·.rs 소스가 없습니다. 저장소의 주 언어가 Python이라는 메타데이터와도 일치합니다.

5-2. 처음에는 이 순서로 읽습니다

  1. deepopen/__init__.py에서 사용자가 호출할 API를 확인합니다.
  2. deepopen/router.py → deepopen/lang.py에서 모델 선택까지 따라갑니다.
  3. deepopen/agent.py → deepopen/common.py에서 토큰·배치·결과 변환을 연결합니다.
  4. tests/에서 경계 사례를 읽고, BENCHMARKS.md의 주장을 JSON 기록과 대조합니다.
  5. 학습을 공부할 때 banking77/와 clinc150/로 확장합니다.

주의할 문서 경로도 있습니다. README는 notebooks/deepopen_finetune_typed_decisions_2xT4_kaggle.ipynb를 안내하지만 실제 경로는 notebooks/laya_finetune_typed_decisions_2xT4_kaggle.ipynb입니다. BENCHMARKS.md에 적힌 research/results/app_benchmark.json도 커밋 57819b8에는 없습니다. 링크가 있다는 사실과 산출물이 포함되어 있다는 사실을 구분해야 합니다.

6학습 포인트 (기술별)

라이브러리를 사용하는 수준에서, 입력·모델·평가의 이유를 설명하는 수준으로

6-1. Python API: 바깥의 편의성과 안쪽의 일관성을 나눕니다

_to_internal()은 사용자가 편하게 쓴 질문을 내부 규격으로 바꾸는 작은 경계입니다. render_criterion()은 문자열·딕셔너리·리스트·숫자를 텍스트로 통일합니다. 이 둘을 읽으면 “여러 입력을 지원한다”는 말을 조건문과 변환 규칙으로 구체화하는 방법을 배울 수 있습니다.

실습 아이디어: tests/test_criteria.py의 사례를 표로 옮겨 보세요. None, 빈 문자열, 0, False가 각각 어떤 문자열을 만드는지 예상합니다. 특히 if not value 한 줄로 전부 처리했을 때 잃어버리는 의미를 설명해 봅니다.

용어
입력 계약
함수에 무엇을 넣을 수 있고, 어떤 값을 돌려주는지 정한 약속입니다. 타입 힌트만으로 입력의 모든 잘못을 막지는 못합니다. 후보가 비어 있거나 질문이 하나도 없는 경우처럼, 소스가 충분히 검사하는지 확인할 경계도 남습니다.

6-2. PyTorch: 배치의 빈칸은 두 종류입니다

attention_mask는 입력 길이의 빈칸을 가리고, marker_mask는 후보 수의 빈칸을 가립니다. 질문마다 길이와 후보 수가 다르기 때문에 둘이 모두 필요합니다. marker_pos.clamp(min=0) 뒤에 대표 벡터를 모으고, 존재하지 않는 후보 점수를 덮는 순서를 따라가 보세요.

실습 아이디어: 후보 2개·3개·5개인 질문 세 개를 그립니다. marker_mask는 [3, 5] 모양이며, 각 행에서 참인 칸 수가 각각 2·3·5여야 합니다. 실제 토크나이저 없이도 배치의 핵심을 이해할 수 있습니다.

6-3. NLP 전처리: 무엇을 읽히고 무엇을 버리는가

email.clean_email_body()는 인용 줄, 일부 회신 머리말, 서명과 면책 문단을 줄이고 기본 max_chars=3000까지만 남깁니다. 주로 영어 표현의 정규식을 사용하므로 한국어 회신 메일도 같은 수준으로 정리된다고 가정해서는 안 됩니다.

실습 아이디어: 본문·영어 회신 머리말·한국어 서명이 섞인 가상 이메일을 만듭니다. 줄 단위로 어느 정규식에 걸리는지 표시하고, “현재 문의의 핵심이 잘려 나갈 수 있는가”를 따져 보세요. 전처리도 정확도에 영향을 주는 모델 입력 설계입니다.

6-4. 확률 평가: 분류를 잘하는가, 확신을 잘 조절하는가

common.ece_score()는 기본 15개 구간에서 평균 신뢰도와 실제 정답 비율의 차이를 모읍니다. 예를 들어 0.9 근처 확률을 준 문제들이 실제로는 절반만 맞았다면 과신입니다. 낮은 ECE만으로 좋은 분류기가 되는 것은 아니며, 정확도·오답 비용과 함께 봐야 합니다.

T4 결과의 calibration_repair는 평가 묶음마다 앞 절반으로 온도를 맞추고 뒤 절반으로 평가합니다. 영어 모델의 평균 ECE 0.4656 → 0.0812, 다국어의 0.3135 → 0.1059는 그 절차의 기록입니다. 새로운 한국어 업무에도 같은 효과가 생긴다는 보장은 없습니다.

실습 아이디어: 같은 logits에 T=0.5·1·2를 적용한 가상 분포를 비교합니다. 양수 온도는 후보 순위를 바꾸지 않고 분포의 뾰족함을 바꿉니다. 정확도를 고치는 작업과 확률을 보정하는 작업이 어떻게 다른지 말로 설명합니다.

6-5. 강화학습: 이 저장소에서 RLCD를 어디까지 볼 수 있나

common.proper_reward()는 로그 점수와 구면 점수를 더하고, 순서형 score에는 누적확률 차이를 벌점으로 줍니다. td_lambda_targets()는 여러 시점의 이진 목표를 섞는 도우미입니다. 함수가 패키지에 있다는 사실과 모든 학습 경로가 그 함수를 사용한다는 사실은 다릅니다.

실제 RLCD 학습 예시는 notebooks/laya_finetune_typed_decisions_2xT4_kaggle.ipynb의 DDP 학습 코드 셀에서 찾을 수 있습니다. logits에 잡음을 더해 여러 확률 분포를 만들고, proper_reward()로 평가한 상대 보상을 정책 손실에 사용합니다. 동시에 soft target 교차 엔트로피도 1.0 가중치로 더합니다.

# 노트북의 학습 목적을 간추린 설명용 표현
adv = reward - 그룹_평균_reward
loss_rl = -(adv * logp).mean()
loss_ce = -(target * log_softmax(logits)).sum(-1).mean()
loss = (loss_rl + 1.0 * loss_ce) / GRAD_ACCUM

# Banking77 원형 구조의 감독학습 경로는 별도입니다.
loss = cross_entropy(logits, label)

여기서 banking77/banking77.py는 교차 엔트로피 감독학습을 하며 action head는 동결합니다. CLINC150도 별도 분류기 학습입니다. README의 “강화학습으로 훈련”이라는 설명을 저장소 안 모든 실험의 학습 방식으로 확대하면 안 됩니다.

훈련 예제의 한계
학습용 노트북의 보정 샘플은 별도 검증셋이 아닙니다

노트북은 train split에서 만든 all_items의 all_items[::15][:400]을 온도 보정에 씁니다. 독립된 보정·평가 자료를 새로 나누는 실습과 구분해야 합니다. 또 cfg["head_checkpointing"]이 아니라 모델 속성을 켜지만, 현재 DecisionModel.forward()에는 해당 플래그를 읽는 분기가 보이지 않습니다. 설정 이름만으로 메모리 절감 효과를 확정하지 않습니다.

6-6. 실험 설계: 복잡한 구조가 성능 향상의 원인인가

banking77/prototype_model.py의 원형 분류기는 원래 logits에 코사인 유사도 분기를 더합니다. 그러나 banking77/RESULTS_V2.md에서는 같은 횟수만큼 추가 학습한 일반 분류기 대조군이 더 높은 테스트 정확도를 냈습니다. 학습 횟수 증가와 구조 변경의 효과를 분리해야 한다는 좋은 사례입니다.

clinc150/round2.py의 symmetric_kl()와 학습 루프에서는 같은 입력을 dropout을 달리해 두 번 읽고 결과가 너무 달라지지 않도록 합니다. train_clinc.supcon()은 같은 라벨끼리 표현을 가깝게 만듭니다. round2_finish.freeze()는 테스트 전에 선택과 파일 해시를 고정합니다.

이 저장소에서 가장 오래 남을 배움은 높은 점수 자체보다, 점수가 왜 달라졌는지 분리해 확인하는 습관입니다.

추가 읽기: IntentModel·SupCon, R-Drop 학습, 평가 전 선택 고정.

7하드웨어 / 시스템 요구사항

소스 공부, 추론, 미세조정은 자원 요구가 서로 다릅니다
목적필요한 환경근거와 범위
소스 학습텍스트 편집기와 일반 PC이 글의 읽기·손계산 과제는 GPU·모델 파일이 필요 없습니다.
CPU 추론호환 Python·PyTorch, 모델 보관 공간과 RAMAgent에 CPU 실행 분기가 있습니다. 공식 최소 RAM 수치는 명시되어 있지 않습니다.
Apple GPUMPS 사용 가능한 PyTorch 환경Agent.__init__()는 CUDA가 없고 MPS를 사용할 수 있으면 MPS를 선택합니다.
NVIDIA 추론CUDA 사용 가능한 PyTorch 환경T4 지연시간은 과거 벤치마크 기록입니다. 배치 크기·입력 길이·가중치 로드가 메모리에 영향을 줍니다.
단일 모델 훈련실험 README 권장: Linux/WSL2, Python 3.12, NVIDIA 16GB VRAM급, CUDA·BF16Banking77·CLINC150 경로의 권장 환경입니다. 16GB를 보장된 최소치로 적지는 않습니다.
DDP 노트북노트북 기준 Kaggle T4 2개FP16, MICRO_BATCH=8, GRAD_ACCUM=4, 4 epochs 설정

7-1. 파라미터 수로 메모리를 거칠게 계산합니다

T4 결과 메타데이터는 영어 모델 421.29M, 다국어 모델 321.91M 파라미터를 기록합니다. FP32 한 값이 4바이트라고 놓으면 영어 약 1.69GB, 다국어 약 1.29GB입니다. typed-decisions도 영어 모델과 같은 421.29M이라고 가정하고 세 체크포인트를 FP32로 보관한다면 가중치만 약 4.66GB라는 계산이 나옵니다.

이것은 십진 단위의 단순 계산이며 실측 RAM이나 최소 VRAM이 아닙니다. 로드 중 원본 가중치와 모델이 함께 존재할 수 있고, 토큰·중간 활성값·프레임워크·GPU 작업 공간이 더 필요합니다. CPU와 MPS 경로는 계산 dtype을 FP32로 잡습니다.

또 CUDA에서 autocast를 켠다고 가중치 저장량까지 자동으로 절반이 된다고 계산하면 안 됩니다. 이 구현은 모델을 장치로 옮길 때 .to(self.device)를 사용하며, 이 호출에 저정밀 dtype을 명시하지 않습니다. 계산 정밀도와 가중치 보관 정밀도는 구분해야 합니다.

7-2. 사전 적재는 지연시간과 상주 메모리의 교환입니다

Router(preload=True)는 기본 세 모델을 모두 올립니다. 영어·한국어만 번갈아 처리할 목적이라면 preload(["english", "multilingual"])처럼 필요한 모델만 지정하는 API도 있습니다. 메모리 여유 없이 사전 적재를 켜면 CPU 폴백이나 로딩 실패를 만날 수 있습니다.

빠른 모델을 고르는 것만큼, 요청 사이에 모델을 다시 로드하지 않도록 상주 정책을 정하는 일이 중요합니다. 모델 교체 비용 7~10초는 README 기준이며, 해당 문서의 측정 조건에 따른 참고값입니다.

초보자의 시작점
GPU를 구하기 전에 입력 계약과 배치 구조부터 이해합니다

장비 없이도 라우팅 우선순위, LRU 동작, 확률 기대값, 평가 분리를 공부할 수 있습니다. 실제 추론은 메타데이터·import 불일치와 모델 파일 준비 상태를 먼저 해결한 별도 실습으로 잡는 편이 명확합니다.

8직접 해볼 수 있는 실습 과제

읽기·표·손계산으로 시작하고, 구현 변경안까지 확장하는 다섯 과제

아래는 소스를 읽고 설계표와 손계산 결과를 만드는 공부 과제입니다. 코드 수정이나 모델 실행은 별도 복사본에서 이어갈 수 있는 확장 활동입니다.

과제 1 · 입문 · 20~30분

한국어 문의를 접수표 세 칸으로 바꾸기

읽을 곳: deepopen/presets.py의 triage_questions()와 Agent._to_internal().

할 일: 가상 고객 문의 다섯 개를 쓰고, 담당 부서는 choice, 긴급도는 score, 환불 요구는 noul로 정의합니다. 긴급도 각 단계의 기준도 문장으로 씁니다.

완료 기준: 세 질문의 type·instructions·criteria 구조를 설명할 수 있고, 기대 정답을 사람이 직접 붙인 표가 있습니다. 모델이 그 정답을 냈다고 적지는 않습니다.

# 입력 설계 예시: 실행 결과가 아니라 사람이 정한 질문입니다.
questions = {
    "urgency": {
        "type": "score",
        "instructions": "현재 문의의 처리 긴급도는 어느 정도인가요?",
        "criteria": [
            "마감이나 업무 차질이 없음",
            "곧 확인이 필요하지만 업무는 가능함",
            "업무가 중단되었거나 오늘 마감이 있음"
        ]
    },
    "refund": {
        "type": "noul",
        "instructions": "고객이 환불을 명시적으로 요청하나요?"
    }
}
과제 2 · 입문 · 30~40분

라우터의 선택 이유를 실행 전에 예측하기

읽을 곳: Router.route(), lang.analyse(), tests/test_router.py의 라우팅 사례.

할 일: 한국어 본문, 영어 본문, 숫자만 있는 상태, 한글과 영문이 섞인 상태를 표에 씁니다. 여기에 lang="en", model="multilingual", task="typed_decisions"를 각각 적용했을 때의 우선순위를 따라갑니다.

완료 기준: 입력·명시 인자·선택 모델·이유가 있는 8행 이상의 표를 만듭니다. 숫자만 있을 때 기본값으로 가는 사례와, 명시 모델이 언어 감지를 덮는 사례를 반드시 넣습니다.

과제 3 · 중급 · 40~60분

토큰 예산과 배치의 빈칸을 직접 그리기

읽을 곳: common.build_sequence()·collate_items().

할 일: 토크나이저 없이 후보 하나가 mask 포함 10토큰이라고 가정합니다. 후보 5개·20개·77개를 head_max_len=192에 넣었을 때 축약 분기를 계산합니다. 최소 4토큰 때문에 목표 예산을 넘을 수 있는지도 확인합니다.

완료 기준: 가정한 길이와 실제 측정 토큰 수를 명확히 구분하고, 입력 표시가 잘리는 상황과 후보 설명만 짧아지는 상황을 나눠 설명합니다. 후보 수가 다른 세 질문의 marker_mask 표도 그립니다.

손계산의 예: 후보가 77개면 축약식의 몫은 (192 - 16) // 77 = 2지만 최소값 때문에 후보별 4토큰을 남깁니다. 후보 영역만 77 × 4 = 308토큰입니다. 이 값은 “항상 192 안에 들어간다”는 해석을 반박하지만, 실제 분류 정확도까지 알려주지는 않습니다.

과제 4 · 중급 · 40~60분

신뢰도와 ECE를 손으로 계산하기

읽을 곳: confidence_from_probs(), ece_score(), research/scripts/bench_local.py의 metrics().

할 일: 이진 확률 [0.9, 0.1]에서 최상위 확률과 엔트로피 신뢰도를 비교합니다. 별도로 “모두 0.9라고 예측한 10문제 중 6개 정답”인 작은 평가 묶음의 ECE를 계산합니다.

완료 기준: 엔트로피 신뢰도 약 0.531과 최상위 확률 0.9를 구분합니다. 두 번째 묶음은 하나의 구간에 모두 들어간다고 놓으면 ECE가 |0.9 - 0.6| = 0.3임을 설명합니다.

과제 5 · 고급 · 1~2시간

이름 변경과 실험 재현성을 점검하는 수정안 쓰기

읽을 곳: pyproject.toml, setup.py, .github/workflows/, tests/, clinc150/round2_finish.py.

할 일: 패키지 이름·버전·import·Hub 모델 주소·README 파일 경로를 대조하는 표를 만듭니다. laya가 과거 실험의 고정 의존성인 곳과 현재 SDK에 남은 이름인 곳을 구분합니다. 테스트 전 선택을 고정하는 절차도 요약합니다.

완료 기준: 수정할 위치, 유지할 과거 실험 참조, 확인할 테스트를 적은 제안서가 있습니다. 현재 소스 전체를 무조건 검색 치환하지 않고, 공개 API와 실험 재현 경로의 의도를 먼저 설명합니다.

실습의 성공은 모델을 한 번 돌렸다는 사실보다, 입력·가정·예상 결과·검증 기준을 서로 연결할 수 있는지로 판단합니다.

9관련 기술 심화 학습 로드맵

8주 동안 API 읽기 → 텐서 추적 → 확률 평가 → 실험 설계로 확장

Python의 함수·리스트·딕셔너리를 읽을 수 있다는 전제로 주당 3~5시간을 잡은 학습안입니다. 신경망 수식을 처음 본다면 3~5주차를 두 번 나누어 진행해도 좋습니다. 실측 성능을 재현하는 계획과 소스 이해 계획을 별도로 기록하세요.

주차배울 주제·읽을 코드한 주의 산출물
1주차Python 자료구조·타입 힌트·공개 API
deepopen/__init__.py, deepopen/presets.py, _to_internal()
세 종류의 질문 정의와 사람이 붙인 예시 정답 5개
2주차문자열·JSON·Unicode·휴리스틱
deepopen/lang.py, deepopen/email.py
혼합 언어 감지와 이메일 정리의 성공·실패 예상표
3주차토큰화·입력 길이·패딩
build_sequence(), collate_items()
[B,L]·[B,K] 텐서와 후보 표시 위치를 그린 도식
4주차인코더·임베딩·공유 점수 계산
DecisionModel.forward()
토큰 벡터에서 후보 logits까지 모양을 붙인 호출 지도
5주차softmax·엔트로피·기대값·온도 보정
confidence_from_probs(), temp_bucket()
확률·신뢰도·점수를 구분한 손계산 노트
6주차추론 운영·LRU·장치 폴백
Router.load(), preload(), Agent.__init__()
영어·한국어 혼합 요청에서 캐시 용량별 모델 교체 횟수 표
7주차감독학습·대조군·검증 분리
banking77/banking77.py, banking77/prototype_model.py
구조 변경과 추가 학습을 분리한 비교 실험 계획서
8주차R-Drop·SupCon·RLCD·결과 고정
clinc150/round2.py, clinc150/round2_finish.py, 학습 노트북
선택 규칙·seed·데이터 버전·평가 지표가 있는 재현성 문서

9-1. 수식은 코드가 답해야 할 질문과 연결합니다

softmax를 배울 때는 “왜 가장 큰 logits를 빼는가”를, 엔트로피를 배울 때는 “왜 후보 수의 로그로 나누는가”를 묻습니다. 텐서 공부에서는 행과 열이 각각 질문·토큰·후보 중 무엇을 뜻하는지 먼저 적습니다. 공식을 외우는 것보다 디버깅할 때 도움이 됩니다.

학습 경로를 확장할 때도 구분이 필요합니다. SDK의 가변 후보 질문은 후보 설명까지 읽지만, CLINC150의 IntentModel은 텍스트의 평균 표현에서 150개 고정 클래스를 예측합니다. 동일한 인코더를 재사용해도 문제와 출력 계약이 바뀌면 다른 모델로 평가해야 합니다.

9-2. 공식 문서를 읽을 때의 길잡이

위 링크는 공식 기술 문서입니다. 예제를 공부할 때는 저장소의 의존성 버전에 맞는 문서를 선택합니다.

학습 순서는 화면을 먼저 붙이는 것보다, 입력이 어떻게 숫자가 되고 그 숫자를 어떻게 검증하는지 이해하는 데 맞춥니다.

10핵심 키워드 사전

앞의 코드를 다시 읽을 때 찾아볼 짧은 번역표
용어쉬운 설명
상태 · state판단의 대상인 문의·메일·JSON·대화입니다. 이 SDK에서는 반드시 학습 알고리즘의 내부 상태를 뜻하는 것은 아닙니다.
스키마질문과 출력의 약속입니다. 담당 부서는 선택형, 긴급도는 단계형처럼 종류와 기준을 정합니다.
비자기회귀답변 토큰을 앞에서부터 순서대로 생성하지 않는 방식입니다. 여기서는 후보들의 점수를 계산합니다.
System 1빠른 판단을 비유하는 이름입니다. 모델의 정확도나 인간 수준의 이해를 보증하는 기술 규격은 아닙니다.
인코더입력 토큰을 문맥이 담긴 숫자 벡터로 바꾸는 부분입니다. SDK는 그 벡터를 후보 평가에 사용합니다.
토크나이저문자열을 모델이 읽는 토큰 ID로 나누는 도구입니다. 한국어 한 글자와 한 토큰이 항상 일치하지는 않습니다.
체크포인트학습된 가중치와 이를 해석할 설정의 묶음입니다. Python 패키지 설치와 모델 준비는 별개입니다.
헤드인코더 출력에 붙어 특정 결과를 만드는 부분입니다. 결정 헤드와 77·150개 고정 분류 헤드는 구조가 다릅니다.
logits확률로 바꾸기 전의 원시 점수입니다. 합이 1일 필요가 없고 음수일 수도 있습니다.
softmax여러 점수를 합이 1인 양수 분포로 바꿉니다. 후보 수에 맞춰 서로 경쟁하는 확률을 만듭니다.
마커 · marker각 후보를 대표하는 벡터의 위치를 알려주는 표시입니다. 이 구현은 mask 토큰을 사용합니다.
패딩길이가 다른 입력을 같은 크기로 맞추려고 넣는 빈칸입니다. 마스크로 연산에 반영할 범위를 구분합니다.
배치여러 입력을 묶어 한 번에 처리하는 단위입니다. 이 SDK에서는 여러 질문이 배치의 각 행이 됩니다.
기대값각 결과에 확률을 곱해 더한 평균입니다. score는 단계 번호의 기대값을 돌려줍니다.
엔트로피확률이 얼마나 여러 후보에 퍼졌는지를 나타냅니다. SDK의 일부 confidence는 이 값을 뒤집어 계산합니다.
캘리브레이션보고한 확률과 실제 정답 비율을 맞추는 보정입니다. 순위가 맞는지와는 다른 성질입니다.
온도 · Tsoftmax 전에 점수를 나누는 양수입니다. 크게 하면 대체로 완만한 분포, 작게 하면 뾰족한 분포가 됩니다.
ECE신뢰도 구간별 예측 확신과 실제 정답 비율의 차이를 가중평균한 값입니다. 어떤 신뢰도를 썼는지 함께 봅니다.
교차 엔트로피정답 쪽에 낮은 확률을 주면 크게 벌점을 주는 학습 손실입니다. 감독학습 실험의 기본 목표입니다.
proper scoring rule참된 믿음의 확률 분포를 정직하게 보고하도록 유도하는 채점 원칙입니다. 그 원칙을 목표로 학습해도 배포 자료에서 완전한 보정이 보장되지는 않습니다.
RLCDREADME에서 사용하는 강화학습 기반 결정 모델 학습 명칭입니다. 노트북은 확률 분포의 보상을 이용한 손실과 soft 교차 엔트로피를 함께 씁니다.
휴리스틱빠르고 단순한 경험 규칙입니다. 여기서는 불용어·문자 범위로 언어를 추정하며 틀릴 수 있습니다.
LRU가장 오래 쓰지 않은 항목부터 버리는 캐시 정책입니다. 여기서는 상주 모델 수를 제한합니다.
콜드·웜 경로모델을 새로 준비해야 하는 요청과 이미 준비된 모델을 쓰는 요청입니다. 같은 추론 모델도 전체 지연이 다릅니다.
FP16·BF16·FP32실수를 저장하거나 계산하는 정밀도 형식입니다. 지원 장치와 연산에 따라 메모리·속도·오차가 달라집니다.
R-Dropdropout 때문에 달라진 두 예측을 가깝게 만들어 학습을 안정시키는 방법입니다. CLINC150 실험에서 대칭 KL 손실을 더합니다.
SupCon정답 라벨이 같은 예제의 벡터를 가깝게, 다른 예제는 구분되게 학습하는 감독 대조학습입니다.
대조군·소거 실험변경 요소를 끄거나 조건을 맞춰 성능 향상의 원인을 확인합니다. 원형 분기를 끈 추가 학습 모델이 한 예입니다.
in-scope·OOS이미 정한 범주 안의 입력과 범주 밖 입력입니다. 알려진 의도 분류 성적이 좋아도 미지의 의도 거절 능력은 따로 평가합니다.
매크로 F1클래스별 F1을 같은 비중으로 평균한 값입니다. 데이터가 많은 클래스에 전체 평가가 치우치는 것을 줄입니다.

11참고 링크

움직이는 소개 페이지와 커밋에 고정한 소스 근거를 함께 남기기

11-1. 공식 저장소와 문서

11-2. 모델 주소와 관련 기술

현재 상태 (2026-10-23 확인)

저장소 활동과 릴리스 현황은 2026-10-23 GitHub 기준입니다. 파일·설정·코드 규모는 커밋 57819b8 기준입니다.

항목확인한 값
저장소deepopen-com/deepopen · TrendShift Daily #11 선정
스타 / 포크2,246 / 219 — 2026-10-23 GitHub 기준
주 언어Python
생성일2026-09-21 — 분석일로부터 약 32일 전
최근 push2026-10-22 — 2026-10-23 GitHub 기준
최근 커밋57819b8 · 2026-10-22
docs: install SDK from GitHub instead of unavailable PyPI package
최신 릴리스없음 — 2026-10-23 GitHub 기준, 최신 릴리스 API: 404 Not Found
패키지 버전pyproject.toml·deepopen/__init__.py: 0.3.4
setup.py: 0.8.3.1. 단일한 릴리스 번호로 확정하지 않습니다.
설치 안내커밋 57819b8의 README는 GitHub에서 pip 설치를 안내하며, 공개 deepopen PyPI 릴리스가 없다고 설명합니다.
코드 규모Python 37개·5,974줄, 그중 SDK 7개·1,436줄, 테스트 3개·630줄. 노트북 코드 셀 1,355줄은 별도 집계입니다.
화면·배포커밋 57819b8에는 프론트엔드 앱·Dockerfile이 없습니다. README의 데모는 외부 링크입니다.
소스 기준커밋 57819b8의 단일 시점입니다. 전체 개발 이력이나 기여자 수를 나타내는 수치는 아닙니다.
라이선스Apache-2.0 — 2026-10-23 GitHub 기준 및 루트 LICENSE 본문
쓰기 전에 알아둘 한계
빠른 판단 엔진의 설계를 배우기 좋지만, 배포 준비가 검증된 제품으로 읽지는 않습니다

패키지와 모델 설정의 일관성이 필요합니다. 남아 있는 laya import, 서로 다른 패키지 버전, README와 다른 Hub 기본 주소를 실제 사용 전에 확인해야 합니다. SDK의 Hub 다운로드에는 revision 고정 인자가 보이지 않으므로 소스 커밋 고정만으로 가중치 버전까지 고정되지 않습니다.

성능은 기록의 조건 안에서 읽습니다. 33ms는 과거 T4 측정이고, 낮은 ECE는 별도 온도 보정 절차 뒤의 값입니다. 고정 분류기·미세조정 모델·네 모델 혼합 결과는 기본 SDK 성능과 다릅니다. 보고서가 언급한 일부 결과·환경 파일은 커밋 57819b8에 포함되어 있지 않습니다.

정형 출력도 오판할 수 있습니다. 후보 설명이나 본문이 잘릴 수 있고, 언어 휴리스틱은 혼합 언어에 약할 수 있습니다. README의 “환각할 것이 없다”는 표현은 자유로운 출력 문장 생성을 하지 않는다는 의미로 제한해 읽어야 합니다. 업무 자동화 여부는 실제 데이터의 정확도·보정·오답 비용을 따로 평가해 정합니다.