Chat templates

How to put your messages in the shape that a model expects.

An instruction model expects a marker before each message. The markers say which part is the system prompt, which part the user said, and where the model must write. That shape is the chat template.

Each model family has its own template. If you send the wrong shape, the model gives a poor answer or no answer.

The template in the model file

Most GGUF files hold their own template.

tmpl := llama.ModelChatTemplate(model)

An empty result means the file holds no template. Then you must give one.

Apply the template

pkg/template renders a Jinja template.

import (
	"github.com/hybridgroup/yzma/pkg/message"
	"github.com/hybridgroup/yzma/pkg/template"
)

messages := []message.Message{
	message.Chat{Role: "system", Content: "You are a helpful robot companion."},
	message.Chat{Role: "user", Content: "Are you ready to go?"},
}

prompt, err := template.Apply(tmpl, messages, true)

The third argument adds the marker that starts the turn of the assistant. Set it to true before you generate an answer.

llama.ChatApplyTemplate does the same with the code in llama.cpp.

Built in templates

yzma holds three templates for a model file that has none.

Name Use it for
chatml Many models. This is the most common shape.
gemma3 The Gemma 3 family.
qwen2.5-instruct The Qwen 2.5 instruct family.
tmpl, ok := template.BuiltinTemplate("chatml")
if !ok {
	// There is no template with that name.
}

The chat example and the vlm example take the name with the -template flag.

llama.ChatBuiltinTemplates() lists the templates that llama.cpp holds.

Thinking mode

Some models, such as Qwen3, have a thinking mode. The model writes its reasoning before the answer. Set EnableThinking to false to stop that.

opts := template.DefaultOptions()
opts.EnableThinking = false

prompt, err := template.ApplyWithOptions(tmpl, messages, true, opts)

Thinking mode is on by default. A model whose template does not use this variable ignores the setting.

Templates with tools

A model that calls tools needs the tool definitions in the prompt.

prompt, err := template.ApplyWithTools(tmpl, messages, tools, true)

You can also put the tools in Options:

opts := template.DefaultOptions()
opts.Tools = tools

When the tools list is empty, the template takes its plain path.

See Tool calling.

Read the template of a file

The modelinfo example prints the metadata of a GGUF file, and the chat template is part of it.

go run ./examples/modelinfo/ -model ~/models/gemma-3-1b-it-Q4_K_M.gguf