프롬프트에 예시를 넣으면 LLM은 뭘 배울까요?

배달 앱에 이런 리뷰가 올라왔습니다. LLM에게 이 리뷰를 긍정·부정·섞임 가운데 하나로 나눠 달라고 시켜 보겠습니다. LLM에게 보내는 글을 프롬프트라고 합니다.

맛은 최고인데 배달이 한 시간 걸렸어요

그림에서 프롬프트에 넣는 예시를 0개, 1개, 3개로 바꿔 보세요. 모델은 하나도 바뀌지 않는데 답의 모양이 달라집니다.

예시
developer리뷰를 긍정, 부정, 섞임 중 하나로 분류해.
예시 1 user포장이 꼼꼼하고 아직 따뜻했어요 assistant긍정
예시 2 user국물이 다 새서 왔어요 assistant부정
예시 3 user양은 많은데 너무 짜요 assistant섞임
user맛은 최고인데 배달이 한 시간 걸렸어요
답이 리뷰는 음식 맛은 칭찬하지만 배달 시간에는 불만이 있어, 긍정과 부정이 섞인 의견으로 볼 수 있습니다.

답의 첫 토큰 후보와 그 확률

“이 리뷰는…”52%
섞임24%
긍정14%
부정6%
보낸 토큰 약 38개 🔒 바뀐 모델 가중치 0개

답과 확률은 설명을 위해 만든 예시 값입니다. 예시가 하나면 형식을 반쯤만 따라 하고 셋이면 한 단어로 몰립니다. 가중치는 모델이 학습하며 정해 둔 수많은 숫자인데, 예시를 넣어도 하나도 바뀌지 않습니다.

Ⅰ API로 부르고 돌아온 응답 펼쳐 보기 프롬프트가 모델 안에서 어떤 모양이 되는지부터 봅니다

LLM은 받은 글 뒤를 이어 씁니다

LLM(Large Language Model)은 아주 많은 글을 읽으면서 다음에 올 말을 맞히도록 학습한 프로그램입니다. 글은 토큰 단위로 읽고 씁니다. 토큰은 단어보다 조금 작은 글 조각입니다.

반 친구들이 한 문장씩 이어 쓰는 릴레이 소설을 떠올리면 비슷합니다. 내 차례가 오면 앞 내용을 다 읽고 그 흐름에 맞는 다음 문장을 씁니다. 다만 LLM은 문장 대신 토큰을 하나씩 고릅니다. 앞에 놓인 글 말고는 아무것도 기억하지 않는다는 점도 다릅니다.

  1. 코드에서는 메시지 목록을 보냅니다. 메시지마다 누가 한 말인지 적는 role이 붙어 있습니다.
  2. 모델 쪽에서는 이 목록이 글 한 줄로 이어 붙습니다. 메시지 사이에 역할 표시가 끼어 있을 뿐, 칸이 나뉜 입력이 아닙니다.
  3. 맨 끝에는 assistant 표시가 열린 채로 놓입니다. 모델은 앞의 글 전체를 읽고 다음 토큰 후보마다 확률을 매깁니다. 이 계산을 정하는 건 모델이 학습으로 정해 둔 수십억 개의 숫자, 가중치입니다.
  4. 확률이 높은 쪽에서 토큰을 하나 고르고 그 토큰을 붙인 글로 다시 계산합니다. 끝 표시를 고르면 멈춥니다. 가중치는 그대로라도 앞의 글이 바뀌면 계산 결과인 확률이 바뀝니다.
developer리뷰를 긍정, 부정, 섞임 중 하나로 분류해. user맛은 최고인데 배달이 한 시간 걸렸어요 messages = [ {…developer…}, {…user…} ]
developer리뷰를 긍정, 부정, 섞임 중 하나로 분류해. 끝 user맛은 최고인데 배달이 한 시간 걸렸어요 끝 assistant이 리뷰는 맛은… 끝

역할 표시는 설명을 위해 단순하게 그렸습니다. 실제 표시는 모델마다 다르고 공개하지 않는 곳도 많습니다.

역할도, 예시도, 지난 대화도 모두 이 한 줄 글의 앞부분입니다. 프롬프트를 바꾸면 모델이 이어 쓸 글이 바뀌고 다음에 올 말의 확률도 따라 바뀝니다.

