TIL/[TIL]

[TIL]GPT Role, Fine-tuning, RAG, LangChain, Streamlit 흐름 정리

namerong 2026. 7. 20. 15:22

이번 학습에서는 GPT API를 사용할 때의 메시지 구조, Function Calling, Fine-tuning 데이터 형식, LangChain 파이프라인, Streamlit 챗봇 동작 흐름을 정리했다.
단순히 GPT에게 질문하는 수준을 넘어서, 원하는 방식으로 답변하게 만들고 외부 도구나 데이터와 연결하는 구조를 다뤘다.

1. GPT 요청의 Role 구조

GPT에게 요청을 보낼 때는 메시지에 role이 붙는다.

Role 의미
system 모델이 따라야 할 기본 역할과 규칙
user 사용자가 입력한 질문이나 요청
assistant 이전에 모델이 답변한 내용
tool Function Calling에서 외부 함수 실행 결과

기본 대화에서는 보통 system, user, assistant가 중요하다.

messages = [
    {"role": "system", "content": "너는 친절한 Python 강사야."},
    {"role": "user", "content": "NumPy shape 설명해줘."}
]

system은 대화의 큰 방향을 잡고, user는 실제 질문을 담는다.
대화가 이어질 때는 이전 assistant 답변도 함께 넣어야 모델이 맥락을 유지할 수 있다.

Streamlit 챗봇에서는 st.session_state.messages에 대화 기록을 저장해서 새 입력이 들어와도 이전 대화를 계속 유지하도록 했다.


2. Function Calling

Function Calling은 모델이 직접 함수를 실행하는 것이 아니다.
모델은 “어떤 함수를 어떤 인자로 호출하면 좋을지”를 정하고, 실제 실행은 Python 코드가 담당한다.

흐름은 다음과 같다.

사용자 질문
-> GPT에게 tools 목록과 함께 전달
-> GPT가 사용할 함수와 arguments 선택
-> Python 코드가 실제 함수 실행
-> 실행 결과를 tool 메시지로 GPT에게 다시 전달
-> GPT가 최종 답변 생성

예제에서는 search_lesson 함수를 tool로 등록했다.

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "search_lesson",
            "description": "수업 자료를 검색한다.",
            "parameters": {
                "type": "object",
                "properties": {
                    "keyword": {"type": "string"}
                },
                "required": ["keyword"]
            }
        }
    }
]

이때 tool schema는 모델에게 “사용 가능한 함수 설명서”를 주는 역할을 한다.
함수 이름, 설명, 필요한 인자 형식이 명확해야 모델이 올바른 호출을 만들 수 있다.


3. Fine-tuning

Fine-tuning은 모델에게 특정 답변 패턴, 말투, 판단 기준을 반복 학습시키는 방식이다.
회사나 서비스에 맞는 일관된 답변 스타일을 만들고 싶을 때 사용할 수 있다.

학습 데이터는 보통 JSONL 형식으로 작성한다.

{"messages":[{"role":"system","content":"너는 AI와 파이썬 수업을 돕는 교육 조교다."},{"role":"user","content":"NumPy의 shape를 설명해줘."},{"role":"assistant","content":"shape는 배열의 모양을 알려주는 값입니다."}]}

JSONL은 한 줄이 하나의 학습 예제가 되는 형식이다.
예제마다 system, user, assistant 메시지를 넣어 모델이 어떤 입력에 어떤 답변을 해야 하는지 학습하게 만든다.

코드에서는 데이터셋 파일을 업로드한 뒤 fine-tuning job을 생성하는 흐름을 확인했다.

uploaded = client.files.create(
    file=f,
    purpose="fine-tune"
)

job = client.fine_tuning.jobs.create(
    training_file=uploaded.id,
    model="gpt-4.1-mini"
)

다만 Fine-tuning은 모든 모델과 모든 환경에서 항상 가능한 것은 아니다. OpenAI API에는 fine-tuning job endpoint가 있고, 지원 모델은 시점과 계정/조직 설정에 따라 달라질 수 있다. 수업에서 “현재 안 된다”는 말은 특정 모델이나 실습 환경 제약으로 이해하는 편이 정확하다. 공식 API 문서 기준으로 fine-tuning job은 지원되는 모델을 선택해 생성하는 구조다. OpenAI Fine-tuning APIOpenAI endpoint/model support


4. Fine-tuning과 RAG 차이

Fine-tuning과 RAG는 목적이 다르다.

