본문 바로가기

IT/개발

ChatGPT API로 구현할때 토큰 수 제한 문제 해결하기(문자열 token 수 세기, tiktoken)

반응형

이전에 chatGPT를 API를 이용해서 Discord bot 을 구현 했습니다. 

 

아래 참조 

https://yongeekd01.tistory.com/193

 

chatGPT를 discord bot으로 만들어보자(초간단, 대화기억, chatGPT-4o)

1. discord 서버 생성하기  우선 discord bot이 일을 하기 위한 서버환경을 만들어 줘야 합니다. 하나 생성해볼까요? discord를 실행하고  좌측의 + 버튼을 눌러서 서버를 생성합니다.   서버의 이름

yongeekd01.tistory.com

 

생각해보니 채팅을 무한히 반복하면 토큰수가 초과되어 세션에 문제가 생기는걸 깜빡 했습니다. 

그부분을 해결해 보겠습니다. 

 

대화를 계속 누적해서 보내다 보니 생길 수 밖에 없는 문제겠네요. 

 

openai에서 제공하는 tiktoken을 이용해서 해결해 보겠습니다.

 

tiktoken은 OpenAI에서 제공하는 토큰화 패키지로, 텍스트를 모델에서 처리할 수 있는 토큰 형태로 변환하는 데 사용됩니다. 
텍스트를 모델 입력으로 제공하기 전에 해당 텍스트를 모델이 이해할 수 있는 형식으로 변환하는 과정이라고 볼수 있습니다. 

 

1. tiktoken을 사용해서 토큰 수 계산 

 

먼저 tiktoken을 설치 합니다. 

pip3 install tiktoken

 

단순히 문자열을 토큰으로 변환 했을때 토큰 수만 세보려면 다음과 같이 하면 됩니다. 

import tiktoken

# 원하는 롬과 코덱을 선택 (여기서는 기본 gpt-4 코덱을 사용)
encoding = tiktoken.encoding_for_model("gpt-4")

# 텍스트를 토큰으로 변환
text = "너는 프로그래머야. 질문의 대답 찾기 위한 파이썬 코딩을 하고 그 코드에 대해서 자세히 설명해줘"
tokens = encoding.encode(text)
print(f"Tokens:", tokens, f" {len(tokens)}")

# 토큰을 다시 텍스트로 변환
original_text = encoding.decode(tokens)
print("Original Text:", original_text)
 

 

 

2. 코드 수정하기 

 

API 사용시 돈문제도 있으니까 ^^ 4K 정도의 90%가 차면 문자열을 누적하는 리스트를 초기화 하는 부분을 추가하도록 하겠습니다. 

 

 

 
import discord
import os
from openai import OpenAI
import tiktoken

discord_bot_token = os.environ.get('DISCORD_BOT_TOKEN')
openai_api_key = os.environ.get('OPENAI_API_KEY')
channel_id = '자신의 채널 아이디' #채널에 오른쪽 버튼 누르면 보입니다.

#history_messages = [{"role": "system", "content": "너는 똑똑한 helper"}]

class MyClient(discord.Client):
   
    tokens = 0 #토큰 수 누적 변수
    history_messages = [{"role": "system", "content": "너는 똑똑한 helper"}]
   
   
    async def on_ready(self):
        print(f'Logged on as {self.user}!')
        channel = client.get_channel(int(channel_id))
        await channel.send("난똑똑해! 무엇이든 물어봐~~")

    async def on_message(self, message):        
        if message.author == client.user:
            #봇자신이 보낸건 처리하지 않기
            print(f'Message from me {message.author}: {message.content}')            
            return
       
        print(f"current tokens = {self.tokens}")
        #system role 빼고 대충 4K, 90%정도 되면 지우기
        if self.tokens > int(4096 * 0.9) :            
            print(f"tokens limit! clear list {self.tokens}")
            self.history_messages = self.history_messages[:1]  # 첫 번째 system role 항목만 남기고 나머지 삭제
            self.tokens = 0

        #이전 대화에 현재 질문 추가하기  
        self.history_messages.append({"role": "user", "content": f"{message.content}"})
        self.tokens += len(encoding.encode(message.content)) #토큰 수 갱신

        completion = chatClient.chat.completions.create(
            model="gpt-4o",
            messages = self.history_messages
        )
       
        #chatgpt응답을 assistant role로 다시 전달하기 위해 저장
        response = {"role": "assistant", "content": f"{completion.choices[0].message.content}"}
        self.history_messages.append(response)
        self.tokens += len(encoding.encode(completion.choices[0].message.content)) #토큰 수 갱신
       
        #실제 질문 답변
        answer = completion.choices[0].message.content
        #print(response)
        print(answer)        
        await message.channel.send(answer)
       

chatClient = OpenAI()
encoding = tiktoken.encoding_for_model("gpt-4") # 원하는 코덱을 선택 (여기서는 기본 gpt-4 코덱을 사용)


intents = discord.Intents.default()
intents.message_content = True
client = MyClient(intents=intents)
client.run(discord_bot_token)

 

 

자 이제 토큰 제한을 어느정도는 해결 할 수 있겠네요

 

반응형