응답은 문장 하나가 아니라 겹겹이 싼 상자입니다

프로그램이 LLM을 쓸 때는 API로 부릅니다. API는 다른 프로그램에 일을 시키는 정해진 주문 양식입니다. 답은 JSON이라는 형식으로 돌아오는데, 이름표가 붙은 칸 안에 또 칸이 들어 있는 구조입니다.

택배 상자를 생각하면 쉽습니다. 겉에는 송장(번호·보낸 곳·시각)이 붙어 있고 안에는 물건과 영수증이 같이 들어 있습니다. 응답도 겉에 id·model이, 안에 답이 든 choices가, 옆에 사용량 영수증 usage가 있습니다.

상자를 눌러 보세요. 그 칸까지 들어가는 Python 경로가 아래에 나옵니다. 다만 택배와 달리 내용물은 모델이 방금 만들었습니다. 같은 요청을 다시 보내도 다른 답이 들어 있을 수 있습니다.

responseSDK가 ChatCompletion이라고 이름 붙인 상자 전체
idchatcmpl-AbC123
modelgpt-5.5
created1760400000
choices[0]답 후보 목록의 첫 번째
message
roleassistant
content이 리뷰는 맛에 대해서는 긍정적이지만…
finish_reason"stop"
usage토큰 영수증
prompt_tokens38 보낸 쪽
completion_tokens118 만든 쪽
그중 reasoning_tokens64 생각에 씀
total_tokens156 = 38 + 118
response.choices[0].message.content

모델이 쓴 답 글자입니다. 대부분의 프로그램은 이 한 칸만 꺼내 씁니다.

값은 아래 코드를 돌렸을 때 나오는 모양의 예시입니다. 실제 응답에는 칸이 더 있는데 여기서는 자주 보는 칸만 남겼습니다.

first_call.pypython
import os
from openai import OpenAI

# 1 API 키는 코드 밖 환경 변수에서
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
TASK = "리뷰를 긍정, 부정, 섞임 중 하나로 분류해."
REVIEW = "맛은 최고인데 배달이 한 시간 걸렸어요"

response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[
        # 2 개발자의 지시
        {"role": "developer", "content": TASK},
        # 3 분류할 리뷰
        {"role": "user", "content": REVIEW},
    ],
)

# 4 응답 상자 전체를 펼쳐 보기
print(response.model_dump_json(indent=2, exclude_none=True))
# 5 답 글자만 꺼내기
print(response.choices[0].message.content)
터미널
$ python first_call.py { "id": "chatcmpl-AbC123", "choices": [ { "finish_reason": "stop", "index": 0, "message": { "content": "이 리뷰는 맛에 대해서는 긍정적이지만 배달 시간에 대해서는 부정적인 의견을 담고 있어 전체적으로는 섞인 감정입니다.", "role": "assistant", "annotations": [] } } ], "created": 1760400000, "model": "gpt-5.5", "object": "chat.completion", "service_tier": "default", "usage": { "completion_tokens": 118, "prompt_tokens": 38, "total_tokens": 156, "completion_tokens_details": { "reasoning_tokens": 64, … }, "prompt_tokens_details": { "cached_tokens": 0, … } } } 이 리뷰는 맛에 대해서는 긍정적이지만 배달 시간에 대해서는 부정적인 의견을 담고 있어 전체적으로는 섞인 감정입니다.

출력은 예시 답입니다. 같은 코드라도 답 문장과 토큰 수는 그때그때 달라집니다. 값이 0인 칸 일부는 …로 줄였습니다.

  1. API 키는 내 계정으로 부른다는 걸 증명하는 비밀번호입니다. 코드에 바로 적으면 저장소에 올릴 때 새어 나가니, 운영체제에 저장해 두는 설정값인 환경 변수에서 읽습니다.
  2. developer 메시지는 이 프로그램을 만든 개발자가 모델에게 주는 지시입니다. 예전 코드에서는 같은 자리에 system을 썼습니다. 왜 이름이 바뀌었는지는 Ⅱ장에서 봅니다.
  3. user 메시지는 사용자가 보낸 말입니다. 이 프로그램에서는 분류할 리뷰 한 줄이 들어갑니다.
  4. model_dump_json은 SDK가 만든 응답 객체를 JSON 글자로 펼쳐 줍니다. exclude_none=True는 비어 있는 칸을 빼서 짧게 보여 줍니다. 처음 API를 배울 때 한 번은 꼭 펼쳐 보는 게 좋습니다.
  5. 답 글자만 꺼내는 경로입니다. choices가 목록이라 [0]으로 첫 번째를 고릅니다. Python 목록은 0번부터 셉니다.

