LLMs는 프롬프트를 읽지 않습니다. 토큰으로 계산합니다.
요약
LLMs는 사용자의 텍스트를 직접 이해하는 것이 아니라, '토큰'이라는 숫자로 변환된 목록(정수)으로 처리합니다. 이 토큰은 AI의 기본 단위이며, 비용 청구와 컨텍스트 제한을 결정하는 핵심 기준입니다. 본 글에서는 토크나이저 작동 원리부터 모델이 다음 토큰을 예측하는 과정까지 상세히 설명하며 프롬프트 작성 방식을 개선할 방법을 제시합니다.
핵심 포인트
- LLMs는 텍스트가 아닌 '토큰'이라는 숫자로만 입력을 처리합니다.
- 토큰은 바이트 쌍 인코딩 같은 알고리즘으로 원시 텍스트를 분해한 조각입니다.
- 모델의 답변 생성 과정은 다음 토큰(숫자)을 예측하는 반복적인 과정입니다.
- 토큰 수를 이해하면 비용 절감 및 더 간결한 프롬프트 작성에 도움이 됩니다.
ChatGPT나 Claude에 프롬프트를 입력한 후, 이 시스템이 어떻게 자신을 이해하는지 궁금해한 적이 있나요? 스포일러를 말씀드리자면, 텍스트를 우리가 하는 방식대로 읽지는 않습니다. 저는 호기심이 생겨 대규모 언어 모델(LLMs)이 입력을 처리하는 방식을 깊이 파고들었고, 이는 제가 프롬프트를 작성하는 방식을 바꾸어 놓았습니다.
전체 포스팅을 한 문장으로 요약하면 다음과 같습니다: 모델은 사용자의 텍스트를 절대 직접 보지 못하며, '토큰'이라는 정수 목록만 볼 수 있고, 이 목록이 청구되는 기준이자 컨텍스트 제한을 계산하는 기준입니다.
간략한 버전
LLMs는 원시 텍스트(raw text)로 작동하지 않습니다. 대신 [바이트 쌍 인코딩(byte-pair encoding)]과 같은 알고리즘을 사용하여 이를 '토큰'이라는 숫자로 변환합니다. 토큰은 AI의 통화입니다. 글자 수당이 아니라 토큰당 비용을 지불하게 됩니다. 아래에서는 텍스트가 토큰으로 변환되는 과정, 토큰이 다시 텍스트로 돌아오는 과정, 그리고 이 모든 것이 비용과 품질에 왜 중요한지를 보여드리겠습니다. 직접 시도해 볼 수 있도록 코드가 포함되어 있습니다.
토큰이란 무엇이며, 왜 신경 써야 할까요?
OpenAI 청구서를 본 적이 있고 (그리고 움찔거린) 분이라면, 단어 단위가 아니라 토큰 단위로 요금이 부과된다는 것을 알아차렸을 것입니다. 그렇다면 토큰은 무엇일까요? 한 문장이 작게 잘려나간 조각들로 이루어져 있다고 상상해 보세요. 때로는 그 조각이 완전한 단어이고, 때로는 반 단어일 수도 있고, 때로는 쉼표일 수도 있습니다. 이 각각의 조각이 하나의 토큰입니다. GPT-4o나 Llama 같은 모델들이 텍스트를 받아들이는 방식은 이런 식이며, 그들이 하는 모든 작업은 이 토큰을 기반으로 실행됩니다.
왜 신경 써야 할까요? 입력되거나 출력되는 토큰 수가 많다는 것은 더 많은 돈을 의미합니다. 그리고 토큰이 어떻게 작동하는지 이해하게 되면, 더 간결한 프롬프트를 작성하여 더 나은 답변을 얻게 됩니다.
1단계: 텍스트가 들어가면 숫자가 나옵니다
보내는 모든 텍스트는 '토크나이저(tokenizer)'에 의해 토큰으로 잘게 쪼개집니다. 저는 GPT-4o가 사용하는 토크나이저이자 OpenAI의 [tiktoken]의 JavaScript 포트인 js-tiktoken을 가지고 직접 실험해 보았습니다:
import { Tiktoken } from 'js-tiktoken/lite';
import o200k_base from 'js-tiktoken/ranks/o200k_base';
import { readFileSync } from 'node:fs';
...
이 코드를 2,294자 길이의 마크다운 파일에 실행해 보니 토큰은 몇 개가 나왔을까요? 단지 484개였습니다.
문자 길이: 2,294
토큰 수: 484
이 파일의 경우 토큰당 약 4.7자가 됩니다. 토큰은 글자가 아닙니다. 청크입니다. 하나의 토큰은 'hello' 같은 전체 단어일 수도 있고, 더 긴 단어의 일부 조각일 수도 있습니다. 이것이 토큰 수가 문자 수보다 훨씬 낮은 이유입니다. 하지만 여전히 청구서에 적힌 숫자입니다.
2단계: 모델이 실제로 처리하는 것
여기 핵심이 있습니다. LLMs는 텍스트가 아닌 토큰으로 학습합니다. 그들이 배운 모든 데이터는 먼저 토큰화되었습니다. 모델이 답변을 '작성'할 때, 그것은 학습 과정에서 포착한 패턴을 기반으로 다음 토큰(숫자)을 예측하는 것입니다. 단어를 쓰는 것이 아닙니다. 나중에 단어로 변환되는 숫자를 생성하는 것입니다.
따라서 순서는 이렇습니다: 사용자의 프롬프트가 숫자 목록이 되고, 모델은 그 숫자들을 계산하여 더 많은 숫자를 예측하며, 이 숫자들은 텍스트로 디코딩됩니다. 정말 놀랍지 않나요?
3단계: 숫자를 다시 텍스트로
이제 역과정입니다. 모델이 토큰을 출력한 후, 토크나이저가 그것들을 읽을 수 있는 형태로 디코딩합니다. 제가 임의의 토큰을 디코딩하여 어떤 결과가 나올지 확인해 보았습니다:
const tokensToText = (tokens: number[]) => {
return tokenizer.decode(tokens);
};
...
토큰 13984는
AI 프로젝트를 위해 프롬프트를 튜닝하기 시작했을 때, 토큰으로 생각하는 것이 정말 큰 차이를 만들었습니다. 짧은 프롬프트는 단순히 비용을 절약해 주었을 뿐만 아니라, 모델이 필요하지 않은 내용을 헤집고 다니지 않았기 때문에 응답도 더 빨랐고 종종 더 정확했습니다. LLM으로 구축한다면 토크나이저를 가지고 놀아보세요. 단락이 일련의 숫자로 줄어드는 것을 보는 것은 이상하게 만족스럽습니다.
이 글에서 제가 신뢰하기 어려울 수 있는 부분
이 숫자들은 하나의 토크나이저와 하나의 파일로 계산된 것입니다. o200k_base는 OpenAI의 인코딩 방식입니다. Claude, Gemini, Llama 각각은 자체적인 방식을 가지고 있으므로, 같은 텍스트라도 각기 다른 개수를 산출합니다. Claude의 경우 토큰 카운팅 엔드포인트를 통해 API로 요청해야 합니다. 제가 얻은 문자당 4.7 토큰이라는 수치는 영어 마크다운을 기준으로 한 것입니다. 코드, JSON, 비영어권 텍스트는 보통 문자당 더 많은 토큰으로 분할됩니다.
'짧은 프롬프트가 더 정확하다'는 것은 제가 본 것일 뿐, 법칙이 아닙니다. 불필요한 컨텍스트를 제거하는 것이 제 프로젝트에 도움이 되었습니다. 모델에게 필요한 컨텍스트를 제거했다면 오히려 해로웠을 것입니다. 유지할 가치가 있는 습관은 잘라내는 것이 아니라 측정하는 것입니다.
토큰이 전체 비용을 결정하지 않습니다. 대부분의 가격표에서 출력 토큰이 입력 토큰보다 더 비싸며, 캐시된 입력 또한 또 다르게 가격이 책정됩니다. 단순히 개수만으로는 비용을 알 수 없습니다.
핵심 요약
LLM은 텍스트를 말하지 않습니다. 토큰을 말합니다. 그 안에는 모두 숫자들로 이루어져 있으며, 이를 아는 것이 이 기술들을 다루는 데 더 능숙하게 만듭니다. 프롬프트를 배포하기 전에, 실제로 호출할 모델의 토크나이저를 통해 실행해 보세요. 코드는 단 10줄이며, 추측을 숫자로 바꿔줍니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기