You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jinja循环中对首个元素执行特殊操作及对话顺序校验

问题1:解决循环内变量无法更新的问题

Jinja中普通变量在循环块内属于局部作用域,修改后不会影响外层变量值,所以你用{% set is_first = "true" %}无法更新外层的is_first。解决方法是用Jinja的namespace对象存储状态,它的属性是可变的,能跨循环迭代保持更新:

修改后的模板代码:

{% set ns = namespace(is_first=false) %}
{% for message in messages %}
    {% if message['role'] == 'system' %}
        {{ '<<SYS>>\n' + message['content'].strip() + '\n<</SYS>>\n\n'}}
        {% set ns.is_first = true %}
    {% elif message['role'] == 'user' and ns.is_first %}
        {% set ns.is_first = false %}
        {{ message['content'].strip() + ' [/INST]' }}
    {% elif message['role'] == 'user' %}
        {{ '[INST] ' + message['content'].strip() + ' [/INST]' }}
    {% elif message['role'] == 'assistant' %}
        {{ message['content'].strip() }}
    {% endif %}
{% endfor %}

核心变化是用ns.is_first替代原有的is_first变量,通过namespace对象维护状态,循环内的修改会持续生效。

问题2:校验对话顺序并抛出错误

可以通过跟踪前一条消息的角色,在循环内校验当前角色是否符合system->user->assistant->user->...的预期顺序,用Jinja的assert语句触发错误:

完整的带校验的模板代码:

{% set ns = namespace(prev_role=None, is_first=false) %}
{% for idx, message in enumerate(messages) %}
    {% set current_role = message['role'] %}
    {% if idx == 0 %}
        {% assert current_role in ['system', 'user'], "第一条消息必须是system或user角色" %}
    {% else %}
        {% if ns.prev_role == 'system' %}
            {% assert current_role == 'user', "system消息后必须紧跟user消息" %}
        {% elif ns.prev_role == 'user' %}
            {% assert current_role == 'assistant', "user消息后必须紧跟assistant消息" %}
        {% elif ns.prev_role == 'assistant' %}
            {% assert current_role == 'user', "assistant消息后必须紧跟user消息" %}
        {% endif %}
    {% endif %}

    {% if current_role == 'system' %}
        {{ '<<SYS>>\n' + message['content'].strip() + '\n<</SYS>>\n\n'}}
        {% set ns.is_first = true %}
    {% elif current_role == 'user' and ns.is_first %}
        {% set ns.is_first = false %}
        {{ message['content'].strip() + ' [/INST]' }}
    {% elif current_role == 'user' %}
        {{ '[INST] ' + message['content'].strip() + ' [/INST]' }}
    {% elif current_role == 'assistant' %}
        {{ message['content'].strip() }}
    {% endif %}

    {% set ns.prev_role = current_role %}
{% endfor %}

这段代码会在对话顺序不符合要求时抛出AssertionError,并附带明确的错误提示。如果是在Hugging Face Tokenizer中使用,大部分版本都支持Jinja的assert语法。

内容的提问来源于stack exchange,提问作者Yaoming Xuan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:43:19