여기서 쓴 SDK는 OpenAI가 만든 openai 패키지(3.31)입니다. 주문 양식을 코드로 채우기 쉽게 만든 도구 모음입니다. usage의 completion_tokens 118개 가운데 64개가 reasoning_tokens인 점이 눈에 띕니다. 이 숫자가 다음 실험의 주인공입니다.

finish_reason이 length면 답이 잘린 것입니다

finish_reason은 모델이 왜 쓰기를 멈췄는지 알려 주는 칸입니다. "stop"이면 스스로 끝 표시를 골라 다 쓴 경우입니다. "length"면 정해 둔 토큰 상한에 걸려 중간에 끊긴 것입니다.

요즘 모델은 대부분 추론 모델입니다. 답을 쓰기 전에 화면에 보이지 않는 생각을 먼저 토큰으로 써 내려가는 모델입니다. 그 생각 토큰도 상한에 함께 셉니다. 아래 슬라이더로 상한 max_completion_tokens를 줄여 보세요.

max_completion_tokens 160
생각 토큰 64/64개 (보이지 않음) 답 토큰 54/54개 옅은 칸 = 상한에 걸려 못 쓴 토큰 한 칸 = 토큰 2개
finish_reason: "stop"
completion_tokens: 118
reasoning_tokens: 64
이 리뷰는 맛에 대해서는 긍정적이지만 배달 시간에 대해서는 부정적인 의견을 담고 있어 전체적으로는 섞인 감정입니다.

토큰 수는 위 터미널 출력의 예시 값(생각 64 + 답 54 = 118)을 따랐습니다. 실제로 생각에 쓰는 양은 질문과 모델에 따라 크게 달라집니다.

상한을 64 아래로 내리면 생각만 하다가 끊깁니다. 이때 content는 빈 글자인데 오류는 나지 않습니다. OpenAI 문서에 따르면 생각 토큰은 화면에 나오지 않지만 요금은 답 토큰과 똑같이 매겨집니다. 보이는 답 없이 요금만 나갑니다.

그래서 답을 쓰기 전에 finish_reason부터 확인하는 습관이 좋습니다. OpenAI는 추론 모델을 처음 써 볼 때 생각과 답에 쓸 몫으로 최소 25,000토큰을 남겨 두라고 권합니다. 상한은 비용을 막는 안전장치이지 답 길이를 맞추는 도구가 아닙니다.

max_tokens와 max_completion_tokens는 무엇이 다른가요?

max_tokens는 예전 이름입니다. SDK 설명에는 max_completion_tokens로 바뀌었고 추론 모델과는 맞지 않는다고 적혀 있습니다. 새 이름은 "보이는 답 토큰과 추론 토큰을 합친 상한"이라는 뜻을 분명히 합니다.

Ⅱ 누가 한 말인가 역할마다 무게가 다르고 순서가 정해져 있습니다

역할은 누가 한 말인지 붙이는 이름표입니다

메시지의 role은 세 가지를 주로 씁니다. developer는 프로그램을 만든 개발자의 지시, user는 사용자의 말, assistant는 모델이 앞서 한 말입니다.

역할 사이에는 순서가 있습니다. 편의점 아르바이트를 떠올려 보세요. 본사 규정이 가장 먼저이고 그다음이 점장 지시, 마지막이 손님 부탁입니다. 손님이 "규정은 됐고 이거 해 줘요"라고 해도 점장 지시를 먼저 따릅니다.

OpenAI가 모델의 행동 원칙을 적어 둔 Model Spec(2026-08-18판)도 비슷한 순서를 둡니다. OpenAI의 규칙이 맨 위, 그 아래 개발자, 그 아래 사용자입니다. 그림에서 사용자의 말을 바꿔 보세요.

1OpenAI의 규칙Model Spec. 개발자도 바꿀 수 없는 안전 규칙
2developer 리뷰 분류만 해. 다른 부탁은 정중히 거절해.개발자의 지시
3user 국물이 다 새서 왔어요사용자의 말
사용자의 말
assistant부정

