Update Jinja docs with new functions and general cleanup (#33097)
This commit is contained in:
@@ -785,14 +785,23 @@ it's time to put an end to them!
|
|||||||
|
|
||||||
## Advanced: Template writing tips
|
## Advanced: Template writing tips
|
||||||
|
|
||||||
If you're unfamiliar with Jinja, we generally find that the easiest way to write a chat template is to first
|
<Tip>
|
||||||
write a short Python script that formats messages the way you want, and then convert that script into a template.
|
|
||||||
|
|
||||||
Remember that the template handler will receive the conversation history as a variable called `messages`.
|
The easiest way to get started with writing Jinja templates is to take a look at some existing ones. You can use
|
||||||
|
`print(tokenizer.chat_template)` for any chat model to see what template it's using. In general, models that support tool use have
|
||||||
|
much more complex templates than other models - so when you're just getting started, they're probably a bad example
|
||||||
|
to learn from! You can also take a look at the
|
||||||
|
[Jinja documentation](https://jinja.palletsprojects.com/en/3.1.x/templates/#synopsis) for details
|
||||||
|
of general Jinja formatting and syntax.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
Jinja templates in `transformers` are identical to Jinja templates elsewhere. The main thing to know is that
|
||||||
|
the conversation history will be accessible inside your template as a variable called `messages`.
|
||||||
You will be able to access `messages` in your template just like you can in Python, which means you can loop over
|
You will be able to access `messages` in your template just like you can in Python, which means you can loop over
|
||||||
it with `{% for message in messages %}` or access individual messages with `{{ messages[0] }}`, for example.
|
it with `{% for message in messages %}` or access individual messages with `{{ messages[0] }}`, for example.
|
||||||
|
|
||||||
You can also use the following tips to convert your code to Jinja:
|
You can also use the following tips to write clean, efficient Jinja templates:
|
||||||
|
|
||||||
### Trimming whitespace
|
### Trimming whitespace
|
||||||
|
|
||||||
@@ -817,46 +826,35 @@ rather than like this:
|
|||||||
Adding `-` will strip any whitespace that comes before the block. The second example looks innocent, but the newline
|
Adding `-` will strip any whitespace that comes before the block. The second example looks innocent, but the newline
|
||||||
and indentation may end up being included in the output, which is probably not what you want!
|
and indentation may end up being included in the output, which is probably not what you want!
|
||||||
|
|
||||||
### For loops
|
|
||||||
|
|
||||||
For loops in Jinja look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
{%- for message in messages %}
|
|
||||||
{{- message['content'] }}
|
|
||||||
{%- endfor %}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that whatever's inside the {{ expression block }} will be printed to the output. You can use operators like
|
|
||||||
`+` to combine strings inside expression blocks.
|
|
||||||
|
|
||||||
### If statements
|
|
||||||
|
|
||||||
If statements in Jinja look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
{%- if message['role'] == 'user' %}
|
|
||||||
{{- message['content'] }}
|
|
||||||
{%- endif %}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note how where Python uses whitespace to mark the beginnings and ends of `for` and `if` blocks, Jinja requires you
|
|
||||||
to explicitly end them with `{% endfor %}` and `{% endif %}`.
|
|
||||||
|
|
||||||
### Special variables
|
### Special variables
|
||||||
|
|
||||||
Inside your template, you will have access to the list of `messages`, but you can also access several other special
|
Inside your template, you will have access several special variables. The most important of these is `messages`,
|
||||||
variables. These include special tokens like `bos_token` and `eos_token`, as well as the `add_generation_prompt`
|
which contains the chat history as a list of message dicts. However, there are several others. Not every
|
||||||
variable that we discussed above. You can also use the `loop` variable to access information about the current loop
|
variable will be used in every template. The most common other variables are:
|
||||||
iteration, for example using `{% if loop.last %}` to check if the current message is the last message in the
|
|
||||||
conversation. Here's an example that puts these ideas together to add a generation prompt at the end of the
|
|
||||||
conversation if add_generation_prompt is `True`:
|
|
||||||
|
|
||||||
```
|
- `tools` contains a list of tools in JSON schema format. Will be `None` or undefined if no tools are passed.
|
||||||
{%- if loop.last and add_generation_prompt %}
|
- `documents` contains a list of documents in the format `{"title": "Title", "contents": "Contents"}`, used for retrieval-augmented generation. Will be `None` or undefined if no documents are passed.
|
||||||
{{- bos_token + 'Assistant:\n' }}
|
- `add_generation_prompt` is a bool that is `True` if the user has requested a generation prompt, and `False` otherwise. If this is set, your template should add the header for an assistant message to the end of the conversation. If your model doesn't have a specific header for assistant messages, you can ignore this flag.
|
||||||
{%- endif %}
|
- **Special tokens** like `bos_token` and `eos_token`. These are extracted from `tokenizer.special_tokens_map`. The exact tokens available inside each template will differ depending on the parent tokenizer.
|
||||||
```
|
|
||||||
|
<Tip>
|
||||||
|
|
||||||
|
You can actually pass any `kwarg` to `apply_chat_template`, and it will be accessible inside the template as a variable. In general,
|
||||||
|
we recommend trying to stick to the core variables above, as it will make your model harder to use if users have
|
||||||
|
to write custom code to pass model-specific `kwargs`. However, we're aware that this field moves quickly, so if you
|
||||||
|
have a new use-case that doesn't fit in the core API, feel free to use a new `kwarg` for it! If a new `kwarg`
|
||||||
|
becomes common we may promote it into the core API and create a standard, documented format for it.
|
||||||
|
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
### Callable functions
|
||||||
|
|
||||||
|
There is also a short list of callable functions available to you inside your templates. These are:
|
||||||
|
|
||||||
|
- `raise_exception(msg)`: Raises a `TemplateException`. This is useful for debugging, and for telling users when they're
|
||||||
|
doing something that your template doesn't support.
|
||||||
|
- `strftime_now(format_str)`: Equivalent to `datetime.now().strftime(format_str)` in Python. This is used for getting
|
||||||
|
the current date/time in a specific format, which is sometimes included in system messages.
|
||||||
|
|
||||||
### Compatibility with non-Python Jinja
|
### Compatibility with non-Python Jinja
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user