[TIL] 문장 학습 모델을 위한 데이터셋 생성 자동화

김시원·2023년 6월 12일
0

TIL

목록 보기
43/50

📌 What I tried

머신 러닝 모델에 [문장과 해당 문장의 label]을 학습시켜야 했고, 이때 필요한 dataset은 최소 1000여개가 필요했다. RNN 모델은 이미 세팅을 완료하였고, 충분한 학습용 dataset만 구축되면 학습을 진행하고 문장으로 입력된 input에 대해 중증도 레벨을 판단하는 인공지능 모델로 이어질 수 있다.

천여개의 Dataset 일일이 만들어줄 수 없어, 자동화할 수 있는 방안을 모색해보았다.

1. PDF file 크롤링

먼저, 중증도 레벨과 증상에 대한 키워드들이 담긴 PDF 파일을 크롤링하여 증상 보고 문장에 들어갈 수 있는 키워드들을 저장해주었다.

import pdfplumber
import re

adult_symptoms_info = []
child_symptoms_info = []

# 15세 이상 page 5~74
# 15세 미만 page 75~158
with pdfplumber.open('./emergency_level.pdf') as pdf:
    for i in range(5, 158):
        page = pdf.pages[i]
        page_text = page.extract_text()
        # 전체 text를 \n 기준으로 나누기
        page_text_arr = page_text.split("\n")
        for j in range(1, len(page_text_arr)):
            # 숫자로 끝나는 문장만 추출
            symptoms_text = re.findall(r".*[0-9]$", page_text_arr[j])
            if(symptoms_text):
                print(symptoms_text)
                # 알파벳 (코드)를 기준으로 쪼개기
                target_symptoms = re.split("[A-Z]+", symptoms_text[0])
                target_symptoms_wo_spaces = [part.strip() for part in target_symptoms]
                # 15세 이상 환자에 대한 증상 키워드
                if(5 <= i <= 74):
                    adult_symptoms_info.append([target_symptoms_wo_spaces[0], target_symptoms_wo_spaces[1]])
                # 15세 미만 환자에 대한 증상 키워드
                elif(75 <= i <= 158):
                    if(len(target_symptoms_wo_spaces) > 1):
                        child_symptoms_info.append([target_symptoms_wo_spaces[0], target_symptoms_wo_spaces[1]])

# 중복되는 증상 제거
unique_adult_data = set(tuple(x) for x in adult_symptoms_info)
unique_adult_list = [list(x) for x in unique_adult_data]
unique_child_data = set(tuple(x) for x in child_symptoms_info)
unique_child_list = [list(x) for x in unique_child_data]

2. OpenAI api를 이용한 문장 생성 자동화

키워드를 다 가져왔다고 하더라도 이를 기반으로 천여개의 문장 dataset을 만들어주기는 어려워서 ChatGPT api를 활용하여 우리의 키워드들이 담긴 list를 돌면서 GPT에 각 증상 레벨별 타당한 문장을 생성해줄 수 있도록 코드를 짜보았다.

import os
import openai

from dotenv import load_dotenv
load_dotenv()

openai.organization = os.environ.get("ORGANIZATION_KEY")
openai.api_key = os.environ.get("OPENAPI_KEY")

completion = openai.ChatCompletion.create(
     model="gpt-3.5-turbo",
     messages=[
        {
             "role": "system", 
             "content": 
                   """
                      너는 구급차에 타고 있는 응급구조사 역할을 맡을거고 현재 환자는 구급차에 타고 있는 상태야.
                      1단계가 가장 위급하고, 5단계가 가장 경미한 증상에 대한 상황이야.
                      다른 설명없이 딱 문장만 제시해줘.
                      말하는 것처럼 작성하는게 아닌 보고서처럼 작성해줘.
                      문장 하나당 큰따옴표로 구분해주고 줄바꿈만 해주면 돼.
                      환자 증상 상태에 대한 문장을 최소 25자로 자세하게 써줘.
                   """
        },
        {
             "role": "user", 
             "content": 
                   f"""
                      {adult_symptoms[i][0]}, {adult_symptoms[i][1]}의 증상을 호소하는 환자에 대해 ktas 중증도 분류에 따라 분류 등급 1, 2, 3, 4, 5단계에 해당하는 상황 예시를 각 단계별로 3개씩 뽑아줘. 
                   """
                }
        ]
)

result = completion.choices[0].message.content
with open("sentences-adult.txt", "a", encoding="utf-8") as file:
     file.write(results + "\n")

3. API 호출 제약으로 인한 스케줄링 필요

gpt-3.5 모델 사용시 1분에 3번의 요청만 가능하다는 제약이 있어, 1분에 3번만 요청을 하도록 scheduling을 해주었다.

import time, schedule

def schedule_api_calls():
    i = 0

    def job():
        nonlocal i
        print(f"{i}", ": ", adult_symptoms[i])
        if i < len(adult_symptoms):
            completion = openai.ChatCompletion.create(
                model="gpt-3.5-turbo",
                messages=[]
            i += 1

        else:
            schedule.cancel_job(job)

    schedule.every(20).seconds.do(job)

schedule_api_calls()

while True:
    schedule.run_pending()
    time.sleep(1)

0개의 댓글