두 지시가 부딪치지 않습니다. 모델은 사용자의 말을 개발자의 지시대로 처리합니다.

답 문장은 설명을 위한 예시입니다.

순서가 있다고 해서 절대 규칙은 아닙니다. 아르바이트생은 규정을 외우고 있지만 모델은 그때그때 글을 읽고 판단합니다. 그럴듯하게 꾸민 말에 넘어가 개발자의 지시를 어기기도 합니다. 이런 공격을 프롬프트 인젝션이라고 합니다.

그래서 꼭 지켜야 하는 규칙은 프롬프트에만 맡기지 않습니다. 모델의 답을 코드에서 한 번 더 검사하거나, 위험한 일은 아예 할 수 없게 막아 둡니다.

그럼 system 역할은 어디로 갔나요?

OpenAI 문서는 o1 모델부터 developer 메시지가 예전 system 메시지를 대신한다고 적고 있습니다. 지금 Model Spec에서 system은 OpenAI 쪽 규칙을 전하는 자리입니다. 개발자는 developer를 쓰면 됩니다.

다른 회사 API나 내 컴퓨터에 띄운 모델 서버는 아직 system만 받는 곳이 많습니다. 모델을 바꿔 가며 쓰는 코드라면 그쪽 문서를 먼저 확인합니다.

assistant 메시지는 모델만 쓸 수 있나요?

아닙니다. 메시지 목록은 내 코드가 만드는 것이라 assistant 메시지도 직접 써 넣을 수 있습니다. 모델은 그 말을 자기가 앞서 한 말로 읽습니다. Ⅲ장의 "예시를 대화처럼 넣는 방법"이 이 성질을 씁니다.

Ⅲ 설명 대신 예시로 보여 주기 제로샷·원샷·퓨샷, 그리고 예시가 실제로 가르치는 것

제로샷·원샷·퓨샷은 예시 개수에 붙인 이름입니다

예시 개수
100%857055 찍어서 맞힐 확률 50% 프롬프트에 넣은 예시 개수
큰 모델 · GPT-3 175B작은 모델 · GPT-3 2.7B

영화 리뷰가 긍정인지 부정인지 맞히는 SST-2라는 문제 묶음에서 GPT-3 두 크기의 정확도입니다(Zhao 외, 2021, 표 1). 175B는 가중치가 1,750억 개, 2.7B는 27억 개라는 뜻입니다. 예시 묶음을 여러 번 바꿔 가며 잰 평균값입니다.

여기서 샷은 예시 한 개를 말합니다. 예시 없이 지시만 주면 제로샷, 하나 주면 원샷, 여러 개 주면 퓨샷입니다. 2020년 GPT-3 논문이 이 이름을 널리 퍼뜨렸습니다.

시험지 맨 위의 "보기" 문제와 비슷합니다. 풀이 하나를 보여 주면 나머지 문제를 같은 형식으로 풉니다. 다만 학생은 보기에서 배운 걸 다음 시험까지 기억하지만 모델은 이번 요청이 끝나면 예시를 잊습니다.

모델 안의 숫자인 가중치는 하나도 바뀌지 않습니다. 논문도 세 방식 모두 가중치를 고치지 않는다고 적었습니다. 프롬프트 안에서만 일어나는 이 배움을 in-context learning이라고 부릅니다. 모델에게 주어진 글, 곧 context 안에서 배운다는 뜻입니다.

그래프를 보면 예시가 늘 도움이 되지도 않습니다. 큰 모델은 예시 하나에 71.6%에서 93.3%로 뛰었습니다. 작은 모델은 8개를 주자 54.0%로, 찍어서 맞히는 수준까지 내려갔습니다.

예시가 알려 주는 건 정답보다 형식입니다

예시의 정답을 일부러 틀리게 적으면 어떻게 될까요? "긍정" 리뷰에 "부정"이라고 적어 보여 주는 식입니다. 아래에서 먼저 예상을 골라 보세요.

예시를 이렇게 망가뜨리면 정확도가 얼마나 떨어지나 (정답을 맞게 적은 예시와 비교)

정답을 무작위로 바꿈리뷰·형식은 그대로0~5%p
리뷰를 엉뚱한 글로 바꿈뉴스 같은 다른 분야 문장3~16%p
답 자리에 무작위 단어긍정·부정 대신 아무 영어 단어5~16%p
0%p816%p

