Stage 04 — BOS가 아니라 문서 경계: UTF-8 byte tokenizer
단일 문서 경계와 순수 UTF-8 byte tokenizer의 정책·비용·실패 경계를 직접 구현하고 검증한다.
Stage 04부터는 구현 전에 먼저 가설을 세운다. 한번 정한 경계 정책은 encoding, loss target, generation 종료, decode, attention, checkpoint까지 퍼진다. 잘못된 경계 추상화의 Blast Radius가 model 전체인 이유다.
테스트: Stage 04 테스트
이번 단계가 답할 질문
decoder-only language model에서 문서의 시작과 끝에 같은 token을 사용하는 것이 올바른 추상화일까, 아니면 BOS와 EOS를 분리해야 할까?
이 질문은 token 하나를 아끼는 문제가 아니다.
처음 세운 가설
decoder-only LM이라면 문서 시작과 끝에 같은 경계 token을 쓰는 것이 꽤 좋은 추상화라고 생각한다. data stream 관점에서 문서 사이에는 사실 하나의 경계만 존재한다.
단일
DOC_BOUNDARYtoken, 일반 text에서 special token 자동 인식 금지, corpus builder의 직접 삽입, byte-level encoding,<UNK>제거, strict UTF-8 정책, debug decode에서만<|doc|>표시, generation seed/stop 공유, checkpoint metadata 검증을 하나의 계약으로 둔다.
핵심 판단은 정확했다. 진짜 비용은 special token 한 줄보다 그 의미를 소비하는 전체 시스템의 정책 복잡도다.
교정 1 — fallback이 아니라 순수 UTF-8 byte tokenizer
character vocabulary에 256개 fallback byte를 섞으면 두 token 공간을 구분하는 protocol이 추가된다. 이번 Stage는 모든 text를 처음부터 UTF-8 byte로 encoding한다.
0..255: 실제 byte 값256:DOC_BOUNDARYprotocol token valid Unicode는 학습 corpus에 없더라도<UNK>없이 표현된다.
문서 stream에서 경계는 왜 하나인가
두 문서 ab, ba를 이어 붙이면 corpus stream은 다음과 같다.
가운데 는 이전 문서의 종료이면서 다음 문서의 시작이다. 문서마다 [D, doc, D]를 이어 붙여 [D,D]를 만드는 대신 corpus builder가 중복 없는 하나의 경계를 삽입한다.

일반 문자열과 protocol token은 다른 입력 경계다
문자열 <|doc|>을 일반 encode에 넣으면 다음 ASCII byte가 된다.
(60, 124, 100, 111, 99, 124, 62)
boundary ID 256은 포함되지 않는다. prompt 내용이 tokenizer control plane을 침범하지 못하며 실제 경계는 corpus builder만 정수 ID로 삽입한다.

교정 2 — decode 책임을 분리한다
decode_text(): byte token만 허용하고 special token이면 실패decode_document(): 정확히 바깥쪽의 boundary만 제거하고 내부 boundary는 거부debug_decode(): debug 화면에서만<|doc|>와 replacement character를 표시 byte0xFF는 보존 가능한 raw data지만 단독으로 valid UTF-8 text는 아니다.decode_bytes()는 원본을 보존하고decode_text()는 실패한다.

Unicode 길이와 계산 비용
문자 수를 , UTF-8 byte token 수를 라 하면 valid Unicode에서
이다. 안녕은 2문자이지만 6 token이다. vocabulary 크기를 , embedding width를 라 하면 token embedding과 output head의 parameter 수는
이다. 일 때 shared boundary는 8224개, BOS/EOS 분리는 8256개로 차이는 32개뿐이다. 그러나 full causal attention은 대략 이므로 한 문자가 4 byte가 되는 최악의 비교에서는 위치 비용이 최대
배가 될 수 있다. token 하나의 parameter 비용과 byte tokenization의 model 전체 비용은 분리해서 판단해야 한다.
중요한 한계 — boundary는 attention barrier가 아니다
DOC_BOUNDARY가 있어도 causal attention은 이전 문서를 읽을 수 있다. 독립 문서가 필요하면 sample/KV cache reset, document segment attention mask, 또는 cross-document context 허용 정책을 별도로 선택해야 한다. boundary는 의미 protocol이지 memory 격리 장치가 아니다.
generation과 checkpoint 계약
generation은 (256,)을 seed로 넣되 이미 존재하는 seed에서 멈추지 않고, 새로 sampling한 token이 256일 때만 종료한다.
checkpoint는 tokenizer version utf8-byte-v1, vocabulary size 257, boundary ID 256, canonical vocabulary SHA-256이 모두 일치해야 load된다.
비용과 Blast Radius
corpus builder는 문서 수, encoding 전 character 수, encoding 후 byte 수, 전체 stream token 수를 각각 제한한다. invalid Unicode, 내부 boundary, invalid UTF-8, vocabulary contract 불일치는 각 입력 경계에서 즉시 실패한다.
직접 실행한 결과
python .\stages\stage_04_byte_tokenizer.py
python -m unittest tests.test_stage_04_byte_tokenizer -v- Stage 04 테스트 12개 통과
- 전체 테스트 44개 통과
- sanity check:
PASS
Stage 04 테스트
이번 Stage가 증명한 것
단일 document boundary는 decoder-only stream의 시작과 끝을 함께 표현하는 올바른 추상화가 될 수 있다. 다만 byte 방식은 <UNK>를 없애는 대신 sequence와 model 계산 비용을 늘리며, boundary 자체는 attention isolation을 제공하지 않는다.
Stage 05의 질문은 “tensor가 아직 없을 때 shape는 주석인가, 실행 시 반드시 검사해야 하는 계약인가?”이다.