[ 플레이데이터 SK네트웍스 Family AI 캠프 ]

[플레이데이터 SK네트웍스 Family AI 캠프 12기] 11주차 회고

AA_D 2025. 5. 12. 15:03

🗓️기간

2주차 : 2025.05.07~2025.05.09 ( 5월 2주 )

 

#. 한 주를 보내며...

  이번주는 파인튜닝, 프롬프트 엔지니어링, 퓨튜닝, 챗봇만드는 방법에 대해서 배웠다. 배우는 내용이 많고 이해하고 암기해야 할 내용이 많았지만, 전체 흐름을 익히고 반복학습을 통해 최대한 이해할려고 노력했다. AI에서 가장 중요한 llm의 성능을 끌어올리는 방법에 대한 내용으라 어려웠지만 하루하루가 매우 즐거웠다.

1. 좋았던 점

 퓨샷튜닝에 대해 자세하게 배우고 생길 수 있는 문제나, 문제시 해결하여 성능을 높히는 방법이 가장 인상깊었다. 이전에도 배웠지만 더 심화 과정을 통해 챗봇 생성까지 연결하면서 전체 흐름을 만들어 더 깊게 이해할 수 있었다.

2. 개선점

 RAG 시스템 구축에서 단순 DB+LLM의 한계점을 극복한 다음 단계를 배우면서 검색-생성의 방식을 더 자세하게 알 수 있었다.

3. 학습내용 및 예제

1. 파인튜닝 (Fine-Tuning)

1.1 파인튜닝 정의:

  • 기존 사전 학습된 모델(GPT-3.5, GPT-4)을 특정 도메인 또는 데이터셋에 맞춰 재학습시키는 과정.
  • 특정 응답 패턴, 어조, 도메인 지식 등을 모델에 학습시켜 원하는 응답 형식을 유도함.

1.2 파인튜닝의 목적:

  • 일반적인 GPT 모델을 특정 도메인(고객센터, 금융, 법률 등)에 최적화.
  • 모델의 응답 패턴을 특정 템플릿에 맞추거나, 기업 맞춤형 지식을 학습시켜 독창적이고 일관된 응답 생성.

1.3 파인튜닝 과정:

① 데이터셋 준비:

  • 데이터 형식: JSONL (prompt와 completion 필드 포함)
  • 데이터 예제:

2. 프롬프트 엔지니어링 (Prompt Engineering)

2.1 프롬프트 엔지니어링 개념:

  • 모델이 원하는 응답을 생성하도록 입력 형식을 설계하는 과정.
  • 프롬프트 설계 요소:
    • System 역할: 모델의 역할 정의
    • User 질문: 사용자 입력
    • Assistant 응답: 모델이 출력해야 하는 형식

3. 퓨튜닝 (Few-shot Tuning)

3.1 퓨튜닝 개념:

  • 몇 개의 예제(Few-shot)를 프롬프트에 포함시켜 모델이 특정 패턴을 학습하도록 유도.

3.2 퓨튜닝 예제:

4. 챗봇 응답 시스템 설계

4.1 정책 문서 기반 응답 생성:

정책 문서 예제:

python
복사편집
 

4. RAG + Fine-Tuning 기반 응답 평가 및 품질 점검 코드

 

import os
import json
from openai import OpenAI
from sentence_transformers import SentenceTransformer, util
from konlpy.tag import Okt

#  OpenAI API Key 설정
os.environ['OPENAI_API_KEY'] = 'Key'
client = OpenAI(api_key=os.environ['OPENAI_API_KEY'])

# 형태소 분석기 초기화
okt = Okt()

# 정책 문서 정의
policy_doc = """
배송 정책: 모든 주문은 2~3일 내 배송됩니다. 도서산간 지역은 5일 소요.
환불 정책: 구매 후 7일 이내 반품 시 전액 환불. 사용한 제품은 환불 불가.
불량 처리: 불량 제품은 고객센터(1234-5678)로 연락 후 교환 또는 환불.
민감 문의: 법적 위협, 욕설 시 고객센터(1234-5678)로 안내.
"""

#  테스트 쿼리 및 정답 데이터 정의
test_inquiries = [
    {"inquiry": "배송 언제 오나요?", "golden_answer": "보통 주문 후 2~3일 내 배송됩니다."},
    {"inquiry": "환불 어떻게 하나요?", "golden_answer": "구매 후 7일 이내 반품 요청 시 전액 환불 가능합니다."},
    {"inquiry": "이거 왜 이래요?", "golden_answer": "자세한 상황을 말씀해 주시면 도와드리겠습니다."},
    {"inquiry": "환불 안 해주면 고소할게요.", "golden_answer": "환불 정책에 따라 7일 이내 반품 시 처리 가능합니다. 고객센터로 연락 부탁드립니다."}
]

