Text Classification
Transformers
Safetensors
deberta-v2
agents
agent-safety
tool-use
prompt-injection
deberta-v3
text-embeddings-inference
Instructions to use kontext-security/Merlin with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use kontext-security/Merlin with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="kontext-security/Merlin")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("kontext-security/Merlin") model = AutoModelForSequenceClassification.from_pretrained("kontext-security/Merlin", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Add Merlin v0.1 model release
Browse filesPublish the calibrated DeBERTa-v3-xsmall checkpoint, tokenizer, model card, preprocessing configuration, and release manifest.
- README.md +82 -0
- config.json +46 -0
- merlin_config.json +37 -0
- model.safetensors +3 -0
- release_manifest.json +29 -0
- tokenizer.json +0 -0
- tokenizer_config.json +25 -0
README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
license_name: merlin-research-release
|
| 4 |
+
base_model: microsoft/deberta-v3-xsmall
|
| 5 |
+
library_name: transformers
|
| 6 |
+
pipeline_tag: text-classification
|
| 7 |
+
tags:
|
| 8 |
+
- agents
|
| 9 |
+
- agent-safety
|
| 10 |
+
- tool-use
|
| 11 |
+
- prompt-injection
|
| 12 |
+
- deberta-v3
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# Merlin
|
| 16 |
+
|
| 17 |
+
Merlin is a 70.8M-parameter local encoder that classifies a proposed AI-agent
|
| 18 |
+
tool invocation as `safe` or `unsafe` using its surrounding context.
|
| 19 |
+
|
| 20 |
+
This repository contains the portable checkpoint. Use the reference package at
|
| 21 |
+
<https://github.com/kontext-security/merlin>; a generic Transformers pipeline
|
| 22 |
+
does **not** reproduce the benchmark because Merlin uses four independently
|
| 23 |
+
budgeted fields, deterministic history normalization, and a validation-fitted
|
| 24 |
+
calibrator.
|
| 25 |
+
|
| 26 |
+
## Inputs
|
| 27 |
+
|
| 28 |
+
1. user request
|
| 29 |
+
2. prior interaction history
|
| 30 |
+
3. current tool name and arguments
|
| 31 |
+
4. tool descriptions/schemas
|
| 32 |
+
|
| 33 |
+
Prior ReAct history is converted to canonical JSON tool/argument/observation
|
| 34 |
+
events. `Thought` and `Final Answer` text is excluded. The current action is
|
| 35 |
+
reduced to tool name and arguments. Each field has its own token budget within a
|
| 36 |
+
512-token packed sequence.
|
| 37 |
+
|
| 38 |
+
## Results
|
| 39 |
+
|
| 40 |
+
Strict binary evaluation on TS-Bench (`0.0` safe; `0.5` and `1.0` unsafe), fixed
|
| 41 |
+
0.5 threshold:
|
| 42 |
+
|
| 43 |
+
| Split | N | Accuracy | Precision | Recall | F1 |
|
| 44 |
+
|---|---:|---:|---:|---:|---:|
|
| 45 |
+
| All TS-Bench | 7,182 | 91.19% | 92.66% | 88.45% | 90.51% |
|
| 46 |
+
| ASB-Traj | 5,231 | 99.73% | 99.76% | 99.68% | 99.72% |
|
| 47 |
+
| AgentDojo-Traj | 1,220 | 71.80% | 51.14% | 50.85% | 51.00% |
|
| 48 |
+
| AgentHarm-Traj | 731 | 62.38% | 83.42% | 59.43% | 69.41% |
|
| 49 |
+
|
| 50 |
+
The pooled score is dominated by ASB-Traj and is not evidence of uniform
|
| 51 |
+
cross-environment performance. See the GitHub repository for the full protocol,
|
| 52 |
+
preprocessing code, data provenance, system measurements, and limitations.
|
| 53 |
+
|
| 54 |
+
## Training
|
| 55 |
+
|
| 56 |
+
- Base: `microsoft/deberta-v3-xsmall` at revision
|
| 57 |
+
`4b419818330868dff6a60ad3e6b1c730f8b8c0c6`
|
| 58 |
+
- Train: 2,192 examples (841 safe, 1,351 unsafe)
|
| 59 |
+
- Validation: 789 examples
|
| 60 |
+
- Epochs: 5; learning rate: 2e-5; batch size: 8; gradient accumulation: 2
|
| 61 |
+
- Sigmoid calibration coefficient: 1.427213430140093
|
| 62 |
+
- Sigmoid calibration intercept: 2.953687013257505
|
| 63 |
+
- Default threshold: 0.5
|
| 64 |
+
|
| 65 |
+
## Intended use
|
| 66 |
+
|
| 67 |
+
Use Merlin as a low-latency, local safety signal before executing an agent tool
|
| 68 |
+
call. It is not a complete authorization layer and should be combined with
|
| 69 |
+
least privilege, deterministic policy, sandboxing, and human confirmation for
|
| 70 |
+
consequential actions.
|
| 71 |
+
|
| 72 |
+
Do not use it as the sole control for high-impact actions, as a general content
|
| 73 |
+
moderator, or outside the documented input representation without evaluation.
|
| 74 |
+
|
| 75 |
+
## Data and license
|
| 76 |
+
|
| 77 |
+
The base model is MIT licensed. Merlin was fine-tuned on TS-Bench data from
|
| 78 |
+
<https://github.com/MurrayTom/ToolSafe>. That repository had no explicit
|
| 79 |
+
repository license at release time, so the checkpoint is marked `other` and no
|
| 80 |
+
raw TS-Bench examples are mirrored here. Review upstream terms before commercial
|
| 81 |
+
use or redistribution. Reference code is Apache-2.0.
|
| 82 |
+
|
config.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"DebertaV2ForSequenceClassification"
|
| 4 |
+
],
|
| 5 |
+
"attention_probs_dropout_prob": 0.1,
|
| 6 |
+
"bos_token_id": null,
|
| 7 |
+
"dtype": "float32",
|
| 8 |
+
"eos_token_id": null,
|
| 9 |
+
"hidden_act": "gelu",
|
| 10 |
+
"hidden_dropout_prob": 0.1,
|
| 11 |
+
"hidden_size": 384,
|
| 12 |
+
"id2label": {
|
| 13 |
+
"0": "safe",
|
| 14 |
+
"1": "unsafe"
|
| 15 |
+
},
|
| 16 |
+
"initializer_range": 0.02,
|
| 17 |
+
"intermediate_size": 1536,
|
| 18 |
+
"label2id": {
|
| 19 |
+
"safe": 0,
|
| 20 |
+
"unsafe": 1
|
| 21 |
+
},
|
| 22 |
+
"layer_norm_eps": 1e-07,
|
| 23 |
+
"legacy": true,
|
| 24 |
+
"max_position_embeddings": 512,
|
| 25 |
+
"max_relative_positions": -1,
|
| 26 |
+
"model_type": "deberta-v2",
|
| 27 |
+
"norm_rel_ebd": "layer_norm",
|
| 28 |
+
"num_attention_heads": 6,
|
| 29 |
+
"num_hidden_layers": 12,
|
| 30 |
+
"pad_token_id": 0,
|
| 31 |
+
"pooler_dropout": 0.0,
|
| 32 |
+
"pooler_hidden_act": "gelu",
|
| 33 |
+
"pooler_hidden_size": 384,
|
| 34 |
+
"pos_att_type": [
|
| 35 |
+
"p2c",
|
| 36 |
+
"c2p"
|
| 37 |
+
],
|
| 38 |
+
"position_biased_input": false,
|
| 39 |
+
"position_buckets": 256,
|
| 40 |
+
"relative_attention": true,
|
| 41 |
+
"share_att_key": true,
|
| 42 |
+
"tie_word_embeddings": true,
|
| 43 |
+
"transformers_version": "5.14.1",
|
| 44 |
+
"type_vocab_size": 0,
|
| 45 |
+
"vocab_size": 128005
|
| 46 |
+
}
|
merlin_config.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema_version": 1,
|
| 3 |
+
"model_name": "Merlin",
|
| 4 |
+
"task": "contextual_tool_invocation_safety",
|
| 5 |
+
"labels": {
|
| 6 |
+
"0": "safe",
|
| 7 |
+
"1": "unsafe"
|
| 8 |
+
},
|
| 9 |
+
"default_threshold": 0.5,
|
| 10 |
+
"calibration": {
|
| 11 |
+
"method": "sigmoid_on_unsafe_logit_margin",
|
| 12 |
+
"coefficient": 1.427213430140093,
|
| 13 |
+
"intercept": 2.953687013257505
|
| 14 |
+
},
|
| 15 |
+
"preprocessing": {
|
| 16 |
+
"max_length": 512,
|
| 17 |
+
"history": "thought_free_canonical_json",
|
| 18 |
+
"current_action": "tool_name_and_arguments",
|
| 19 |
+
"field_budgets": {
|
| 20 |
+
"request": 96,
|
| 21 |
+
"history": 144,
|
| 22 |
+
"action": 128,
|
| 23 |
+
"schema": 128
|
| 24 |
+
},
|
| 25 |
+
"field_markers": {
|
| 26 |
+
"request": "[USER_REQUEST]",
|
| 27 |
+
"history": "[INTERACTION_HISTORY]",
|
| 28 |
+
"action": "[CURRENT_ACTION]",
|
| 29 |
+
"schema": "[TOOL_DESCRIPTIONS]"
|
| 30 |
+
}
|
| 31 |
+
},
|
| 32 |
+
"base_model": {
|
| 33 |
+
"id": "microsoft/deberta-v3-xsmall",
|
| 34 |
+
"revision": "4b419818330868dff6a60ad3e6b1c730f8b8c0c6"
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:075d68f8bb4c1b4b98e2d2b2c0d5b013056b202172b080b34e7364b698844c86
|
| 3 |
+
size 283201512
|
release_manifest.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"files": {
|
| 3 |
+
"README.md": {
|
| 4 |
+
"sha256": "164567319e0d19e6b6668418b08cb4b74aa5038bb3f9354b532a2349e598e547",
|
| 5 |
+
"size": 2980
|
| 6 |
+
},
|
| 7 |
+
"config.json": {
|
| 8 |
+
"sha256": "efef456ee38a88cd92f6adf908a6f3d3c257fee52737ba8f05814617561b0b32",
|
| 9 |
+
"size": 1032
|
| 10 |
+
},
|
| 11 |
+
"merlin_config.json": {
|
| 12 |
+
"sha256": "11541251d6caf677e3f621627e95ced7f3fd228e008ccdf6c7c2343b5ef76011",
|
| 13 |
+
"size": 888
|
| 14 |
+
},
|
| 15 |
+
"model.safetensors": {
|
| 16 |
+
"sha256": "075d68f8bb4c1b4b98e2d2b2c0d5b013056b202172b080b34e7364b698844c86",
|
| 17 |
+
"size": 283201512
|
| 18 |
+
},
|
| 19 |
+
"tokenizer.json": {
|
| 20 |
+
"sha256": "d6c20af053b5d86d986a9f70898c1fceccb9d93e7ce6f63dabc899a12a53b031",
|
| 21 |
+
"size": 8340654
|
| 22 |
+
},
|
| 23 |
+
"tokenizer_config.json": {
|
| 24 |
+
"sha256": "141468772d3b095cc30275fd9c05dff92a78619c341487da9f5549a3564ea6cb",
|
| 25 |
+
"size": 601
|
| 26 |
+
}
|
| 27 |
+
},
|
| 28 |
+
"schema_version": 1
|
| 29 |
+
}
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": true,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": "[CLS]",
|
| 5 |
+
"cls_token": "[CLS]",
|
| 6 |
+
"do_lower_case": false,
|
| 7 |
+
"eos_token": "[SEP]",
|
| 8 |
+
"extra_special_tokens": [
|
| 9 |
+
"[USER_REQUEST]",
|
| 10 |
+
"[INTERACTION_HISTORY]",
|
| 11 |
+
"[CURRENT_ACTION]",
|
| 12 |
+
"[TOOL_DESCRIPTIONS]"
|
| 13 |
+
],
|
| 14 |
+
"is_local": false,
|
| 15 |
+
"local_files_only": false,
|
| 16 |
+
"mask_token": "[MASK]",
|
| 17 |
+
"model_max_length": 1000000000000000019884624838656,
|
| 18 |
+
"pad_token": "[PAD]",
|
| 19 |
+
"sep_token": "[SEP]",
|
| 20 |
+
"split_by_punct": false,
|
| 21 |
+
"tokenizer_class": "DebertaV2Tokenizer",
|
| 22 |
+
"unk_id": 3,
|
| 23 |
+
"unk_token": "[UNK]",
|
| 24 |
+
"vocab_type": "spm"
|
| 25 |
+
}
|