"리뷰 → 답" 형식 자체를 없애면(리뷰만, 또는 답만 나열) 예시를 아예 안 준 것과 비슷하거나 더 나빠졌습니다.

%p(퍼센트포인트)는 정확도가 몇 칸 내려갔는지입니다. 80%가 75%가 되면 5%p입니다. 막대의 옅은 부분부터 진한 끝까지가 연구에서 나온 하락 폭의 범위입니다. Min 외(2022)가 모델 12개, 데이터 묶음 26개에서 예시 16개로 쟀습니다. 정답을 무작위로 바꿨을 때 분류 문제의 평균 하락은 2.6%p였습니다.

정답을 엉터리로 바꿔도 거의 그대로였습니다. 반대로 리뷰 자리에 엉뚱한 글을 넣거나 답 자리에 아무 단어나 넣으면 크게 떨어졌습니다. 예시는 "어떤 글이 들어오고 답은 어떤 단어 중 하나로, 어떤 모양으로 쓰는가"를 보여 주는 역할이 큽니다.

히어로에서 예시를 넣자 긴 문장 대신 "섞임" 한 단어가 나온 것도 같은 이유입니다. 그렇다고 정답이 아무래도 좋다는 뜻은 아닙니다. 같은 연구에서도 어떤 모델·데이터에서는 14%p 가까이 떨어졌습니다. 예시의 정답은 맞게 적는 게 기본입니다.

예시 순서만 바꿔도 답이 쏠립니다

Zhao 외(2021)는 같은 예시 4개를 순서만 바꿔 넣었습니다. 작은 GPT-3(2.7B)의 정확도가 54.3%에서 93.4%까지 오갔습니다. 찍는 수준과 거의 최고 수준이 순서 하나로 갈렸습니다.

원인으로 꼽은 쏠림은 세 가지입니다. 모델은 예시에 많이 나온 답 쪽으로 기웁니다. 맨 끝에 가까운 예시의 답도 따라갑니다. 평소에 흔히 보던 단어를 더 고르기도 합니다.

그림에서 순서를 바꿔 보세요. 새 리뷰는 그대로인데 답이 기우는 쪽이 달라집니다. 이렇게 한쪽으로 쏠린 만큼 틀리는 리뷰가 늘어 정확도가 크게 흔들렸습니다. 실제로는 답이 골고루 섞이게 예시를 고르고 순서를 몇 가지로 바꿔 시험해 봅니다.

예시 순서
↓ 새 리뷰 “배달은 빨랐는데 맛은 그냥 그래요”를 긍정이라고 답할 확률
긍정 42%
부정 58%

긍정·부정 예시를 2개씩 같은 수로 넣고 순서만 바꿨습니다. 막대는 세 쏠림 가운데 "끝에 가까운 예시를 따라가는 쏠림" 하나만 단순하게 그린 예시 값입니다. 실제 크기는 모델과 문제에 따라 다릅니다.

예시를 넣는 두 가지 방법

첫 번째는 developer 메시지 안에 예시를 태그로 묶어 넣는 방법입니다. 태그는 <example>처럼 꺾쇠로 감싼 표시로, 어디부터 어디까지가 예시인지 알려 줍니다. OpenAI와 Anthropic 문서가 모두 이 방법을 권합니다.

두 번째는 예시를 지난 대화처럼 넣는 방법입니다. user 메시지에 예시 리뷰를, assistant 메시지에 정답을 직접 써 넣습니다. 모델은 자기가 앞서 그렇게 답했다고 읽고 같은 모양으로 이어 갑니다.

A. 지시 안에 태그로

메시지 2개 developer리뷰를 긍정, 부정, 섞임 중 하나로 분류해.
<examples>
<example>리뷰: 포장이 꼼꼼하고… 답: 긍정</example>
<example>리뷰: 국물이 다 새서… 답: 부정</example>
<example>리뷰: 양은 많은데… 답: 섞임</example>
</examples>
user맛은 최고인데 배달이 한 시간 걸렸어요

B. 지난 대화처럼

메시지 8개 developer리뷰를 긍정, 부정, 섞임 중 하나로 분류해. user포장이 꼼꼼하고 아직 따뜻했어요 assistant긍정 user국물이 다 새서 왔어요 assistant부정 user양은 많은데 너무 짜요 assistant섞임 user맛은 최고인데 배달이 한 시간 걸렸어요
developer분류해. <examples>…긍정…부정…섞임</examples> 끝 user맛은 최고인데… 끝 assistant▍
developer분류해. 끝 user포장이… 끝 assistant긍정 끝 user국물이… 끝 assistant부정 끝 user양은… 끝 assistant섞임 끝 user맛은 최고인데… 끝 assistant▍

↑ 모델이 읽는 한 줄 글로 바꾸면 둘 다 "예시 세 개 다음에 새 리뷰"라는 같은 흐름입니다

few_shot.pypython
# ... client, TASK, REVIEW 는 first_call.py 와 같다

# 1 예시 목록: (리뷰, 정답)
EXAMPLES = [
    ("포장이 꼼꼼하고 아직 따뜻했어요", "긍정"),
    ("국물이 다 새서 왔어요", "부정"),
    ("양은 많은데 너무 짜요", "섞임"),
]

# 2 방법 A: 지시 안에 예시를 태그로 묶어 넣기
def in_developer(review):
    shots = "\n".join(
        f"<example>\n리뷰: {r}\n답: {a}\n</example>"
        for r, a in EXAMPLES
    )
    content = f"{TASK}\n\n<examples>\n{shots}\n</examples>"
    return [
        {"role": "developer", "content": content},
        {"role": "user", "content": review},
    ]

# 3 방법 B: 예시를 지난 대화처럼 user·assistant 쌍으로
def as_turns(review):
    messages = [{"role": "developer", "content": TASK}]
    for r, a in EXAMPLES:
        messages.append({"role": "user", "content": r})
        messages.append({"role": "assistant", "content": a})
    messages.append({"role": "user", "content": review})
    return messages

for build in (in_developer, as_turns):
    messages = build(REVIEW)
    response = client.chat.completions.create(
        model="gpt-5.5", messages=messages
    )
    answer = response.choices[0].message.content
    # 4 함수 이름, 보낸 메시지 수, 답
    print(build.__name__, len(messages), answer)
터미널
$ python few_shot.py in_developer 2 섞임 as_turns 8 섞임

출력은 예시 답입니다. 제로샷 때 긴 문장이던 답이 두 방법 모두 한 단어로 바뀐 것만 보면 됩니다.

  1. 예시를 데이터로 따로 둡니다. 리뷰와 정답을 짝으로 적은 목록입니다. 프롬프트 문장과 섞어 쓰지 않으면 예시를 바꾸거나 늘리기 쉽습니다.
  2. 방법 A는 예시를 태그로 감싸 developer 메시지 하나에 넣습니다. 메시지는 2개뿐이고 지시와 예시가 한곳에 있어 읽기 쉽습니다.
  3. 방법 B는 예시마다 user·assistant 메시지 한 쌍을 만듭니다. 예시가 3개면 메시지가 8개가 됩니다. 모델이 자기 답의 모양을 그대로 따라 하기 좋습니다.
  4. 두 방법을 같은 리뷰로 돌려 메시지 수와 답을 나란히 찍습니다. 답 모양이 같으면 다루기 편한 쪽을 고르면 됩니다.

예시는 요청할 때마다 다시 보내야 합니다. API는 앞 요청을 기억하지 않기 때문입니다(AI Agent 시리즈 첫 글에서 그림으로 다뤘습니다). 진짜 대화를 이어 가는 멀티턴도 같은 원리라, 예시 뒤에 지난 대화를 차례로 붙여 보냅니다.

매번 보내는 예시는 돈이 계속 드나요?

입력 토큰으로 매번 셉니다. 다만 앞부분이 매번 똑같으면 OpenAI가 그 부분을 저장해 두고 다시 쓰는 프롬프트 캐싱이 적용될 수 있습니다. 응답의 usage.prompt_tokens_details.cached_tokens에 그 수가 찍힙니다. 그래서 바뀌지 않는 지시와 예시는 앞에, 바뀌는 리뷰는 뒤에 둡니다.

2026년 기준으로 달라진 것

OpenAI는 새 프로젝트에 Responses API를 권합니다. 이 글에서 쓴 Chat Completions는 SDK 설명에 "계속 지원한다"고 적혀 있어 그대로 써도 됩니다. 다른 회사 모델과 로컬 모델 서버도 대부분 Chat Completions 양식을 받습니다.

