인공지능/자연어 처리

모델 추론 코드 작성하기 - Transformer, peft, inference

이게될까 2024. 9. 19. 14:04
728x90
728x90

이번에 오류가 너무 많았습니다..

그냥 generation을 통해서 모델 추론을 진행했더니 모델 출력이 이상한 것만 나오질 않나...

제 서버에서는 Config가 없다고 모델이 불러와 지지도 않지 않나....

transformers 버전 때문에 출력이 다르게 나오지 않나....

pipeline이 안 불러와지는 서버가 있지 않나....

등등 다양한 오류가 있었습니다....

결국 저는 제 서버에서 config 없으니 모델 안 불러지는 것을 peft를 통해 base 모델을 넣고, 추론을 진행하였습니다.

import json
import os
import torch
from setproctitle import setproctitle
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
from peft import PeftModel, PeftConfig

setproctitle은 서버에서 gpu를 누가 쓰는지 확인하기 위해 넣었습니다.

setproctitle("__")
os.environ["CUDA_VISIBLE_DEVICES"] = "5"
# 테스트 데이터 경로 및 저장 경로 설정
test_data_path = "ESConv_trans_test.json"
output_file = "inference_results.txt"
based_model = "KULLM3"
base_model = "/kor_esc_kullmv3"
device = "cuda"

각종 경로를 불러옵니다.

저기서 gpu번호도 지정해주는데 이상하게 오류가 나는 서버도 있더라고요.. 진짜.....

def load_test_data(test_data_path):
    # JSON 파일에서 테스트 데이터를 로드
    with open(test_data_path, 'r') as f:
        test_data = json.load(f)
    return test_data
    
    
test_data = load_test_data(test_data_path)

test 데이터도 가지고 옵니다!

base__model = AutoModelForCausalLM.from_pretrained(based_model).to("cpu")

베이스 모델도 가지고 옵니다.

굳이 cpu 지정안해줘도 될 것 같네요 

tokenizer = AutoTokenizer.from_pretrained("/data/ssh5131/code/KULLM/emp_kullm/train_sft_peft/trained_model/kor_esc_kullmv3")
model = PeftModel.from_pretrained(base__model, "/data/ssh5131/code/KULLM/emp_kullm/train_sft_peft/trained_model/kor_esc_kullmv3")

남들은 여기서 그냥 전부 AutoModelForCausalLM으로 불러왔으나 저는 이상하게 안되기 때문에 그냥 PeftModel로 불러왔습니다.

chat_pipeline = pipeline(
    "text-generation",
    model = model,
    eos_token_id = tokenizer.eos_token_id,
    tokenizer = tokenizer,
    max_new_tokens = 512,
    do_sample = False,
    use_cache = True,
    device = "cuda:0"
)
chat = [
  {"role": "user", "content": "안녕하세요, 제가 오늘 슬픈 일이 있었어요"}]
output = chat_pipeline(chat)
print(output[0]['generated_text'])

[{'role': 'user', 'content': '안녕하세요, 제가 오늘 슬픈 일이 있었어요'}, {'role': 'assistant', 'content': '안녕하세요. 오늘 슬픈 일이 있었다니 정말 마음이 아프실 것 같아 걱정되네요. 혹시 그 일에 대해 이야기하고 싶다면 듣고 싶습니다. 혹은 다른 방식으로 도움을 드릴 수 있는 부분이 있다면 언제든지 말씀해 주세요.'}]

 

테스트를 한번 진행해봤씁니다.

경고문 하나가 나오는데 출력은 잘 나와서 무시하면 되겠습니다.

