IBM 发布 LLMON 标记语言及 Granite 4.1 3B/8B 预览模型
LLMON: An LLM-Native Markup Language, now in Granite 4.1 3B and 8B
IBM 在 Hugging Face 发布 LLMON(LLM 对象符号)标记语言,并推出基于 Granite 4.1 的 granite-4.1-3b-LLMON-preview 和 granite-4.1-8b-LLMON-preview 两个实验性预览模型,同时开源 GitHub 工具包。
原文给出 LLMON 标记语言的设计动机与两个预览模型,读者可据此理解指令与数据分离如何降低间接提示注入风险。
大型语言模型(LLMs)依赖于它们的上下文来生成下一组标记。在长时间的轨迹中,上下文会填充多种类型的组件:系统提示、过去的对话回合、对检索到的文档起作用的指令、工具响应或用户数据、限制允许输出的要求以及推理链。上下文具有丰富的结构,其中大部分对模型来说是隐式的,或者编码在如 JSON 这样的格式中,而这些格式并非为被 LLMs 消化而设计。这是 LLMs,尤其是规模较小的 LLMs,之所以脆弱并且在意外方式下失败的主要原因之一。缺乏显式结构也可能被攻击者利用,例如以提示注入的形式。
为了解决这个问题,我们开发了 LLMON(LLM 对象符号,发音为“lemon”),这是一种为模型显式传达结构和语义的 LLM 本地标记语言。语义上连贯的组件用有意义的标签进行标记,这些标签被包装在保留的特殊标记分隔符中。数据模式,包括嵌套,以对因果 LLM 无歧义的方式声明。唯一的 ID 使得能够指向特定的指令,这些指令可以位于上下文的任何位置,并将它们绑定到它们应该作用的数据有效负载上,类似于编程语言中函数的调用和向它们传递参数的方式。
今天我们发布了两个实验性预览模型,它们是从 Granite 4.1 基础模型派生出来的,经过训练以消费和生成 LLMON 标记的文本:granite-4.1-3b-LLMON-preview 和 granite-4.1-8b-LLMON-preview。我们还发布了一个 GitHub 仓库,其中包含一个用于处理 LLMON 的工具包以及工作流程和模板的示例。
它使能够实现:
- 由于显式指令/数据分离,LLMON 模型大多忽略了隐藏在用户数据中的间接提示注入。对于某些基准测试,攻击成功率降至几乎为零,而常规指令调优模型则有很大概率被劫持。这是在相对于 Granite 4.1 Instruct 模型保持一般能力的同时实现的。
- 无关的段落、旧的聊天回合和工具输出不会因为每个指令都与它所应用的确切数据绑定而被拉入答案中。
- 指令、数据和要求被明确标记,以便模型能够在应用程序代码级别利用它们的结构和含义。在 Mellea 中试试,它通过自动 LLMON 化其 LLM 调用来启用 LLMON 支持。
- 您不再需要担心强迫 LLMs 遵守 JSON 结构。使用我们的转换器将现有的 JSON 转换为 LLMON 而不会丢失。您还可以定义自己的结构和相关的标签,并在 LLMON 模型之上微调 LoRA 以理解它。
为什么不是 JSON?
JSON 是为解析器设计的,而不是为因果语言模型设计的。分词器不受语法约束,并且结构由可能出现在普通文本中的标记({, ", :) 编码。对模型来说,文档中的一个引号和一个关闭字段的引号是同一个标记。对解析器来说很清晰的转义规则对模型来说只是统计模式。嵌套深度通过计算括号来编码,而转换器在长跨度上尤其弱于处理这一点。
另一方面,LLMON 是一种类似 XML 的标记语言,其结构分隔符是保留的特殊标记而不是字符,因此结构和内容使用词汇的不同部分。标签在每个跨度(span)的开头声明,跨度之间的边界是明确的。嵌套结构在本地声明,因此模型不需要在长跨度上跟踪层次结构。
由于大多数团队已经围绕 JSON 构建了管道,我们创建了 转换工具 和示例笔记本,以无损失的方式将 JSON 翻译为 LLMON 并反向翻译。
LLMON 与聊天模板有什么关系?
LLMON 不会取代聊天模板;相反,它丰富了它们。常规聊天模板告诉模型哪个部分属于哪个角色(系统、用户、助手),而 LLMON 告诉模型每个组件的含义以及组件之间的关系,无论是在角色内部还是跨角色。
LLMON 预览模型随附自己的聊天模板,因此你可以构建与传递给任何聊天模型的相同 messages 列表,并像往常一样调用 apply_chat_template;它渲染下面显示的 LLMON。唯一的区别是现在一个回合可以命名它的部分,并标记每个部分 exec:True 或 False。标记为 True 的部分被绑定到渲染输出底部的 exec 块中,该块声明要运行的指令及其操作对象;标记为 False 的部分仍然渲染到上下文中,但没有任何引用。
messages = [ { "role": "user",
"instruction": [{ "value": "Write a short paragraph about", "exec": True }],
"data": [{ "value": "IBM Company", "exec": True }],
"requirement": [ {"value": "Use less than 10 words", "exec": True},
{"value": "Do not use commas", "exec": True}]
} ]
模型接收如下内容(此处添加了换行和缩进以提高可读性,因为模板不发出任何内容):
<|open|>instr<|:|>Ȗ<|close|>Write a short paragraph about<|open_end|>
<|open|>data<|:|>ä¦<|close|>IBM Company<|open_end|>
<|open|>req<|:|>Á¼<|close|>Use less than 10 words<|open_end|>
<|open|>req<|:|>¢¬<|close|>Do not use commas<|open_end|>
<|open|>exec<|:|>ÄÐ<|close|>
<|open|>exec<|.|>instruction<|close|>instr<|:|>Ȗ<|open_end|>
<|open|>exec<|.|>input<|close|>data<|:|>ä¦<|open_end|>
<|open|>exec<|.|>requirement<|close|>req<|:|>Á¼<|open_end|>
<|open|>exec<|.|>requirement<|close|>req<|:|>¢¬<|open_end|>
<|open|>exec<|.|>output<|close|>assistant<|:|>ãø<|open_end|>
<|open_end|>
<|open|>assistant<|:|>ãø<|close|>
这两个字符的块 ID 是从一组固定的 ID 中抽取的,这个分词器将它们编码为单个标记,因此无论抽取哪个 ID,寻址一个块始终需要两个标记。
虽然角色仍然是一个用户的回合,但其组成部分以五个独立的可寻址块的形式到达模型,并由第六个(执行块)绑定在一起,该块声明:在这个数据上执行这个指令,遵守这两个要求,并将答案放在这里命名的块中,这是模型随后填充的助手块。传统的模板会将所有组件展平为一个字符串,并让模型推断哪个部分是任务,哪个是主题,哪些是约束。
LLMON 如何应对提示注入攻击
间接提示注入是一种攻击类型,其中恶意指令隐藏在数据负载中,例如检索到的文档、工具响应或用户提供的数据。这是 LLMON 的指令/数据分离设计旨在解决的问题。
我们将 LLMON 预览与多个开源和闭源模型进行了比较。我们在 OPI 基准上进行了评估,该基准将注入放置在经典 NLP 任务的 数据中。采用了多种攻击策略。我们报告了鲁棒性,定义为 1 - 攻击成功率:模型未执行注入指令的攻击比例。
All非LLMON模型高度易受攻击,以高概率执行注入的指令。LLMON实际上在这个基准测试中消除了这个问题,相对于我们测试的最佳前沿模型避免了47%的攻击,相对于最佳开源模型避免了95%。我们在其他基准测试(ASB和StruQ)上观察到类似的趋势。值得注意的是,这些基准测试测试的是对静态间接提示注入的鲁棒性。指令/数据分离直接解决了这种类型的攻击。我们正在积极研究改进在多个聊天回合中展开的自适应攻击。
通用能力
安全性的提升不会以通用能力的损失为代价。在标准基准类别中,LLMON模型的表现与Granite 4.1 Instruct模型相当。
简而言之,如果你今天正在实验Granite 4.1 3B或8B,你可以替换为LLMON预览版,应该看到相当相当的通用性能,但提示注入的抵抗能力更强。不需要转换管道。命名回合的各个部分(例如,指令、数据、要求,如上面的示例所示)就足够了。发送的聊天模板会为你将这些转换为LLMON块。我们的LLMON-converters库更进一步:如果一个部分本身是结构化的,例如JSON文档,将其LLMON化会保留其结构作为类型的、可单独寻址的块,而不是一个不透明的字符串。
我们如何训练模型
模型从Granite 4.1基础检查点开始,而不是发布的指令模型,因此LLMON行为是在后训练期间学习的,而不是在现有的聊天格式上叠加的。
LLMON定义了六个分隔符,用于标记标签的开始和结束,并允许嵌套和锚定;它们被安装在分词器中作为保留的单个标记。我们将一个传统的指令微调语料库重新序列化为LLMON:每个提示组件都成为它自己的可寻址块,并且每个回合都包含一个执行块,命名要运行的指令、它操作的输入以及输出去向。任务混合是一个常规指令模型看到的(聊天、多回合、RAG、工具调用),这就是为什么基准测试性能与常规微调模型保持接近的原因。此外,我们使用装饰性指令和数据块来增强数据,这些块在上下文中存在但故意未绑定,而目标输出保持不变。因此,模型学习遵循执行块规定的依赖关系并忽略其余部分。强化学习随后进行:五个连续的GRPO阶段跨越多领域推理、RLHF、知识校准和数学,然后是一个最终DPO阶段,该阶段基于模型对注入尝试的自有响应构建的一千对政策偏好对。
由此产生的特权规则是从此布局中得出的,而不是添加的护栏:通过执行块到达的指令是权威的,而作为输入(数据、文档、工具模式、工具结果)到达的任何内容都是要读取的,而不是要遵循的命令。此外,执行块中未调用的指令和数据跨度被忽略。这是一种学习行为,而不是强制的保证。要看看LLMON模型中的注意力层是如何运作的,请尝试在Hugging Face Spaces上使用LLMON注意力可视化。
使用自己的词汇(ScienceWorld)
LLMON 不依赖于固定的模式:你可以选择适合你领域的标签名和结构,并微调一个适配器来读取和写入它们。我们在 ScienceWorld 上展示了这一点,这是一个基于文本的基准,其中代理通过一次发出一个命令来执行基本的科学任务(例如烧水),并从模拟器接收分数。我们定义了一个词汇表,它捕获了在解决这些任务中涉及的规划轨迹的结构。词汇表包括 instr.task.goal、req.planning_policy.rule、data.state.room、data.state.inventory 和 assistant.next_action 这样的标签。我们使用这些标签渲染了 ScienceWorld 参考解决方案的每一步,并在 LLMON 模型之上微调了一个 LoRA。然后训练好的模型玩未包含的游戏,并使用新的词汇表写入它的下一个动作。这个笔记本 演示了从转换参考轨迹到玩测试游戏以及评估未训练的基模型对适配器的评分的完整工作流程。另一个工具调用代理的例子可以在 这个笔记本 中找到。
今天试试
这是一个实验性预览,准备好进行探索和评估,但尚未用于生产。
- 模型: granite-4.1-3b-LLMON-preview & granite-4.1-8b-LLMON-preview
- 可视化演示: LLMON 注意力可视化
- LLMON 仓库: https://github.com/generative-computing/llmon
- Mellea: https://github.com/generative-computing/mellea
- 论文: https://arxiv.org/abs/2610.38120, https://arxiv.org/abs/2603.22519
告诉我们你的发现:什么有效,什么无效,以及你想看到哪些用例。在 GitHub Discussions 中发布。
来源: Hugging Face Blog · huggingface.co


