반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

How to count tokens with tiktoken

오늘 다를 예제는 아래 CookBook 페이지에 있는 토큰 관련 에제 입니다.

https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb

 

GitHub - openai/openai-cookbook: Examples and guides for using the OpenAI API

Examples and guides for using the OpenAI API. Contribute to openai/openai-cookbook development by creating an account on GitHub.

github.com

 

tiktoken 은 openAI 에서 제공하는 오픈 소스 토크나이저 입니다.

 

이 모듈은 문자열과 인코딩 방법을 전달하면 그 문자열을 토큰으로 나눠서 리스트에 담아서 반환합니다.

예를 들어 tiktoken is great! 이라는 문자열을 gpt2라는 인코딩을 사용하면 어떻게 토큰이 나누어 지는지 질문하면 아래처럼 response를 줍니다.

["t", "ik", "token", " is", " great", "!"]

이 문자열은 총 6개의 토큰으로 구성 돼 있습니다.

대개 1개의 단어가 1개의 토큰이 되지만 꼭 그렇지만은 않습니다.

그리고 인코딩 방법에 따라서 토큰을 나누는게 조금 다릅니다.

 

GPT-3 같은 모델은 텍스트를 토큰들의 집합으로 봅니다. 그렇기 때문에 문자열을 토큰으로 분할하게 되면 유용하게 사용할 수 있습니다. 

이 모델이 사용하기에 너무 많은 토큰의 갯수는 아닌지를 알아 볼 수도 있고 이 토큰 갯수에 따라서 API 요청에 대한 과금이 매겨지기 때문에 이 요청을 하면 돈이 얼마가 들지 미리 알 수 있습니다.

 

GPT-3의 모델들은 하나의 인코딩만을 사용하는 것이 아니고 모델별로 다른 인코딩을 사용하는 경우가 있습니다.

 

이 tiktoken은 OpenAI 모델들이 사용하는 아래 세가지 인코딩 방법을 제공합니다.

 

p50k_base는 gpt2 와 많은 부분 겹치는 인코딩 입니다. 코드가 아닌 어플리케이션인 경우 일반적으로 동일하게 토큰을 나눕니다.

 

Tokenizer libraries and languages

gpt2 인코딩은 다음과 같은 많은 프로그래밍 언어에서 사용할 수 있는 tokenizer가 제공 됩니다.

 

(OpenAI는 3rd party 라이브러리에 대해서는 그 성능과 리스크에 대한 보장을 하지 않습니다.)

 

p50k_base와 cl100k_base 인코딩의 경우 2023년 1월 현재 tiktoken에서만 tokenizer가 가능합니다.

How strings are typically tokenized

영어로 된 텍스트인 경우 토큰의 길이는 일반적으로 문자 하나이거나 단어 하나가 한개의 토큰이 됩니다. (e.g., "t" or " great")

다른 언어에서는 한문자보다 짧거나 한단어보다 길 수 있습니다.

공백은 일반적으로 단어의 시작으로 그룹화 됩니다. (e.g., " is" instead of "is " or " "+"is")

OpenAI Tokenizer를 사용해서 문자열이 어떻게 tokenized 되는지 빠르게 체크할 수 있습니다.

 

0. Install tiktoken

이 tiktoken을 사용하려면 먼저 이 모듈을 인스톨 해야 합니다.

pip install tiktoken

 

1. Import tiktoken

그러면 이 tiktoken을 import 할 수 있습니다.

import tiktoken

 

2. Load an encoding

tiktoken.get_encoding()을 사용해서 인코딩을 로딩 합니다. 이 때 인코딩 이름을 파라미터로 전달합니다.

처음 이 작업을 할 때는 인터넷에 연결 돼 있어야 합니다.

한번 로딩한 다음에는 인터넷이 연결 돼 있지 않아도 사용할 수 있습니다.

encoding = tiktoken.get_encoding("gpt2")

3. Turn text into tokens with encoding.encode()

.encode() 메소드는 문자열을 token integer들로 변환합니다.

 

 

위에서 tiktoken is great! 이 아래와 같은 토큰들로 나누어 진다고 했습니다.

["t", "ik", "token", " is", " great", "!"]

그렇다면 t는 83이고 ik 는 1134 이고 token 은 30001 ..... 마지막으로 ! 는 0 이 됩니다.

 

아래 함수는 토큰 갯수를 계산해서 반환해 주는 함수 입니다.