max_samples = 5
with open("inference_results0.txt", 'a') as f:
        generated_responses = []
        
        for i, item in enumerate(test_data):
            f.write(f"Dialog: {i}\n")
            
            if i >= max_samples:
                break
            
            dialog = item['dialog']
            chat = []
            
            # 롤 매핑 설정 (user는 고정, assistant는 모델이 생성)
            inputs = ""
            for j, turn in enumerate(dialog):
                if turn['speaker'] == 'usr':
                    if j > 0 and chat and chat[-1]['role'] == 'user':
                        # 이전 발화가 'user'인 경우 현재 내용을 이어붙임
                        chat[-1]['content'] += ' ' + turn['trans_text']
                        f.write(f"user (updated): {turn['trans_text']}\n\n")
                    else:
                        # 새로운 'user' 발화를 추가
                        chat.append({"role": "user", "content": turn['trans_text']})
                        f.write(f"user: {turn['trans_text']}\n\n")
                                    
                elif turn['speaker'] == 'sys':
                    if not chat:
                        continue
                    
                    if chat and chat[-1]['role'] == 'assistant':
                        continue
                    
                    # 여기서는 모델이 assistant 발화 부분을 생성
                    print("input: " + str(chat))
                    
                    output = chat_pipeline(chat)
                    response = output[0]['generated_text']
                    
                    #response = response[0]  # 리스트의 첫 번째 요소를 가져옴
                    generated_response = response[len(chat):]
                    
                    chat= response
                    
                    #generated_response = response[len(chat):]

                    
                    f.write(str(generated_response) + "\n\n")
                    
                    #chat.append({"role": "assistant", "content": generated_response})
                    
                    print("response: " + str(generated_response))
                    print("-------------------")

            
            if chat and chat[-1]['role'] == 'assistant':
                f.write("\n")
                f.flush()  # 매번 저장하여 데이터 유실 방지
                f.write("Last data \n\n " + str(chat) + "\n-------------\n\n\n")
                continue
            print("input: " + str(chat))
                    
            output = chat_pipeline(chat)
            response = output[0]['generated_text']
            
            #response = response[0]  # 리스트의 첫 번째 요소를 가져옴
            generated_response = response[len(chat):]
            
            chat= response
            
            #generated_response = response[len(chat):]

            
            f.write(str(generated_response) + "\n\n")
            
            #chat.append({"role": "assistant", "content": generated_response})
            
            print("response: " + str(generated_response))
            print("-------------------")
            
            
            f.write("Last data \n\n " + str(chat) + "\n-------------\n\n\n")
                            
            # 추론 결과 바로 파일에 저장
            #f.write(f"Dialog: {inputs.strip()}\n")
            #f.write(f"Generated Response: {response.strip()}\n")
            f.write("\n")
            f.flush()  # 매번 저장하여 데이터 유실 방지

저는 이렇게 추론을 진행하였습니다.

 

각종 오류가 많아서 고치고 고치고 하다 보니......

그래도 오류 없이 진행됩니다.

 

아래는 결과 입니다.

Dialog: 0
user: 안녕 나는 괜찮아, 조금 슬프지만

[{'role': 'assistant', 'content': '안녕, 네가 슬프다는 것을 알고 있어. 슬픔은 자연스러운 감정이고, 때로는 우리가 중요한 것들을 배우고 성장하는 데 도움을 줄 수 있어. 슬픔을 느끼는 것이 너를 정의하지 않고, 그 감정을 받아들이고 이해하는 것이 중요해. 혹시 슬픔을 느끼는 이유가 있거나, 어떤 일이 있었는지 나누고 싶다면 듣고 싶어. 때로는 감정을 표현하는 것만으로도 조금 나아질 수 있어.'}]

user: 휴일이 다가오면서 저는 제가 무엇을 할 것인지에 대해 매우 스트레스와 긴장을 받았습니다.

