본문 바로가기
AI

Zero-shot/Few-shot, Pydantic

by 발빠진 쥐 2026. 7. 10.

Agentic AI 공부를 시작한지 2주정도 됐는데요

모르는게 너무 많아서 힘드네요... 그래도 뭔가 시야가 점점 넓어져서 좋습니다 

 

Zero-shot / Few-shot, 근데 이거 "Learning"이 맞나?

먼저 Zero-shot learning은 기존 모델이 추가 학습 없이 정보를 분류하는 것, Few-shot learning은 예시가 몇 개 있는 프롬프트를 주는 것이라고 배웠습니다.

근데 배우다가 "엥? Learning이랑 Prompt가 뭔 차이지?"라는 의문이 들었습니다. 둘 다 "AI한테 뭔가 알려준다"는 느낌인데 왜 부르는 이름이 다른가 싶었거든요.

정리해보니:

  • Learning(학습) = 모델 파라미터(가중치) 자체를 바꾸는 것
  • Prompt(프롬프트) = 모델은 그대로 두고, 입력으로 주는 텍스트만 바꾸는 것

즉 Zero-shot이든 Few-shot이든, 모델 가중치는 전혀 안 건드리고 그냥 "입력 문장에 예시를 몇 개 끼워 넣느냐"의 차이일 뿐입니다. 그래서 엄밀히 말하면 "Zero-shot/Few-shot Learning"보다 "Zero-shot/Few-shot Prompt(prompting)"이라는 표현이 더 정확한 것 같습니다. "Learning"이라는 단어 때문에 진짜 모델을 재학습시키는 건 줄 알았는데, 실제로는 프롬프트만 바뀌는 거였습니다.

 

아래서 좀 더 자세히 다루겠습니다.

1) Zero-shot Learning (전통적 머신러닝 의미)

모델이 학습 때 한 번도 본 적 없는 새로운 클래스/작업을, 추론 시점에 (예시 하나 없이) 맞혀내게 하는 학습 방식/모델 설계를 말합니다. 예를 들면, "말"과 "얼룩말"의 속성(다리 개수, 줄무늬 있음 등)을 학습해둔 모델이, 학습 데이터엔 없던 "얼룩말 사진"을 보고도 "다리가 4개고 줄무늬가 있으니 얼룩말이겠다"고 속성 정보를 조합해 추론하는 것. 여기서 중요한 건 모델을 이렇게 추론할 수 있도록 설계/학습시키는 연구 분야라는 점입니다.

2) Few-shot Learning (전통적 머신러닝 의미)

새로운 클래스/작업에 대해 아주 적은 수(1~5개)의 labeled 예시만 가지고 모델이 그 작업을 학습하게 하는 방식. 메타러닝(learning to learn), 프로토타입 네트워크 같은 기법들이 여기 속해. 이것도 "모델을 어떻게 설계/학습시킬 것인가"에 대한 연구 방법론 입니다.

3) Zero-shot Prompting (LLM 시대 실제 사용 의미)

이미 학습이 끝난 LLM한테, 예시 없이 지시문만 던져서 바로 작업을 시키는 것. 예:

"다음 문장의 감정을 긍정/부정으로 분류해줘: '오늘 진짜 좋은 하루였다'"

모델 파라미터는 하나도 안 바뀌고, 그냥 이 프롬프트 하나만 던진 거야. 우리 프로젝트의 week01_prompt_parts(), week02_prompt_parts()도 지금 다 이 방식이야 — 예시 문장 하나 없이 "이런 규칙으로 판단해"라는 지시문만 있잖아.

4) Few-shot Prompting (LLM 시대 실제 사용 의미)

지시문에 더해서 입력-출력 예시(demonstration) 몇 개를 프롬프트 안에 같이 끼워 넣는 것. 예:

"다음 문장의 감정을 분류해줘.예시1: '완전 별로였다' → 부정예시2: '최고의 하루였다' → 긍정이제 분류해줘: '오늘 진짜 좋은 하루였다'"

이렇게 예시를 보여주면 모델이 "아, 이런 패턴으로 답하면 되는구나"를 프롬프트 안에서만 파악해. 이것도 파라미터는 안 바뀌어.

 

 

정리

실제로 모델 파라미터가 바뀌나? 언제 쓰는 용어

