로컬 LLM에 '안녕하세요'를 넣었더니 'coding!'이 돌아온 이유
요약
로컬 LLM을 분석하는 도구를 개발하며, 채팅 템플릿(chat template)의 중요성을 발견했습니다. 입력 방식만 변경했을 뿐인데도, 템플릿 사용 여부에 따라 모델의 응답 품질과 종료 메커니즘이 완전히 달라지는 것을 확인했습니다.
핵심 포인트
- 채팅 템플릿은 LLM에게 사용자/어시스턴트 역할을 구분하는 필수 형식입니다.
- 템플릿을 사용하지 않으면, 모델이 문장을 끝내지 못하고 무한 반복하거나 이상한 출력을 할 수 있습니다.
- 모델별 채팅 템플릿 형식(Llama, Gemma 등)은 `tokenizer_config.json`에서 확인할 수 있습니다.
서론
로컬 LLM의 내부를 "해부"하는 데스크톱 앱인 'AI Dissection Editor'를 개인적으로 만들고 있습니다. 추론 엔진을 transformers를 사용하지 않고 PyTorch로 직접 구현했는데, 작동하게 되어 처음 "안녕하세요"를 입력했을 때 돌아온 것이 이것이었습니다.
coding! 안녕하세요, 안녕하신가요? 안녕하세요, 안녕하신가요? 안녕하세요, 안녕하신가요? …
인사를 받고 싶었는데, "coding!"으로 시작하며 같은 문장을 끊임없이 반복합니다. 모델이 고장난 건지 생각했지만, 원인은 채팅 템플릿(chat template)을 사용하지 않았기 때문이었습니다.
동일한 모델로, 입력 방식만 변경하기
모델은 Qwen2.5-0.5B-Instruct(24층)입니다. 생성 설정은 같고, 입력 전달 방식만 바꿨습니다.
| 입력 토큰 수 | 생성 결과 |
|---|---|
| 템플릿 없음 | 1 |
| 템플릿 있음 | 30 |

템플릿이 있는 경우, 제대로 답변을 하고 게다가 스스로 대화를 끝내고 있습니다.
채팅 템플릿이란?
LLM은 본래 "문장의 다음 내용을 예측하는" 것입니다. 채팅용(Instruct) 모델은 그 위에 "여기부터 여기까지가 사용자 발언이고, 여기부터가 어시스턴트의 답변"이라는 정해진 형식으로 학습되었습니다. 이 형식이 바로 채팅 템플릿입니다.
Qwen2.5의 경우, "안녕하세요"는 실제로는 다음과 같은 형태로 모델에 들어갑니다.
<|im_start|>system
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>
<|im_start|>user
...
1 토큰이었던 입력이 30 토큰이 된 것은 이 형식 분량 때문입니다. 마지막 <|im_start|>assistant로 모델에게 "여기부터 답변을 쓸 차례다"라고 전달됩니다. 답변 작성을 마치면, 모델은 <|im_end|>를 출력합니다. 템플릿이 있는 경우 16 토큰에서 멈춘 것은 이것을 보고 생성을 종료했기 때문입니다.
템플릿이 없는 경우, 모델에게 "안녕하세요"는 답변해야 할 발언이 아니라, 쓰다가 만 문장입니다. 그래서 다음 내용을 계속 씁니다. "coding!"이 나온 것은 학습 데이터 속에서 "안녕하세요" 뒤에 자주 이어지던 무언가였을 것입니다(왜 coding인지는 솔직히 모르겠습니다). 그리고 "끝의 신호"를 내는 장면도 아니기 때문에, 정해진 토큰 수를 다 쓸 때까지 계속 쓰고, 같은 문장의 반복에 빠졌습니다.
템플릿 내용은 모델이 가지고 있다
채팅 템플릿은 모델마다 다릅니다(Llama, Gemma, Mistral... 등 각각 형식이 다릅니다). Hugging Face 형식의 모델이라면, tokenizer_config.json의 chat_template에 Jinja2 템플릿으로 들어 있습니다.
transformers를 사용하고 있다면 apply_chat_template()이 자동으로 처리해 주는 부분이지만, 직접 구현하는 경우에는 이것도 스스로 작성해야 했습니다. 이 앱에서는 다음 순서로 처리를 합니다:
chat_template가 있으면 Jinja2로 그대로 렌더링한다 - Jinja2를 사용할 수 없으면 ChatML(Qwen)・Llama 3・Gemma・Mistral의 내장 형식으로 대신 조립한다- 템플릿이 없는 모델(Instruct가 아닌 베이스 모델)이라면, 그렇게 알리는 에러를 발생시킨다
실험에도 영향을 준다
템플릿의 유무는 답변의 자연스러움뿐만 아니라, 모델 내부를 탐색하는 실험 결과에도 영향을 미칩니다.
아첨(Sycophancy) 실험을 평가할 수 없었음: '매일 밤샘하면 성적이 오르죠?'라는 질문에 아첨하기 어렵게 하는 방향의 벡터를 추가하는 실험을 했을 때, 템플릿이 없으면 모델이 답변하지 않고 계속 글을 쓰기 때문에 '아첨했는지 여부'를 판단할 수 없었습니다. 하지만 템플릿을 넣은 후에는 '그건 틀렸어요. 성적이 오르리라는 법은 없어요'라고 답변하게 되었고, 비교가 가능해졌습니다.
거절(Refusal)은 템플릿이 없을 때는 나오지 않음: 위험한 요청을 거절하는 행동은 '어시스턴트로서 답변할 때' 나타나는 것이기 때문에, 템플릿이 있어야 관찰할 수 있습니다.
같은 조향이라도 효과가 달라짐: 13번째 레이어에 '고마워 - 최악이야' 방향을 추가하는 실험에서는, 템플릿이 없을 때는 scale=1로 말투가 바뀌었지만, 템플릿이 있는 경우에는 scale=1로는 아무것도 변하지 않았고, scale=4에서야 겨우 'Oh? I agree! …'와 같은 경쾌한 답변으로 바뀌었습니다.
'모델의 행동을 조사하고 싶다'인지 '계속 쓰는 능력을 조사하고 싶다'인지에 따라 템플릿 사용 여부를 의식적으로 선택할 필요가 있습니다.
결론
모델이 고장 난 것처럼 보인다면, 가장 먼저 '챗 템플릿을 사용했는지'를 의심하는 것이 이번 교훈입니다.
이 앱에서는 화면 상단의 '챗 템플릿 적용'에서 실행 및 관찰의 모든 기능에 대해 템플릿의 온/오프를 전환할 수 있습니다. 동일한 입력으로 양쪽을 모두 시도해 비교해보면, 모델이 '계속 쓰는 것'과 '답변하는 것'의 차이를 잘 알 수 있습니다.
아직 개인 개발 초기 버전이며, 동작 확인은 Qwen2.5-0.5B만 가능합니다(화면은 일본어/영어에 대응하고 있습니다). 사용해 보신 감상을 Issue나 댓글로 남겨주시면 감사하겠습니다.
토론

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn ML의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기