[{'role': 'assistant', 'content': '휴일이 다가오면서 무엇을 할지 고민하는 것은 매우 흔한 경험입니다. 이러한 스트레스와 긴장을 줄이기 위해 몇 가지 제안을 드릴 수 있습니다:\n\n1. **계획을 세우세요**: 휴일 동안 할 일을 미리 계획하면 불확실성을 줄일 수 있습니다. 여행, 가족 모임, 휴식 등 다양한 옵션을 고려해 보세요.\n\n2. **우선순위를 정하세요**: 모든 것을 한 번에 해결하려고 하지 마세요. 가장 중요하고 즐거울 것 같은 활동부터 시작하세요.\n\n3. **유연성을 가지세요**: 계획이 바뀔 수 있다는 것을 인정하고 유연하게 대처하세요. 때로는 예상치 못한 기회가 나타날 수 있습니다.\n\n4. **소셜 미디어 사용을 줄이세요**: 소셜 미디어에서 다른 사람들의 휴일 계획을 보며 자신의 계획을 비교하는 것은 스트레스를 더할 수 있습니다. 가능하다면 소셜 미디어 사용을 줄이세요.\n\n5. **현재에 집중하세요**: 계획하는 동안 현재 순간에 집중하고, 긍정적인 감정을 느끼려고 노'}]

user: 네. 저는 대학생이고 캠퍼스에서 살고 있습니다. 이사 오기 전날 아버지가 저에게 용서할 수 없는 말을 하셨고 그 이후로 대화를 나누지 못했습니다.

user (updated): 방학 동안 집에서 살 수밖에 없지만 매우 두렵습니다.

[{'role': 'assistant', 'content': '이사 오기 전날 아버지의 말로 인해 대화를 나누지 못하고 있는 상황이 매우 힘드실 것 같습니다. 이러한 상황에서는 여러 가지 방법을 시도해 볼 수 있습니다.\n\n1. **대화 시도**: 가능하다면, 아버지와 대화를 시도해 보는 것이 좋습니다. 당신의 감정을 솔직하게 표현하고, 아버지의 말이 당신에게 어떤 영향을 미쳤는지 이해를 구하세요. 때로는 오해에서 비롯된 말일 수도 있으며, 상황을 개선할 방법을 함께 찾아볼 수도 있습니다.\n\n2. **중재자 찾기**: 가족 구성원 중 중립적인 관계를 가진 사람이 있다면, 그 사람을 중재자로 삼아 대화를 시도해 볼 수 있습니다. 중재자는 양측의 의견을 전달하고, 이해를 돕는 역할을 할 수 있습니다.\n\n3. **시간 주기**: 때로는 시간이 지나면서 감정이 진정되고 상황이 더 명확하게 보일 수 있습니다. 잠시 시간을 두고, 상황을 다시 평가해 보세요.\n\n4. **지원 받기**: 친구, 가족 구성원, 또는 전문가의 도움'}]

user: 우리 집이 크지 않아서 말이 안 통하지만 계속 마주칠 거라는 건 알아요.

user (updated): 도망칠 차도 없고

[{'role': 'assistant', 'content': '그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그럼 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 집 앞에 차를 세우고 도망칠 거야. 그렇다면 우리 '}]

user: 감사합니다. 추수감사절 연휴는 잘 보내겠지만 코로나19가 우리를 영원히 집으로 돌려보낼까 봐 더 긴장됩니다.

user (updated): 솔직히 말해서 많지 않아요. 햄스터를 키우고 있지만 학교에 같이 있어서 집에 돌아갈 곳이 없습니다.

[{'role': 'assistant', 'content': '추수감사절 연휴를 즐기시길 바랍니다. 코로나19로 인해 집에 머무르는 시간이 늘어났지만, 이 시기를 자기 성장과 새로운 취미 발견에 활용해 보시는 것은 어떨까요? 햄스터를 키우는 것도 좋은 활동이 될 수 있습니다. 집에 돌아갈 곳이 없다고 느끼실 수 있지만, 이 시간을 자신만의 공간을 만들고, 새로운 것을 배우는 시간으로 활용해 보세요. 어려움이 있다면 언제든지 도움을 요청해 주세요.'}]

 

아직 좋은 결과를 보여주고 있진 못하지만 그래도 준수한 출력을 보여주는 중입니다. ㅎㅎ.,,,...

 

728x90