Text Generation
Transformers
ONNX
Safetensors
English
scribelm
feature-extraction
hemanth-hm
causal-lm
style-transfer
writing-assistant
wasm
conversational
custom_code
Instructions to use gnumanth/scribelm with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use gnumanth/scribelm with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="gnumanth/scribelm", trust_remote_code=True) messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("gnumanth/scribelm", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use gnumanth/scribelm with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "gnumanth/scribelm" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "gnumanth/scribelm", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/gnumanth/scribelm
- SGLang
How to use gnumanth/scribelm with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "gnumanth/scribelm" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "gnumanth/scribelm", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "gnumanth/scribelm" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "gnumanth/scribelm", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use gnumanth/scribelm with Docker Model Runner:
docker model run hf.co/gnumanth/scribelm
Upload fine-tuned ScribeLMForAuthoring (71.1M PyTorch FP32 + 95.7 MB Int8 ONNX)
Browse files- README.md +28 -0
- calibration_metrics.json +41 -0
- chat_template.jinja +6 -0
- config.json +40 -0
- model.safetensors +3 -0
- modeling_scribelm.py +268 -0
- onnx/model_quantized.onnx +3 -0
- onnx/onnx_meta.json +5 -0
- tokenizer.json +0 -0
- tokenizer_config.json +19 -0
README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
library_name: transformers
|
| 4 |
+
tags:
|
| 5 |
+
- scribelm
|
| 6 |
+
- style-transfer
|
| 7 |
+
- technical-writing
|
| 8 |
+
- onnx
|
| 9 |
+
- smollm2
|
| 10 |
+
datasets:
|
| 11 |
+
- gnumanth/scribelm-dataset
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
# `gnumanth/scribelm` — 71.1M Multi-Head Authoring & Voice Critic Model (`PyTorch FP32` + `ONNX QUInt8`)
|
| 15 |
+
|
| 16 |
+
Fine-tuned on **388 Markdown blog posts (`~230,000` tokens)** and social threads authored by **Hemanth HM** (`h3manth.com/scribe`).
|
| 17 |
+
|
| 18 |
+
## Architecture (`ScribeLMForAuthoring`, `71.13M` params)
|
| 19 |
+
- **Backbone**: 12-layer `SmolLM2` causal transformer (`d=576`, `vocab=49,152`, eager attention for WASM SIMD compatibility).
|
| 20 |
+
- **4 Joint Heads**:
|
| 21 |
+
1. `lm_head`: Causal text generation (`blog`, `rewrite`, `social`, `critic`).
|
| 22 |
+
2. `voice_head`: Calibrated `p_hemanth` authenticity probability (`AUROC = 0.9988`).
|
| 23 |
+
3. `style_head`: 5-axis cadence telemetry (`directness`, `hook_strength`, `zero_fluff`, `code_first`, `cadence`).
|
| 24 |
+
4. `task_head`: 4-way writing task router (`100.0%` held-out accuracy).
|
| 25 |
+
|
| 26 |
+
## Artifacts Included
|
| 27 |
+
- `model.safetensors`: `271.35 MB` PyTorch FP32 weights
|
| 28 |
+
- `onnx/model_quantized.onnx`: `95.71 MB` (`3.97x` smaller) `QUInt8` dynamically quantized ONNX model for `onnxruntime-web` (WASM SIMD) and CPU edge execution
|
calibration_metrics.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_id": "gnumanth/scribelm",
|
| 3 |
+
"parameters": 71129674,
|
| 4 |
+
"training_seconds": 386.42,
|
| 5 |
+
"epochs": 2,
|
| 6 |
+
"final_validation": {
|
| 7 |
+
"val_lm_loss": 4.8837,
|
| 8 |
+
"val_perplexity": 132.1137,
|
| 9 |
+
"val_task_accuracy": 1.0,
|
| 10 |
+
"val_style_mae": 0.1604,
|
| 11 |
+
"voice_auroc": 1.0,
|
| 12 |
+
"voice_ece": 0.1072,
|
| 13 |
+
"voice_brier": 0.0374,
|
| 14 |
+
"epoch": 2,
|
| 15 |
+
"train_loss": 4.7738
|
| 16 |
+
},
|
| 17 |
+
"history": [
|
| 18 |
+
{
|
| 19 |
+
"val_lm_loss": 5.1513,
|
| 20 |
+
"val_perplexity": 172.6528,
|
| 21 |
+
"val_task_accuracy": 1.0,
|
| 22 |
+
"val_style_mae": 0.1693,
|
| 23 |
+
"voice_auroc": 1.0,
|
| 24 |
+
"voice_ece": 0.0963,
|
| 25 |
+
"voice_brier": 0.0502,
|
| 26 |
+
"epoch": 1,
|
| 27 |
+
"train_loss": 7.2724
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
"val_lm_loss": 4.8837,
|
| 31 |
+
"val_perplexity": 132.1137,
|
| 32 |
+
"val_task_accuracy": 1.0,
|
| 33 |
+
"val_style_mae": 0.1604,
|
| 34 |
+
"voice_auroc": 1.0,
|
| 35 |
+
"voice_ece": 0.1072,
|
| 36 |
+
"voice_brier": 0.0374,
|
| 37 |
+
"epoch": 2,
|
| 38 |
+
"train_loss": 4.7738
|
| 39 |
+
}
|
| 40 |
+
]
|
| 41 |
+
}
|
chat_template.jinja
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% for message in messages %}{% if loop.first and messages[0]['role'] != 'system' %}{{ '<|im_start|>system
|
| 2 |
+
You are a helpful AI assistant named SmolLM, trained by Hugging Face<|im_end|>
|
| 3 |
+
' }}{% endif %}{{'<|im_start|>' + message['role'] + '
|
| 4 |
+
' + message['content'] + '<|im_end|>' + '
|
| 5 |
+
'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant
|
| 6 |
+
' }}{% endif %}
|
config.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"ScribeLMForAuthoring"
|
| 4 |
+
],
|
| 5 |
+
"auto_map": {
|
| 6 |
+
"AutoConfig": "modeling_scribelm.ScribeLMConfig",
|
| 7 |
+
"AutoModel": "modeling_scribelm.ScribeLMForAuthoring"
|
| 8 |
+
},
|
| 9 |
+
"base_model_name": "HuggingFaceTB/SmolLM2-135M-Instruct",
|
| 10 |
+
"dropout": 0.1,
|
| 11 |
+
"dtype": "float32",
|
| 12 |
+
"hidden_act": "silu",
|
| 13 |
+
"hidden_size": 576,
|
| 14 |
+
"intermediate_size": 1536,
|
| 15 |
+
"layer_indices": [
|
| 16 |
+
0,
|
| 17 |
+
1,
|
| 18 |
+
2,
|
| 19 |
+
3,
|
| 20 |
+
9,
|
| 21 |
+
12,
|
| 22 |
+
15,
|
| 23 |
+
18,
|
| 24 |
+
26,
|
| 25 |
+
27,
|
| 26 |
+
28,
|
| 27 |
+
29
|
| 28 |
+
],
|
| 29 |
+
"max_position_embeddings": 2048,
|
| 30 |
+
"model_type": "scribelm",
|
| 31 |
+
"num_attention_heads": 9,
|
| 32 |
+
"num_hidden_layers": 12,
|
| 33 |
+
"num_key_value_heads": 3,
|
| 34 |
+
"num_style_axes": 5,
|
| 35 |
+
"num_tasks": 4,
|
| 36 |
+
"rms_norm_eps": 1e-05,
|
| 37 |
+
"rope_theta": 100000.0,
|
| 38 |
+
"transformers_version": "5.12.1",
|
| 39 |
+
"vocab_size": 49152
|
| 40 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:879e8e752524fbbb5366e89837905c7c0afb026e28314029bfc354c6cd2d0a51
|
| 3 |
+
size 284532904
|
modeling_scribelm.py
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Custom Hugging Face PreTrainedConfig and PreTrainedModel for `scribelm`.
|
| 3 |
+
|
| 4 |
+
Architecture: `ScribeLMForAuthoring` (~70.8M parameters)
|
| 5 |
+
- Backbone: 12-layer Llama/SmolLM2 Causal Transformer (`hidden_size=576`, `num_attention_heads=9`,
|
| 6 |
+
`num_key_value_heads=3`, `intermediate_size=1536`, `vocab_size=49152`) initialized from
|
| 7 |
+
`HuggingFaceTB/SmolLM2-135M-Instruct`.
|
| 8 |
+
- Joint Multi-Task Heads:
|
| 9 |
+
1. `lm_head`: Causal language modeling head generating Hemanth HM blog posts, rewrites, and social threads.
|
| 10 |
+
2. `voice_head`: Calibrated `p_hemanth` logit scoring authentic practitioner voice vs corporate/LLM fluff.
|
| 11 |
+
3. `style_head`: 5-axis style telemetry head predicting `(directness, hook_strength, zero_fluff, code_first, cadence)`.
|
| 12 |
+
4. `task_head`: 4-way writing task router `(blog, rewrite, social, critic)`.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
from __future__ import annotations
|
| 16 |
+
|
| 17 |
+
from typing import Any, Dict, List, Optional
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
import torch.nn as nn
|
| 21 |
+
import torch.nn.functional as F
|
| 22 |
+
from transformers import AutoConfig, AutoModelForCausalLM, PretrainedConfig, PreTrainedModel
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
TASK_NAMES = ["blog", "rewrite", "social", "critic"]
|
| 26 |
+
TASK_TO_ID = {name: i for i, name in enumerate(TASK_NAMES)}
|
| 27 |
+
STYLE_AXES = ["directness", "hook_strength", "zero_fluff", "code_first", "cadence"]
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class ScribeLMConfig(PretrainedConfig):
|
| 31 |
+
model_type = "scribelm"
|
| 32 |
+
|
| 33 |
+
def __init__(
|
| 34 |
+
self,
|
| 35 |
+
base_model_name: str = "HuggingFaceTB/SmolLM2-135M-Instruct",
|
| 36 |
+
vocab_size: int = 49152,
|
| 37 |
+
hidden_size: int = 576,
|
| 38 |
+
intermediate_size: int = 1536,
|
| 39 |
+
num_hidden_layers: int = 12,
|
| 40 |
+
num_attention_heads: int = 9,
|
| 41 |
+
num_key_value_heads: int = 3,
|
| 42 |
+
hidden_act: str = "silu",
|
| 43 |
+
max_position_embeddings: int = 2048,
|
| 44 |
+
rms_norm_eps: float = 1e-5,
|
| 45 |
+
rope_theta: float = 100000.0,
|
| 46 |
+
num_tasks: int = 4,
|
| 47 |
+
num_style_axes: int = 5,
|
| 48 |
+
dropout: float = 0.1,
|
| 49 |
+
layer_indices: Optional[List[int]] = None,
|
| 50 |
+
**kwargs: Any,
|
| 51 |
+
) -> None:
|
| 52 |
+
super().__init__(**kwargs)
|
| 53 |
+
self.base_model_name = base_model_name
|
| 54 |
+
self.vocab_size = vocab_size
|
| 55 |
+
self.hidden_size = hidden_size
|
| 56 |
+
self.intermediate_size = intermediate_size
|
| 57 |
+
self.num_hidden_layers = num_hidden_layers
|
| 58 |
+
self.num_attention_heads = num_attention_heads
|
| 59 |
+
self.num_key_value_heads = num_key_value_heads
|
| 60 |
+
self.hidden_act = hidden_act
|
| 61 |
+
self.max_position_embeddings = max_position_embeddings
|
| 62 |
+
self.rms_norm_eps = rms_norm_eps
|
| 63 |
+
self.rope_theta = rope_theta
|
| 64 |
+
self.num_tasks = num_tasks
|
| 65 |
+
self.num_style_axes = num_style_axes
|
| 66 |
+
self.dropout = dropout
|
| 67 |
+
self.layer_indices = layer_indices or [0, 1, 2, 3, 9, 12, 15, 18, 26, 27, 28, 29]
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
class ScribeLMForAuthoring(PreTrainedModel):
|
| 71 |
+
config_class = ScribeLMConfig
|
| 72 |
+
_tied_weights_keys = ["causal_lm.lm_head.weight"]
|
| 73 |
+
all_tied_weights_keys = {"causal_lm.lm_head.weight": "causal_lm.model.embed_tokens.weight"}
|
| 74 |
+
|
| 75 |
+
def __init__(self, config: ScribeLMConfig, preload_pretrained: bool = False) -> None:
|
| 76 |
+
super().__init__(config)
|
| 77 |
+
self.config = config
|
| 78 |
+
self.all_tied_weights_keys = {"causal_lm.lm_head.weight": "causal_lm.model.embed_tokens.weight"}
|
| 79 |
+
|
| 80 |
+
llama_cfg = AutoConfig.from_pretrained(config.base_model_name)
|
| 81 |
+
llama_cfg.num_hidden_layers = config.num_hidden_layers
|
| 82 |
+
llama_cfg._attn_implementation = "eager"
|
| 83 |
+
|
| 84 |
+
if preload_pretrained:
|
| 85 |
+
full_lm = AutoModelForCausalLM.from_pretrained(
|
| 86 |
+
config.base_model_name,
|
| 87 |
+
dtype=torch.float32,
|
| 88 |
+
)
|
| 89 |
+
full_lm.config._attn_implementation = "eager"
|
| 90 |
+
keep = config.layer_indices[: config.num_hidden_layers]
|
| 91 |
+
full_lm.model.layers = nn.ModuleList([full_lm.model.layers[i] for i in keep])
|
| 92 |
+
full_lm.config.num_hidden_layers = config.num_hidden_layers
|
| 93 |
+
self.causal_lm = full_lm
|
| 94 |
+
else:
|
| 95 |
+
llama_cfg.torch_dtype = torch.float32
|
| 96 |
+
self.causal_lm = AutoModelForCausalLM.from_config(llama_cfg).float()
|
| 97 |
+
|
| 98 |
+
self.causal_lm = self.causal_lm.float()
|
| 99 |
+
h = config.hidden_size
|
| 100 |
+
self.dropout = nn.Dropout(config.dropout)
|
| 101 |
+
self.voice_head = nn.Sequential(
|
| 102 |
+
nn.Linear(h, h // 2),
|
| 103 |
+
nn.SiLU(),
|
| 104 |
+
nn.Linear(h // 2, 1),
|
| 105 |
+
)
|
| 106 |
+
self.style_head = nn.Sequential(
|
| 107 |
+
nn.Linear(h, h // 2),
|
| 108 |
+
nn.SiLU(),
|
| 109 |
+
nn.Linear(h // 2, config.num_style_axes),
|
| 110 |
+
)
|
| 111 |
+
self.task_head = nn.Linear(h, config.num_tasks)
|
| 112 |
+
self.causal_lm.lm_head.weight = self.causal_lm.model.embed_tokens.weight
|
| 113 |
+
|
| 114 |
+
def tie_weights(self, **kwargs: Any) -> None:
|
| 115 |
+
self.causal_lm.lm_head.weight = self.causal_lm.model.embed_tokens.weight
|
| 116 |
+
|
| 117 |
+
def forward(
|
| 118 |
+
self,
|
| 119 |
+
input_ids: torch.Tensor,
|
| 120 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 121 |
+
labels: Optional[torch.Tensor] = None,
|
| 122 |
+
voice_labels: Optional[torch.Tensor] = None,
|
| 123 |
+
style_labels: Optional[torch.Tensor] = None,
|
| 124 |
+
task_labels: Optional[torch.Tensor] = None,
|
| 125 |
+
) -> Dict[str, torch.Tensor]:
|
| 126 |
+
if attention_mask is None:
|
| 127 |
+
attention_mask = torch.ones_like(input_ids)
|
| 128 |
+
|
| 129 |
+
out = self.causal_lm(
|
| 130 |
+
input_ids=input_ids,
|
| 131 |
+
attention_mask=attention_mask,
|
| 132 |
+
use_cache=False,
|
| 133 |
+
output_hidden_states=True,
|
| 134 |
+
)
|
| 135 |
+
logits = out.logits
|
| 136 |
+
last_hidden = out.hidden_states[-1]
|
| 137 |
+
|
| 138 |
+
mask_f = attention_mask.unsqueeze(-1).to(last_hidden.dtype)
|
| 139 |
+
pooled = (last_hidden * mask_f).sum(dim=1) / mask_f.sum(dim=1).clamp(min=1.0)
|
| 140 |
+
pooled_drop = self.dropout(pooled)
|
| 141 |
+
|
| 142 |
+
voice_logit = self.voice_head(pooled_drop).squeeze(-1)
|
| 143 |
+
style_pred = torch.sigmoid(self.style_head(pooled_drop))
|
| 144 |
+
task_logits = self.task_head(pooled_drop)
|
| 145 |
+
|
| 146 |
+
result: Dict[str, torch.Tensor] = {
|
| 147 |
+
"logits": logits,
|
| 148 |
+
"next_token_logits": logits[:, -1, :],
|
| 149 |
+
"voice_logit": voice_logit,
|
| 150 |
+
"p_hemanth": torch.sigmoid(voice_logit),
|
| 151 |
+
"style_scores": style_pred,
|
| 152 |
+
"task_logits": task_logits,
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
total_loss = None
|
| 156 |
+
if labels is not None:
|
| 157 |
+
shift_logits = logits[:, :-1, :].contiguous()
|
| 158 |
+
shift_labels = labels[:, 1:].contiguous()
|
| 159 |
+
lm_loss = F.cross_entropy(
|
| 160 |
+
shift_logits.view(-1, shift_logits.size(-1)),
|
| 161 |
+
shift_labels.view(-1),
|
| 162 |
+
ignore_index=-100,
|
| 163 |
+
)
|
| 164 |
+
result["lm_loss"] = lm_loss
|
| 165 |
+
total_loss = lm_loss
|
| 166 |
+
|
| 167 |
+
if voice_labels is not None:
|
| 168 |
+
v_loss = F.binary_cross_entropy_with_logits(
|
| 169 |
+
voice_logit.view(-1),
|
| 170 |
+
voice_labels.view(-1).to(voice_logit.dtype),
|
| 171 |
+
)
|
| 172 |
+
result["voice_loss"] = v_loss
|
| 173 |
+
total_loss = v_loss if total_loss is None else total_loss + 0.35 * v_loss
|
| 174 |
+
|
| 175 |
+
if style_labels is not None:
|
| 176 |
+
s_loss = F.smooth_l1_loss(style_pred, style_labels.to(style_pred.dtype))
|
| 177 |
+
result["style_loss"] = s_loss
|
| 178 |
+
total_loss = s_loss if total_loss is None else total_loss + 0.45 * s_loss
|
| 179 |
+
|
| 180 |
+
if task_labels is not None:
|
| 181 |
+
t_loss = F.cross_entropy(task_logits, task_labels.view(-1).long())
|
| 182 |
+
result["task_loss"] = t_loss
|
| 183 |
+
total_loss = t_loss if total_loss is None else total_loss + 0.20 * t_loss
|
| 184 |
+
|
| 185 |
+
if total_loss is not None:
|
| 186 |
+
result["loss"] = total_loss
|
| 187 |
+
|
| 188 |
+
return result
|
| 189 |
+
|
| 190 |
+
@torch.no_grad()
|
| 191 |
+
def generate_text(
|
| 192 |
+
self,
|
| 193 |
+
tokenizer: Any,
|
| 194 |
+
prompt: str,
|
| 195 |
+
max_new_tokens: int = 96,
|
| 196 |
+
temperature: float = 0.25,
|
| 197 |
+
top_p: float = 0.9,
|
| 198 |
+
repetition_penalty: float = 1.15,
|
| 199 |
+
) -> Dict[str, Any]:
|
| 200 |
+
self.eval()
|
| 201 |
+
device = next(self.parameters()).device
|
| 202 |
+
enc = tokenizer(
|
| 203 |
+
prompt,
|
| 204 |
+
return_tensors="pt",
|
| 205 |
+
truncation=True,
|
| 206 |
+
max_length=256,
|
| 207 |
+
)
|
| 208 |
+
input_ids = enc["input_ids"].to(device)
|
| 209 |
+
attention_mask = enc["attention_mask"].to(device)
|
| 210 |
+
|
| 211 |
+
first_out = self.forward(input_ids=input_ids, attention_mask=attention_mask)
|
| 212 |
+
p_hemanth = float(first_out["p_hemanth"][0].item())
|
| 213 |
+
style_vec = [round(float(x), 4) for x in first_out["style_scores"][0].tolist()]
|
| 214 |
+
task_probs = torch.softmax(first_out["task_logits"][0], dim=-1).tolist()
|
| 215 |
+
pred_task_idx = int(torch.argmax(first_out["task_logits"][0]).item())
|
| 216 |
+
|
| 217 |
+
generated: List[int] = []
|
| 218 |
+
cur_ids = input_ids
|
| 219 |
+
cur_mask = attention_mask
|
| 220 |
+
|
| 221 |
+
eos_id = tokenizer.eos_token_id
|
| 222 |
+
for step in range(max_new_tokens):
|
| 223 |
+
if step == 0:
|
| 224 |
+
next_logits = first_out["next_token_logits"][0].clone()
|
| 225 |
+
else:
|
| 226 |
+
step_out = self.causal_lm(
|
| 227 |
+
input_ids=cur_ids,
|
| 228 |
+
attention_mask=cur_mask,
|
| 229 |
+
use_cache=False,
|
| 230 |
+
)
|
| 231 |
+
next_logits = step_out.logits[0, -1, :].clone()
|
| 232 |
+
|
| 233 |
+
# Repetition penalty over recently generated tokens
|
| 234 |
+
for seen_id in set(generated[-48:]):
|
| 235 |
+
if next_logits[seen_id] > 0:
|
| 236 |
+
next_logits[seen_id] /= repetition_penalty
|
| 237 |
+
else:
|
| 238 |
+
next_logits[seen_id] *= repetition_penalty
|
| 239 |
+
|
| 240 |
+
if temperature <= 1e-4:
|
| 241 |
+
next_token = int(torch.argmax(next_logits).item())
|
| 242 |
+
else:
|
| 243 |
+
scaled = next_logits / temperature
|
| 244 |
+
sorted_logits, sorted_indices = torch.sort(scaled, descending=True)
|
| 245 |
+
cum_probs = torch.cumsum(torch.softmax(sorted_logits, dim=-1), dim=-1)
|
| 246 |
+
remove_mask = cum_probs > top_p
|
| 247 |
+
remove_mask[..., 1:] = remove_mask[..., :-1].clone()
|
| 248 |
+
remove_mask[..., 0] = False
|
| 249 |
+
sorted_logits[remove_mask] = -float("inf")
|
| 250 |
+
probs = torch.softmax(sorted_logits, dim=-1)
|
| 251 |
+
sampled_idx = int(torch.multinomial(probs, num_samples=1).item())
|
| 252 |
+
next_token = int(sorted_indices[sampled_idx].item())
|
| 253 |
+
|
| 254 |
+
if eos_id is not None and next_token == eos_id and len(generated) >= 8:
|
| 255 |
+
break
|
| 256 |
+
generated.append(next_token)
|
| 257 |
+
next_t = torch.tensor([[next_token]], dtype=torch.long, device=device)
|
| 258 |
+
cur_ids = torch.cat([cur_ids, next_t], dim=1)
|
| 259 |
+
cur_mask = torch.cat([cur_mask, torch.ones_like(next_t)], dim=1)
|
| 260 |
+
|
| 261 |
+
text_out = tokenizer.decode(generated, skip_special_tokens=True).strip()
|
| 262 |
+
return {
|
| 263 |
+
"text": text_out,
|
| 264 |
+
"p_hemanth": round(p_hemanth, 4),
|
| 265 |
+
"predicted_task": TASK_NAMES[pred_task_idx],
|
| 266 |
+
"task_probs": {TASK_NAMES[i]: round(float(task_probs[i]), 4) for i in range(len(TASK_NAMES))},
|
| 267 |
+
"style_scores": {STYLE_AXES[i]: style_vec[i] for i in range(len(STYLE_AXES))},
|
| 268 |
+
}
|
onnx/model_quantized.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7cd3fef3858c7e5100336207d29524061e6c2b07f48dc49e8165aea44930eede
|
| 3 |
+
size 100360911
|
onnx/onnx_meta.json
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"fp32_mb": 379.86,
|
| 3 |
+
"int8_mb": 95.71,
|
| 4 |
+
"compression_ratio": 3.97
|
| 5 |
+
}
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": "<|im_start|>",
|
| 5 |
+
"clean_up_tokenization_spaces": false,
|
| 6 |
+
"eos_token": "<|im_end|>",
|
| 7 |
+
"errors": "replace",
|
| 8 |
+
"extra_special_tokens": [
|
| 9 |
+
"<|im_start|>",
|
| 10 |
+
"<|im_end|>"
|
| 11 |
+
],
|
| 12 |
+
"is_local": false,
|
| 13 |
+
"local_files_only": false,
|
| 14 |
+
"model_max_length": 8192,
|
| 15 |
+
"pad_token": "<|im_end|>",
|
| 16 |
+
"tokenizer_class": "GPT2Tokenizer",
|
| 17 |
+
"unk_token": "<|endoftext|>",
|
| 18 |
+
"vocab_size": 49152
|
| 19 |
+
}
|