From e307a93057c6b993b20162fbeeeec9e3cc974f34 Mon Sep 17 00:00:00 2001 From: ModelHub XC Date: Thu, 2 Jul 2026 23:56:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=EF=BC=8C=E7=94=B1ModelHub=20XC=E7=A4=BE=E5=8C=BA=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Model: cunxin/llama-email-fraud-detector Source: Original Platform --- .gitattributes | 36 ++++++ README.md | 284 +++++++++++++++++++++++++++++++++++++++++ chat_template.jinja | 93 ++++++++++++++ config.json | 40 ++++++ generation_config.json | 12 ++ model.safetensors | 3 + tokenizer.json | 3 + tokenizer_config.json | 22 ++++ 8 files changed, 493 insertions(+) create mode 100644 .gitattributes create mode 100644 README.md create mode 100644 chat_template.jinja create mode 100644 config.json create mode 100644 generation_config.json create mode 100644 model.safetensors create mode 100644 tokenizer.json create mode 100644 tokenizer_config.json diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..52373fe --- /dev/null +++ b/.gitattributes @@ -0,0 +1,36 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +tokenizer.json filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md new file mode 100644 index 0000000..d0f4d40 --- /dev/null +++ b/README.md @@ -0,0 +1,284 @@ +--- +language: + - en +license: llama3.2 +base_model: meta-llama/Llama-3.2-3B-Instruct +tags: + - llama + - text-generation + - email + - fraud-detection + - phishing + - cybersecurity + - fine-tuned + - lora +datasets: + - SetFit/enron_spam +metrics: + - accuracy +pipeline_tag: text-generation +model-index: + - name: llama-email-fraud-detector + results: + - task: + type: text-generation + name: Email Fraud Analysis + dataset: + name: Enron Email + Synthetic (held-out test set) + type: custom + metrics: + - name: Threat Types + type: custom + value: 11 +--- + +# Llama Email Fraud Detector (bf16) + +A fine-tuned **Llama-3.2-3B-Instruct** model for structured email fraud/phishing analysis. Given an email, the model outputs a detailed JSON verdict including 11 threat type labels, a 0-100 risk score, human-readable reasoning, and a suggested action. + +This is the **explanation layer** of a dual-model anti-fraud pipeline. The discriminative model ([cunxin/roberta-email-fraud-detector](https://huggingface.co/cunxin/roberta-email-fraud-detector), 99.5% accuracy, <50ms) provides a fast binary pre-screen; its result is passed to this generative model as a `[CLASSIFIER HINT]` prior. The final verdict is reconciled by the backend service. + +For GPUs with limited VRAM (< 12 GB), use the AWQ 4-bit quantized version: [cunxin/llama-email-fraud-detector-awq](https://huggingface.co/cunxin/llama-email-fraud-detector-awq). + +--- + +基于 **Llama-3.2-3B-Instruct** 微调的结构化邮件欺诈/钓鱼分析模型。输入一封邮件,模型输出包含 11 种威胁类型标签、0-100 风险分数、可读推理说明和建议操作的详细 JSON 判决。 + +本模型是双模型反欺诈流水线的**解释层**。判别模型([cunxin/roberta-email-fraud-detector](https://huggingface.co/cunxin/roberta-email-fraud-detector),99.5% 准确率,<50ms)提供快速二元预筛,其结果以 `[CLASSIFIER HINT]` 先验传入本生成式模型。最终判决由后端服务融合。 + +低显存 GPU(< 12 GB)请使用 AWQ 4-bit 量化版:[cunxin/llama-email-fraud-detector-awq](https://huggingface.co/cunxin/llama-email-fraud-detector-awq)。 + +## Model Details / 模型详情 + +| | | +|---|---| +| **Architecture** | `LlamaForCausalLM` (Decoder-only Transformer with RoPE, GQA, SwiGLU) | +| **Base Model** | `meta-llama/Llama-3.2-3B-Instruct` | +| **Parameters** | 3,237,063,680 (3.2B) | +| **Fine-Tuning** | LoRA (r=16, alpha=32, dropout=0.1) merged into base weights | +| **Trainable Parameters** | 24,313,856 (0.75% of total) | +| **Precision** | bfloat16 | +| **Model Size** | 6.4 GB | +| **Context Window** | 4,096 tokens (inference) / 2,048 tokens (training) | +| **Vocabulary** | 128,256 tokens | + +### Lineage / 模型血统 + +``` +meta-llama/Llama-3.2-3B-Instruct (Meta AI — instruction-tuned on 3T tokens) + │ + ├── LoRA fine-tuning (r=16, alpha=32, 7 target modules) + │ Training: ~12K email conversations with structured JSON labels + │ Hint injection: 75% correct / 15% adversarial / 10% no hint + │ + ├── Merge LoRA adapters into base weights + │ + ├─► cunxin/llama-email-fraud-detector (this model, bf16, 6.4 GB) + │ + └─► cunxin/llama-email-fraud-detector-awq (AWQ 4-bit, 2.2 GB) +``` + +## Output Format / 输出格式 + +The model outputs structured JSON with 6 fields: + +模型输出包含 6 个字段的结构化 JSON: + +```json +{ + "is_fraud": true, + "risk_score": 95, + "confidence_level": 0.97, + "detected_threats": ["DOMAIN_MISMATCH", "CREDENTIAL_REQUEST", "URGENCY_FEAR"], + "reason": "The sender domain 'amaz0n-verify.com' typosquats amazon.com. The email requests account credentials via a suspicious URL and uses urgency tactics to pressure immediate action.", + "suggestion": "Do not click any links. Do not enter any credentials. Report this email as phishing to your IT department." +} +``` + +### Threat Types & Scoring / 威胁类型与评分 + +The model detects 11 threat categories. Risk score = sum of triggered threat points (capped at 100). + +模型检测 11 种威胁类别。风险分数 = 触发的威胁点数之和(上限 100)。 + +| Label / 标签 | Points / 分值 | Description / 描述 | +|---|---|---| +| `CREDENTIAL_REQUEST` | 35 | Asks for passwords, SSN, credit card numbers / 请求密码、身份证号、信用卡号 | +| `DOMAIN_MISMATCH` | 30 | Sender domain does not match claimed organization / 发件人域名与声称的组织不匹配 | +| `URL_DISCREPANCY` | 30 | Links point to suspicious or mismatched domains / 链接指向可疑或不匹配的域名 | +| `TOO_GOOD_TO_BE_TRUE` | 30 | Unrealistic promises (lottery wins, free money) / 不切实际的承诺(中奖、免费资金) | +| `PROMPT_INJECTION` | 30 | Attempts to manipulate AI analysis / 试图操纵 AI 分析 | +| `URGENCY_FEAR` | 15 | Pressure tactics ("act now", "account suspended") / 施压策略("立即行动"、"账号已冻结") | +| `REPLY_TO_MISMATCH` | 15 | Reply-To address differs from sender / 回复地址与发件人不同 | +| `GENERIC_SALUTATION` | 8 | Impersonal greeting ("Dear Customer") / 非个人化称呼("尊敬的客户") | +| `ANOMALOUS_TIMING` | 8 | Sent at unusual hours for the timezone / 在不寻常的时间发送 | +| `MISSING_SIGNATURE` | 8 | No professional email signature / 缺少专业邮件签名 | +| `GRAMMAR_ANOMALY` | 5 | Unusual grammar or spelling patterns / 异常的语法或拼写模式 | + +**RULE D**: Any high-weight threat (>=30 pts) forces `is_fraud = true`. + +**规则 D**:任何高权重威胁(>=30 分)强制 `is_fraud = true`。 + +## Dual-Model Pipeline / 双模型流水线 + +This model is designed to work with [cunxin/roberta-email-fraud-detector](https://huggingface.co/cunxin/roberta-email-fraud-detector) in a reconciled pipeline: + +本模型设计为与 [cunxin/roberta-email-fraud-detector](https://huggingface.co/cunxin/roberta-email-fraud-detector) 配合使用: + +``` +Email Input + │ + ├──► RoBERTa (discriminative, <50ms) + │ │ + │ ▼ + │ is_fraud=True/False, confidence=0.97, risk_score=99 + │ │ + │ ▼ [CLASSIFIER HINT] + ├──► Llama (generative, ~1-3s) ◄── this model + │ │ + │ ▼ + │ Full JSON analysis (11 threat types, reasoning, suggestion) + │ + ▼ +Reconciliation (backend) + │ + ▼ +Final verdict +``` + +### STEP 4 Hint Rules / 提示规则 + +When a `[CLASSIFIER HINT]` is provided, the model applies these rules after its own independent analysis: + +| Scenario / 场景 | Action / 操作 | +|---|---| +| Both agree / 两者一致 | Keep generative result / 保留生成式结果 | +| Hint=FRAUD, gen=safe, risk < 40 | Follow hint (classifier caught something subtle) / 遵循提示 | +| Hint=FRAUD, gen=safe, RULE D triggered | Override hint (generative has hard evidence) / 推翻提示 | +| Hint=NOT FRAUD, gen=fraud, RULE D triggered | Override hint (generative has hard evidence) / 推翻提示 | +| Hint=NOT FRAUD, gen=fraud, risk < 60 | Follow hint (only weak signals) / 遵循提示 | + +## Usage / 使用方法 + +### With vLLM (Recommended) / 使用 vLLM(推荐) + +```bash +# Set in .env +MODEL_PATH=cunxin/llama-email-fraud-detector + +# Start service +docker compose --profile gpu up -d + +# Test +curl -X POST http://localhost:8000/predict_generative \ + -H "Content-Type: application/json" \ + -d '{"sender":"security@amaz0n-verify.com","subject":"URGENT: Account locked","content":"Click to verify: http://amaz0n-secure.xyz"}' +``` + +### With Transformers / 使用 Transformers + +```python +from transformers import AutoTokenizer, AutoModelForCausalLM +import torch, json + +model_name = "cunxin/llama-email-fraud-detector" +tokenizer = AutoTokenizer.from_pretrained(model_name) +model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16, device_map="auto") + +email = json.dumps({ + "date": "2026-02-25T10:00:00Z", + "sender": "security@amaz0n-verify.com", + "recipient": "you@example.com", + "subject": "URGENT: Your account has been locked", + "content": "Click here to verify: http://amaz0n-secure.xyz/verify" +}) + +messages = [ + {"role": "system", "content": "You are an email fraud analyst. Analyze the email and return a JSON verdict."}, + {"role": "user", "content": f"Analyze the following email:\n{email}"} +] + +input_ids = tokenizer.apply_chat_template(messages, return_tensors="pt").to(model.device) +output = model.generate(input_ids, max_new_tokens=512, temperature=0.1) +response = tokenizer.decode(output[0][input_ids.shape[-1]:], skip_special_tokens=True) +print(response) +``` + +## Training / 训练详情 + +### Fine-Tuning Method / 微调方法 + +| | | +|---|---| +| **Method** | LoRA (Low-Rank Adaptation) via `peft` + SFT via `trl.SFTTrainer` | +| **LoRA Rank** | 16 | +| **LoRA Alpha** | 32 (effective scale = 2x) | +| **LoRA Dropout** | 0.1 | +| **Target Modules** | `q_proj`, `k_proj`, `v_proj`, `o_proj`, `gate_proj`, `up_proj`, `down_proj` | +| **Optimizer** | AdamW (weight_decay=0.05, label_smoothing=0.05) | +| **LR Schedule** | Cosine with 10% linear warmup | +| **Learning Rate** | 2e-4 | +| **Epochs** | 3 | +| **Batch Size** | 2 (grad_accum=8, effective=16) | +| **Max Sequence Length** | 2,048 tokens | +| **Mixed Precision** | FP16 (CUDA) | +| **Loss** | Causal LM (next-token prediction on assistant turn only) | + +### Training Data / 训练数据 + +~12,000 email conversations generated from the Enron corpus and synthetic sources: + +约 12,000 个邮件对话,从 Enron 语料库和合成数据生成: + +| Source / 来源 | Count / 数量 | Role / 用途 | +|---|---|---| +| Fraud emails (train) | ~500 per class | Primary training / 主要训练集 | +| Normal emails (train) | ~500 per class | Primary training / 主要训练集 | +| Correction pool (optional) | ~14K fraud + ~15K normal | Extra training via `--include-correction` | +| AI-generated modern emails | ~800 per class | Extra training via `--include-aigen` | + +Each email is converted into a 3-turn chat conversation (system prompt -> user email -> assistant JSON verdict) with: +- **75%** include a correct `[CLASSIFIER HINT]` (teach trust of accurate priors) +- **15%** include an adversarial wrong hint (teach RULE D override) +- **10%** have no hint (teach independent reasoning) +- **60%** of fraud examples include `[HEURISTIC ANALYSIS]` context + +## Hardware Requirements / 硬件要求 + +| Configuration / 配置 | VRAM / 显存 | +|---|---| +| bf16 (this model) | >= 12 GB (RTX 3060 desktop, RTX 4070+) | +| AWQ 4-bit ([llama-email-fraud-detector-awq](https://huggingface.co/cunxin/llama-email-fraud-detector-awq)) | >= 6 GB (RTX 3050, 3060 laptop) | + +## Intended Use / 预期用途 + +- Email fraud/phishing detection with detailed threat analysis and human-readable reasoning / 提供详细威胁分析和可读推理的邮件欺诈/钓鱼检测 +- Explanation layer for automated email security systems / 自动化邮件安全系统的解释层 +- Part of a multi-model pipeline (discriminative pre-screen + generative analysis + reconciliation) / 多模型流水线的组成部分 +- Microsoft Office Add-in integration for Outlook/Word / Microsoft Office 插件集成 + +## Limitations / 局限性 + +- Primarily trained on English emails; may underperform on other languages / 主要在英文邮件上训练 +- Training data includes Enron corpus (early 2000s); modern attack patterns partially covered by AI-generated synthetic data / 训练数据包含 Enron 语料库,现代攻击模式部分由 AI 生成合成数据覆盖 +- Inference latency ~1-3s per email (use RoBERTa for real-time filtering) / 推理延迟约 1-3 秒/封 +- Structured JSON output depends on prompt engineering; edge cases may produce malformed JSON / 边缘情况可能产生格式错误的 JSON + +## Related Models / 相关模型 + +| Model / 模型 | Type / 类型 | Size / 大小 | Speed / 速度 | Use Case / 用途 | +|---|---|---|---|---| +| [cunxin/roberta-email-fraud-detector](https://huggingface.co/cunxin/roberta-email-fraud-detector) | Discriminative | 475 MB | <50ms | Fast binary pre-screen / 快速二元预筛 | +| **cunxin/llama-email-fraud-detector** (this) | Generative | 6.4 GB | ~1-3s | Detailed threat analysis / 详细威胁分析 | +| [cunxin/llama-email-fraud-detector-awq](https://huggingface.co/cunxin/llama-email-fraud-detector-awq) | Generative (quantized) | 2.2 GB | ~1-3s | Same as above, for low VRAM / 同上,低显存版 | + +## Citation / 引用 + +```bibtex +@misc{cunxin2025llama-email-fraud, + title={Llama Email Fraud Detector}, + author={cunxin}, + year={2025}, + url={https://huggingface.co/cunxin/llama-email-fraud-detector} +} +``` diff --git a/chat_template.jinja b/chat_template.jinja new file mode 100644 index 0000000..489f794 --- /dev/null +++ b/chat_template.jinja @@ -0,0 +1,93 @@ +{{- bos_token }} +{%- if custom_tools is defined %} + {%- set tools = custom_tools %} +{%- endif %} +{%- if not tools_in_user_message is defined %} + {%- set tools_in_user_message = true %} +{%- endif %} +{%- if not date_string is defined %} + {%- if strftime_now is defined %} + {%- set date_string = strftime_now("%d %b %Y") %} + {%- else %} + {%- set date_string = "26 Jul 2024" %} + {%- endif %} +{%- endif %} +{%- if not tools is defined %} + {%- set tools = none %} +{%- endif %} + +{#- This block extracts the system message, so we can slot it into the right place. #} +{%- if messages[0]['role'] == 'system' %} + {%- set system_message = messages[0]['content']|trim %} + {%- set messages = messages[1:] %} +{%- else %} + {%- set system_message = "" %} +{%- endif %} + +{#- System message #} +{{- "<|start_header_id|>system<|end_header_id|>\n\n" }} +{%- if tools is not none %} + {{- "Environment: ipython\n" }} +{%- endif %} +{{- "Cutting Knowledge Date: December 2023\n" }} +{{- "Today Date: " + date_string + "\n\n" }} +{%- if tools is not none and not tools_in_user_message %} + {{- "You have access to the following functions. To call a function, please respond with JSON for a function call." }} + {{- 'Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}.' }} + {{- "Do not use variables.\n\n" }} + {%- for t in tools %} + {{- t | tojson(indent=4) }} + {{- "\n\n" }} + {%- endfor %} +{%- endif %} +{{- system_message }} +{{- "<|eot_id|>" }} + +{#- Custom tools are passed in a user message with some extra guidance #} +{%- if tools_in_user_message and not tools is none %} + {#- Extract the first user message so we can plug it in here #} + {%- if messages | length != 0 %} + {%- set first_user_message = messages[0]['content']|trim %} + {%- set messages = messages[1:] %} + {%- else %} + {{- raise_exception("Cannot put tools in the first user message when there's no first user message!") }} +{%- endif %} + {{- '<|start_header_id|>user<|end_header_id|>\n\n' -}} + {{- "Given the following functions, please respond with a JSON for a function call " }} + {{- "with its proper arguments that best answers the given prompt.\n\n" }} + {{- 'Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}.' }} + {{- "Do not use variables.\n\n" }} + {%- for t in tools %} + {{- t | tojson(indent=4) }} + {{- "\n\n" }} + {%- endfor %} + {{- first_user_message + "<|eot_id|>"}} +{%- endif %} + +{%- for message in messages %} + {%- if not (message.role == 'ipython' or message.role == 'tool' or 'tool_calls' in message) %} + {{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n'+ message['content'] | trim + '<|eot_id|>' }} + {%- elif 'tool_calls' in message %} + {%- if not message.tool_calls|length == 1 %} + {{- raise_exception("This model only supports single tool-calls at once!") }} + {%- endif %} + {%- set tool_call = message.tool_calls[0].function %} + {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' -}} + {{- '{"name": "' + tool_call.name + '", ' }} + {{- '"parameters": ' }} + {{- tool_call.arguments | tojson }} + {{- "}" }} + {{- "<|eot_id|>" }} + {%- elif message.role == "tool" or message.role == "ipython" %} + {{- "<|start_header_id|>ipython<|end_header_id|>\n\n" }} + {%- if message.content is mapping or message.content is iterable %} + {{- message.content | tojson }} + {%- else %} + {{- message.content }} + {%- endif %} + {{- "<|eot_id|>" }} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' }} +{%- endif %} diff --git a/config.json b/config.json new file mode 100644 index 0000000..e1f8702 --- /dev/null +++ b/config.json @@ -0,0 +1,40 @@ +{ + "architectures": [ + "LlamaForCausalLM" + ], + "attention_bias": false, + "attention_dropout": 0.0, + "bos_token_id": 128000, + "dtype": "bfloat16", + "eos_token_id": [ + 128001, + 128008, + 128009 + ], + "head_dim": 128, + "hidden_act": "silu", + "hidden_size": 3072, + "initializer_range": 0.02, + "intermediate_size": 8192, + "max_position_embeddings": 131072, + "mlp_bias": false, + "model_type": "llama", + "num_attention_heads": 24, + "num_hidden_layers": 28, + "num_key_value_heads": 8, + "pad_token_id": null, + "pretraining_tp": 1, + "rms_norm_eps": 1e-05, + "rope_parameters": { + "factor": 32.0, + "high_freq_factor": 4.0, + "low_freq_factor": 1.0, + "original_max_position_embeddings": 8192, + "rope_theta": 500000.0, + "rope_type": "llama3" + }, + "tie_word_embeddings": true, + "transformers_version": "5.4.0", + "use_cache": true, + "vocab_size": 128256 +} diff --git a/generation_config.json b/generation_config.json new file mode 100644 index 0000000..174cd81 --- /dev/null +++ b/generation_config.json @@ -0,0 +1,12 @@ +{ + "bos_token_id": 128000, + "do_sample": true, + "eos_token_id": [ + 128001, + 128008, + 128009 + ], + "temperature": 0.6, + "top_p": 0.9, + "transformers_version": "5.4.0" +} diff --git a/model.safetensors b/model.safetensors new file mode 100644 index 0000000..be970f7 --- /dev/null +++ b/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:919b60928fd0c83bb839cb086ab0c2d8eb9a821fe3dd343b90ac1e54357a9f15 +size 6425529112 diff --git a/tokenizer.json b/tokenizer.json new file mode 100644 index 0000000..8e89913 --- /dev/null +++ b/tokenizer.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:912e72517f7521f3273166a7879fe54c52b397f8c48ea80f8f1ed794beb24c09 +size 17210184 diff --git a/tokenizer_config.json b/tokenizer_config.json new file mode 100644 index 0000000..786e218 --- /dev/null +++ b/tokenizer_config.json @@ -0,0 +1,22 @@ +{ + "backend": "tokenizers", + "bos_token": "<|begin_of_text|>", + "clean_up_tokenization_spaces": true, + "eos_token": "<|eot_id|>", + "is_local": true, + "max_length": 2048, + "model_input_names": [ + "input_ids", + "attention_mask" + ], + "model_max_length": 131072, + "pad_to_multiple_of": null, + "pad_token": "<|eot_id|>", + "pad_token_type_id": 0, + "padding_side": "right", + "stride": 0, + "tokenizer_class": "TokenizersBackend", + "truncation_side": "right", + "truncation_strategy": "longest_first", + "chat_template": "{{- bos_token }}\n{%- if custom_tools is defined %}\n {%- set tools = custom_tools %}\n{%- endif %}\n{%- if not tools_in_user_message is defined %}\n {%- set tools_in_user_message = true %}\n{%- endif %}\n{%- if not date_string is defined %}\n {%- if strftime_now is defined %}\n {%- set date_string = strftime_now(\"%d %b %Y\") %}\n {%- else %}\n {%- set date_string = \"26 Jul 2024\" %}\n {%- endif %}\n{%- endif %}\n{%- if not tools is defined %}\n {%- set tools = none %}\n{%- endif %}\n\n{#- This block extracts the system message, so we can slot it into the right place. #}\n{%- if messages[0]['role'] == 'system' %}\n {%- set system_message = messages[0]['content']|trim %}\n {%- set messages = messages[1:] %}\n{%- else %}\n {%- set system_message = \"\" %}\n{%- endif %}\n\n{#- System message #}\n{{- \"<|start_header_id|>system<|end_header_id|>\\n\\n\" }}\n{%- if tools is not none %}\n {{- \"Environment: ipython\\n\" }}\n{%- endif %}\n{{- \"Cutting Knowledge Date: December 2023\\n\" }}\n{{- \"Today Date: \" + date_string + \"\\n\\n\" }}\n{%- if tools is not none and not tools_in_user_message %}\n {{- \"You have access to the following functions. To call a function, please respond with JSON for a function call.\" }}\n {{- 'Respond in the format {\"name\": function name, \"parameters\": dictionary of argument name and its value}.' }}\n {{- \"Do not use variables.\\n\\n\" }}\n {%- for t in tools %}\n {{- t | tojson(indent=4) }}\n {{- \"\\n\\n\" }}\n {%- endfor %}\n{%- endif %}\n{{- system_message }}\n{{- \"<|eot_id|>\" }}\n\n{#- Custom tools are passed in a user message with some extra guidance #}\n{%- if tools_in_user_message and not tools is none %}\n {#- Extract the first user message so we can plug it in here #}\n {%- if messages | length != 0 %}\n {%- set first_user_message = messages[0]['content']|trim %}\n {%- set messages = messages[1:] %}\n {%- else %}\n {{- raise_exception(\"Cannot put tools in the first user message when there's no first user message!\") }}\n{%- endif %}\n {{- '<|start_header_id|>user<|end_header_id|>\\n\\n' -}}\n {{- \"Given the following functions, please respond with a JSON for a function call \" }}\n {{- \"with its proper arguments that best answers the given prompt.\\n\\n\" }}\n {{- 'Respond in the format {\"name\": function name, \"parameters\": dictionary of argument name and its value}.' }}\n {{- \"Do not use variables.\\n\\n\" }}\n {%- for t in tools %}\n {{- t | tojson(indent=4) }}\n {{- \"\\n\\n\" }}\n {%- endfor %}\n {{- first_user_message + \"<|eot_id|>\"}}\n{%- endif %}\n\n{%- for message in messages %}\n {%- if not (message.role == 'ipython' or message.role == 'tool' or 'tool_calls' in message) %}\n {{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\\n\\n'+ message['content'] | trim + '<|eot_id|>' }}\n {%- elif 'tool_calls' in message %}\n {%- if not message.tool_calls|length == 1 %}\n {{- raise_exception(\"This model only supports single tool-calls at once!\") }}\n {%- endif %}\n {%- set tool_call = message.tool_calls[0].function %}\n {{- '<|start_header_id|>assistant<|end_header_id|>\\n\\n' -}}\n {{- '{\"name\": \"' + tool_call.name + '\", ' }}\n {{- '\"parameters\": ' }}\n {{- tool_call.arguments | tojson }}\n {{- \"}\" }}\n {{- \"<|eot_id|>\" }}\n {%- elif message.role == \"tool\" or message.role == \"ipython\" %}\n {{- \"<|start_header_id|>ipython<|end_header_id|>\\n\\n\" }}\n {%- if message.content is mapping or message.content is iterable %}\n {{- message.content | tojson }}\n {%- else %}\n {{- message.content }}\n {%- endif %}\n {{- \"<|eot_id|>\" }}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|start_header_id|>assistant<|end_header_id|>\\n\\n' }}\n{%- endif %}\n" +} \ No newline at end of file