[커널아카데미] 백엔드 12기 18주차 회고(토이프로젝트4)

david1-p·2025년 7월 26일

회고

목록 보기
18/27

토이 프로젝트 2주차로 진입을 했다.
지난주에 작성한 파이프라인 설계에 대해 개략적인 내용을 적었다.
이번주 내가 맡은 파트는 AI에게 퓨샷을 넣어서 난이도와 정답출력 정확도를 올리는 것이었다.
내가 사용한 퓨샷 프롬프트를 최소화해서 적었다.
생각보다 할게 너무 많다.. 이번주 고생했는데, 다음주까지 고생하고 좀 쉬어야겠다.

1. 예상 문제 생성(RAG) 파이프라인 설계

목표

지정된 교재 범위 내 예상 문제(객관식·주관식) 생성
사용자 오답 이력 기반 개인화

전체 흐름

  1. 범위 선택
    사용자 입력(챕터/페이지 범위)
  2. 키워드 추출 & 메타데이터 저장
    페이지 번호, 챕터 정보 포함
  3. 벡터 인덱싱
    키워드 임베딩 → ElasticSearch 벡터 DB 색인
  4. 모델 프롬프트 구성
    범위 정보 + 사용자 오답 이력 전달
  5. 문제 생성
    객관식: 개념 확인형
    주관식: 심화 서술형
  6. 답안 평가
    사용자의 답변 임베딩 → 벡터 유사도 비교 → 정답 처리

설계 고려 사항

DB 역할 분리
ElasticSearch: 벡터 검색 전용
MySQL: 세션·오답 이력·통계 저장
프롬프트 템플릿 관리
DB에서 동적 로딩 → 유지보수 용이
캐싱 전략
이미 임베딩된 데이터 재사용 → 처리 속도 개선


2. PDF 문서 처리 및 텍스트 분할

문제 상황

  1. LangChain의 RecursiveCharacterTextSplitter 사용 중
  2. AttributeError: 'dict' object has no attribute 'page_content'` 오류 발생

원인 분석

  1. split_documentsDocument 객체 입력을 기대
  2. PDF 로더에서 반환된 데이터가 dict 형태였음

해결 과정

from langchain.document_loaders import PyMuPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.schema import Document

# 1) 올바른 로더로 Document 리스트 확보
loader = PyMuPDFLoader("book.pdf")
docs: list[Document] = loader.load()

# 2) TextSplitter로 분할
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50
)
chunks = splitter.split_documents(docs)
print(f"분할된 청크 수: {len(chunks)}")
  • 적절한 로더 선택: PyMuPDFLoader → Document 반환
  • 타입 검증 추가: isinstance(doc, Document) 체크로 안전성 확보

3. 퓨샷 프롬프트 예시

  • 설명 부분 → LLM에게 역할·목표·출력 형식을 명확히 전달
  • Few-Shot 예시 → 쉬움·보통·어려움 각 단계별로 2~3문제씩(실제 기출 기반)
  • 최종 요청 → “챕터·난이도·문제 수”를 받아 동일 포맷으로 생성

퓨샷 프롬프트 예시

You are a Java education expert and question-generation engine.  
Your task is to create high-quality multiple-choice questions based on the “Java의 정석” textbook.  
Follow these rules exactly:

1. OUTPUT FORMAT (strict):
   - Each question block MUST start with “### [Qn] (난이도: {쉬움|보통|어려움})”
   - Then “Q: {질문 텍스트}”
   - Then exactly four choices, labeled “A) …  B) …  C) …  D) …”
   - Mark the correct choice with a trailing “✅”.
   - Provide a one-sentence KEYWORD TAG (concept) below the choices.

2. DIFFICULTY GUIDELINES:
   - **쉬움**: 기본 개념이나 문법 확인 수준. 계산·로직이 복잡하지 않아야 함.
   - **보통**: 두 개 이상의 개념 연결 또는 간단한 코드 분석.
   - **어려움**: 심화 개념, 예외 케이스, 다단계 로직 또는 실무 응용.

3. TONE & CONTENT:
   - 문제문은 한국어로 작성.
   - 오답 보기는 납득 가능한 오답(개념적 함정)을 포함.
   - 불필요한 힌트나 설명은 삽입하지 말 것.
profile
DONE IS BETTER THAN PERFECT.

0개의 댓글