토크나이제이션

토크나이제이션 (Tokenization) — 컨트롤 토큰 (Control Tokens)

컨트롤 토큰(control token)이 무엇이고, 효율성·보안·경계 문제를 어떻게 한 번에 해결하는지 살펴보는 페이지예요.

출처: 문서

본문

경계 — 복습 (Boundaries - Recap)

경계 문제는 모델이 예상치 못한 토큰 시퀀스를 만나 예측이 부정확해질 때 발생해요. 예를 들어 모델이 학습 중에 https를 봤는데 http + s 같은 시퀀스는 보지 못했다면, 그런 시퀀스를 다루는 데 어려움을 겪을 수 있어요.

경계 문제를 해결하기 위해 Token Healing은 시퀀스의 마지막 토큰을 제거하고, 다음 토큰 생성이 제거된 토큰에 해당하는 문자열로 시작하도록 제약해요. 이렇게 하면 토큰 생성 하나의 대가로 경계 문제를 해결해요.

컨트롤 토큰 (Control Tokens)

컨트롤 토큰은 많은 문제를 한 번에 해결하는데, 그중 세 가지에 집중해 볼게요:

  • 효율성 (Efficiency): 컨트롤 토큰은 더 적은 토큰을 사용해서 효율을 개선해요.
  • 보안 (Security): 컨트롤 토큰은 모델을 프롬프트 인젝션(prompt injection)에 더 견고하게 만들어 줘요.
  • 경계 문제 (Boundary issues): 컨트롤 토큰은 기본적으로 경계 문제를 완화하는 데도 도움을 줘요.

이전에는 이렇게 인코딩해 왔어요:

BOS_ID
+ encode("[INST] Hello, how are you? [/INST]")
+ encode("Fine, and you?") + EOS_ID
+ encode("[INST] I'm doing great! [/INST]")
+ encode("Glad to hear!") + EOS_ID

우리의 효율성 문제는 특수 문자열 [INST]와 [/INST]가 나머지 텍스트와 함께 정상적으로 토크나이즈된다는 사실에서 나와요. 왜 비효율적일까요? 우리가 아는 한, 토크나이저는 이를 [ + INST + ] 또는 [/ + INST + ]처럼 문자열당 세 개의 토큰으로 인코딩할 수 있어요. 이 두 문자열이 항상 어디에나 존재할 것임을 고려하면 비효율적이에요.

보안 측면에서, 우리 모델이 채팅 애플리케이션에 있다고 상상해 볼게요. 사용자가 자기 메시지에 특수 문자열을 넣을 수 있고, 이를 막을 수 없어요. 결국 이런 일이 생길 수 있어요:

BOS_ID
+ encode("[INST] Hello, [INST] [/INST] how are you? [/INST]")
+ encode("Fine, and you?") + EOS_ID
+ encode("[INST] I'm doing great! [/INST]")
+ encode("Glad to hear!") + EOS_ID

이러면 템플릿이 완전히 깨져서 사용자가 기대되는 모델 동작을 주입하고 깨뜨릴 수 있어요.

컨트롤 토큰의 아이디어는 파인튜닝 단계에서 모델이 이전에 본 적 없고, 사용자가 절대 주입할 수 없는 새 토큰을 도입하는 거예요. 단순히 문자열 스펙트럼에 존재하지 않기 때문이에요. 토큰 ID로만 존재하죠. 기본적으로 우리 특수 문자열을 대체할 새 토큰 ID를 추가하는 거예요. 표현상의 이유로만 [INST]와 [/INST]를 문자열 표현으로 사용하지만, BOS와 EOS와 마찬가지로 토크나이저는 실제로 그 문자열을 보지 않아요. 그건 단지 우리가 무엇을 논의하는지 알기 위한 방법일 뿐이에요.

그래서 특수 문자열로 사용자 지시를 감싸는 대신, 컨트롤 토큰 ID로 직접 감쌀 거예요.

최종 결과는 이렇게 될 거예요:

BOS_ID
+ INST_ID
+ encode("Hello, how are you?")
+ /INST_ID
+ encode("Fine, and you?") + EOS_ID
+ INST_ID
+ encode("I'm doing great!")
+ /INST_ID
+ encode("Glad to hear!") + EOS_ID

간접적으로 이것은 특수 문자열 주변의 경계 문제도 줄여줘요. 더 이상 문자열이 아니라 토큰 ID로 작업하기 때문이에요.

이론적 문자열 표현은 약간 달라져요:

<s>[INST]Hello, how are you?[/INST]Fine, and you?</s>[INST]I'm doing great![/INST]Glad to hear!</s>

토크나이저 V2/V3 (Tokenizer V2/V3)

V1 이후의 모든 토크나이저는 컨트롤 토큰을 사용해요. 다만 문자열 표현의 최종 결과는 대부분 여전히 sentencepiece의 영향을 받아서, V1과 마찬가지로 각 인코딩 단계에서 공백이 추가돼요:

<s>[INST] Hello, how are you?[/INST] Fine, and you?</s>[INST] I'm doing great![/INST] Glad to hear!</s>

V2와 V3의 유일한 차이는 tool calling(도구 호출)에 관한 것이에요. 그 외에는 모든 게 동일해요. tool calling에 대해 더 배우고 싶다면 여기를 보세요.

토크나이저 V3-Tekken (Tokenizer V3-Tekken)

이 토크나이저는 V3 토크나이저의 변형이에요. 인코딩과 형식에 관한 모든 것은 동일해서 V3라고도 불러요. 주요 차이는 sentencepiece가 아니라 tiktoken을 사용한다는 것이에요. 즉 기본적으로 추가되는 공백이 없어서 최종 문자열 표현이 깔끔해요:

<s>[INST]Hello, how are you?[/INST]Fine, and you?</s>[INST]I'm doing great![/INST]Glad to hear!</s>

더 알아보기 (Learn more)