구분 목적
Prompt Engineering 요청을 명확하게 작성해 답변 품질 개선
RAG 외부 문서나 DB를 검색해서 답변 근거로 사용
Fine-tuning 말투, 형식, 판단 패턴을 모델에 학습
Tools 계산, 검색, 저장, API 호출 같은 실제 행동 수행

지식 주입이 목적이라면 보통 RAG가 더 적합하다.
예를 들어 회사 정책, 매뉴얼, 상품 정보처럼 자주 바뀌는 데이터는 모델에 학습시키기보다 검색해서 참고하게 만드는 편이 관리하기 쉽다.

반면 Fine-tuning은 “항상 이런 말투로 답해라”, “이런 입력은 이런 카테고리로 분류해라”처럼 일관된 응답 패턴을 만들 때 더 적합하다.


5. LangChain과 PromptTemplate

LangChain은 LLM 작업을 조립하기 쉽게 도와주는 프레임워크다.
프롬프트, 모델, 출력 파서를 하나의 흐름으로 연결할 수 있다.

PromptTemplate은 반복되는 프롬프트 구조에 변수를 넣어 재사용하게 해준다.

template = PromptTemplate.from_template(
    """
    너는 AI 기초 강사다.
    {audience}에게 {topic}을 쉽게 설명해라.
    """
)

여기서 {audience}, {topic} 같은 부분이 변수다.

Python의 f-string과 비슷하게 값을 끼워 넣는다고 보면 된다.

name = "Python"
text = f"{name}을 배운다"

f-string은 문자열 안에 변수값을 바로 넣을 수 있는 Python 문법이다.


6. LCEL 파이프라인

LangChain에서는 | 연산자로 작업 흐름을 연결할 수 있다.
이것을 LCEL이라고 한다.

chain = template | model | StrOutputParser()

흐름은 다음과 같다.

입력값
-> PromptTemplate으로 프롬프트 생성
-> ChatOpenAI 모델 호출
-> Parser로 출력 형식 정리
-> 최종 결과 반환

즉, 직접 매번 prompt 만들고 -> API 호출하고 -> 응답 파싱하는 코드를 길게 쓰지 않고, 하나의 파이프라인으로 묶는 방식이다.

JSON 결과가 필요할 때는 JsonOutputParser와 Pydantic 모델을 함께 사용했다.

class Quiz(BaseModel):
    question: str
    choices: list[str]
    answer: str
    explanation: str

이렇게 하면 AI 응답을 그냥 문자열이 아니라 프로그램에서 바로 다룰 수 있는 dict 형태로 받을 수 있다.


7. Streamlit 챗봇 흐름

Streamlit은 Python으로 간단한 웹 화면을 만들 수 있는 도구다.
이번 예제에서는 AI 상담 챗봇 화면을 만들었다.

동작 흐름은 다음과 같다.

.env에서 OPENAI_API_KEY 로드
-> Streamlit 화면 제목 표시
-> session_state에 대화 기록 저장
-> 사용자 입력 받기
-> user 메시지를 기록에 추가
-> OpenAI API 호출
-> assistant 답변을 기록에 추가
-> 화면에 대화 출력

핵심은 st.session_state.messages다.

if "messages" not in st.session_state:
    st.session_state.messages = [
        {"role": "system", "content": "너는 사용자를 도와주는 상담사야."}
    ]

Streamlit은 화면이 다시 실행되는 구조라서, 대화 기록을 일반 변수에만 두면 사라질 수 있다.
그래서 session_state에 저장해 이전 대화 내용을 유지한다.


8. 핵심 정리

  1. GPT 요청은 system, user, assistant 역할을 기준으로 대화 맥락을 구성한다.
  2. Function Calling에서 모델은 함수를 직접 실행하지 않고, 호출할 함수와 인자를 선택한다.
  3. 실제 함수 실행은 Python 서버 코드가 담당한다.
  4. Fine-tuning은 지식 주입보다 말투, 형식, 판단 패턴 학습에 더 적합하다.
  5. 자주 바뀌는 회사 문서나 정책 지식은 Fine-tuning보다 RAG가 관리하기 쉽다.
  6. LangChain은 프롬프트, 모델, 파서를 파이프라인처럼 연결하게 해준다.
  7. template | model | parser 구조는 입력부터 출력 형식까지의 흐름을 명확하게 만든다.
  8. Streamlit은 Python 코드만으로 간단한 AI 웹 UI를 만들 수 있고, 대화 기록은 session_state로 유지한다.