Skip to content

Step 16: Chat template engine — Jinja2-subset interpreter #30

Closed

Description

@kkokosa

Roadmap Step

Step 14 — Chat template engine

Dependencies

  • Depends on Step 4 (BPE tokenizer — ITokenizer, GGUF vocabulary loading)

Scope

  • Jinja2-subset parser — tokenize and parse a subset of Jinja2 syntax: variable interpolation ({{ }}), for loops ({% for %}), conditionals ({% if/elif/else %}), string filters (trim, strip), raise_exception(), basic expressions and comparisons
  • Template compiler — parse template string into an AST of template nodes (text, expression, for, if, etc.), then evaluate against a context dictionary
  • IChatTemplate implementation — JinjaChatTemplate implementing Apply(messages, options) → string
  • GGUF integration — load template from tokenizer.chat_template metadata key
  • Context variables — messages (list of ChatMessage), add_generation_prompt (bool), bos_token, eos_token, special tokens
  • Known formats — verify correct output for Llama 3, ChatML (Qwen), Mistral template formats
  • Fallback — if no template in model metadata, use ChatML as configurable default with a warning

Key Files

  • src/DotLLM.Tokenizers/ChatTemplates/JinjaLexer.cs (new)
  • src/DotLLM.Tokenizers/ChatTemplates/JinjaParser.cs (new)
  • src/DotLLM.Tokenizers/ChatTemplates/JinjaEvaluator.cs (new)
  • src/DotLLM.Tokenizers/ChatTemplates/JinjaChatTemplate.cs (new — implements IChatTemplate)
  • src/DotLLM.Tokenizers/IChatTemplate.cs (existing interface)
  • src/DotLLM.Tokenizers/ChatMessage.cs (existing)
  • src/DotLLM.Tokenizers/ChatTemplateOptions.cs (existing)

Tests

  • tests/DotLLM.Tests.Unit/Tokenizers/ChatTemplates/JinjaLexerTests.cs
  • tests/DotLLM.Tests.Unit/Tokenizers/ChatTemplates/JinjaParserTests.cs
  • tests/DotLLM.Tests.Unit/Tokenizers/ChatTemplates/JinjaChatTemplateTests.cs
  • Known-answer tests for Llama 3, ChatML, Mistral template formats
  • Edge cases: empty system message, multi-turn conversation, add_generation_prompt true/false

References

  • docs/TOKENIZERS.md — "Chat Template Engine" section
  • HuggingFace tokenizer_config.json for real template strings
  • Jinja2 documentation (subset only)

Acceptance Criteria

  • Jinja2 lexer: tokenizes {{ }}, {% %}, {# #}, text literals, strings, identifiers, operators
  • Jinja2 parser: produces AST for variable interpolation, for loops, if/elif/else, filters, expressions
  • Jinja2 evaluator: evaluates AST against context dictionary, handles string operations, comparisons, method calls (.strip(), .role, array indexing)
  • JinjaChatTemplate correctly formats Llama 3 template output
  • JinjaChatTemplate correctly formats ChatML (Qwen) template output
  • JinjaChatTemplate correctly formats Mistral template output
  • add_generation_prompt appends assistant turn prefix when true
  • Template loaded from GGUF tokenizer.chat_template metadata
  • Fallback to ChatML with warning when no template found
  • raise_exception() in template produces clear error
  • Unit tests with known-answer verification for all supported formats

Activity

  1. added
    enhancementNew feature or request
    phase-2Phase 2: Practical local inference
    on Mar 5, 2026
  2. changed the title [-]Step 14: Chat template engine — Jinja2-subset interpreter[/-] [+]Step 16: Chat template engine — Jinja2-subset interpreter[/+] on Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestphase-2Phase 2: Practical local inference

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions