news 2026/9/14 17:44:16

lm-evaluation-harness Chat Template 分隔符处理更新:apply_chat_template 模式下 target_delimiter 置空机制解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
lm-evaluation-harness Chat Template 分隔符处理更新:apply_chat_template 模式下 target_delimiter 置空机制解析

lm-evaluation-harness Chat Template 分隔符处理更新:apply_chat_template 模式下 target_delimiter 置空机制解析

【免费下载链接】lm-evaluation-harnessA framework for few-shot evaluation of language models.项目地址: https://gitcode.com/GitHub_Trending/lm/lm-evaluation-harness

导读

本文围绕 lm-evaluation-harness 中docs/chat-template-readme.md记录的变更展开,讲解在请求构造过程中应用 Chat Template 时,系统如何将 target delimiter 由默认空白符改为空字符串,从而避免 Chat 模型自带格式化约定与默认分隔符系统相互干扰。读者将掌握apply_chat_template的完整行为、target_delimiterloglikelihoodmultiple_choice两类任务中的不同处理逻辑、以及 gen_prefix 对分隔符决策的例外影响,并能将这套规则直接用于自建任务 YAML 与 CLI 评估命令的配置。

背景:默认分隔符与 Prompt 拼接模型

在 lm-evaluation-harness 中,每个任务对每条样本构造 Prompt 时遵循一个统一约定:上下文文本与目标文本之间插入一个target_delimiter。默认值为单个空格" ",该默认值定义在任务配置类TaskConfig中(见 lm_eval/config/task.py)。

整体拼接关系可表示为:

doc_to_text(doc) + target_delimiter + doc_to_target(doc)
  • doc_to_text(doc):从样本中提取问题/上下文;
  • target_delimiter:默认" ",可在任务 YAML 中以同名键覆盖;
  • doc_to_target(doc):从样本中提取标准答案/目标文本。

这一设计对基础模型(base model)很友好:模型被要求预测“一个空白符 + 答案”,从而以最大似然(loglikelihood)方式打分。但对于经过指令微调、自带对话格式的 Chat 模型,空白符插入的位置往往与模板自带的换行、缩进约定冲突,导致生成或打分的目标序列与模型在训练时见过的格式不一致。

变更内容:apply_chat_template 下分隔符置空

本次更新的核心改动可概括为一条规则:

apply_chat_templateTrue时,构造请求所用的 target delimiter 置为空字符串"",而不再使用配置的分隔符(默认" ")。

其意义在于:

  • 防止 Chat Template 的格式化结果与默认分隔符系统相互干扰;
  • 对 multiple-choice 类任务尤其关键,因为模板本身已经负责处理空格与换行。

原文档给出的直观对比(变更前 vs 变更后)如下:

# Before(默认分隔符 " ") <user>Question: What color is the sky?\nAnswer:<assistant> blue # After(分隔符为空) <user>Question: What color is the sky?\nAnswer:<assistant>blue

可以看出,变更前答案前残留一个多余空格,变更后答案紧贴<assistant>之后的模板原生格式,更符合 Chat 模型的训练分布。

源码级实现:分隔符在请求构造链中的真实走向

上述行为并非仅在文档层面声明,而是落实在任务请求构造代码中。核心逻辑位于Task.construct_requests()(见 lm_eval/api/task.py)。

对于loglikelihood输出类型,请求直接以(ctx, doc_to_target(doc))作为参数对,不经过分隔符拼接:

if self.OUTPUT_TYPE == "loglikelihood": arguments = (ctx, self.doc_to_target(doc))

而对于multiple_choice输出类型,分隔符逻辑最为关键:

elif self.OUTPUT_TYPE == "multiple_choice": choices = self.doc_to_choice(doc) target_delimiter = self.config.target_delimiter if apply_chat_template: target_delimiter = ( self.config.target_delimiter if self.config.gen_prefix and not ends_with_whitespace(self.config.gen_prefix) else "" ) ... arguments = [(ctx, f"{target_delimiter}{cont}") for cont in choices]

代码显示,apply_chat_template=True时存在一个带条件的例外

  • 若任务配置了gen_prefix,且gen_prefix不以空白字符结尾,则仍保留target_delimiter
  • 其余情况(无 gen_prefix,或 gen_prefix 以空白结尾)一律置空。

这意味着“置空分隔符”规则在 gen_prefix(例如Answer:)场景下会被有意放宽,以保证Answer:与答案之间保留必要的间隔;而一旦Answer:自带尾部空格,间隔又回归空串,避免出现双重空格。从源码结构看,这一分支是为了同时兼容“模板自带间隔”与“gen_prefix 显式要求间隔”两种诉求。

gen_prefix的取值优先级同样定义在任务类中(见 lm_eval/api/task.py):若其在样本features中则为字段引用,否则会经apply_template模板渲染得到。

apply_chat_template 的开启路径:从 CLI 到 Evaluator

apply_chat_template的取值可以是布尔值或字符串:True表示应用模型默认 Chat Template,字符串则按名称指定模板(见 lm_eval/evaluator.py)。在 CLI 层面对应--apply_chat_template参数,Python API 的simple_evaluate/evaluate亦接受同名关键字参数。

在 evaluator 中,开启后通过以下方式把模板能力注入任务上下文(见 lm_eval/evaluator.py):

chat_template=lm.chat_template(apply_chat_template) if apply_chat_template

