ardanlabs/jinja

Jinja template engine for Go programs

Go

20

38 commits

updated Oct 6, 2026

See the code

README

jinja

A pure-Go Jinja template engine purpose-built for rendering LLM chat templates. It compiles and executes the Jinja templates embedded in GGUF model files, turning conversations and tool definitions into the exact token sequences each model expects. Zero dependencies, zero CGO.

Copyright 2026 Ardan Labs

[email protected]

Project Status

Go Reference Go Report Card go.mod Go version Linux

Install

go get github.com/ardanlabs/jinja

Quick Start

The API has two steps: compile a template once, then render it with data as many times as needed. Compiled templates are safe for concurrent use.

package main

import (
	"fmt"
	"log"

	"github.com/ardanlabs/jinja"
)

func main() {
	tmpl, err := jinja.Compile("Hello {{ name }}!")
	if err != nil {
		log.Fatal(err)
	}

	result, err := tmpl.Render(map[string]any{
		"name": "World",
	})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(result)
	// Output: Hello World!
}

Chat Template Example

The primary use case is rendering LLM chat templates. Each model ships a Jinja template that formats conversations into the token layout the model was trained on.

const chatTemplate = `{%- if messages[0].role == 'system' -%}
<|im_start|>system
{{ messages[0].content }}<|im_end|>
{%- endif %}
{%- for message in messages -%}
{%- if message.role != 'system' %}
<|im_start|>{{ message.role }}
{{ message.content }}<|im_end|>
{%- endif -%}
{%- endfor %}
{%- if add_generation_prompt %}
<|im_start|>assistant
{%- endif -%}`

tmpl, err := jinja.Compile(chatTemplate)
if err != nil {
	log.Fatal(err)
}

result, err := tmpl.Render(map[string]any{
	"messages": []any{
		map[string]any{"role": "system", "content": "You are a helpful assistant."},
		map[string]any{"role": "user", "content": "What is the capital of France?"},
		map[string]any{"role": "assistant", "content": "The capital of France is Paris."},
		map[string]any{"role": "user", "content": "What about Germany?"},
	},
	"add_generation_prompt": true,
})

See the examples directory for more, including tool calling.

Supported Features