Zero-shot Learning 학습 방식에 따라 다름 (보통 사전 학습된 표현/속성을 활용) 전통 ML/DL 논문
Few-shot Learning 소량의 예시로 실제로 학습(메타러닝 등)하는 경우도 있음 전통 ML/DL 논문
Zero-shot Prompting ❌ 안 바뀜, 그냥 지시문만 LLM 실무/실제 우리 코드
Few-shot Prompting ❌ 안 바뀜, 지시문+예시만 LLM 실무 (GPT-3 논문 때문에 "few-shot learning"이라고도 흔히 불림)

 

결론: 지금 제가 하고 있는 카나나 클론코딩 프로젝트에서 다루는 건 사실상 다 Zero-shot/Few-shot Prompting(파라미터 안 바꾸고 입력만 바꾸는 것) 인듯 합니다.

 

 

 


Pydantic - 데이터의 틀을 정의하는 라이브러리

Pydantic은 파이썬에서 "데이터가 이런 모양이어야 한다"는 틀(스키마)을 정의하고, 실제 데이터가 그 틀에 맞는지 자동으로 검사해주는 라이브러리입니다. class로 정의하지만 함수 없이 데이터의 모양만 정의한다는 점이 특징입니다 → 이게 Pydantic 모델입니다.

코드로 보면 이런 식입니다:

class ExtractionResult(BaseModel):
    kind: Literal["schedule", "todo", "unknown"]
    schedule: ScheduleCreate | None = None
    todo: TodoCreate | None = None
    question: str | None = None

여기서 중요한 패턴이 하나 있습니다. kind라는 라벨 필드로 먼저 종류를 나누고, 그 종류에 해당하는 필드만 채우는 방식 — 이걸 discriminated union pattern이라고 부릅니다. 과제에서는 schedule, todo, unknown, reminder(알림) 이렇게 4개 타입이 있었고, 이번 주 핵심은 딱 하나였습니다:

"kind로 분기하고, kind에 맞는 서브 모델만 채운다"는 패턴을 Pydantic으로 구현하는 것.

 

전체 흐름을 정리하면:

BaseModel로 타입 선언 (Pydantic)
      ↓
JSON Schema로 자동 변환
      ↓
LLM & LangChain이 그 스키마 보고 파싱

BaseModel 타입 선언 자체는 키 누락을 막아주는 장점이 있지만, 대신 프롬프트를 잘 써야 하고 오류도 꽤 발생하는 편이라 신경 쓸 게 좀 많다는 걸 체감했습니다.

근데 이게 자연어 파싱 문제랑 무슨 상관이야?

여기서 막혔던 부분이 하나 있습니다. "kind로 구분하는 방식은 이해가 감 ㅇㅇ. 근데 이게 LLM이 기본적으로 자연어를 출력하는(그래서 다시 파싱해야 하는) 문제랑 무슨 상관이지? 그리고 Pydantic에 왜 AI 프롬프트가 중요한 거지?"

풀어보니:

  • response_format이 "애초에 자유 문장을 못 만들게 막고 JSON만 뱉게 강제하는 것" 자체가 파싱 문제의 해결책이었습니다.
  • kind 필드는 그 JSON 안에서 "이건 일정이야, 이건 할 일이야"라고 분류해두는 정리함 라벨 역할입니다.
  • Field(description=...)에 쓴 한국어 설명은 그냥 주석이 아니라, 그대로 LLM한테 "이 필드는 이런 의미다"라고 알려주는 프롬프트 역할을 합니다. 그래서 description을 대충 쓰면 안 되는 거였습니다.

예를 들어 Literal["low", "medium", "high"]만 있으면 LLM은 "이 셋 중 하나를 골라야 하는구나"까지는 알지만, 뭘 기준으로 low/medium/high를 나눠야 하는지는 모릅니다. description이 바로 그 판단 기준을 알려주는 것이었습니다.

1개 스케줄 vs 10개 스케줄, 난이도 차이가 큼

구조화 과제를 해보면서 느낀 건데, 스케줄 1개를 구조화하는 것과 10개를 한 번에 구조화하는 것은 난이도 차이가 꽤 컸습니다. 왜 이렇게 차이가 크게 느껴지는지는 아직 명확히 설명은 못 하겠고, 다음에 더 파봐야 할 부분으로 남겨둡니다.