IBM推LLMON标记语言:用结构化标签防住大模型提示注入
IBM Granite团队推出LLMON,一种专为大语言模型设计的标记语言。它通过显式分离指令与数据,利用保留特殊令牌界定结构,显著降低提示注入攻击成功率。新版3B和8B预览模型在保持通用能力的同时,能精准识别执行块,忽略未绑定的干扰信息,为构建更安全的AI应用提供了新思路。
大模型为什么要有一套自己的标记语言
大语言模型(LLM)干活的基本方式,是盯着上下文一个令牌接一个令牌往下生成。对话轮次一多、任务一复杂,上下文窗口里就堆满了东西:系统提示词、历史对话、检索到的文档片段、工具返回的结果,还有用户输入的数据。这些内容搅在一起,结构多半是隐式的,或者只能硬塞进JSON之类的格式里。
麻烦在于,JSON这类格式原本是给程序解析器设计的,不是给因果语言模型“消化”的。对模型来说,JSON里的引号和括号不过是普通令牌,嵌套层级、转义规则它并不真懂。结构上这么一含糊,小型模型容易出错,安全上也留了口子——攻击者能把恶意指令藏进用户数据,诱导模型去做不该做的事,这就是“提示注入”。
IBM Granite团队为此做了LLMON(LLM Object Notation,读作“lemon”)。这是一种原生于大语言模型的标记语言,目的是把结构和语义明明白白告诉模型。LLMON用有意义的标签把语义连贯的组件包起来,边界则靠保留的特殊令牌分隔符来划定。数据模式连同嵌套关系,对因果LLM来说就此没了歧义。更关键的是它引入了唯一ID机制,指令可以指向上下文里任意特定的数据负载,精确程度类似编程语言中函数调用传参。
眼下IBM基于Granite 4.1基础模型放出了两个实验性预览版本:granite-4.1-3b-LLMON-preview和granite-4.1-8b-LLMON-preview。相关工具库也在GitHub上开源了,里面有处理LLMON的工具包、工作流示例和模板。
JSON为大模型所不适的缘由
不少开发者习惯拿JSON和大模型打交道,其实这是种妥协。JSON的结构靠字符支撑,比如{、"、:而这些字符在正常文本里照样会出现。tokenizer(分词器)并没有被约束去尊重JSON语法。在模型眼里,文档内部的引号和闭合字段的引号是同一个令牌。解析器看着清晰的转义规则,对模型只是统计规律。再加上Transformer架构处理长跨度内的括号计数和嵌套深度本来就弱,结构解析很容易出错。
LLMON不一样。它类似XML,但结构分隔符用的是tokenizer词汇表里的保留特殊令牌,不是普通字符。也就是说,结构和内容分属词汇表的不同部分。每个片段开头都明确声明标签,片段之间的边界一眼可见。嵌套结构在局部声明,模型不必在长上下文里追着层级跑。
大多数团队已有基于JSON的流程,IBM也考虑到了,提供了转换工具,JSON转LLMON、LLMON转JSON都能无损完成。迁移门槛因此降低,开发者不用重构整个数据管道就能试新方案。
LLMON与聊天模板之间是什么关系
LLMON不是要取代聊天模板,而是给它加码。传统聊天模板告诉模型哪部分属于哪个角色(如system、user、assistant),LLMON则进一步说明每个组件是什么意思,以及组件之间在角色内部、跨角色如何关联。
LLMON预览模型自带专用聊天模板。开发者构建消息列表的方式与常规聊天模型无异,调用apply_chat_template即可。不同之处在于,现在可以给对话轮次的各个部分命名,并标记exec: True 或 False。
标记为 True的部分会被绑定到渲染输出底部的exec块中,明确指定要运行哪条指令、作用于哪些数据;标记为False的部分仍会渲染到上下文里,但不会被任何指令引用。举个例子,一个用户请求可能包含指令、数据、需求三部分,LLMON会把它们渲染成五个独立的可寻址块,再用第六个块(exec块)把它们串起来:执行该指令,使用该数据,遵循这些要求,并把答案填进指定的助手块。
传统模板则把所有组件压扁成一个字符串,哪部分是任务、哪部分是主体、哪部分是约束,全得模型自己猜。LLMON用显式绑定把这种猜测去掉了。
提示注入攻击如何被挡住
间接提示注入是常见攻击手段,恶意指令藏在检索文档、工具响应或用户提供的数据载荷里。LLMON的核心设计——指令与数据显式分离——针对的正是这一点。
OPI基准测试中,研究人员把注入指令藏在经典NLP任务的数据部分。结果显示,非LLMON模型极易中招,高概率执行注入的恶意指令;LLMON模型在该基准测试中几乎把这一问题抹平。与测试中表现最好的前沿模型相比,LLMON多挡下47%的攻击;与最好的开源模型相比,这个数字达到95%。ASB、StruQ等其他基准测试也呈现类似趋势。
安全性提升来自LLMON的“特权规则”:只有经执行块到达的指令才有权威性,作为输入到达的内容(数据、文档、工具结果)只算阅读材料,不是待执行的命令。没在执行块中被调用的指令和数据片段,模型会忽略。这是学出来的行为,不是硬编码的护栏。
通用能力没有因此打折
一般说来,安全加固往往要拿通用能力换,LLMON模型没走这条路。在标准基准测试类别中,LLMON模型的表现与Granite 4.1 Instruct模型持平。
换句话说,眼下用Granite 4.1 3B或8B的人,换成LLMON预览版就行。转换管道不用动,只要在构建消息时给轮次各部分起好名字,比如instruction、data、requirement,内置聊天模板会自己把它转成LLMON块。通用性能基本相当,抗提示注入的能力则更强。
碰上本身就带结构的内容,比如JSON文档,交给LLMON转换器处理,它会被保留成有类型、可单独寻址的块,而非一坨不透明的字符串。这样一来,模型对复杂数据结构的理解能更细。
模型训练细节
LLMON的训练起点是Granite 4.1基础检查点,并非在已发布的Instruct模型上叠加。也就是说,它的行为是在后训练阶段学到的。
这套模型定义了六个分隔符,用来标记标签的起止,支持嵌套和锚定,并以保留的单令牌形式装进tokenizer。研究团队把传统指令微调语料重新序列化成LLMON格式:每个提示组件都成为可单独寻址的块,每个轮次带一个执行块,写明要跑哪条指令、操作什么对象、结果输出到哪里。
任务混合里保留了常规Instruct模型见过的东西,聊天、多轮对话、RAG、工具调用都在,所以基准测试成绩能保持接近。数据中还加进了诱饵指令和数据块——它们在上下文里,却故意不被绑定,目标输出照旧不变。模型因此得学会按执行块规定的依赖关系走,其余部分一概不理。
之后是强化学习:五个顺序的GRPO阶段,覆盖多领域推理、RLHF、知识校准和数学,最后接一个基于DPO的阶段,所用的一千个在线偏好对取自模型自身对注入尝试的响应。
自定义词汇表:以ScienceWorld为例
LLMON并不绑死在某套固定模式上。标签名称和结构可以按领域自己选,再微调适配器让它读写这些标签。
在ScienceWorld基准测试中,代理要发出命令来完成烧水这类基础科学任务。研究团队定义了一套词汇表,用来捕获规划轨迹的结构,其中包括instr.task.goal、req.planning_policy.rule、data.state.room等标签。参考解决方案的每一步都用这些标签渲染,随后在LLMON模型之上微调了一个LoRA。
训练后的模型在持有游戏中表现不错,还能用新词汇表写出下一步动作。这正说明LLMON的灵活:开发者可以给特定应用场景定义专属的结构化语言,再用轻量级微调让模型学会。GitHub仓库里有完整笔记本示例,从转换参考轨迹到玩游戏、评分,全过程都覆盖了。
如何开始尝试
这次放出的LLMON模型是实验性预览版,适合探索和评估,眼下不建议直接上生产环境。想试的话,可以从Hugging Face获取granite-4.1-3b-LLMON-preview和granite-4.1-8b-LLMON-preview两个模型。
想直观看看LLMON在注意力层怎么工作,可以跑一下LLMON Attention Visualization演示。另外,Mellea项目已经原生支持LLMON,能自动把LLM调用“LLMON化”,是个不错的上手工具。
IBM团队希望开发者在GitHub Discussions里反馈使用感受:哪些地方管用,哪些地方出问题,还希望看到哪些用例。这种早期反馈对完善LLMON生态很关键。参与的人多了,LLMON有希望成为构建安全、可靠大模型应用的标准基础设施之一。