Template Syntax

  • Variable output: {{ expr }}
  • Statements: {% if %}, {% for %}, {% set %}, {% macro %}, {% block %}
  • Whitespace control: {%- ... -%}, {{- ... -}}
  • Comments: {# ... #}
  • String concatenation with ~
  • Inline if expressions: {{ x if condition else y }}
  • Slice notation: {{ items[::-1] }}

Filters

abs · batch · capitalize · count · default / d · dictsort · escape / e · first · float · fromjson · indent · int · items · join · last · length · list · lower · map · max · min · reject · rejectattr · replace · reverse · round · safe · select · selectattr · sort · string · sum · title · tojson · trim · unique · upper · wordcount

Tests

defined · undefined · none · boolean · integer · float · number · string · mapping · iterable · sequence · callable · true · false · odd · even · upper · lower · sameas · eq · ne · gt · ge · lt · le · in

Global Functions

namespace · range · dict · joiner · cycler · raise_exception · strftime_now

String Methods

.strip() · .split() · .startswith() · .endswith() · .upper() · .lower() · .replace() · .find() · .count() · .lstrip() · .rstrip()

Dict Methods

.get() · .items() · .keys() · .values() · .update()

Tested Models

The test suite compiles and renders the chat templates from these models:

ModelFamily
DeepSeek-V4-FlashDeepSeek V4
gemma-4-26B-A4B-itGemma 4
GLM-5.2GLM 5
gpt-oss-20bGPT-OSS
Kimi-K3Kimi K3
lagunaLaguna
LFM2.5-VL-1.6BLFM2.5
Llama-3.2-1B-InstructLlama 3.2
Ministral-3-14B-Instruct-2512Mistral 3
Mistral-Medium-3.5-128BMistral Medium 3.5
NVIDIA-Nemotron-3-Super-120B-A12BNemotron 3
Qwen2-Audio-7BQwen2-Audio
Qwen3-8BQwen3
Qwen3-VL-30B-A3B-InstructQwen3-VL
Qwen3.5-35B-A3BQwen3.5
Qwen3.6-35B-A3BQwen3.6
rnj-1-instructRNJ-1

License

Licensed under the Apache License, Version 2.0. See LICENSE for the full text.

ardanlabs/jinja

Jinja template engine for Go programs

Go

20

38 commits

updated Oct 6, 2026

See the code

README

jinja

A pure-Go Jinja template engine purpose-built for rendering LLM chat templates. It compiles and executes the Jinja templates embedded in GGUF model files, turning conversations and tool definitions into the exact token sequences each model expects. Zero dependencies, zero CGO.

Copyright 2026 Ardan Labs

[email protected]

Project Status

Go Reference Go Report Card go.mod Go version Linux

Install

go get github.com/ardanlabs/jinja

Quick Start

The API has two steps: compile a template once, then render it with data as many times as needed. Compiled templates are safe for concurrent use.

package main

import (
	"fmt"
	"log"

	"github.com/ardanlabs/jinja"
)

func main() {
	tmpl, err := jinja.Compile("Hello {{ name }}!")
	if err != nil {
		log.Fatal(err)
	}

	result, err := tmpl.Render(map[string]any{
		"name": "World",
	})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(result)
	// Output: Hello World!
}

Chat Template Example

The primary use case is rendering LLM chat templates. Each model ships a Jinja template that formats conversations into the token layout the model was trained on.

const chatTemplate = `{%- if messages[0].role == 'system' -%}
<|im_start|>system
{{ messages[0].content }}<|im_end|>
{%- endif %}
{%- for message in messages -%}
{%- if message.role != 'system' %}
<|im_start|>{{ message.role }}
{{ message.content }}<|im_end|>
{%- endif -%}
{%- endfor %}
{%- if add_generation_prompt %}
<|im_start|>assistant
{%- endif -%}`

tmpl, err := jinja.Compile(chatTemplate)
if err != nil {
	log.Fatal(err)
}

result, err := tmpl.Render(map[string]any{
	"messages": []any{
		map[string]any{"role": "system", "content": "You are a helpful assistant."},
		map[string]any{"role": "user", "content": "What is the capital of France?"},
		map[string]any{"role": "assistant", "content": "The capital of France is Paris."},
		map[string]any{"role": "user", "content": "What about Germany?"},
	},
	"add_generation_prompt": true,
})

See the examples directory for more, including tool calling.

Supported Features

Template Syntax

  • Variable output: {{ expr }}
  • Statements: {% if %}, {% for %}, {% set %}, {% macro %}, {% block %}
  • Whitespace control: {%- ... -%}, {{- ... -}}
  • Comments: {# ... #}
  • String concatenation with ~
  • Inline if expressions: {{ x if condition else y }}
  • Slice notation: {{ items[::-1] }}

Filters

abs · batch · capitalize · count · default / d · dictsort · escape / e · first · float · fromjson · indent · int · items · join · last · length · list · lower · map · max · min · reject · rejectattr · replace · reverse · round · safe · select · selectattr · sort · string · sum · title · tojson · trim · unique · upper · wordcount

Tests

defined · undefined · none · boolean · integer · float · number · string · mapping · iterable · sequence · callable · true · false · odd · even · upper · lower · sameas · eq · ne · gt · ge · lt · le · in

Global Functions

namespace · range · dict · joiner · cycler · raise_exception · strftime_now

String Methods

.strip() · .split() · .startswith() · .endswith() · .upper() · .lower() · .replace() · .find() · .count() · .lstrip() · .rstrip()

Dict Methods

.get() · .items() · .keys() · .values() · .update()

Tested Models

The test suite compiles and renders the chat templates from these models:

ModelFamily
DeepSeek-V4-FlashDeepSeek V4
gemma-4-26B-A4B-itGemma 4
GLM-5.2GLM 5
gpt-oss-20bGPT-OSS
Kimi-K3Kimi K3
lagunaLaguna
LFM2.5-VL-1.6BLFM2.5
Llama-3.2-1B-InstructLlama 3.2
Ministral-3-14B-Instruct-2512Mistral 3
Mistral-Medium-3.5-128BMistral Medium 3.5
NVIDIA-Nemotron-3-Super-120B-A12BNemotron 3
Qwen2-Audio-7BQwen2-Audio
Qwen3-8BQwen3
Qwen3-VL-30B-A3B-InstructQwen3-VL
Qwen3.5-35B-A3BQwen3.5
Qwen3.6-35B-A3BQwen3.6
rnj-1-instructRNJ-1

License

Licensed under the Apache License, Version 2.0. See LICENSE for the full text.

Project health

Latest release

v1.8.0 · Oct 6, 2026

Releases this year

9

Significant stargazers

Lucas Bremgartner

197 followers · starred Apr 2026

Ron Evans

1,028 followers · starred Apr 2026