def num_tokens_from_string(string: str, encoding_name: str) -> int:
    """Returns the number of tokens in a text string."""
    encoding = tiktoken.get_encoding(encoding_name)
    num_tokens = len(encoding.encode(string))
    return num_tokens

함수 이름은 num_tokens_from_string() 이고 파라미터로는 String 과 인코딩 이름이 전달 됩니다.

그리고 반환 타입은 integer 입니다.

 

get_encoding()을 사용해서 사용할 encoding을 정의 합니다.

그리고 len() 함수를 사용해서 인코드해서 얻은 리스트의 아이템 갯수를 num_tokens 변수에 넣습니다.

이 아이템들이 각각의 토큰들 입니다.

 

이 함수를 사용해서 토큰의 갯수를 아래와 같이 얻을 수 있습니다.

 

4. Turn tokens into text with encoding.decode()

인코딩이 있으면 디코딩도 있겠죠.

.decode()를 사용하면 숫자로 된 토큰 정보를 문자로 바꿀 수 있습니다.

 

Warning : .decode()는 single tokens에 적용될 수 있지만 utf-8 boundaries가 아닌 경우 토큰의 손실이 발생 할 수 있습니다.

single tokens의경우 decode_single_token_bytes() 는 단일 정수 토큰을 그것이 나타내는 바이트로 안전하게 변환합니다. 

여기서 각 string 앞에 있는 b가 가리키는 것은 이 String들이 byte string들이라는 의미 입니다.

 

5. Comparing encodings

그렇다면 각 인코딩 별로 어떻게 입력값을 분할 해서 토큰으로 나누는지를 알아 보겠습니다.

 

def compare_encodings(example_string: str) -> None:
    """Prints a comparison of three string encodings."""
    # print the example string
    print(f'\nExample string: "{example_string}"')
    # for each encoding, print the # of tokens, the token integers, and the token bytes
    for encoding_name in ["gpt2", "p50k_base", "cl100k_base"]:
        encoding = tiktoken.get_encoding(encoding_name)
        token_integers = encoding.encode(example_string)
        num_tokens = len(token_integers)
        token_bytes = [encoding.decode_single_token_bytes(token) for token in token_integers]
        print()
        print(f"{encoding_name}: {num_tokens} tokens")
        print(f"token integers: {token_integers}")
        print(f"token bytes: {token_bytes}")

이 compare_encodings() 함수는 string을 입력 파라미터로 받습니다. return 값은 없고 그냥 이 함수 안에서 계산해서 그 정보를 print 해 줍니다.

 

첫번째 있는 print 문은 Example string : 입력 받은 문자열 을 출력합니다.

그 다음 for 문이 있는데 각 인코딩 별로 이 for 문안에 있는 작업을 해 줄 겁니다.

우선 get_encoding() 을 사용해서 사용할 encoding을 세팅해 줍니다.

그리고 encode()를 사용해서 토큰으로 나눠 줍니다. (결과값을 리스트 형식으로 반환 합니다.)

그리고 len()을 이용해서 이 리스트안에 있는 아이템 갯수들을 num_tokens에 담습니다.

그리고 decode_single_token_bytes()를 사용해서 각 바이트별 텍스트를 token_bytes에 담습니다.

그 다음 인코딩 이름과 토큰 리스트의 인티저 값 그리고 각 바이트 별 문자를 표시해 줍니다.

 

이렇게 한 단어인데 긴것을 넣어 봤습니다. 이것은 반체제주의라는 의미라고 합니다.

gpt2와 p50k_base는 5개의 토큰으로 나눴고 cl100k_base는 6개의 토큰으로 나눴습니다.

 

한번 OpenAI의 토크나이저 페이지에 가서 같은 문자열을 넣고 확인해 보겠습니다.

gpt2와 p50k_base 인코딩과 동일한 결과를 볼 수 있습니다.

이 OpenAI 토크나이저 페이지는 아래에 가시면 볼 수 있습니다.

 

https://platform.openai.com/tokenizer

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

그 다음 계산식도 넣어보고 일본어도 넣어 봤습니다.

 

그리고 한글도 넣어 봤습니다.

그리고 긴 영어 문장도 한번 넣어 봤구요.

 

 

이 예제들에서는 gpt2와 p50k_base가 동일하게 나왔습니다.

cl100k_base는 어떤 때는 다른 두개보다 더 많은 토큰으로 나누었고 또 어떤 때는 토큰수가 더 적을 때도 있었습니다.

 

인코딩 방법에 따라 이렇게 다른 결과들이 나옵니다.

 

반응형