
예전에 개인 맞춤형 식단표 프로젝트를 진행한 적이 있는데, 그때는 단순 LLM과 RAG로만 구현했기 때문에 모델이 음식에 특화된 파인튜닝이 거쳐진 모델이면 결과가 더 좋았을 것이라는 생각을 한적이 있다.
해서, OpenAI 파인튜닝 기능을 시험해보고자 음식의 칼로리와 영양성분 정보를 정확히 제공하는 모델을 만들기 위해 약 400개의 음식 데이터를 사용해 파인튜닝을 진행하였다.
주요 컬럼은 음식명, 중량(g), 에너지(kcal), 탄수화물(g), 당류(g), 지방(g), 단백질(g), 칼슘(mg), 나트륨(mg) 등
import pandas as pd
import json
excel_file_path = "음식데이터.xlsx"
# 데이터셋 로드
df = pd.read_excel(excel_file_path, engine="openpyxl")
# JSONL 파일로 저장
with open("health_food_data.jsonl", "w") as f:
for _, row in df.iterrows():
prompt = f"{row['음 식 명']}의 칼로리와 영양 정보를 알려줘."
completion = (
f"중량: {row['중량(g)']}g, 에너지: {row['에너지(kcal)']}kcal, "
f"탄수화물: {row['탄수화물(g)']}g, 당류: {row['당류(g)']}g, "
f"지방: {row['지방(g)']}g, 단백질: {row['단백질(g)']}g, "
f"칼슘: {row['칼슘(mg)']}mg, 나트륨: {row['나트륨(mg)']}mg, "
f"인: {row['인(mg)']}mg, 칼륨: {row['칼륨(mg)']}mg, "
f"마그네슘: {row['마그네슘(mg)']}mg, 철: {row['철(mg)']}mg, "
f"아연: {row['아연(mg)']}mg, 콜레스테롤: {row['콜레스테롤(mg)']}mg, "
f"트랜스지방: {row['트랜스지방(g)']}g"
)
chat_data = {
"messages": [
{"role": "user", "content": prompt},
{"role": "assistant", "content": completion},
]
}
f.write(json.dumps(chat_data, ensure_ascii=False) + "\n")
# init.py
import os
import openai
from dotenv import load_dotenv
load_dotenv()
openai.api_key = os.environ.get("OPENAI_API_KEY")
# fine-tuning.py
# JSONL로 변환한 데이터 준비
file_path = ("/Users/ruahkim/coding/ai-test/openai-fine-tuning/docs/health_food_data.jsonl")
# 데이터셋 업로드
response = openai.files.create(file=open(file_path, "rb"), purpose="fine-tune")
# 파인튜닝 작업 id 확인
file_id = response.id
print(f"Uploaded file ID: {file_id}")
file_id = "file-file-qGjAqVzbmSj4eFRD6m4xRxw0"# 파인튜닝 작업생성
fine_tune_response = openai.fine_tuning.jobs.create(
training_file=file_id, model="gpt-3.5-turbo"
)
# 파인튜닝 아이디 확인
fine_tune_id = fine_tune_response.id
print(f"find_tuning_job_id: {fine_tune_id}")
fine_tune_id = "ftjob-e6ohdQ1kMpGiIOfObsyyZyif"# 파인튜닝 상태 모니터링
status = openai.fine_tuning.jobs.retrieve(fine_tuning_job_id=fine_tune_id)
print(f"fine-tune status : {status.status}")
succeeded 라고 뜨기때문에 status.status를 주기적으로 확인한다. 작업 중에는 running이라고 뜬다.
# 파인튜닝 완료 후 모델 사용
if status.status == "succeeded":
fine_tuned_model = status.fine_tuned_model
print(f"fine_tuned model : {fine_tuned_model}")
# 모델을 사용하여 예측 수행
# 프롬프트 설정
messages = [
{
"role": "user",
"content": "비빔밥 영양성분이 어떻게 되나요",
}
]
completion = openai.chat.completions.create(
model=fine_tuned_model, messages=messages, max_tokens=300, temperature=0.78
)
print(f"Model Response : {completion.choices[0].message.content.strip()}")

파인튜닝을 통해 특정 음식의 영양성분 정보를 정확히 제공하는 모델을 간단히 만들어보았다.
기존 ChatGPT 모델도 일반적인 질문에는 답할 수 있지만, 파인튜닝된 모델은 제공된 데이터에 맞춰 더 정확한 정보를 제공한다.
JSONL 변환과 데이터 정제가 조금 번거로웠지만, 한 번 준비해 두면 이후 활용하기 좋고, openai의 단점인 hallusination도 어느정도 잡을 수 있다.
데이터를 건강쪽에 맞추어서 더 보강한다면 각 영양성분에 맞추어 개인 건강에 따라 음식을 추천해줄수 있을 것이라는 생각이 든다.