随后在Task.fewshot_context()中,chat_templateapply_chat_template一并被使用(见 lm_eval/api/task.py):消息列表(system / few-shot / 评测样本)先按build_qa_turn()构造为Message序列,apply_chat_template为真时再统一交给chat_template(res)渲染为单轮或对话式文本。

需要特别说明的是:置空分隔符的生效点位于请求构造(construct_requests)阶段,即实际送入模型的 loglikelihood 打分对;而fewshot_context生成的展示文本仍会保留target_delimiter(通过build_qa_turn(..., tgt_delim=self.config.target_delimiter, ...),见 lm_eval/api/task.py)。也就是说,--write_out输出的样例文本与真正打分的 continuation 之间可能存在细微差异,这正是文档所描述“防止模板格式化与默认分隔符系统相互干扰”的底层原因。

如何配置与验证

1. 任务侧:在 YAML 中显式控制分隔符

在自建任务配置中可按需覆盖分隔符相关字段:

task: my_chat_mc_task output_type: multiple_choice target_delimiter: " " # 默认即 " ",可显式声明或留空 doc_to_text: "Question: {{question}}" doc_to_choice: ["A", "B", "C", "D"] doc_to_target: "{{answer}}"

配合运行时开启 Chat Template 后,multiple_choice 请求中的分隔符会自动置空(除非命中 gen_prefix 例外分支),无需在 YAML 中手工清空。

2. 评估侧:CLI 与 Python API

CLI 方式:

lm_eval --model hf \ --model_args pretrained=your-chat-model \ --tasks my_chat_mc_task \ --apply_chat_template

Python 方式(等价):

from lm_eval import simple_evaluate results = simple_evaluate( model="hf", model_args="pretrained=your-chat-model", tasks=["my_chat_mc_task"], apply_chat_template=True, fewshot_as_multiturn=True, # 将 few-shot 示例作为多轮对话 )

其中fewshot_as_multiturn控制 few-shot 示例是作为独立 user/assistant 多轮消息(True)还是折叠进单条 user 消息(False),与 Chat Template 渲染密切相关(默认True,见 lm_eval/evaluator.py)。

3. 验证输出

可通过--write_out导出构造出的实际输入文本,检查<assistant>后是否紧贴答案、无多余空格:

lm_eval --model hf \ --model_args pretrained=your-chat-model \ --tasks my_chat_mc_task \ --apply_chat_template \ --write_out \ --limit 10

同时,请求缓存指纹会因apply_chat_template而异——任务缓存键在开启时追加-chat_template后缀(见 lm_eval/api/task.py),--cache_requests场景下模板开关不会串用旧缓存。

常见陷阱与边界

  • 不要同时依赖默认空格与模板自带空格:对 Chat 模型,模板通常已在<assistant>后包含换行/空格,若仍保留默认" "会出现双空格或错位,这正是本变更消除的问题;
  • gen_prefix 例外:配置了不带尾部空格的gen_prefix(如Answer:)时,分隔符不会被置空,以免Answer:与答案粘连;这是刻意保留的行为,不是 bug;
  • fewshot 与评测样本的分隔符来源不同:few-shot 示例使用FewshotConfig中的target_delimiter(由fewshot_config或全局配置继承,见 lm_eval/config/task.py),评测样本使用任务级target_delimiter,两者在 Chat 模板场景下的最终渲染均以模板为准;
  • 缓存指纹区分apply_chat_template会修改缓存键与 tokenizer 指纹(如 lm_eval/models/api_models.py 的apply_chat_template实现),切换开关后建议清理旧请求缓存,避免命中过期结果。

总结

lm-evaluation-harness 通过将apply_chat_template=True场景下的 target delimiter 置空,消除了 Chat 模板格式化与默认空格分隔符之间的冲突,使 Chat 模型的 loglikelihood 打分与多选任务请求构造更贴近模型原生对话分布。理解construct_requests中置空规则、gen_prefix 例外分支与fewshot_context渲染路径的差异,是正确配置--apply_chat_template与编写 Chat 任务 YAML 的关键。相关实现细节可在 lm_eval/api/task.py、lm_eval/evaluator.py 与 lm_eval/config/task.py 中继续深入。

【免费下载链接】lm-evaluation-harnessA framework for few-shot evaluation of language models.项目地址: https://gitcode.com/GitHub_Trending/lm/lm-evaluation-harness

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 17:43:48

Java基本数据类型详解与使用指南

1. Java基本数据类型概述 Java作为一门强类型编程语言&#xff0c;其数据类型系统是构建程序的基础。在Java中&#xff0c;数据类型分为两大类&#xff1a;基本数据类型&#xff08;Primitive Types&#xff09;和引用数据类型&#xff08;Reference Types&#xff09;。基本数…

作者头像 李华
网站建设 2026/9/14 17:43:00

土拱效应原理与工程应用解析

1. 土拱效应示意图解析与应用场景土拱效应是岩土工程中一个重要的力学现象&#xff0c;指在土体内部由于应力重分布形成的拱形承载结构。这种现象常见于隧道支护、挡土墙设计、桩基工程等领域&#xff0c;理解土拱效应对于工程稳定性分析至关重要。这张示意图通过可视化方式展示…

作者头像 李华
网站建设 2026/9/14 17:40:49

random seq

我建议 8bit,先用前6位,后两位以后留给 error/BUSY: localparam bit [7:0] RAND_ADDR = 8b0000_0001; localparam bit [7:0] RAND_DATA = 8b0000_0010; localparam bit [7:0] RAND_SIZE = 8b0000_0100; localparam bit [7:0] RAND_BURST = 8b0000_1000; localparam bit …

作者头像 李华