A zero-dependency PHP implementation of the Jinja templating engine, specifically designed for parsing and rendering machine learning (ML) chat templates. This project is heavily inspired by HuggingFace's Jinja template engine in JavaScript, intended primarily for ML chat templates, but is versatile enough to be used for general purposes of parsing most Jinja templates.
Install Jinja PHP through Composer:
composer require codewithkyrian/jinja-php
Here's how you can use Jinja PHP to render a template:
$sourceString = "{{ bos_token }}{% for message in messages %}{% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}{{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}{% endif %}{% if message['role'] == 'user' %}{{ '[INST] ' + message['content'] + ' [/INST]' }}{% elif message['role'] == 'assistant' %}{{ message['content'] + eos_token + ' ' }}{% else %}{{ raise_exception('Only user and assistant roles are supported!') }}{% endif %}{% endfor %}";
$args = [
'messages' => [
['role' => 'user', 'content' => 'Hello!'],
['role' => 'assistant', 'content' => 'Hi! How are you?'],
['role' => 'user', 'content' => 'I am doing great.'],
['role' => 'assistant', 'content' => 'That is great to hear.'],
],
"add_generation_prompt" => true,
"bos_token" => "<s>",
"eos_token" => "</s>",
"unk_token" => "<unk>",
];
$template = new Template($sourceString);
$rendered = $template->render($args);
// <s>[INST] Hello! [/INST]Hi! How are you?</s> [INST] I am doing great. [/INST]That is great to hear.</s>
{% if %}, {% elif %}, {% else %}, {% endif %}{% for %}, {% else %}, {% endfor %} with loop variables (loop.index, loop.index0, loop.first, loop.last, loop.length, loop.previtem, loop.nextitem){% break %}, {% continue %} for loop control{{ value if condition else other_value }}{{ variable }}messages[-1], array[-2] (Python-style)user.name, messages[0]['content']none, Nonetrue, false, True, False{{ "Hello" ~ " " ~ "World" }}{% macro name(arg1, arg2) %}...{% endmacro %} with {{ name() }} calls{{ function(arg1, arg2) }}{{ function(param1=value1, param2=value2) }}{{ function(*args) }}lower, upper, title, capitalize, strip, lstrip, rstripreplace, split, startswith, endswith, indentlength, join, map, reverse, sorttojson, default{% filter filter_name %}...{% endfilter %}{# This is a comment #}{% set variable = value %} and block sets {% set variable %}{% endset %}{% call macro_name() %}...{% endcall %}{{ raise_exception('Error message') }}~ operatorrange(): Generate number sequencesraise_exception(): Throw runtime exceptionslen(): Get length of arrays/strings{%- and -%}{% extends %}, {% block %}, {% include %}groupby, batch{% if user.isActive %}
Hello, {{ user.name }}!
{% elif user.isGuest %}
Hello, Guest!
{% else %}
Please log in.
{% endif %}
{% for user in users %}
{{ loop.index }} - {{ user.name }}
{% if loop.first %}First user{% endif %}
{% if loop.last %}Last user{% endif %}
{% else %}
No users found.
{% endfor %}
{% macro format_user(user) %}
<div class="user">
<h3>{{ user.name|title }}</h3>
<p>{{ user.email|lower }}</p>
</div>
{% endmacro %}
{{ format_user(current_user) }}
{{ "Hello World!"|upper|replace("WORLD", "PHP") }}
{{ " hello "|strip|capitalize }}
{{ "apple,banana,cherry"|split(",")|join(" and ") }}
{{ "Hello" ~ " " ~ "World" }}
{% for item in items|sort %}
{{ item }}
{% endfor %}
{{ messages[-1]['content'] }} {# Last message #}
{{ array|length }} {# Array length #}
{% set greeting = "Hello, " ~ user.name %}
{{ greeting }}
{% set user_info %}
Name: {{ user.name }}
Email: {{ user.email }}
{% endset %}
{{ user_info|indent(2) }}
{% filter upper %}
This text will be uppercase
{% endfilter %}
{# This is a comment that won't appear in output #}
{{ variable }} {# Inline comment #}
{% if user.role == 'admin' %}
Admin panel
{% else %}
{{ raise_exception('Access denied') }}
{% endif %}
{{ (user.isActive and user.hasPermission) or user.isAdmin }}
{{ messages|length > 0 and messages[-1].role == 'user' }}
{{ "Hello" if user.name else "Guest" }}
Jinja PHP comes with a comprehensive test suite to ensure functionality remains consistent and reliable. To run the tests:
composer test
The test suite includes:
Jinja PHP is designed for performance with:
Jinja PHP is designed to be robust and feature-rich, offering support for a wide range of functionalities. If there's a feature you need that isn't currently implemented, we encourage you to request it. Additionally, if you're proficient with PHP and understand the internals of templating engines, consider contributing to the project by submitting a pull request with your proposed feature.
If you find any issues or have a question, feel free to open an issue in the repo.
This project is licensed under the MIT License. See the LICENSE file for more information.
How can I help you explore Laravel packages today?