Responses API는 같은 일을 다른 칸 이름으로 합니다. developer 지시는 instructions에, 사용자 입력은 input에 넣고 답 글자는 output_text로 꺼냅니다.

Chat Completions

Responses API

messages · developer개발자 지시
instructions
messages · user사용자 입력
input
choices[0].message.content답 글자
output_text
usage.prompt_tokens
usage.input_tokens
usage.completion_tokens
usage.output_tokens
messages를 내 코드가 이어 붙임멀티턴
previous_response_id앞 응답 번호만 보내면 OpenAI 서버가 대화를 이어 줌
Responses API로 같은 호출을 쓰면
responses_call.pypython
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

response = client.responses.create(
    model="gpt-5.5",
    # 1 developer 메시지 자리
    instructions="리뷰를 긍정, 부정, 섞임 중 하나로 분류해.",
    # 2 사용자 입력
    input="맛은 최고인데 배달이 한 시간 걸렸어요",
)
# 3 글만 모아 꺼내기
print(response.output_text)
  1. instructions는 developer 메시지를 맨 앞에 끼워 넣는 칸입니다. 지시와 입력이 칸으로 나뉘어 코드가 짧아집니다.
  2. input에는 글 한 줄을 그대로 넣어도 되고 메시지 목록을 넣어도 됩니다. 퓨샷 방법 B는 목록으로 넣습니다.
  3. output_text는 응답 안의 글을 모아 주는 편의 기능입니다. 응답의 output 목록에는 생각 요약이나 도구 호출이 섞일 수 있어서 첫 칸이 늘 답이라고 가정하면 안 된다고 문서에 적혀 있습니다.

추론 모델에서는 퓨샷을 쓰는 순서도 바뀌었습니다. OpenAI 문서는 추론 모델이 예시 없이도 좋은 답을 내는 경우가 많으니 제로샷부터 써 보고 필요할 때 예시를 더하라고 권합니다. 예시를 넣을 때는 지시와 꼭 맞게 고르라고 덧붙입니다.

temperature처럼 답의 들쭉날쭉함을 정하는 옵션도 조건이 붙었습니다. 추론 모델은 생각의 양을 정하는 reasoning_effort가 none이 아니면 이 옵션을 빼야 한다고 OpenAI 문서는 적고 있습니다. 강의 자료에 temperature가 있다면 모델과 함께 확인해야 합니다.

예시는 모델을 가르치는 게 아니라 이어 쓸 글의 모양을 보여 줍니다

가중치는 그대로이고 다음 요청에는 남지 않습니다. 그래서 프롬프트를 고칠 때는 아래 순서로 점검합니다.

  1. developer 메시지에 할 일과 답의 모양(한 단어, 목록, JSON 등)을 적었는가
  2. 제로샷으로 먼저 돌려 보고 finish_reason과 usage까지 확인했는가
  3. 답의 모양이 흔들리면 예시를 1~5개 넣었는가. 형식이 같고 답이 골고루 섞이며 실제 입력과 닮은 예시인가
  4. 예시 순서를 바꿔도 결과가 버티는가
  5. 꼭 지켜야 하는 규칙을 프롬프트에만 맡기지 않고 코드로도 검사하는가

참고 자료

  1. Brown 외, Language Models are Few-Shot Learners (2020) — 제로샷·원샷·퓨샷 정의
  2. Min 외, Rethinking the Role of Demonstrations (2022) — 정답 라벨보다 형식이 중요하다는 실험
  3. Zhao 외, Calibrate Before Use (2021) — 예시 개수에 따른 정확도(표 1), 순서를 바꾼 실험(3장)
  4. OpenAI, Text generation — developer·user 메시지와 우선순위
  5. OpenAI Model Spec (2026-08-18) — 지시의 우선순위
  6. OpenAI, Reasoning models — 추론 토큰과 25,000토큰 권장
  7. OpenAI, Reasoning best practices — 제로샷부터 써 보라는 권장
  8. OpenAI, Prompt engineering — developer 메시지에 예시 넣기
  9. OpenAI, Migrate to the Responses API
  10. OpenAI, Using the latest model — temperature 제약
  11. Anthropic, Claude prompting best practices — 예시 3~5개, example 태그
  12. openai (PyPI) — 3.31.0, 2026-10-14