Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

22장. 시스템 프롬프트와 Chat Template

이 장의 목표 “분명히 한국어로 답하라고 했는데 영어가 나와요” “Cursor에선 되는데 Ollama에선 답이 이상해요”

이런 일의 90%는 Chat Template 문제입니다. 이걸 이해하고 넘어갑니다.


22.1 시스템 프롬프트 — 모델의 “성격 설정”

채팅에는 보통 세 종류의 역할이 있습니다.

system    — 모델의 성격·규칙
user      — 사용자 메시지
assistant — 모델의 답

시스템 프롬프트는 대화 전체에 영향을 주는 지시입니다.

OpenAI 형식 예:

{
  "messages": [
    {"role": "system", "content": "너는 한국어로만 답하는 시니어 엔지니어야."},
    {"role": "user",   "content": "Python에서 비동기란 뭐야?"}
  ]
}

시스템 프롬프트는:

  • 대화가 길어져도 효과 유지
  • 사용자 프롬프트보다 우선 적용
  • 모델 입장에선 “법“에 가까움

22.2 시스템 프롬프트로 가능한 것

  • 언어 강제: “모든 답변은 한국어”
  • 톤 설정: “정중한 존댓말로”
  • 역할 고정: “너는 비트북 회사의 사내 비서”
  • 거절 정책: “회사 보안 이슈가 의심되면 답변 거절”
  • 출력 형식: “항상 JSON으로 답해”

22.3 시스템 프롬프트 작성 팁

짧고 명확하게

❌ “너는 매우 친절하고 똑똑하며 정확하고 자세하고…” → 길어질수록 약발이 떨어집니다.

✅ “너는 비트북 회사의 한국어 사내 비서야. 정중한 존댓말로 답해.”

우선순위 명시

여러 규칙이면 번호를 매기세요.

규칙:
1. 모든 답은 한국어 존댓말.
2. 모르는 내용은 "모르겠습니다"로.
3. 회사 기밀 의심되면 답변 거절.

길이도 모델과 균형

간단한 8B 모델 → 시스템 프롬프트 짧게 (200자 이내)
큰 32B+ 모델   → 시스템 프롬프트 길어도 잘 따름

22.4 Chat Template — 모델이 진짜 보는 입력

여기가 중요한 부분입니다.

OpenAI 형식의 메시지는 모델이 직접 보지 않습니다.

각 모델마다 정해진 Chat Template 으로 한 덩어리 텍스트로 변환되어 들어갑니다.

예시. Qwen3의 Chat Template:

<|im_start|>system
너는 한국어로 답하는 비서야.<|im_end|>
<|im_start|>user
안녕<|im_end|>
<|im_start|>assistant

마지막 줄이 비어있는 이유?

모델이 이 위치부터 다음 토큰을 예측 하기 시작하기 때문입니다.

Llama 3의 Chat Template은 또 다릅니다:

<|begin_of_text|><|start_header_id|>system<|end_header_id|>
너는 한국어로 답하는 비서야.<|eot_id|><|start_header_id|>user<|end_header_id|>
안녕<|eot_id|><|start_header_id|>assistant<|end_header_id|>

같은 의미의 대화도 모델마다 완전히 다른 모양의 토큰 시퀀스가 됩니다.


22.5 Chat Template이 잘못 적용되면

증상이 무서울 정도로 다양합니다.

  • “AI assistant” 라며 자기 소개부터 시작
  • 답을 하다가 다음 사용자 차례를 자기가 채움
  • 시스템 프롬프트를 무시
  • 답변이 끝나지 않고 무한 반복
  • 한국어 / 영어가 섞임

원인은 거의 다 잘못된 chat template.

Qwen 모델에 Llama 템플릿 적용  →  답이 이상해짐
Base 모델에 Chat 템플릿 적용   →  답이 깨짐

22.6 어디서 적용되나?

좋은 소식: 대부분의 도구가 자동으로 처리 해줍니다.

