LLMs는 다음 토큰을 생성하기 위해 컨텍스트(context)에 의존합니다. 긴 추이를 거치면서 컨텍스트는 시스템 프롬프트(system prompt), 과거 대화 턴, 검색된 문서를 기반으로 작동하는 지침, 도구 응답 또는 사용자 데이터, 허용되는 출력을 제약하는 요구 사항, 그리고 추론 체인 등으로 수많은 유형의 구성 요소로 채워집니다. 컨텍스트는 풍부한 구조를 가지고 있으며, 그 대부분은 모델에게 암묵적이거나 LLM이 처리하도록 설계되지 않은 JSON과 같은 형식에 인코딩되어 있습니다. 이것이 LLMs, 특히 규모가 작은 모델들이 취약하여 때때로 예상치 못한 방식으로 실패하는 주요 이유 중 하나입니다. 명시적인 구조의 부족은 또한 공격자들에 의해 악용될 수 있으며, 예를 들어 프롬프트 주입(prompt injection) 형태를 띨 수 있습니다.
이 문제를 해결하기 위해, 우리는 모델에게 구조와 의미론을 명시적으로 전달하는 LLM 네이티브 마크업 언어인 LLMON (LLM Object Notation, 발음은 “레몬”)을 개발했습니다. 의미론적으로 일관된 구성 요소들은 의미 있는 태그로 표시되며 예약된 특수 토큰 구분자(reserved special-token delimiters)로 감싸집니다. 중첩을 포함한 데이터 스키마는 인과적 LLM(causal LLM)에게 모호하지 않은 방식으로 기술됩니다. 고유 ID를 사용하면 컨텍스트의 어느 곳에나 존재할 수 있는 특정 지침을 가리킬 수 있으며, 이를 해당 지침이 작동해야 하는 데이터 페이로드와 연결할 수 있습니다. 이는 프로그래밍 언어에서 함수가 호출되고 인수가 전달되는 방식과 유사합니다.
오늘 우리는 Granite 4.1 기본 모델에서 파생되었으며, LLMON으로 마크업된 텍스트를 소비하고 생성하도록 훈련된 두 가지 실험적 프리뷰 모델, 즉 granite-4.1-3b-LLMON-preview와 granite-4.1-8b-LLMON-preview를 출시합니다. 또한 LLMON을 다루는 도구 키트(toolkit)와 워크플로우 및 템플릿 예시가 포함된 GitHub 저장소도 공개합니다.
이것이 가능하게 하는 것:
사용자 데이터에 숨겨진 간접 프롬프트 주입(Indirect prompt injections)은 명시적인 지침/데이터 분리 덕분에 LLMON 모델에 의해 대부분 무시됩니다. 일부 벤치마크에서는 공격 성공률이 거의 0으로 떨어지는 반면, 일반적인 명령어 조정(instruction-tuned) 모델들은 높은 확률로 탈취당합니다. 이는 Granite 4.1 Instruct 모델 대비 일반적인 성능을 유지하면서 달성되었습니다.
각 지침이 적용되는 정확한 데이터에 바인딩되기 때문에 관련 없는 구절, 오래된 채팅 턴(chat turns), 도구 출력(tool outputs)이 답변으로 끌어와지지 않습니다.
지침(Instructions), 데이터(data), 요구사항(requirements)은 명확하게 표시되어 애플리케이션 코드 수준에서 모델이 그 구조와 의미를 활용할 수 있습니다. Mellea에서는 LLM 호출을 자동으로 LLMON화하여 네이티브 LLMON 지원을 제공하므로 이를 사용해 볼 수 있습니다.
더 이상 LLM에게 JSON 구조를 준수하도록 강제하는 것에 대해 걱정할 필요가 없습니다. 변환기(converters)를 사용하여 기존 JSON을 손실 없이 LLMON으로 변환하세요. 또한 자체 구조와 관련 태그를 정의하고, 이를 이해하기 위해 LLMON 모델 위에 LoRA를 튜닝할 수도 있습니다.
JSON은 파서(parsers)를 위해 설계되었지, 인과 언어 모델(causal language models)을 위한 것이 아닙니다. 토크나이저는 문법을 존중하도록 제약되지 않으며, 구조는 일반 텍스트에서도 나타날 수 있는 토큰({, ", :})에 의해 인코딩됩니다. 모델에게 있어 문서 내부의 따옴표와 필드를 닫는 따옴표는 동일한 토큰입니다. 파서에게 명확한 이스케이프 규칙(Escaping rules)은 모델에게 단지 통계적 패턴일 뿐입니다. 중첩 깊이(Nesting depth)는 대괄호를 세어 인코딩되는데, 트랜스포머(transformers)가 특히 긴 범위에서 취약한 것으로 알려진 부분입니다.
반면에 LLMON은 구조적 구분자(structural delimiters)가 문자가 아닌 예약된 특수 토큰인 XML과 유사한 마크업 언어입니다. 따라서 구조와 내용은 어휘의 별도 부분을 사용합니다. 태그는 각 스팬(span)의 시작 부분에 명시되며, 스팬 간 경계는 명확합니다. 중첩 구조는 로컬하게(locally) 정의되므로 모델이 긴 범위에 걸쳐 계층 구조를 추적할 필요가 없습니다.
대부분의 팀이 이미 JSON을 기반으로 파이프라인을 구축하고 있기 때문에, 우리는 JSON을 손실 없이(lossless) LLMON으로 변환하고 다시 되돌리는 변환 도구와 예제 노트북을 만들었습니다.
LLMON은 채팅 템플릿을 대체하는 것이 아니라, 이를 풍부하게 만듭니다. 일반적인 채팅 템플릿이 모델에게 어떤 부분이 어떤 역할(system, user, assistant)에 속하는지 알려주는 반면, LLMON은 각 구성 요소가 무엇을 의미하며, 역할 내부와 역할을 가로질러 어떻게 서로 관련되는지를 알려줍니다.
LLMON 프리뷰 모델에는 자체 채팅 템플릿이 포함되어 있으므로, 평소와 같이 모든 채팅 모델에 전달할 messages 리스트를 구성하고 apply_chat_template을 호출하면 아래에 표시된 LLMON이 렌더링됩니다. 유일한 차이점은 이제 한 턴(turn)이 자신의 부분에 이름을 붙이고 각각의 부분을 exec: True 또는 False로 표시할 수 있다는 것입니다. True로 표시된 부분은 렌더링된 출력 하단에 있는 exec 블록에 바인딩되어, 어떤 지침을 실행해야 하는지, 그리고 그것이 무엇을 대상으로 작동하는지를 명시합니다. 반면, False로 표시된 부분은 여전히 컨텍스트에 렌더링되지만 아무것도 참조하지 않습니다.
messages = [ { "role": "user",
"instruction": [{ "value": "Write a short paragraph about", "exec": True }],
"data": [{ "value": "IBM Company", "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|>
...
두 글자 블록 ID는 이 토크나이저가 단일 토큰으로 인코딩하는 고정된 세트에서 가져오므로, 어떤 ID가 사용되든 블록을 지정하는 데 항상 2개의 토큰 비용이 발생합니다.
역할(role)은 여전히 단일 사용자 턴이지만, 그 구성 요소들은 모델에 다섯 개의 분리 가능한 주소 지정 블록으로 도달하며, 여섯 번째 블록(실행 블록, exec block)이 이들을 하나로 묶습니다. 이 실행 블록은 '이 지침을, 이 데이터에 대해, 다음 두 가지 제약 조건의 적용을 받아 실행하고, 그 답을 여기에 이름 붙여진 블록에 넣으라'고 명시합니다. 기존의 템플릿 방식이었다면 모든 구성 요소를 하나의 문자열로 평탄화(flattened)하여 모델이 어떤 부분이 작업이고, 어떤 부분이 주제이며, 어떤 부분이 제약 조건인지 추론하도록 맡겼을 것입니다.
간접 프롬프트 주입(Indirect prompt injection)은 검색된 문서, 도구 응답 또는 사용자 제공 데이터와 같은 데이터 페이로드에 악성 명령어가 숨겨지는 유형의 공격입니다. 이는 LLMON의 지침/데이터 분리 구조가 해결하도록 설계된 문제입니다.
우리는 여러 오픈 소스 및 클로즈드 소스 모델과 비교하여 LLMON 미리 보기 버전을 테스트했습니다. 우리는 고전적인 자연어 처리(NLP) 작업의 데이터에 주입을 배치하는 OPI 벤치마크를 사용하여 평가했습니다. 몇 가지 공격 전략이 사용되었습니다. 우리는 강건성(robustness), 즉 '1 − 공격 성공률'로 정의되는 지표를 보고합니다. 이는 모델이 주입된 명령어를 수행하지 않는 공격의 비율입니다.
LLMON이 아닌 모든 모델은 매우 취약하여, 높은 확률로 주입된 명령어들을 실행했습니다. LLMON은 이 벤치마크에서 문제를 사실상 제거했으며, 테스트한 최고의 최신(frontier) 모델 대비 47% 더 많은 공격을 회피했고, 최고의 오픈 소스 모델 대비 95%를 초과하는 수치를 보였습니다. 우리는 다른 벤치마크(ASB 및 StruQ)에서도 유사한 추세를 관찰했습니다. 주목할 점은 이 벤치마크들이 정적 간접 프롬프트 주입에 대한 강건성을 테스트한다는 것입니다. 지침/데이터 분리 구조는 이러한 유형의 공격을 직접적으로 해결합니다. 우리는 여러 채팅 턴에 걸쳐 전개되는 적응형 공격(adaptive attacks) 개선에도 적극적으로 노력하고 있습니다.
안전성 향상은 일반적인 성능 저하를 초래하지 않습니다. 표준 벤치마크 카테고리 전반에 걸쳐, LLMON 모델들은 Granite 4.1 Instruct 모델과 비슷한 수준의 성능을 발휘했습니다.
요약하자면, 오늘 Granite 4.1 3B 또는 8B를 실험해 본다면 LLMON 프리뷰를 교체하여 사용할 수 있으며, 프롬프트 주입(prompt injection)에 대한 저항력이 훨씬 강력하면서도 유사한 일반 성능을 확인할 수 있습니다. 별도의 변환 파이프라인은 필요하지 않습니다. 터널의 부분 이름 지정(예: 위 예시에서와 같은 instruction, data, requirement)만으로 충분합니다. 제공되는 채팅 템플릿이 이를 LLMON 블록으로 자동 변환해 줍니다. 당사의 LLMON-converters 라이브러리는 한 단계 더 깊게 들어갑니다. 만약 해당 부분이 JSON 문서처럼 자체적으로 구조화되어 있다면, LLMON으로 변환하는 과정에서 그 구조를 하나의 불투명한 문자열(opaque string)이 아닌, 유형별로 개별 주소 지정 가능한 블록(typed, individually addressable blocks) 형태로 보존합니다.
해당 모델들은 출시된 명령어 모델(instruct models) 대신 Granite 4.1 기본 체크포인트(base checkpoints)에서 시작하기 때문에, LLMON 동작 방식은 기존 채팅 형식 위에 레이어링되는 것이 아니라 포스트 트레이닝(post-training) 과정에서 학습됩니다.
LLMON은 태그의 시작과 끝을 표시하고 중첩 및 고정(anchoring)을 허용하는 6개의 구분자(delimiters)를 정의하며, 이는 토크나이저에 예약된 단일 토큰으로 설치됩니다. 우리는 기존 명령어 튜닝 코퍼스(instruction-tuning corpus)를 LLMON 형식으로 재직렬화했습니다. 모든 프롬프트 구성 요소가 자체 주소 지정 가능한 블록이 되며, 각 터널은 실행 블록(execution block)을 포함하여 어떤 명령어를 실행할지, 어떤 입력값을 사용할지, 그리고 출력이 어디로 갈지를 명시합니다.
작업 혼합(task mix)은 일반 명령어 모델이 보는 것과 동일합니다 (채팅, 다중 턴(multi-turn), RAG, 도구 호출(tool calling)). 이것이 바로 벤치마크 성능이 기존에 튜닝된 모델과 가깝게 유지되는 이유입니다. 게다가, 우리는 데이터에 미끼 명령어(decoy instructions)와 데이터 블록을 추가하여 컨텍스트 내에 존재하지만 의도적으로 연결되지 않은 상태로 남겨두고, 목표 출력은 변경하지 않았습니다. 따라서 모델은 실행 블록이 지시하는 종속성을 따르고 나머지는 무시하도록 학습합니다.
강화학습(Reinforcement learning) 단계가 이어집니다: 다중 도메인 추론, RLHF, 지식 보정(knowledge calibration), 수학을 아우르는 5단계의 순차적 GRPO 단계가 진행된 후, 모델 자체 응답을 이용해 구축한 천 개의 온-정책 선호 쌍(on-policy preference pairs)에 대한 최종 DPO 단계가 수행됩니다.
결과적인 권한 규칙은 추가된 가드레일(guardrail)이라기보다는 이 레이아웃 자체에서 도출됩니다. 실행 블록을 통해 전달되는 명령어는 권위적이며, 입력으로 전달되는 모든 것(데이터, 문서, 도구 스키마, 도구 결과)은 따를 명령이 아니라 읽어야 할 자료입니다. 게다가, 실행 블록에서 호출되지 않은 명령어와 데이터 범위는 무시됩니다. 이는 강제된 보장이 아닌 학습된 행동입니다.
이 현상이 LLMON 모델의 어텐션 레이어(attention layer)에서 어떻게 작동하는지 확인하려면 Hugging Face Spaces의 LLMON Attention Visualization을 사용해 보세요.
LLMON은 고정된 스키마에 묶여 있지 않습니다. 사용자는 자신의 도메인에 맞는 태그 이름과 구조를 선택하고, 이를 읽고 쓰는 어댑터(adapter)를 미세 조정할 수 있습니다. 우리는 에이전트가 한 번에 하나의 명령을 내리고 시뮬레이터로부터 점수를 받으며 기초 과학 과제(예: 물 끓이기)를 수행하는 텍스트 기반 벤치마크인 ScienceWorld에서 이를 시연합니다. 우리는 이러한 과제를 해결하는 데 관련된 계획 궤적(planning trajectories)의 구조를 포착하는 어휘집을 정의했습니다. 이 어휘집에는 instr.task.goal, req.planning_policy.rule, data.state.room, data.state.inventory, 그리고 assistant.next_action과 같은 태그가 포함됩니다. 우리는 ScienceWorld의 참조 솔루션(reference solutions)의 모든 단계를 이 태그들로 렌더링하고 LLMON 모델 위에 LoRA를 조정했습니다.
훈련된 모델은 그 후 별도로 보관된 게임(held-out games)을 플레이하고 새로운 어휘집으로 다음 행동을 작성합니다. 이 노트북은 참조 궤적을 변환하는 것부터 테스트 게임을 플레이하고 비훈련 기반 모델 대비 어댑터의 점수를 매기는 전체 워크플로우를 안내합니다. 도구 호출 에이전트(tool-calling agents)를 위한 또 다른 예시는 이 노트북에서 찾을 수 있습니다.
이것은 탐색 및 평가 준비는 되었지만 프로덕션(production)용은 아닌 실험적 미리 보기입니다.
발견한 내용을 알려주세요: 무엇이 작동했는지, 어떤 문제점(broke)이 있었는지, 그리고 어떤 사용 사례를 보고 싶은지. GitHub Discussions에 게시해 주세요.