목표 : AI 답변이 생성되는 커뮤니티 사이트를 구현하는데, 단순히 API를 가져와서 사용하지 않고 더 깊은 CS지식을 가진 모델을 구축하여 사용하고자 한다.
과정
- Gemma2 Fine tuning with software engineering interview qa dataset
- 커뮤니티 서비스 구현 및 파인 튜닝한 모델 이식
1. Unsloth를 사용한 Gemma2 Fine tuning
colab을 사용하여 fine-tuning 하고자 했지만, 모델을 가져오니 RAM 메모리가 가득차서 세션이 종료되는 문제가 발생했다.
이를 해결하기 위해, 파인튜닝을 효율적으로 할 수 있도록 메모리를 60% 절약해주는 unsloth를 사용하였다.
unsloth를 설치하는데 CUDA , PyTorch, Python 버전이 계속 꼬여서 삽질을 엄청 했다.
https://www.kaggle.com/code/danielhanchen/kaggle-mistral-7b-unsloth-notebook
최종적으로 위 노트북을 참고하였고, model과 dataset 부분을 수정하여 사용했다.
base model은 "unsloth/gemma-2b-it-bnb-4bit"를 가져왔고, 데이터셋 전처리 코드는 다음과 같다.
import pandas as pd
from sklearn.model_selection import train_test_split
from datasets import Dataset
# # CSV 파일 로드
data = pd.read_csv('/kaggle/input/software-engineering-interview-questions-dataset/Software Questions.csv', encoding='cp949')
# 데이터프레임을 딕셔너리로 변환하여 huggingface Dataset으로 변환
dataset = Dataset.from_dict({
'instruction': data['Question'].tolist(),
'input': [""] * len(data),
'output': data['Answer'].tolist()
})
alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
### Instruction:
{}
### Input:
{}
### Response:
{}"""
EOS_TOKEN = tokenizer.eos_token # Must add EOS_TOKEN
def formatting_prompts_func(examples):
instructions = examples["instruction"]
inputs = examples["input"]
outputs = examples["output"]
texts = []
for instruction, input, output in zip(instructions, inputs, outputs):
# Must add EOS_TOKEN, otherwise your generation will go on forever!
text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN
texts.append(text)
return { "text" : texts, }
pass
from datasets import load_dataset
dataset = load_dataset("yahma/alpaca-cleaned", split = "train")
dataset = dataset.map(formatting_prompts_func, batched = True,)
하이퍼 파라미터 세팅 후 모델을 학습했고,
학습된 모델에 alpaca 형식으로 데이터를 입력하면 아래와 같이 출력되는 것을 볼 수 있다.

모델을 huggingface에 save_method = ("merged_16bit")로 업로드 하였고(https://huggingface.co/Chaea/Gemma-2-2b-it-preddit), 아래와 같이 불러와서 사용할 수 있다.
if False:
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "Chaea/Gemma-2-2b-it-preddit", # YOUR MODEL YOU USED FOR TRAINING
max_seq_length = max_seq_length,
dtype = dtype,
load_in_4bit = load_in_4bit,
)
FastLanguageModel.for_inference(model) # Enable native 2x faster inference
inputs = tokenizer(
[
alpaca_prompt.format(
"What is the difference between compilation and interpretation?", # instruction
"", # input
"", # output - leave this blank for generation!
)
], return_tensors = "pt").to("cuda")
from transformers import TextStreamer
text_streamer = TextStreamer(tokenizer)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 128)
LM Studio에 불러와서 사용할 수 있는 -gguf 형태도 따로 저장해서 huggingface 업로드함
(https://huggingface.co/Chaea/Gemma-2-2b-it-preddit-gguf)
2. 커뮤니티 서비스 구현 및 모델 이식

서비스 링크 : http://ec2-13-124-135-251.ap-northeast-2.compute.amazonaws.com/
개발 스택
- Frontend : React, Typescript, Next.js
- Backend : Node.js
- Database : PostgreSQL
위는 Gemma2 API를 사용하여 구현한 커뮤니티 서비스이다.
위의 Typescript 코드에 huggingface에 업로드 해 놓은 모델을 가져와서 붙이는 일만 남았다.
공식 문서를 참고하여 @huggingface/inference로 모델을 인퍼런스하는 코드를 아래와 같이 작성하였다.
const out = await inference.chatCompletion({
model: "Chaea/Gemma-2-2b-it-preddit",
messages: [{
role: "user",
content: prompt
}],
max_tokens: 128,
headers: { "x-wait-for-model": "true" }
});
여기서 문제가 발생했는데, 모델 명만 google/Gemma-2-2b-it 로 바꿔서 인퍼런스 해보면 출력이 잘 되는데, 내가 커스텀한 모델을 넣었을 땐 time out이 발생했다.

huggingface 사이트에서 text generation을 테스트해도 똑같이 time out 발생하는 것을 확인했다.

몇 시간 뒤에는 아래와 같은 메시지가 뜨면서 Inference API도 막혔다.

이 부분에 대해서 알아보았더니, 개인 모델들은 접근이 많지 않아서 Inference API 제공을 회수하며,
모델을 사용하려면 유료로 카드를 등록하여 Inference Endpoints (Dedicated) 방식을 사용해야 한다고 한다.
Inference Endpoints 방식은 전용 서버에서 모델을 배포하고 관리할 수 있도록 Hugging Face가 제공하는 인프라로, 서버 자원을 예약하여 모델을 항상 사용할 수 있게 하는 방식이다.
모델을 로컬로 다운받아서 인퍼런스 할 수도 있지만, 현재 서비스가 Node.js로 구현되어 호환성 문제가 있었다.
한 예시로, Hugging Face의 transformers 라이브러리는 Node.js에서 실행할 수 없기 때문에 Python 스크립트를 따로 호출한다음 Node.js와 상호작용하는 과정이 필요한데, 이 과정이 오버헤드가 컸다.
따라서 로컬 인퍼런스 또는 Inference API를 사용하지 않고 OpenAI의 API를 사용하는 방식을 가져가기로 했다.
결론
- 모델 파인튜닝해서 Hugging Face 업로드 완료
- 커뮤니티 서비스 개발 완료
- But, 파인튜닝한 모델을 서비스에서 사용하지는 않음