도구자동 적용?
LM Studio✅ 모델의 tokenizer_config.json 자동
Ollama✅ Modelfile에 내장
mlx-lm✅ HF 토크나이저
llama.cpp (--chat-template)⚠ 모델에 따라 명시 필요

문제가 되는 건 보통:

  • llama.cpp 직접 호출
  • 옛 GGUF 파일 (tokenizer_config 누락)
  • 직접 OpenAI 호환 클라이언트를 짤 때 base 모델에 chat 형식으로 호출

22.7 모델 카드에서 Chat Template 찾기

Hugging Face 모델 페이지의 “Files and versions”tokenizer_config.json 을 열면 이런 게 보입니다.

{
  "chat_template": "{% if messages[0]['role'] == 'system' %}...",
  ...
}

이 안에 Jinja2 템플릿으로 모양이 정의되어 있습니다.

또는 README의 “Chat Format” 또는 “Usage” 섹션에 명시되어 있습니다.

직접 살 일은 별로 없지만, “내 코드가 이상해질 때” 한 번씩 들여다보세요.


22.8 직접 호출할 때 안전한 방법 (Python)

transformers 라이브러리는 모델별 chat template을 알아서 적용합니다.

from transformers import AutoTokenizer

tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B-Instruct")

messages = [
    {"role": "system", "content": "너는 한국어로 답해."},
    {"role": "user",   "content": "안녕"},
]

prompt = tok.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True,
)
print(prompt)

이 출력이 위 22.4 절의 그 모양입니다.

add_generation_prompt=True 가 중요: “이제 모델이 말할 차례” 표시를 끝에 붙여줍니다.


22.9 컨텍스트 캐싱

대화가 길어지면 prefill이 매번 느려집니다.

같은 시스템 프롬프트 + 같은 앞부분 대화 → 결과 같음.

그래서 도구들이 이전 KV Cache를 재활용 합니다.

도구컨텍스트 캐싱
Ollama자동 (같은 세션 내)
LM Studio자동
llama.cpp--prompt-cache 옵션
mlx-lm자동

시스템 프롬프트를 자주 바꾸지 않을수록 prefill 비용을 절약할 수 있습니다.


22.10 시스템 프롬프트 실전 모음

사내 비서 (38장과 연결)

당신은 비트북 회사의 사내 비서입니다.

규칙:
1. 모든 답은 한국어 존댓말.
2. 회사 내부 자료에 없는 내용은 "확인 필요"로 표시.
3. 사람·계정 정보는 절대 추측하지 않음.

코딩 어시스턴트 (37장과 연결)

You are a senior software engineer.
Respond in Korean for explanations,
but keep code, file paths, and shell commands in their original form.

Rules:
1. No unnecessary preamble.
2. When unsure, say so. Don't fabricate APIs.
3. Suggest tests when modifying logic.

JSON 출력기

모든 답은 다음 JSON으로만:
{
  "summary": "...",
  "tags": ["...", "..."],
  "confidence": 0.0-1.0
}

다른 텍스트 절대 금지. 코드블록도 금지.

이 장에서 기억할 한 가지

모델은 OpenAI 형식 메시지를 직접 안 본다.

Chat Template으로 모델별 모양의 텍스트로 변환된 뒤에야 본다.

답이 이상하면 가장 먼저 잘못된 template을 의심하세요.


손으로 해볼 것

1. 시스템 프롬프트 효과 체감

LM Studio에서 같은 8B 모델에 두 번 같은 질문.

A. 시스템 프롬프트 비움:

사용자: 안녕

B. 시스템 프롬프트:

너는 비트북 회사의 한국어 사내 비서야.
정중한 존댓말로만 답해.

같은 사용자 메시지로 답을 비교하세요.

2. apply_chat_template 출력 확인 (선택)

가상환경에서:

(.venv) $ pip install transformers

위 22.8 코드를 실행해서 모델이 진짜로 보는 텍스트가 어떻게 생겼는지 직접 확인.


다음 장에서는 Temperature, Top-p, Top-k — “창의성 슬라이더“의 정체를 봅니다.