如何在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
相关产品推荐
相关产品推荐

