Instructions to use plasmova/nova-v3 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use plasmova/nova-v3 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="plasmova/nova-v3", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("plasmova/nova-v3", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use plasmova/nova-v3 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "plasmova/nova-v3" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "plasmova/nova-v3", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/plasmova/nova-v3
- SGLang
How to use plasmova/nova-v3 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 "plasmova/nova-v3" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "plasmova/nova-v3", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'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 "plasmova/nova-v3" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "plasmova/nova-v3", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use plasmova/nova-v3 with Docker Model Runner:
docker model run hf.co/plasmova/nova-v3
Add KV cache support for generation
Browse files- modeling_nova.py +63 -12
modeling_nova.py
CHANGED
|
@@ -2,7 +2,7 @@ import torch
|
|
| 2 |
import torch.nn as nn
|
| 3 |
import torch.nn.functional as F
|
| 4 |
from transformers import GenerationMixin, PreTrainedModel
|
| 5 |
-
from transformers.modeling_outputs import
|
| 6 |
|
| 7 |
try:
|
| 8 |
from .configuration_nova import NovaConfig
|
|
@@ -45,7 +45,7 @@ class NovaBlock(nn.Module):
|
|
| 45 |
self.up = nn.Linear(d, ff, bias=False)
|
| 46 |
self.down = nn.Linear(ff, d, bias=False)
|
| 47 |
|
| 48 |
-
def forward(self, x, cos, sin, attention_mask):
|
| 49 |
batch, length, _ = x.shape
|
| 50 |
h = self.n1(x)
|
| 51 |
q = self.wq(h).view(batch, length, self.h, self.hd)
|
|
@@ -54,17 +54,26 @@ class NovaBlock(nn.Module):
|
|
| 54 |
q = _rope(self.qn(q), cos, sin).to(v.dtype).transpose(1, 2)
|
| 55 |
k = _rope(self.kn(k), cos, sin).to(v.dtype).transpose(1, 2)
|
| 56 |
v = v.transpose(1, 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
repeat = self.h // self.kv
|
| 58 |
k = k.repeat_interleave(repeat, dim=1)
|
| 59 |
v = v.repeat_interleave(repeat, dim=1)
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
mask = causal[None, None, :, :]
|
| 62 |
if attention_mask is not None:
|
| 63 |
mask = mask & attention_mask[:, None, None, :].to(torch.bool)
|
| 64 |
out = F.scaled_dot_product_attention(q, k, v, attn_mask=mask)
|
| 65 |
x = x + self.wo(out.transpose(1, 2).reshape(batch, length, -1))
|
| 66 |
h = self.n2(x)
|
| 67 |
-
|
|
|
|
| 68 |
|
| 69 |
|
| 70 |
class NovaModel(PreTrainedModel):
|
|
@@ -99,25 +108,42 @@ class NovaModel(PreTrainedModel):
|
|
| 99 |
attention_mask=None,
|
| 100 |
position_ids=None,
|
| 101 |
inputs_embeds=None,
|
|
|
|
|
|
|
| 102 |
**kwargs,
|
| 103 |
):
|
| 104 |
if inputs_embeds is None:
|
| 105 |
inputs_embeds = self.emb(input_ids)
|
| 106 |
batch, length, _ = inputs_embeds.shape
|
| 107 |
if position_ids is None:
|
| 108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
cos = self.cos[position_ids].unsqueeze(-2)
|
| 110 |
sin = self.sin[position_ids].unsqueeze(-2)
|
| 111 |
hidden = inputs_embeds
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
|
| 116 |
|
| 117 |
class NovaForCausalLM(PreTrainedModel, GenerationMixin):
|
| 118 |
config_class = NovaConfig
|
| 119 |
base_model_prefix = "model"
|
| 120 |
_tied_weights_keys = []
|
|
|
|
| 121 |
|
| 122 |
def __init__(self, config):
|
| 123 |
super().__init__(config)
|
|
@@ -134,8 +160,25 @@ class NovaForCausalLM(PreTrainedModel, GenerationMixin):
|
|
| 134 |
return None
|
| 135 |
|
| 136 |
def prepare_inputs_for_generation(self, input_ids, attention_mask=None, **kwargs):
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
def forward(
|
| 141 |
self,
|
|
@@ -144,13 +187,19 @@ class NovaForCausalLM(PreTrainedModel, GenerationMixin):
|
|
| 144 |
position_ids=None,
|
| 145 |
inputs_embeds=None,
|
| 146 |
labels=None,
|
|
|
|
|
|
|
| 147 |
**kwargs,
|
| 148 |
):
|
| 149 |
-
|
|
|
|
|
|
|
| 150 |
input_ids=input_ids,
|
| 151 |
attention_mask=attention_mask,
|
| 152 |
position_ids=position_ids,
|
| 153 |
inputs_embeds=inputs_embeds,
|
|
|
|
|
|
|
| 154 |
)
|
| 155 |
logits = F.linear(hidden, self.model.emb.weight)
|
| 156 |
loss = None
|
|
@@ -160,5 +209,7 @@ class NovaForCausalLM(PreTrainedModel, GenerationMixin):
|
|
| 160 |
labels[..., 1:].contiguous().view(-1),
|
| 161 |
ignore_index=-100,
|
| 162 |
)
|
| 163 |
-
return
|
|
|
|
|
|
|
| 164 |
|
|
|
|
| 2 |
import torch.nn as nn
|
| 3 |
import torch.nn.functional as F
|
| 4 |
from transformers import GenerationMixin, PreTrainedModel
|
| 5 |
+
from transformers.modeling_outputs import CausalLMOutputWithPast
|
| 6 |
|
| 7 |
try:
|
| 8 |
from .configuration_nova import NovaConfig
|
|
|
|
| 45 |
self.up = nn.Linear(d, ff, bias=False)
|
| 46 |
self.down = nn.Linear(ff, d, bias=False)
|
| 47 |
|
| 48 |
+
def forward(self, x, cos, sin, attention_mask, past_key_value=None, use_cache=False):
|
| 49 |
batch, length, _ = x.shape
|
| 50 |
h = self.n1(x)
|
| 51 |
q = self.wq(h).view(batch, length, self.h, self.hd)
|
|
|
|
| 54 |
q = _rope(self.qn(q), cos, sin).to(v.dtype).transpose(1, 2)
|
| 55 |
k = _rope(self.kn(k), cos, sin).to(v.dtype).transpose(1, 2)
|
| 56 |
v = v.transpose(1, 2)
|
| 57 |
+
if past_key_value is not None:
|
| 58 |
+
k = torch.cat((past_key_value[0], k), dim=-2)
|
| 59 |
+
v = torch.cat((past_key_value[1], v), dim=-2)
|
| 60 |
+
present = (k, v) if use_cache else None
|
| 61 |
repeat = self.h // self.kv
|
| 62 |
k = k.repeat_interleave(repeat, dim=1)
|
| 63 |
v = v.repeat_interleave(repeat, dim=1)
|
| 64 |
+
key_length = k.size(-2)
|
| 65 |
+
past_length = key_length - length
|
| 66 |
+
query_positions = past_length + torch.arange(length, device=x.device)
|
| 67 |
+
key_positions = torch.arange(key_length, device=x.device)
|
| 68 |
+
causal = key_positions[None, :] <= query_positions[:, None]
|
| 69 |
mask = causal[None, None, :, :]
|
| 70 |
if attention_mask is not None:
|
| 71 |
mask = mask & attention_mask[:, None, None, :].to(torch.bool)
|
| 72 |
out = F.scaled_dot_product_attention(q, k, v, attn_mask=mask)
|
| 73 |
x = x + self.wo(out.transpose(1, 2).reshape(batch, length, -1))
|
| 74 |
h = self.n2(x)
|
| 75 |
+
x = x + self.down(F.silu(self.gate(h)) * self.up(h))
|
| 76 |
+
return x, present
|
| 77 |
|
| 78 |
|
| 79 |
class NovaModel(PreTrainedModel):
|
|
|
|
| 108 |
attention_mask=None,
|
| 109 |
position_ids=None,
|
| 110 |
inputs_embeds=None,
|
| 111 |
+
past_key_values=None,
|
| 112 |
+
use_cache=False,
|
| 113 |
**kwargs,
|
| 114 |
):
|
| 115 |
if inputs_embeds is None:
|
| 116 |
inputs_embeds = self.emb(input_ids)
|
| 117 |
batch, length, _ = inputs_embeds.shape
|
| 118 |
if position_ids is None:
|
| 119 |
+
past_length = past_key_values[0][0].size(-2) if past_key_values else 0
|
| 120 |
+
if attention_mask is not None:
|
| 121 |
+
position_ids = attention_mask.long().cumsum(-1) - 1
|
| 122 |
+
position_ids.masked_fill_(attention_mask == 0, 0)
|
| 123 |
+
position_ids = position_ids[:, -length:]
|
| 124 |
+
else:
|
| 125 |
+
position_ids = torch.arange(
|
| 126 |
+
past_length, past_length + length, device=inputs_embeds.device
|
| 127 |
+
).unsqueeze(0).expand(batch, -1)
|
| 128 |
cos = self.cos[position_ids].unsqueeze(-2)
|
| 129 |
sin = self.sin[position_ids].unsqueeze(-2)
|
| 130 |
hidden = inputs_embeds
|
| 131 |
+
presents = () if use_cache else None
|
| 132 |
+
for i, block in enumerate(self.blocks):
|
| 133 |
+
layer_past = past_key_values[i] if past_key_values is not None else None
|
| 134 |
+
hidden, present = block(
|
| 135 |
+
hidden, cos, sin, attention_mask, layer_past, use_cache
|
| 136 |
+
)
|
| 137 |
+
if use_cache:
|
| 138 |
+
presents += (present,)
|
| 139 |
+
return self.norm(hidden), presents
|
| 140 |
|
| 141 |
|
| 142 |
class NovaForCausalLM(PreTrainedModel, GenerationMixin):
|
| 143 |
config_class = NovaConfig
|
| 144 |
base_model_prefix = "model"
|
| 145 |
_tied_weights_keys = []
|
| 146 |
+
_supports_cache_class = False
|
| 147 |
|
| 148 |
def __init__(self, config):
|
| 149 |
super().__init__(config)
|
|
|
|
| 160 |
return None
|
| 161 |
|
| 162 |
def prepare_inputs_for_generation(self, input_ids, attention_mask=None, **kwargs):
|
| 163 |
+
past_key_values = kwargs.get("past_key_values")
|
| 164 |
+
if past_key_values is not None:
|
| 165 |
+
input_ids = input_ids[:, -1:]
|
| 166 |
+
if attention_mask is not None:
|
| 167 |
+
position_ids = attention_mask.long().cumsum(-1) - 1
|
| 168 |
+
position_ids.masked_fill_(attention_mask == 0, 0)
|
| 169 |
+
position_ids = position_ids[:, -input_ids.size(1):]
|
| 170 |
+
else:
|
| 171 |
+
past_length = past_key_values[0][0].size(-2) if past_key_values else 0
|
| 172 |
+
position_ids = torch.arange(
|
| 173 |
+
past_length, past_length + input_ids.size(1), device=input_ids.device
|
| 174 |
+
).unsqueeze(0).expand(input_ids.size(0), -1)
|
| 175 |
+
return {
|
| 176 |
+
"input_ids": input_ids,
|
| 177 |
+
"attention_mask": attention_mask,
|
| 178 |
+
"position_ids": position_ids,
|
| 179 |
+
"past_key_values": past_key_values,
|
| 180 |
+
"use_cache": kwargs.get("use_cache", True),
|
| 181 |
+
}
|
| 182 |
|
| 183 |
def forward(
|
| 184 |
self,
|
|
|
|
| 187 |
position_ids=None,
|
| 188 |
inputs_embeds=None,
|
| 189 |
labels=None,
|
| 190 |
+
past_key_values=None,
|
| 191 |
+
use_cache=None,
|
| 192 |
**kwargs,
|
| 193 |
):
|
| 194 |
+
if use_cache is None:
|
| 195 |
+
use_cache = self.config.use_cache
|
| 196 |
+
hidden, presents = self.model(
|
| 197 |
input_ids=input_ids,
|
| 198 |
attention_mask=attention_mask,
|
| 199 |
position_ids=position_ids,
|
| 200 |
inputs_embeds=inputs_embeds,
|
| 201 |
+
past_key_values=past_key_values,
|
| 202 |
+
use_cache=use_cache,
|
| 203 |
)
|
| 204 |
logits = F.linear(hidden, self.model.emb.weight)
|
| 205 |
loss = None
|
|
|
|
| 209 |
labels[..., 1:].contiguous().view(-1),
|
| 210 |
ignore_index=-100,
|
| 211 |
)
|
| 212 |
+
return CausalLMOutputWithPast(
|
| 213 |
+
loss=loss, logits=logits, past_key_values=presents
|
| 214 |
+
)
|
| 215 |
|