# 간단한 RAG 검색 함수
def simple_rag(query, document):
    """
    사용자 쿼리에 기반하여 정책 문서에서 관련된 문장을 추출하는 RAG 함수

    Args:
    - query (str): 사용자 입력
    - document (str): 정책 문서

    Returns:
    - str: 관련된 정책 문장 또는 전체 정책 문서
    """
    # 형태소 분석을 통해 명사, 동사 추출
    keywords = [word for word, pos in okt.pos(query, norm=True, stem=True) 
                if pos in ['Noun', 'Verb'] and len(word) > 1]

    # 정책 문서를 줄 단위로 분할
    lines = document.split('\n')

    # 키워드가 포함된 문장 추출
    relevant = [line for line in lines if any(keyword in line for keyword in keywords)]

    # 매칭된 문장이 없으면 전체 문서 반환
    return '\n'.join(relevant) if relevant else document

# OpenAI API 호출 함수
def call_openapi(messages, model='gpt-3.5-turbo', temperature=0.3, max_tokens=100):
    """
    OpenAI API를 호출하여 응답을 생성하는 함수

    Args:
    - messages (list): 대화 형식 메시지 리스트
    - model (str): 사용할 모델
    - temperature (float): 응답의 창의성 조정
    - max_tokens (int): 최대 토큰 수

    Returns:
    - str: 모델의 응답
    - int: 사용된 토큰 수
    """
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            temperature=temperature,
            max_tokens=max_tokens
        )
        return response.choices[0].message.content, response.usage.total_tokens
    except Exception as e:
        print(f"API 호출 오류: {e}")
        return "API 호출 오류", 0

# 품질 평가 함수
def evaluate_response(response, golden_answer, inquiry):
    """
    모델 응답을 정답과 비교하여 품질을 평가하는 함수

    Args:
    - response (str): 모델 응답
    - golden_answer (str): 정답
    - inquiry (str): 사용자 입력

    Returns:
    - dict: 평가 결과 (정확성, 유사도, 자연스러움)
    """
    # 키워드 기반 정확성 체크
    keywords = {
        "배송": ["2~3일"],
        "환불": ["7일"],
        "고소": ["고객센터"],
        "이거 왜": ["자세한", "도와"]
    }
    intent = next((k for k in keywords if k in inquiry), None)
    accuracy = all(kw in response for kw in keywords.get(intent, [])) if intent else True

    # 유사도 계산
    model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')
    embeddings = model.encode([response, golden_answer], convert_to_tensor=True)
    similarity = util.cos_sim(embeddings[0], embeddings[1]).item()

    # 자연스러움 체크 (종결 표현 포함 여부)
    is_natural = any(ending in response for ending in ["습니다", "됩니다", "합니다"])

    return {
        "accuracy": accuracy,
        "similarity": similarity,
        "is_natural": is_natural
    }

# 테스트 및 평가
results = []
issues = []

for item in test_inquiries:
    inquiry = item["inquiry"]
    golden_answer = item["golden_answer"]

    # RAG 검색
    retrieved_info = simple_rag(inquiry, policy_doc)

    # 프롬프트 생성
    prompt = f"""
    당신은 친절한 고객 지원 쳇봇입니다. 다음 정책을 참고해 문의에 정확히 답변하세요, 존댓말 유지.
    정책:
    {retrieved_info}
    문의: "{inquiry}"
    답변:
    """
    
    messages = [
        {"role": "system", "content": "정책 준수, 존댓말 유지"},
        {"role": "user", "content": prompt}
    ]

    # OpenAI API 호출 및 응답 생성
    response, tokens = call_openapi(messages, model='gpt-3.5-turbo')

    # 품질 평가
    eval_results = evaluate_response(response, golden_answer, inquiry)
    
    # 결과 저장
    result = {
        "inquiry": inquiry,
        "response": response,
        "golden_answer": golden_answer,
        "accuracy": eval_results["accuracy"],
        "similarity": eval_results["similarity"],
        "is_natural": eval_results["is_natural"],
        "tokens": tokens
    }
    results.append(result)

    # 문제점 기록 (정확성, 자연스러움 중 하나라도 False인 경우)
    if not eval_results["accuracy"] or not eval_results["is_natural"]:
        issues.append(result)

# 결과 출력
print("=== 테스트 결과 ===")
for res in results:
    print(f"문의: {res['inquiry']}\n응답: {res['response']}\n정답: {res['golden_answer']}")
    print(f"정확성: {res['accuracy']}, 유사도: {res['similarity']:.2f}, 자연스러움: {res['is_natural']}\n")

# 문제점 출력
print("=== 문제점 ===")
for issue in issues:
    print(f"문의: {issue['inquiry']}\n응답: {issue['response']}\n정확성: {issue['accuracy']}\n")

4. 12주차의 목표

  rag에 대해 완벽히 마스터하자.