대규모 언어 모델(LLM)에서 자연어 처리의 핵심 개념 중 하나는 토큰(Token)입니다. OpenAI에서 개발한 tiktoken 라이브러리는 바로 이 토큰수를 예상할 수 있는 라이브러리입니다. 이번에는 tiktoken를 어떻게 활용할 수 있는지 코드와 함께 정리해 보겠습니다.
OpenAI LLM 토큰수 계산하기
tiktoken 라이브러리
tiktoken은 OpenAI의 모델들이 텍스트를 인코딩(토큰화)하고 디코딩하는 데 사용하는 BPE(Byte Pair Encoding)입니다. 쉽게 말해, 우리가 작성하는 문장을 모델이 이해할 수 있는 작은 숫자(토큰 ID)들의 배열로 변환하거나, 반대로 토큰 ID 배열을 다시 우리가 읽을 수 있는 문장으로 변환해 주는 역할을 합니다.
다음과 같이 활용됩니다.
- 토큰 수 예측: LLM API는 토큰 사용량에 따라 비용을 부과하고, 특정 토큰 한도를 가집니다. tiktoken을 사용하면 API 호출 전에 정확한 토큰 수를 예측하여 비용을 최적화하고 모델의 한계를 관리할 수 있습니다.
- 성능 최적화: 토큰 수가 적을수록 모델의 처리 속도가 빨라지므로, 효율적인 토큰 관리는 애플리케이션의 응답 속도를 향상시킵니다.
- 모델 이해: 텍스트가 모델 내부에서 어떻게 분해되는지 이해하는 데 도움이 됩니다.
tiktoken 라이브러리 활용하기
우선 설치부터 해볼까요?
pip install tiktoken
이제 기본적인 기능 중 토큰수 계산에 가장 중요한 함수는 encoding_for_model 입니다. 이 함수는 내부적으로 encoding_name_for_model 함수를 호출하여 실제 인코딩 이름을 가져오고, 그 이름을 확인하여 최종 Endcoding 객체를 반환하도록 합니다.
- encoding_name_for_model(model_name) 호출:
- 이 함수는 입력된 model_name에 해당하는 토크나이저의 이름(문자열)을 찾아 반환합니다.
- MODEL_TO_ENCODING 딕셔너리 확인: 먼저 model_name이 MODEL_TO_ENCODING 딕셔너리에 직접 매핑되어 있는지 확인합니다. 이 딕셔너리에는 "gpt-4o", "gpt-3.5-turbo", "text-embedding-ada-002"와 같은 정확한 모델 이름과 그에 해당하는 인코딩 이름(예: "o200k_base", "cl100k_base")이 매핑되어 있습니다.
- 예: model_name = "gpt-4o"는 MODEL_TO_ENCODING에서 "gpt-4o": "o200k_base"를 찾아 "o200k_base"를 반환합니다.
- 예: model_name = "gpt-3.5" (일반적인 축약형)도 이 딕셔너리에 직접 매핑되어 있습니다.
- MODEL_PREFIX_TO_ENCODING 딕셔너리 확인 (접두사 매칭): 만약 MODEL_TO_ENCODING에 직접적인 매핑이 없으면, MODEL_PREFIX_TO_ENCODING 딕셔너리를 순회하면서 model_name이 특정 접두사로 시작하는지 확인합니다.
- 이 방식은 gpt-4-0314, gpt-3.5-turbo-0301와 같이 모델 버전이 뒤에 붙는 경우에도 올바른 인코딩을 찾을 수 있도록 합니다. 예를 들어, gpt-4-0314는 "gpt-4-" 접두사에 매칭되어 "cl100k_base"를 반환합니다.
- "TODO: these will likely be replaced by an API endpoint" 주석에서 알 수 있듯이, 이 매핑 로직은 미래에는 OpenAI API를 통해 동적으로 제공될 가능성이 있습니다.
- KeyError 발생: 만약 어떤 매핑에서도 model_name을 찾지 못하면 KeyError를 발생시켜, 해당 모델에 대한 토크나이저를 자동으로 매핑할 수 없음을 알리고 tiktoken.get_encoding을 사용하여 명시적으로 인코딩을 지정하도록 안내합니다.
- get_encoding(encoding_name) 호출:
- encoding_name_for_model에서 반환된 인코딩 이름(예: "o200k_base", "cl100k_base")을 인자로 받아, 실제로 해당 이름에 해당하는 Encoding 객체를 로드하거나 반환합니다. 이 Encoding 객체는 encode(), decode(), num_tokens_from_messages() 등 실제 토큰화 작업을 수행하는 메서드를 포함하고 있습니다.
아무리 설명해도 한번 구현하는 것만은 못하죠. 다음과 같이 간단하게 코드를 구성해봤어요.
import tiktoken
# 모델 이름을 통해 인코딩 가져오기
model_35 = "gpt-3.5-turbo"
model_4o = "gpt-4o"
encoding_35 = tiktoken.encoding_for_model(model_35)
encoding_4o = tiktoken.encoding_for_model(model_4o)
# 2. 텍스트를 토큰화 (인코딩)
text = "안녕하세요, tiktoken 라이브러리 사용법을 알려드릴게요."
print(f"원본 텍스트: {text}")
tokens_35 = encoding_35.encode(text)
print(f"{model_35}모델로 토큰화된 결과 (토큰 ID): {tokens_35}")
print(f"{model_35}모델로 토큰화된 토큰 수: {len(tokens_35)}")
# 3. 각 토큰이 어떤 텍스트에 해당하는지 확인 (바이트 형태로 반환)
token_bytes_35 = [encoding_35.decode_single_token_bytes(token) for token in tokens_35]
print(f"{model_35}모델: 각 토큰의 원문 (바이트): {token_bytes_35}")
print("----------------------------")
tokens_4o = encoding_4o.encode(text)
print(f"{model_4o}모델로 토큰화된 결과 (토큰 ID): {tokens_4o}")
print(f"{model_4o}모델로 토큰화된 토큰 수: {len(tokens_4o)}")
token_bytes_4o = [encoding_4o.decode_single_token_bytes(token) for token in tokens_4o]
print(f"{model_4o}모델: 각 토큰의 원문 (바이트): {token_bytes_4o}")
이 코드를 실행한 결과는 다음과 같아요.
원본 텍스트: 안녕하세요, tiktoken 라이브러리 사용법을 알려드릴게요.
gpt-3.5-turbo모델로 토큰화된 결과 (토큰 ID): [31495, 230, 75265, 243, 92245, 11, 87272, 5963, 5251, 46981, 13094, 98038, 234, 61394, 29102, 41820, 28617, 243, 18359, 24814, 234, 22289, 97, 30446, 20701, 112, 58901, 36811, 13]
gpt-3.5-turbo모델로 토큰화된 토큰 수: 29
gpt-3.5-turbo모델: 각 토큰의 원문 (바이트): [b'\xec\x95', b'\x88', b'\xeb\x85', b'\x95', b'\xed\x95\x98\xec\x84\xb8\xec\x9a\x94', b',', b' tik', b'token', b' \xeb', b'\x9d\xbc', b'\xec\x9d\xb4', b'\xeb\xb8', b'\x8c', b'\xeb\x9f\xac', b'\xeb\xa6\xac', b' \xec\x82\xac\xec\x9a\xa9', b'\xeb\xb2', b'\x95', b'\xec\x9d\x84', b' \xec\x95', b'\x8c', b'\xeb\xa0', b'\xa4', b'\xeb\x93\x9c', b'\xeb\xa6', b'\xb4', b'\xea\xb2\x8c', b'\xec\x9a\x94', b'.']
----------------------------
gpt-4o모델로 토큰화된 결과 (토큰 ID): [14307, 171731, 11, 260, 8251, 2488, 143767, 33204, 13689, 4960, 27525, 22070, 3281, 104661, 9389, 70984, 7996, 7952, 13]
gpt-4o모델로 토큰화된 토큰 수: 19
gpt-4o모델: 각 토큰의 원문 (바이트): [b'\xec\x95\x88', b'\xeb\x85\x95\xed\x95\x98\xec\x84\xb8\xec\x9a\x94', b',', b' t', b'ikt', b'oken', b' \xeb\x9d\xbc\xec\x9d\xb4', b'\xeb\xb8\x8c', b'\xeb\x9f\xac', b'\xeb\xa6\xac', b' \xec\x82\xac\xec\x9a\xa9', b'\xeb\xb2\x95', b'\xec\x9d\x84', b' \xec\x95\x8c\xeb\xa0\xa4', b'\xeb\x93\x9c', b'\xeb\xa6\xb4', b'\xea\xb2\x8c', b'\xec\x9a\x94', b'.']
두 가지 모델(`gpt-4o`와 `gpt-3.5-turbo`)로 동일한 텍스트를 토큰화했을 때, 토큰 ID와 토큰 수가 다르게 나오는 것을 확인할 수 있습니다.
gpt-4o는 19개의 토큰으로, gpt-3.5-turbo는 29개의 토큰으로 텍스트를 표현했습니다.
이런 차이는 각 모델이 사용하는 토크나이저의 학습 방식과 어휘(Vocabulary)가 다르기 때문이죠. 효율적인 토크나이저는 문장을 더 적은 토큰으로 표현하여, 결과적으로 API 호출 비용을 절감하고 처리 속도를 높일 수 있어요.
OpenAI API input/output token(토큰) 계산 및 확인 방법 - LLM 모델 사용량과 비용 #1
이번에는 토큰(Token) 수 계산 방법에 대해 살펴보도록 할게요. OpenAI API를 사용하다 보면 토큰(Token) 수에 따라 비용이 책정되는 것을 볼 수 있는데요, 이것은 LLM기반 생성형 AI 모델을 사용함에 있
eco7t.tistory.com
'프로그래밍 언어 > Python' 카테고리의 다른 글
Gemini CLI로 Gemini 2.5 Pro를 무료로 사용해 보자! #1 (0) | 2025.06.27 |
---|---|
파이썬 GIL과 멀티스레딩 - 멀티코어 환경에서 병렬 처리와 성능 한계 #1 (0) | 2025.06.09 |
Flask 데이터베이스, SQLAlchemy와 SQLite로 모델, 마이그레이션, CRUD - Flask #5 (0) | 2025.04.17 |
Flask 폼 처리, 사용자 입력, GET/POST 차이, CSRF 보안 설정 방법 - Flask #4 (0) | 2025.04.15 |
웹 UI 개발을 위한 Flask 템플릿 엔진 Jinja2 조건문과 템플릿 구조 가이드 - Flask #3 (0) | 2025.04.10 |