')">

인공지능 모형 만들기

LORA-FinBert

Posted by Jong-June Jeon on June 27, 2024

GPT2 입문

GPT2 모형 불러오기 위해는 transformers가 설치되어 있어야 합니다.

# 패키지 로드
import torch
from transformers import GPT2LMHeadModel, GPT2Tokenizer
from transformers import StoppingCriteria, StoppingCriteriaList
# 코드분석을 위한 패키지
import inspect

GPT2LMHeadModel을 이용해서 모형을 로드합니다.

model_name = "gpt2"
model = GPT2LMHeadModel.from_pretrained(model_name)
tokenizer = GPT2Tokenizer.from_pretrained(model_name)

# 모델을 평가 모드로 설정
model.eval()

# 모델을 CPU로 이동
device = torch.device("cpu")
model.to(device)

대화를 시작할 데이터를 입력합니다. 화자를 구분하기 위해서 You: , AI: 를 이용합니다. user_input은 대화 내용을 입력하지만 GPT 모형으로 전달할 데이터에는 user_input의 앞과 뒤에 "You: "와 "\nAI: "를 추가합니다. 다음 만들어진 입력 문자열을 tokenizer를 이용해 토큰으로 만듭니다.

chat_history = "You: Hello!\nAI: Hi there! How can I help you today?"

user_input = "Can you introduce me yourself?" 
# 첫반쩨 입력 텍스트 업데이트
chat_history += f"\nYou: {user_input}\nAI:"

# 토큰화
inputs = tokenizer(chat_history, return_tensors="pt").to(device)   

inputs는 input_ids와 attention_mask 를 가진 dict 입니다. input_ids 는 tokenizer.decode를 이용하여 문자열로 변환할 수 있습니다. attention_mask는 Attention 모형의 mask로 특정한 토큰의 정보가 전달되지 않도록 통제할 수 있습니다. 0의 값을 가진 위치의 토큰은 출력값으로 전달되지 않습니다.

model.generate 는 입력토큰을 받아 출력토큰을 만들어주는 핵심적인 기능을 하는 함수입니다. 이 함수는 Transformer의 decoder로 최대 출력 토큰의 개수, 생성방법, 중복억제와 같은 여러가지 세밀한 선택사항을 설정할 수 있습니다. 여기서는 최대길이(max_length), 패드토큰의 설정(pad_token_id), 조기종료 설정(early_stopping)을 보여줍니다.

max_length = 50

outputs = model.generate(
    inputs['input_ids'],
    max_length=max_length,
    pad_token_id=tokenizer.eos_token_id,
    early_stopping=True
    )
print(outputs)  

print(outputs) 은 출력토큰들을 보여줍니다. 아래 tokenizer.decode 를 이용해서 문자를 확인할 수 있습니다. 많은 경우 결과가 반복되어 출력됨을 확인할 수 있습니다. 이는 model.generate 에서 토큰을 순차적으로 생성하는 과정 (샘플링 과정)에서 흔히 발생하는 현상으로 이를 통제하기 위한 많은 방법들이 제안되었습니다.

response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(response)

출력물의 조정을 위한 함수

파이썬 출력을 쉽게 확인하기 위해서 필요한 함수를 정의합니다.

# 긴 텍스트의 분할 출력 함수 정의 
def print_long_text(text, line_length=80):
    # 줄바꿈 문자를 기준으로 텍스트 분할
    paragraphs = text.split('\n')
    
    for paragraph in paragraphs:
        # 줄바꿈 문자 제거
        paragraph = paragraph.strip()
        
        # 지정된 길이로 분할하여 출력
        lines = [paragraph[i:i + line_length] for i in range(0, len(paragraph), line_length)]
        for line in lines:
            print(line)
        # 각 문단 사이에 줄바꿈 추가
        print()

다음은 이전 대화 내용을 함께 저장하여 처리하는 간단한 방법을 보여줍니다. 기존의 내화 내용에 새로운 문장을 더하여 입력값을 전달합니다. 대화를 처음부터 다시 수행하겠습니다.

chat_history = "You: Hello!\nAI: Hi there! How can I help you today?"
user_input = "Can you introduce me yourself?" 
# 첫반쩨 입력 텍스트 업데이트
chat_history += f"\nYou: {user_input}\nAI:"
  
# 토큰화
inputs = tokenizer(chat_history, return_tensors="pt").to(device)   
# 입력전달
max_length = 100
outputs = model.generate(
    inputs['input_ids'],
    max_length=max_length,
    pad_token_id=tokenizer.eos_token_id,
    early_stopping=True
    )
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print_long_text(response, line_length=80)

다음 response를 chat_history