LLM 모델 중 chat (instruct) 모델의 경우에는 /v1/completions를 통한 텍스트 문자열 대신 /v1/chat/completions를 통한 role과 content로 이루어진 messages 배열을 입력으로 받습니다.
이런 메세지 배열을 실제로 모델에 입력하기 앞서 텍스트 문자열 형식으로 변환하여야 하는데 이때 chat template이 사용됩니다.
chat template은 위에 messages 배열을 어떤 포맷의 텍스트 문자열로 변환할지를 결정하는 jinja template를 의미합니다.
아래는 많은 chat template format 중 하나인 chatml format의 간소화된 예시입니다.
위에 messages 배열을 chatml format을 통해 변환하면 다음과 같은 텍스트 문자열이 생성됩니다.
기본적으로 <|im_start|>과 <|im_end|>는 각각 턴의 시작과 끝을 나타내며, 마지막 하이라이팅된 부분은 model에게 지침을 제공하기 위해 add_generation_prompt 옵션을 True로 하여 앞으로 생성해야할 부분의 시작을 (header를) 랜더링 한 결과이다.
이렇게 랜더링된 텍스트를 모델에게 입력하면 모델은 다음과 같이 응답을 생성합니다.
여기서 실제로 모델은 <맥락과 턴에 맞게 생성된 응답>과 <|im_end|>를 생성하였고, stop token (eos token)으로 <|im_end|>이 인식되어 생성이 중단되었습니다.
여기까지 완료되면 /v1/chat/completions에 대한 응답으로 모델의 응답이 반환됩니다.
여기까지가 chatml format을 예시로 한 chat template과 /v1/chat/completions의 내부 동작 방식에 대한 설명이였습니다.
다만 Base model이 아닌 Instruct model의 경우 학습단계에서 특정한 chat template을 사용하므로, 해당 모델의 chat template을 사용하여야 합니다.
모델별로 매우 다양한 chat template이 존재하며 아래는 그 정리입니다.
mistral 계열은 특징으로 렌더링 결과가 개행 없이 한 줄로 나온다는 점이 있는데, 아래에서는 시각적 편의를 위해 줄바꿈을 추가하였습니다.
또한 mistralai는 chat template를 가장 자주 업데이트하고 개선하는데 버전 별로 공백처리, 개행처리 등의 개선을 보는 것도 재미있습니다.
BOS: <s>
EOS: </s>
For more information about the tokenizer please refer to mistral-common
모델 별로 학습할 때 사용된 탬플릿을 찾아서 올바르게 사용하는 것이 모델 성능에 큰 영향을 미치는데, 이를 찾는 방법은 어렵지 않다.
huggingface files에서 tokenizer_config.json 파일 찾기
모델이 instrcut 모델이라면 높은 확율로 tokenizer_config.json 파일에 chat template 필드가 존재한다.
보통 한줄로 포맷팅되어 있으며 여기에 탬플릿이 존재한다면 대부분 그대로 사용하면 된다.
model card에 명시된 "Prompting Template" 찾기
모델 제작자가 친절한 경우 어떤 탬플릿이 작동작하는지에 대하여 서술해두는 경우가 있습니다.
어떤 방법으로 학습했는지에 따라 완전히 다른 탬플릿이 사용되기도 하니 이를 참고하여 사용하면 됩니다.
아래의 경우 Mistral [INST] 탬플릿과 ChatML의 혼합된 형태를 사용하고 있습니다.
e.g. Sao10K/MN-12B-Lyra-v3