2025-11-22 23:27:14 +08:00
|
|
|
use anyhow::Result;
|
2025-11-13 00:33:27 +08:00
|
|
|
use candle_core::{D, IndexOp, Tensor};
|
2025-11-09 15:40:29 +08:00
|
|
|
use candle_nn::{
|
2025-12-10 00:05:46 +08:00
|
|
|
Activation, Conv2d, Embedding, Init, LayerNorm, Linear, Module, RmsNorm, VarBuilder, embedding,
|
|
|
|
|
linear, linear_no_bias,
|
2025-11-22 23:27:14 +08:00
|
|
|
ops::{sigmoid, softmax},
|
|
|
|
|
rms_norm,
|
2025-11-09 15:40:29 +08:00
|
|
|
};
|
2025-11-22 23:27:14 +08:00
|
|
|
use candle_transformers::models::segment_anything::LayerNorm2d;
|
2025-11-09 15:40:29 +08:00
|
|
|
|
2025-11-13 00:33:27 +08:00
|
|
|
use crate::{
|
2025-11-22 23:27:14 +08:00
|
|
|
models::{
|
2025-12-10 00:05:46 +08:00
|
|
|
common::{
|
|
|
|
|
GateUpDownMLP, NaiveAttention, TwoLinearMLP, eager_attention_forward, get_conv2d,
|
|
|
|
|
get_layer_norm,
|
|
|
|
|
},
|
2025-11-22 23:27:14 +08:00
|
|
|
deepseek_ocr::config::{DeepseekOCRConfig, DeepseekV2Config},
|
|
|
|
|
},
|
|
|
|
|
position_embed::rope::RoPE,
|
|
|
|
|
utils::tensor_utils::{
|
|
|
|
|
index_select_2d, interpolate_bicubic, interpolate_linear_1d, masked_scatter_dim0, nonzero,
|
|
|
|
|
onehot, prepare_causal_attention_mask, quick_gelu, topk,
|
|
|
|
|
},
|
2025-11-13 00:33:27 +08:00
|
|
|
};
|
2025-11-09 15:40:29 +08:00
|
|
|
|
|
|
|
|
pub struct PatchEmbed {
|
|
|
|
|
proj: Conv2d,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PatchEmbed {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
in_chans: usize,
|
|
|
|
|
embed_dim: usize,
|
|
|
|
|
kernel_size: usize,
|
|
|
|
|
stride: usize,
|
|
|
|
|
padding: usize,
|
|
|
|
|
) -> Result<Self> {
|
2025-12-10 00:05:46 +08:00
|
|
|
let proj = get_conv2d(
|
|
|
|
|
vb.pp("proj"),
|
|
|
|
|
in_chans,
|
|
|
|
|
embed_dim,
|
|
|
|
|
kernel_size,
|
2025-11-09 15:40:29 +08:00
|
|
|
padding,
|
|
|
|
|
stride,
|
2025-12-10 00:05:46 +08:00
|
|
|
1,
|
|
|
|
|
1,
|
|
|
|
|
true,
|
|
|
|
|
)?;
|
2025-11-09 15:40:29 +08:00
|
|
|
Ok(Self { proj })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let xs = self.proj.forward(xs)?;
|
|
|
|
|
let xs = xs.permute((0, 2, 3, 1))?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Attention {
|
|
|
|
|
num_heads: usize,
|
2025-11-22 23:27:14 +08:00
|
|
|
// head_dim: usize,
|
2025-11-09 15:40:29 +08:00
|
|
|
qkv: Linear,
|
|
|
|
|
proj: Linear,
|
|
|
|
|
scaling: f64,
|
|
|
|
|
use_rel_pos: bool,
|
|
|
|
|
rel_pos_h: Option<Tensor>,
|
|
|
|
|
rel_pos_w: Option<Tensor>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Attention {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
dim: usize,
|
|
|
|
|
num_heads: usize,
|
|
|
|
|
qkv_bias: bool,
|
|
|
|
|
use_rel_pos: bool,
|
|
|
|
|
input_size: Option<(usize, usize)>,
|
|
|
|
|
) -> Result<Self> {
|
|
|
|
|
let head_dim = dim / num_heads;
|
|
|
|
|
let scaling = 1.0 / (head_dim as f64).sqrt();
|
|
|
|
|
let qkv = if qkv_bias {
|
|
|
|
|
linear(dim, dim * 3, vb.pp("qkv"))?
|
|
|
|
|
} else {
|
|
|
|
|
linear_no_bias(dim, dim * 3, vb.pp("qkv"))?
|
|
|
|
|
};
|
|
|
|
|
let proj = linear(dim, dim, vb.pp("proj"))?;
|
|
|
|
|
let mut rel_pos_h = None;
|
|
|
|
|
let mut rel_pos_w = None;
|
|
|
|
|
if use_rel_pos {
|
|
|
|
|
if input_size.is_none() {
|
|
|
|
|
return Err(anyhow::anyhow!(
|
|
|
|
|
"Input size must be provided if using relative positional encoding."
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
let input_size = input_size.unwrap();
|
|
|
|
|
let h_len = 2 * input_size.0 - 1;
|
|
|
|
|
let w_len = 2 * input_size.1 - 1;
|
|
|
|
|
rel_pos_h = Some(vb.get_with_hints((h_len, head_dim), "rel_pos_h", Init::Const(0.))?);
|
|
|
|
|
rel_pos_w = Some(vb.get_with_hints((w_len, head_dim), "rel_pos_w", Init::Const(0.))?);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
|
num_heads,
|
2025-11-22 23:27:14 +08:00
|
|
|
// head_dim,
|
2025-11-09 15:40:29 +08:00
|
|
|
qkv,
|
|
|
|
|
proj,
|
|
|
|
|
scaling,
|
|
|
|
|
use_rel_pos,
|
|
|
|
|
rel_pos_h,
|
|
|
|
|
rel_pos_w,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-13 00:33:27 +08:00
|
|
|
fn get_rel_pos(&self, q_size: usize, k_size: usize, rel_pos: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let max_rel_dist = 2 * std::cmp::max(q_size, k_size) - 1;
|
|
|
|
|
let rel_pos_resized = if rel_pos.dim(0)? != max_rel_dist {
|
2025-11-22 23:27:14 +08:00
|
|
|
let rel_pos_t = rel_pos
|
2025-11-13 00:33:27 +08:00
|
|
|
.to_dtype(candle_core::DType::F32)?
|
|
|
|
|
.t()?
|
|
|
|
|
.unsqueeze(0)?
|
|
|
|
|
.contiguous()?;
|
2025-11-22 23:27:14 +08:00
|
|
|
let rel_pos_resized = interpolate_linear_1d(&rel_pos_t, max_rel_dist, None)?;
|
|
|
|
|
rel_pos_resized
|
2025-11-13 00:33:27 +08:00
|
|
|
.squeeze(0)?
|
|
|
|
|
.t()?
|
|
|
|
|
.contiguous()?
|
2025-11-22 23:27:14 +08:00
|
|
|
.to_dtype(rel_pos.dtype())?
|
2025-11-13 00:33:27 +08:00
|
|
|
} else {
|
|
|
|
|
rel_pos.clone()
|
|
|
|
|
};
|
|
|
|
|
let q_coords = Tensor::arange(0 as f32, q_size as f32, rel_pos.device())?
|
|
|
|
|
.unsqueeze(D::Minus1)?
|
|
|
|
|
.affine((k_size as f64 / q_size as f64).max(1.0), 0.0)?;
|
|
|
|
|
let k_coords = Tensor::arange(0 as f32, k_size as f32, rel_pos.device())?
|
|
|
|
|
.unsqueeze(0)?
|
|
|
|
|
.affine((q_size as f64 / k_size as f64).max(1.0), 0.0)?;
|
|
|
|
|
let relative_coords = q_coords
|
|
|
|
|
.broadcast_sub(&k_coords)?
|
|
|
|
|
.affine(1.0, (k_size - 1) as f64)?
|
|
|
|
|
.affine((q_size as f64 / k_size as f64).max(1.0), 0.0)?;
|
|
|
|
|
let relative_coords = relative_coords
|
|
|
|
|
.to_dtype(candle_core::DType::U32)?
|
|
|
|
|
.contiguous()?;
|
|
|
|
|
let rel_pos_resized = rel_pos_resized.contiguous()?;
|
|
|
|
|
let res = index_select_2d(&rel_pos_resized, &relative_coords)?;
|
|
|
|
|
Ok(res)
|
|
|
|
|
}
|
2025-11-09 15:40:29 +08:00
|
|
|
|
2025-11-13 00:33:27 +08:00
|
|
|
fn add_decomposed_rel_pos(
|
|
|
|
|
&self,
|
|
|
|
|
q: &Tensor,
|
|
|
|
|
rel_pos_h: &Tensor,
|
|
|
|
|
rel_pos_w: &Tensor,
|
|
|
|
|
q_size: (usize, usize),
|
|
|
|
|
k_size: (usize, usize),
|
|
|
|
|
) -> Result<(Tensor, Tensor)> {
|
|
|
|
|
let (q_h, q_w) = q_size;
|
|
|
|
|
let (k_h, k_w) = k_size;
|
2025-11-25 17:45:09 +08:00
|
|
|
let rh = self.get_rel_pos(q_h, k_h, rel_pos_h)?; // (q_h, k_h, dim)
|
|
|
|
|
let rw = self.get_rel_pos(q_w, k_w, rel_pos_w)?; // (q_w, k_w, dim)
|
2025-11-13 00:33:27 +08:00
|
|
|
let (b, _, dim) = q.dims3()?;
|
2025-11-22 23:27:14 +08:00
|
|
|
let r_q = q.reshape((b, q_h, q_w, dim))?.contiguous()?;
|
|
|
|
|
let r_q_ = r_q.unsqueeze(D::Minus2)?; // (b, q_h, q_w, 1, dim)
|
|
|
|
|
// rel_h = torch.einsum("bhwc,hkc->bhwk", r_q, Rh)
|
|
|
|
|
// rel_w = torch.einsum("bhwc,wkc->bhwk", r_q, Rw)
|
|
|
|
|
let rh_ = rh.unsqueeze(1)?.unsqueeze(0)?; // (1, h, 1, k, dim)
|
|
|
|
|
let rel_h = r_q_.broadcast_mul(&rh_)?.sum(D::Minus1)?;
|
|
|
|
|
let rw_ = rw.unsqueeze(0)?.unsqueeze(0)?; // (1, 1, w, k, dim)
|
|
|
|
|
let rel_w = r_q_.broadcast_mul(&rw_)?.sum(D::Minus1)?;
|
2025-11-13 00:33:27 +08:00
|
|
|
let rel_h = rel_h
|
|
|
|
|
.unsqueeze(D::Minus1)?
|
|
|
|
|
.reshape((b, q_h * q_w, k_h, 1))?;
|
|
|
|
|
let rel_w = rel_w
|
|
|
|
|
.unsqueeze(D::Minus2)?
|
|
|
|
|
.reshape((b, q_h * q_w, 1, k_w))?;
|
|
|
|
|
Ok((rel_h, rel_w))
|
|
|
|
|
}
|
2025-11-09 15:40:29 +08:00
|
|
|
|
2025-11-22 23:27:14 +08:00
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
2025-11-13 00:33:27 +08:00
|
|
|
let (b, h, w, _) = xs.dims4()?;
|
|
|
|
|
// (3, B, n_head, h*w, head_dim)
|
|
|
|
|
let qkv = self
|
|
|
|
|
.qkv
|
|
|
|
|
.forward(xs)?
|
|
|
|
|
.reshape((b, h * w, 3, self.num_heads, ()))?
|
|
|
|
|
.permute((2, 0, 3, 1, 4))?
|
|
|
|
|
.contiguous()?;
|
|
|
|
|
let query_states = qkv.i(0)?.contiguous()?;
|
|
|
|
|
let key_states = qkv.i(1)?.contiguous()?;
|
|
|
|
|
let value_states = qkv.i(2)?.contiguous()?;
|
|
|
|
|
let xs = if self.use_rel_pos {
|
|
|
|
|
let q_reshape = query_states.reshape((b * self.num_heads, h * w, ()))?;
|
|
|
|
|
let (rel_h, rel_w) = self.add_decomposed_rel_pos(
|
|
|
|
|
&q_reshape,
|
|
|
|
|
self.rel_pos_h.as_ref().unwrap(),
|
|
|
|
|
self.rel_pos_w.as_ref().unwrap(),
|
|
|
|
|
(h, w),
|
|
|
|
|
(h, w),
|
|
|
|
|
)?;
|
|
|
|
|
let (_, rel_h_dim1, rel_h_dim2, rel_h_dim3) = rel_h.dims4()?;
|
|
|
|
|
let rel_h = rel_h.reshape((b, self.num_heads, rel_h_dim1, rel_h_dim2, rel_h_dim3))?;
|
|
|
|
|
let (_, rel_w_dim1, rel_w_dim2, rel_w_dim3) = rel_w.dims4()?;
|
|
|
|
|
let rel_w = rel_w.reshape((b, self.num_heads, rel_w_dim1, rel_w_dim2, rel_w_dim3))?;
|
|
|
|
|
let attn_bias = rel_h.broadcast_add(&rel_w)?.reshape((
|
|
|
|
|
b,
|
|
|
|
|
self.num_heads,
|
|
|
|
|
rel_h_dim1,
|
|
|
|
|
rel_h_dim2 * rel_w_dim3,
|
|
|
|
|
))?;
|
2025-11-22 23:27:14 +08:00
|
|
|
eager_attention_forward(
|
2025-11-13 00:33:27 +08:00
|
|
|
&query_states,
|
|
|
|
|
&key_states,
|
|
|
|
|
&value_states,
|
|
|
|
|
None,
|
|
|
|
|
Some(&attn_bias),
|
|
|
|
|
self.scaling,
|
2025-11-22 23:27:14 +08:00
|
|
|
)?
|
2025-11-13 00:33:27 +08:00
|
|
|
} else {
|
|
|
|
|
eager_attention_forward(
|
|
|
|
|
&query_states,
|
|
|
|
|
&key_states,
|
|
|
|
|
&value_states,
|
|
|
|
|
None,
|
|
|
|
|
None,
|
|
|
|
|
self.scaling,
|
|
|
|
|
)?
|
|
|
|
|
};
|
|
|
|
|
// (b, h*w, n_head, dim)
|
|
|
|
|
let xs = xs.reshape((b, h * w, ()))?.reshape((b, h, w, ()))?;
|
|
|
|
|
let xs = self.proj.forward(&xs)?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-09 15:40:29 +08:00
|
|
|
pub struct Block {
|
|
|
|
|
norm1: LayerNorm,
|
|
|
|
|
attn: Attention,
|
2025-11-13 00:33:27 +08:00
|
|
|
norm2: LayerNorm,
|
2025-12-03 17:21:01 +08:00
|
|
|
mlp: TwoLinearMLP,
|
2025-11-13 00:33:27 +08:00
|
|
|
window_size: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Block {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
dim: usize,
|
|
|
|
|
num_heads: usize,
|
|
|
|
|
mlp_ratio: f32,
|
|
|
|
|
qkv_bias: bool,
|
|
|
|
|
eps: f64,
|
|
|
|
|
act: Activation,
|
|
|
|
|
use_rel_pos: bool,
|
2025-11-22 23:27:14 +08:00
|
|
|
// rel_pos_zero_init: bool,
|
2025-11-13 00:33:27 +08:00
|
|
|
window_size: usize,
|
|
|
|
|
input_size: Option<(usize, usize)>,
|
|
|
|
|
) -> Result<Self> {
|
2025-12-10 00:05:46 +08:00
|
|
|
let norm1 = get_layer_norm(vb.pp("norm1"), eps, dim)?;
|
2025-11-13 00:33:27 +08:00
|
|
|
let input_size = if window_size == 0 {
|
|
|
|
|
input_size
|
|
|
|
|
} else {
|
|
|
|
|
Some((window_size, window_size))
|
|
|
|
|
};
|
|
|
|
|
let attn = Attention::new(
|
|
|
|
|
vb.pp("attn"),
|
|
|
|
|
dim,
|
|
|
|
|
num_heads,
|
|
|
|
|
qkv_bias,
|
|
|
|
|
use_rel_pos,
|
|
|
|
|
input_size,
|
|
|
|
|
)?;
|
2025-12-10 00:05:46 +08:00
|
|
|
let norm2 = get_layer_norm(vb.pp("norm2"), eps, dim)?;
|
2025-11-13 00:33:27 +08:00
|
|
|
let mlp_dim = (dim as f32 * mlp_ratio) as usize;
|
2025-12-03 17:21:01 +08:00
|
|
|
let mlp = TwoLinearMLP::new(vb.pp("mlp"), dim, mlp_dim, act, true, "lin1", "lin2")?;
|
2025-11-13 00:33:27 +08:00
|
|
|
Ok(Self {
|
|
|
|
|
norm1,
|
|
|
|
|
attn,
|
|
|
|
|
norm2,
|
|
|
|
|
mlp,
|
|
|
|
|
window_size,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn window_partition(
|
|
|
|
|
&self,
|
|
|
|
|
x: &Tensor,
|
|
|
|
|
window_size: usize,
|
|
|
|
|
) -> Result<(Tensor, (usize, usize))> {
|
|
|
|
|
let (b, h, w, c) = x.dims4()?;
|
|
|
|
|
let pad_h = (window_size - h % window_size) % window_size;
|
|
|
|
|
let pad_w = (window_size - w % window_size) % window_size;
|
|
|
|
|
let x = if pad_h > 0 || pad_w > 0 {
|
|
|
|
|
let x = x.pad_with_zeros(1, 0, pad_h)?;
|
2025-11-22 23:27:14 +08:00
|
|
|
x.pad_with_zeros(2, 0, pad_w)?
|
2025-11-13 00:33:27 +08:00
|
|
|
} else {
|
|
|
|
|
x.clone()
|
|
|
|
|
};
|
|
|
|
|
let hp = h + pad_h;
|
|
|
|
|
let wp = w + pad_w;
|
|
|
|
|
let x = x.reshape((
|
|
|
|
|
b,
|
|
|
|
|
hp / window_size,
|
|
|
|
|
window_size,
|
|
|
|
|
wp / window_size,
|
|
|
|
|
window_size,
|
|
|
|
|
c,
|
|
|
|
|
))?;
|
|
|
|
|
let windows = x.permute((0, 1, 3, 2, 4, 5))?.contiguous()?.reshape((
|
|
|
|
|
(),
|
|
|
|
|
window_size,
|
|
|
|
|
window_size,
|
|
|
|
|
c,
|
|
|
|
|
))?;
|
|
|
|
|
Ok((windows, (hp, wp)))
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-22 23:27:14 +08:00
|
|
|
pub fn window_unpartition(
|
|
|
|
|
&self,
|
|
|
|
|
windows: &Tensor,
|
|
|
|
|
window_size: usize,
|
|
|
|
|
pad_hw: (usize, usize),
|
|
|
|
|
hw: (usize, usize),
|
|
|
|
|
) -> Result<Tensor> {
|
|
|
|
|
let (hp, wp) = pad_hw;
|
|
|
|
|
let (h, w) = hw;
|
|
|
|
|
let b = windows.dim(0)? / (hp * wp / window_size / window_size);
|
|
|
|
|
let last_dim = windows.dim(D::Minus1)?;
|
|
|
|
|
let x = windows.reshape(&[
|
|
|
|
|
b,
|
|
|
|
|
hp / window_size,
|
|
|
|
|
wp / window_size,
|
|
|
|
|
window_size,
|
|
|
|
|
window_size,
|
|
|
|
|
last_dim,
|
|
|
|
|
])?;
|
|
|
|
|
let mut x = x
|
|
|
|
|
.permute((0, 1, 3, 2, 4, 5))?
|
|
|
|
|
.contiguous()?
|
|
|
|
|
.reshape((b, hp, wp, ()))?;
|
|
|
|
|
if hp > h || wp > w {
|
|
|
|
|
x = x.i((.., 0..h, 0..w, ..))?
|
|
|
|
|
}
|
|
|
|
|
Ok(x)
|
|
|
|
|
}
|
2025-11-13 00:33:27 +08:00
|
|
|
|
2025-11-22 23:27:14 +08:00
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let shortcut = xs.clone();
|
|
|
|
|
let xs = self.norm1.forward(xs)?;
|
|
|
|
|
let xs = if self.window_size > 0 {
|
|
|
|
|
let h = xs.dim(1)?;
|
|
|
|
|
let w = xs.dim(2)?;
|
|
|
|
|
let (x, (hp, wp)) = self.window_partition(&xs, self.window_size)?;
|
|
|
|
|
let x = self.attn.forward(&x)?;
|
|
|
|
|
self.window_unpartition(&x, self.window_size, (hp, wp), (h, w))?
|
|
|
|
|
} else {
|
|
|
|
|
self.attn.forward(&xs)?
|
|
|
|
|
};
|
|
|
|
|
let x = shortcut.add(&xs)?;
|
|
|
|
|
let x = x.add(&self.mlp.forward(&self.norm2.forward(&x)?)?)?;
|
|
|
|
|
Ok(x)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-13 00:33:27 +08:00
|
|
|
|
2025-11-22 23:27:14 +08:00
|
|
|
pub struct Neck {
|
|
|
|
|
conv2d_0: Conv2d,
|
|
|
|
|
layernorm_1: LayerNorm2d,
|
|
|
|
|
conv2d_2: Conv2d,
|
|
|
|
|
layernorm_3: LayerNorm2d,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Neck {
|
|
|
|
|
pub fn new(vb: VarBuilder, embed_dim: usize, out_chans: usize) -> Result<Self> {
|
2025-12-10 00:05:46 +08:00
|
|
|
let conv2d_0 = get_conv2d(vb.pp("0"), embed_dim, out_chans, 1, 0, 1, 1, 1, false)?;
|
2025-11-22 23:27:14 +08:00
|
|
|
let layernorm_1 = LayerNorm2d::new(out_chans, 0.000001, vb.pp("1"))?;
|
2025-12-10 00:05:46 +08:00
|
|
|
let conv2d_2 = get_conv2d(vb.pp("2"), out_chans, out_chans, 3, 1, 1, 1, 1, false)?;
|
2025-11-22 23:27:14 +08:00
|
|
|
let layernorm_3 = LayerNorm2d::new(out_chans, 0.000001, vb.pp("3"))?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
conv2d_0,
|
|
|
|
|
layernorm_1,
|
|
|
|
|
conv2d_2,
|
|
|
|
|
layernorm_3,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let xs = self.conv2d_0.forward(xs)?;
|
|
|
|
|
let xs = self.layernorm_1.forward(&xs)?;
|
|
|
|
|
let xs = self.conv2d_2.forward(&xs)?;
|
|
|
|
|
let xs = self.layernorm_3.forward(&xs)?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
2025-11-09 15:40:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ImageEncoderViT {
|
2025-11-22 23:27:14 +08:00
|
|
|
// img_size: usize,
|
2025-11-09 15:40:29 +08:00
|
|
|
patch_embed: PatchEmbed,
|
|
|
|
|
pos_embed: Option<Tensor>,
|
|
|
|
|
blocks: Vec<Block>,
|
2025-11-22 23:27:14 +08:00
|
|
|
neck: Neck,
|
|
|
|
|
net_2: Conv2d,
|
|
|
|
|
net_3: Conv2d,
|
2025-11-09 15:40:29 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-22 23:27:14 +08:00
|
|
|
impl ImageEncoderViT {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
img_size: usize,
|
|
|
|
|
patch_size: usize,
|
|
|
|
|
in_chans: usize,
|
|
|
|
|
embed_dim: usize,
|
|
|
|
|
depth: usize,
|
|
|
|
|
num_heads: usize,
|
|
|
|
|
mlp_ratio: f32,
|
|
|
|
|
out_chans: usize,
|
|
|
|
|
qkv_bias: bool,
|
|
|
|
|
act: Activation,
|
|
|
|
|
use_abs_pos: bool,
|
|
|
|
|
use_rel_pos: bool,
|
|
|
|
|
// rel_pos_zero_init: bool,
|
|
|
|
|
window_size: usize,
|
|
|
|
|
global_attn_indexes: Vec<usize>,
|
|
|
|
|
) -> Result<Self> {
|
|
|
|
|
let patch_embed = PatchEmbed::new(
|
|
|
|
|
vb.pp("patch_embed"),
|
|
|
|
|
in_chans,
|
|
|
|
|
embed_dim,
|
|
|
|
|
patch_size,
|
|
|
|
|
patch_size,
|
|
|
|
|
0,
|
|
|
|
|
)?;
|
|
|
|
|
let pos_embed = if use_abs_pos {
|
|
|
|
|
Some(vb.get_with_hints(
|
|
|
|
|
(1, img_size / patch_size, img_size / patch_size, embed_dim),
|
|
|
|
|
"pos_embed",
|
|
|
|
|
Init::Const(0.),
|
|
|
|
|
)?)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
let mut blocks = Vec::new();
|
|
|
|
|
let vb_blocks = vb.pp("blocks");
|
|
|
|
|
for i in 0..depth {
|
|
|
|
|
let window_size = if global_attn_indexes.contains(&i) {
|
|
|
|
|
0
|
|
|
|
|
} else {
|
|
|
|
|
window_size
|
|
|
|
|
};
|
2025-11-09 15:40:29 +08:00
|
|
|
|
2025-11-22 23:27:14 +08:00
|
|
|
let block = Block::new(
|
|
|
|
|
vb_blocks.pp(i),
|
|
|
|
|
embed_dim,
|
|
|
|
|
num_heads,
|
|
|
|
|
mlp_ratio,
|
|
|
|
|
qkv_bias,
|
|
|
|
|
1e-6,
|
|
|
|
|
act,
|
|
|
|
|
use_rel_pos,
|
|
|
|
|
// rel_pos_zero_init,
|
|
|
|
|
window_size,
|
|
|
|
|
Some((img_size / patch_size, img_size / patch_size)),
|
|
|
|
|
)?;
|
|
|
|
|
blocks.push(block);
|
|
|
|
|
}
|
2025-11-09 15:40:29 +08:00
|
|
|
|
2025-11-22 23:27:14 +08:00
|
|
|
let neck = Neck::new(vb.pp("neck"), embed_dim, out_chans)?;
|
2025-12-10 00:05:46 +08:00
|
|
|
|
|
|
|
|
let net_2 = get_conv2d(vb.pp("net_2"), 256, 512, 3, 1, 2, 1, 1, false)?;
|
|
|
|
|
let net_3 = get_conv2d(vb.pp("net_3"), 512, 1024, 3, 1, 2, 1, 1, false)?;
|
2025-11-22 23:27:14 +08:00
|
|
|
Ok(Self {
|
|
|
|
|
// img_size,
|
|
|
|
|
patch_embed,
|
|
|
|
|
pos_embed,
|
|
|
|
|
blocks,
|
|
|
|
|
neck,
|
|
|
|
|
net_2,
|
|
|
|
|
net_3,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
fn get_abs_pos_sam(&self, abs_pos: &Tensor, tgt_size: usize) -> Result<Tensor> {
|
|
|
|
|
let src_size = abs_pos.dim(1)?;
|
|
|
|
|
if src_size != tgt_size {
|
|
|
|
|
let old_pos_embed = abs_pos.permute((0, 3, 1, 2))?;
|
|
|
|
|
let new_pos_embed = interpolate_bicubic(
|
|
|
|
|
&old_pos_embed,
|
|
|
|
|
(tgt_size, tgt_size),
|
|
|
|
|
Some(true),
|
|
|
|
|
Some(false),
|
|
|
|
|
)?;
|
|
|
|
|
let new_pos_embed = new_pos_embed.permute((0, 2, 3, 1))?;
|
|
|
|
|
Ok(new_pos_embed)
|
|
|
|
|
} else {
|
|
|
|
|
Ok(abs_pos.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let mut x = self.patch_embed.forward(xs)?;
|
|
|
|
|
if self.pos_embed.is_some() {
|
|
|
|
|
let dim1 = x.dim(1)?;
|
|
|
|
|
let pos = self.get_abs_pos_sam(self.pos_embed.as_ref().unwrap(), dim1)?;
|
|
|
|
|
x = x.broadcast_add(&pos)?;
|
|
|
|
|
}
|
|
|
|
|
for blk in &self.blocks {
|
|
|
|
|
x = blk.forward(&x)?;
|
|
|
|
|
}
|
|
|
|
|
let x = x.permute((0, 3, 1, 2))?;
|
|
|
|
|
let x = self.neck.forward(&x)?;
|
|
|
|
|
let x = self.net_2.forward(&x)?;
|
|
|
|
|
let x = self.net_3.forward(&x)?;
|
|
|
|
|
Ok(x)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct CLIPVisionEmbeddings {
|
|
|
|
|
class_embedding: Tensor,
|
|
|
|
|
patch_embedding: Conv2d,
|
|
|
|
|
// position_embedding: Embedding,
|
|
|
|
|
// position_ids: Tensor,
|
|
|
|
|
pos_embeds: Tensor,
|
|
|
|
|
embed_dim: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CLIPVisionEmbeddings {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
hidden_size: usize,
|
|
|
|
|
image_size: usize,
|
|
|
|
|
patch_size: usize,
|
|
|
|
|
num_channels: usize,
|
|
|
|
|
) -> Result<Self> {
|
|
|
|
|
let class_embedding =
|
|
|
|
|
vb.get_with_hints(hidden_size, "class_embedding", Init::Const(0.0))?;
|
2025-12-10 00:05:46 +08:00
|
|
|
|
|
|
|
|
let patch_embedding = get_conv2d(
|
|
|
|
|
vb.pp("patch_embedding"),
|
2025-11-22 23:27:14 +08:00
|
|
|
num_channels,
|
|
|
|
|
hidden_size,
|
|
|
|
|
patch_size,
|
2025-12-10 00:05:46 +08:00
|
|
|
0,
|
|
|
|
|
patch_size,
|
|
|
|
|
1,
|
|
|
|
|
1,
|
|
|
|
|
false,
|
2025-11-22 23:27:14 +08:00
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
let num_patches = (image_size / patch_size).pow(2);
|
|
|
|
|
let num_positions = num_patches + 1;
|
|
|
|
|
let position_embedding =
|
|
|
|
|
embedding(num_positions, hidden_size, vb.pp("position_embedding"))?;
|
|
|
|
|
let position_ids = Tensor::arange(0u32, num_positions as u32, vb.device())?;
|
|
|
|
|
let pos_embeds = position_embedding.forward(&position_ids)?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
class_embedding,
|
|
|
|
|
patch_embedding,
|
|
|
|
|
// position_embedding,
|
|
|
|
|
// position_ids,
|
|
|
|
|
pos_embeds,
|
|
|
|
|
embed_dim: hidden_size,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_abs_pos(&self, tgt_size: usize) -> Result<Tensor> {
|
2025-11-27 14:28:47 +08:00
|
|
|
// println!("self.pos_embeds: {:?}", self.pos_embeds);
|
2025-11-25 17:45:09 +08:00
|
|
|
let abs_pos_new = self.pos_embeds.clone();
|
2025-11-22 23:27:14 +08:00
|
|
|
let (len, dim) = abs_pos_new.dims2()?;
|
|
|
|
|
let src_size = ((len - 1) as f32).sqrt() as usize;
|
|
|
|
|
let tgt_size = (tgt_size as f32).sqrt() as usize;
|
|
|
|
|
let pos_embeds = if src_size != tgt_size {
|
|
|
|
|
let cls_token = abs_pos_new.i(0)?.unsqueeze(0)?;
|
|
|
|
|
let old_pos_embed = abs_pos_new.i(1..)?;
|
|
|
|
|
let old_pos_embed = old_pos_embed
|
|
|
|
|
.reshape((1, src_size, src_size, dim))?
|
|
|
|
|
.permute((0, 3, 1, 2))?
|
|
|
|
|
.contiguous()?;
|
|
|
|
|
let new_pos_embed = interpolate_bicubic(
|
|
|
|
|
&old_pos_embed,
|
|
|
|
|
(tgt_size, tgt_size),
|
|
|
|
|
Some(true),
|
|
|
|
|
Some(false),
|
|
|
|
|
)?;
|
|
|
|
|
let new_pos_embed = new_pos_embed
|
|
|
|
|
.permute((0, 2, 3, 1))?
|
|
|
|
|
.reshape((tgt_size * tgt_size, dim))?;
|
|
|
|
|
Tensor::cat(&[cls_token, new_pos_embed], 0)?.unsqueeze(0)?
|
|
|
|
|
} else {
|
|
|
|
|
self.pos_embeds.clone()
|
|
|
|
|
};
|
|
|
|
|
Ok(pos_embeds)
|
|
|
|
|
}
|
|
|
|
|
pub fn forward(&self, pixel_values: &Tensor, patch_embeds: Option<&Tensor>) -> Result<Tensor> {
|
|
|
|
|
let bs = pixel_values.dim(0)?;
|
|
|
|
|
let patch_embeds = match patch_embeds {
|
|
|
|
|
Some(t) => t.clone(),
|
|
|
|
|
None => self.patch_embedding.forward(pixel_values)?,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let patch_embeds = patch_embeds.flatten(2, D::Minus1)?.transpose(1, 2)?;
|
|
|
|
|
let class_embeds = self.class_embedding.expand((bs, 1, self.embed_dim))?;
|
|
|
|
|
let embeddings = Tensor::cat(&[class_embeds, patch_embeds], 1)?;
|
|
|
|
|
let pos_embeds = self.get_abs_pos(embeddings.dim(1)?)?;
|
|
|
|
|
let embeddings = embeddings.broadcast_add(&pos_embeds)?;
|
|
|
|
|
Ok(embeddings)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct NoTPAttention {
|
|
|
|
|
num_heads: usize,
|
|
|
|
|
head_dim: usize,
|
|
|
|
|
qkv_proj: Linear,
|
|
|
|
|
out_proj: Linear,
|
|
|
|
|
scaling: f64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NoTPAttention {
|
|
|
|
|
pub fn new(vb: VarBuilder, hidden_size: usize, num_heads: usize) -> Result<Self> {
|
|
|
|
|
let qkv_proj = linear(hidden_size, hidden_size * 3, vb.pp("qkv_proj"))?;
|
|
|
|
|
let out_proj = linear(hidden_size, hidden_size, vb.pp("out_proj"))?;
|
|
|
|
|
let head_dim = hidden_size / num_heads;
|
|
|
|
|
let scaling = 1.0 / (head_dim as f64).sqrt();
|
|
|
|
|
Ok(Self {
|
|
|
|
|
num_heads,
|
|
|
|
|
head_dim,
|
|
|
|
|
qkv_proj,
|
|
|
|
|
out_proj,
|
|
|
|
|
scaling,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let (bs, seq_len, _) = xs.dims3()?;
|
|
|
|
|
let qkv = self.qkv_proj.forward(xs)?;
|
|
|
|
|
let qkv = qkv
|
|
|
|
|
.reshape((bs, seq_len, 3, self.num_heads, self.head_dim))?
|
|
|
|
|
.permute((2, 0, 3, 1, 4))?;
|
|
|
|
|
let q = qkv.i(0)?.contiguous()?;
|
|
|
|
|
let k = qkv.i(1)?.contiguous()?;
|
|
|
|
|
let v = qkv.i(2)?.contiguous()?;
|
|
|
|
|
let output = eager_attention_forward(&q, &k, &v, None, None, self.scaling)?;
|
|
|
|
|
let output = output.reshape((bs, seq_len, ()))?;
|
|
|
|
|
let output = self.out_proj.forward(&output)?;
|
|
|
|
|
Ok(output)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct NoTPFeedForward {
|
|
|
|
|
fc1: Linear,
|
|
|
|
|
fc2: Linear,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NoTPFeedForward {
|
|
|
|
|
pub fn new(vb: VarBuilder, dim: usize, hidden_dim: usize) -> Result<Self> {
|
|
|
|
|
let fc1 = linear(dim, hidden_dim, vb.pp("fc1"))?;
|
|
|
|
|
let fc2 = linear(hidden_dim, dim, vb.pp("fc2"))?;
|
|
|
|
|
Ok(Self { fc1, fc2 })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let output = self.fc1.forward(xs)?;
|
|
|
|
|
let output = quick_gelu(&output)?;
|
|
|
|
|
let output = self.fc2.forward(&output)?;
|
|
|
|
|
Ok(output)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct NoTPTransformerBlock {
|
|
|
|
|
self_attn: NoTPAttention,
|
|
|
|
|
mlp: NoTPFeedForward,
|
|
|
|
|
layer_norm1: LayerNorm,
|
|
|
|
|
layer_norm2: LayerNorm,
|
|
|
|
|
}
|
|
|
|
|
impl NoTPTransformerBlock {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
hidden_size: usize,
|
|
|
|
|
num_heads: usize,
|
|
|
|
|
ffn_hidden_size: usize,
|
|
|
|
|
eps: f64,
|
|
|
|
|
) -> Result<Self> {
|
|
|
|
|
let self_attn = NoTPAttention::new(vb.pp("self_attn"), hidden_size, num_heads)?;
|
|
|
|
|
let mlp = NoTPFeedForward::new(vb.pp("mlp"), hidden_size, ffn_hidden_size)?;
|
2025-12-10 00:05:46 +08:00
|
|
|
let layer_norm1 = get_layer_norm(vb.pp("layer_norm1"), eps, hidden_size)?;
|
|
|
|
|
let layer_norm2 = get_layer_norm(vb.pp("layer_norm2"), eps, hidden_size)?;
|
2025-11-22 23:27:14 +08:00
|
|
|
Ok(Self {
|
|
|
|
|
self_attn,
|
|
|
|
|
mlp,
|
|
|
|
|
layer_norm1,
|
|
|
|
|
layer_norm2,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let x = self.layer_norm1.forward(xs)?;
|
|
|
|
|
let x = self.self_attn.forward(&x)?;
|
|
|
|
|
let res = x.add(xs)?;
|
|
|
|
|
let x = self.layer_norm2.forward(&res)?;
|
|
|
|
|
let x = self.mlp.forward(&x)?;
|
|
|
|
|
let out = x.add(&res)?;
|
|
|
|
|
Ok(out)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct NoTPTransformer {
|
|
|
|
|
layers: Vec<NoTPTransformerBlock>,
|
|
|
|
|
}
|
|
|
|
|
impl NoTPTransformer {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
num_layers: usize,
|
|
|
|
|
hidden_size: usize,
|
|
|
|
|
num_heads: usize,
|
|
|
|
|
ffn_hidden_size: usize,
|
|
|
|
|
eps: f64,
|
|
|
|
|
) -> Result<Self> {
|
|
|
|
|
let mut layers = Vec::new();
|
|
|
|
|
let vb_layers = vb.pp("layers");
|
|
|
|
|
for i in 0..num_layers {
|
|
|
|
|
let blocks = NoTPTransformerBlock::new(
|
|
|
|
|
vb_layers.pp(i),
|
|
|
|
|
hidden_size,
|
|
|
|
|
num_heads,
|
|
|
|
|
ffn_hidden_size,
|
|
|
|
|
eps,
|
|
|
|
|
)?;
|
|
|
|
|
layers.push(blocks);
|
|
|
|
|
}
|
|
|
|
|
Ok(Self { layers })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let mut x = xs.clone();
|
|
|
|
|
for layer in &self.layers {
|
|
|
|
|
x = layer.forward(&x)?;
|
|
|
|
|
}
|
|
|
|
|
Ok(x)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct VitModel {
|
|
|
|
|
embeddings: CLIPVisionEmbeddings,
|
|
|
|
|
transformer: NoTPTransformer,
|
|
|
|
|
pre_layrnorm: LayerNorm,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl VitModel {
|
|
|
|
|
pub fn new(
|
|
|
|
|
vb: VarBuilder,
|
|
|
|
|
image_size: usize,
|
|
|
|
|
patch_size: usize,
|
|
|
|
|
num_channels: usize,
|
|
|
|
|
num_layers: usize,
|
|
|
|
|
hidden_size: usize,
|
|
|
|
|
num_heads: usize,
|
|
|
|
|
ffn_hidden_size: usize,
|
|
|
|
|
eps: f64,
|
|
|
|
|
) -> Result<Self> {
|
|
|
|
|
let embeddings = CLIPVisionEmbeddings::new(
|
|
|
|
|
vb.pp("embeddings"),
|
|
|
|
|
hidden_size,
|
|
|
|
|
image_size,
|
|
|
|
|
patch_size,
|
|
|
|
|
num_channels,
|
|
|
|
|
)?;
|
|
|
|
|
let transformer = NoTPTransformer::new(
|
|
|
|
|
vb.pp("transformer"),
|
|
|
|
|
num_layers,
|
|
|
|
|
hidden_size,
|
|
|
|
|
num_heads,
|
|
|
|
|
ffn_hidden_size,
|
|
|
|
|
eps,
|
|
|
|
|
)?;
|
2025-12-10 00:05:46 +08:00
|
|
|
let pre_layrnorm = get_layer_norm(vb.pp("pre_layrnorm"), eps, hidden_size)?;
|
2025-11-22 23:27:14 +08:00
|
|
|
Ok(Self {
|
|
|
|
|
embeddings,
|
|
|
|
|
transformer,
|
|
|
|
|
pre_layrnorm,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor, patch_embeds: Option<&Tensor>) -> Result<Tensor> {
|
|
|
|
|
let x = self.embeddings.forward(xs, patch_embeds)?;
|
|
|
|
|
let hidden_states = self.pre_layrnorm.forward(&x)?;
|
|
|
|
|
let output = self.transformer.forward(&hidden_states)?;
|
|
|
|
|
Ok(output)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct MoEGate {
|
|
|
|
|
top_k: usize,
|
|
|
|
|
// n_routed_experts: usize,
|
|
|
|
|
routed_scaling_factor: f64,
|
|
|
|
|
scoring_func: String,
|
|
|
|
|
// alpha: f32,
|
|
|
|
|
// seq_aux: bool,
|
|
|
|
|
topk_method: String,
|
|
|
|
|
// n_group: usize,
|
|
|
|
|
// topk_group: usize,
|
|
|
|
|
norm_topk_prob: bool,
|
|
|
|
|
// gating_dim: usize,
|
|
|
|
|
linear: Linear,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MoEGate {
|
|
|
|
|
pub fn new(vb: VarBuilder, config: &DeepseekV2Config) -> Result<Self> {
|
|
|
|
|
let linear = linear_no_bias(config.hidden_size, config.n_routed_experts, vb)?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
top_k: config.num_experts_per_tok,
|
|
|
|
|
// n_routed_experts: config.n_routed_experts,
|
|
|
|
|
routed_scaling_factor: config.routed_scaling_factor,
|
|
|
|
|
scoring_func: config.scoring_func.clone(),
|
|
|
|
|
// alpha: config.aux_loss_alpha,
|
|
|
|
|
// seq_aux: config.seq_aux,
|
|
|
|
|
topk_method: config.topk_method.clone(),
|
|
|
|
|
// n_group: config.n_group,
|
|
|
|
|
// topk_group: config.topk_group,
|
|
|
|
|
norm_topk_prob: config.norm_topk_prob,
|
|
|
|
|
// gating_dim: config.hidden_size,
|
|
|
|
|
linear,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<(Tensor, Tensor)> {
|
|
|
|
|
let (_, _, dim) = xs.dims3()?;
|
|
|
|
|
let xs = xs.reshape(((), dim))?;
|
|
|
|
|
let logits = self
|
|
|
|
|
.linear
|
|
|
|
|
.forward(&xs)?
|
|
|
|
|
.to_dtype(candle_core::DType::F32)?;
|
|
|
|
|
let scores = if self.scoring_func == "softmax" {
|
|
|
|
|
softmax(&logits, D::Minus1)?
|
|
|
|
|
} else if self.scoring_func == "sigmoid" {
|
|
|
|
|
sigmoid(&logits)?
|
|
|
|
|
} else {
|
|
|
|
|
return Err(anyhow::anyhow!(format!(
|
|
|
|
|
"insupportable scoring function for MoE gating: {}",
|
|
|
|
|
self.scoring_func
|
|
|
|
|
)));
|
|
|
|
|
};
|
|
|
|
|
let (topk_weight, topk_idx) = if self.topk_method == "greedy" {
|
|
|
|
|
topk(&scores, self.top_k)?
|
|
|
|
|
} else {
|
|
|
|
|
return Err(anyhow::anyhow!(format!(
|
|
|
|
|
"insupportable topk_method function for MoE gating: {}",
|
|
|
|
|
self.topk_method
|
|
|
|
|
)));
|
|
|
|
|
};
|
|
|
|
|
let topk_weight = if self.top_k > 1 && self.norm_topk_prob {
|
|
|
|
|
topk_weight
|
|
|
|
|
.broadcast_div(&topk_weight.sum_keepdim(D::Minus1)?.affine(1.0, 1e-20)?)?
|
|
|
|
|
.affine(self.routed_scaling_factor, 0.0)?
|
|
|
|
|
} else {
|
|
|
|
|
topk_weight.affine(self.routed_scaling_factor, 0.0)?
|
|
|
|
|
};
|
|
|
|
|
let topk_weight = topk_weight.to_dtype(xs.dtype())?;
|
|
|
|
|
Ok((topk_idx, topk_weight))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct DeepseekV2MoE {
|
|
|
|
|
// num_experts_per_tok: usize,
|
|
|
|
|
// ep_size: usize,
|
|
|
|
|
// experts_per_rank: usize,
|
|
|
|
|
// ep_rank: usize,
|
2025-12-03 17:21:01 +08:00
|
|
|
experts: Vec<GateUpDownMLP>,
|
2025-11-22 23:27:14 +08:00
|
|
|
gate: MoEGate,
|
2025-12-03 17:21:01 +08:00
|
|
|
shared_experts: GateUpDownMLP,
|
2025-11-22 23:27:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DeepseekV2MoE {
|
|
|
|
|
pub fn new(vb: VarBuilder, config: &DeepseekV2Config) -> Result<Self> {
|
|
|
|
|
// let ep_size = 1;
|
|
|
|
|
// let experts_per_rank = config.n_routed_experts;
|
|
|
|
|
// let ep_rank = 0;
|
|
|
|
|
let mut experts = Vec::new();
|
|
|
|
|
let vb_experts = vb.pp("experts");
|
|
|
|
|
for i in 0..config.n_routed_experts {
|
2025-12-03 17:21:01 +08:00
|
|
|
let mlp = GateUpDownMLP::new(
|
2025-11-22 23:27:14 +08:00
|
|
|
vb_experts.pp(i),
|
|
|
|
|
config.hidden_size,
|
|
|
|
|
config.moe_intermediate_size,
|
|
|
|
|
Activation::Silu,
|
2025-12-03 17:21:01 +08:00
|
|
|
false,
|
2025-11-22 23:27:14 +08:00
|
|
|
)?;
|
|
|
|
|
experts.push(mlp);
|
|
|
|
|
}
|
|
|
|
|
let gate = MoEGate::new(vb.pp("gate"), config)?;
|
2025-12-03 17:21:01 +08:00
|
|
|
let shared_experts = GateUpDownMLP::new(
|
2025-11-22 23:27:14 +08:00
|
|
|
vb.pp("shared_experts"),
|
|
|
|
|
config.hidden_size,
|
|
|
|
|
config.moe_intermediate_size * config.n_shared_experts,
|
|
|
|
|
Activation::Silu,
|
2025-12-03 17:21:01 +08:00
|
|
|
false,
|
2025-11-22 23:27:14 +08:00
|
|
|
)?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
// num_experts_per_tok: config.num_experts_per_tok,
|
|
|
|
|
// ep_size,
|
|
|
|
|
// experts_per_rank,
|
|
|
|
|
// ep_rank,
|
|
|
|
|
experts,
|
|
|
|
|
gate,
|
|
|
|
|
shared_experts,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn moe_infer(&self, xs: &Tensor, topk_idx: &Tensor, topk_weight: &Tensor) -> Result<Tensor> {
|
|
|
|
|
let expert_mask = onehot(topk_idx, self.experts.len())?
|
|
|
|
|
.permute((2, 1, 0))?
|
|
|
|
|
.to_dtype(candle_core::DType::U32)?;
|
|
|
|
|
let expert_hit = expert_mask.sum((D::Minus1, D::Minus2))?;
|
|
|
|
|
let expert_hit_vec = expert_hit.to_vec1::<u32>()?;
|
|
|
|
|
let expert_hit_vec: Vec<usize> = expert_hit_vec
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter_map(|(i, &val)| if val > 0 { Some(i) } else { None })
|
|
|
|
|
.collect();
|
|
|
|
|
let mut final_xs = xs.zeros_like()?;
|
|
|
|
|
for i in expert_hit_vec {
|
|
|
|
|
let expert = &self.experts[i];
|
|
|
|
|
let tokens = expert_mask.i(i)?;
|
|
|
|
|
let (topk_id, token_id) = nonzero(&tokens)?;
|
|
|
|
|
let token_id_tensor = Tensor::new(token_id.as_slice(), xs.device())?;
|
|
|
|
|
let select_tokens = xs.index_select(&token_id_tensor, 0)?;
|
|
|
|
|
let select_xs = expert.forward(&select_tokens)?;
|
|
|
|
|
let select_weight = topk_weight.index_select(&token_id_tensor, 0)?.gather(
|
|
|
|
|
&Tensor::new(topk_id.as_slice(), xs.device())?.unsqueeze(D::Minus1)?,
|
|
|
|
|
D::Minus1,
|
|
|
|
|
)?;
|
|
|
|
|
let select_xs = select_xs.broadcast_mul(&select_weight)?;
|
|
|
|
|
final_xs = final_xs.index_add(&token_id_tensor, &select_xs, 0)?;
|
|
|
|
|
}
|
|
|
|
|
Ok(final_xs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Module for DeepseekV2MoE {
|
|
|
|
|
fn forward(&self, xs: &Tensor) -> candle_core::Result<Tensor> {
|
|
|
|
|
let identity = xs.clone();
|
|
|
|
|
let (bs, seq_len, embedding_dim) = xs.dims3()?;
|
|
|
|
|
let (topk_idx, topk_weight) = self
|
|
|
|
|
.gate
|
|
|
|
|
.forward(xs)
|
|
|
|
|
.map_err(|e| candle_core::Error::Msg(format!("{e}")))?;
|
|
|
|
|
let xs = xs.reshape((bs * seq_len, embedding_dim))?;
|
|
|
|
|
let xs = self
|
|
|
|
|
.moe_infer(&xs, &topk_idx, &topk_weight)
|
|
|
|
|
.map_err(|e| candle_core::Error::Msg(format!("{e}")))?;
|
|
|
|
|
let xs = xs.reshape((bs, seq_len, embedding_dim))?;
|
|
|
|
|
let xs_shared_experts = self.shared_experts.forward(&identity)?;
|
|
|
|
|
let xs = xs.add(&xs_shared_experts)?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub enum DeepseekV2Proj {
|
|
|
|
|
MOE(DeepseekV2MoE),
|
2025-12-03 17:21:01 +08:00
|
|
|
MLP(GateUpDownMLP),
|
2025-11-22 23:27:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DeepseekV2Proj {
|
|
|
|
|
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
|
|
|
|
match self {
|
|
|
|
|
DeepseekV2Proj::MLP(model) => {
|
|
|
|
|
let xs = model.forward(xs)?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
|
|
|
|
DeepseekV2Proj::MOE(model) => {
|
|
|
|
|
let xs = model.forward(xs)?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct DeepseekV2DecoderLayer {
|
2025-12-03 17:21:01 +08:00
|
|
|
self_attn: NaiveAttention,
|
2025-11-22 23:27:14 +08:00
|
|
|
mlp: DeepseekV2Proj,
|
|
|
|
|
input_layernorm: RmsNorm,
|
|
|
|
|
post_attention_layernorm: RmsNorm,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DeepseekV2DecoderLayer {
|
|
|
|
|
pub fn new(vb: VarBuilder, config: &DeepseekV2Config, layer_id: usize) -> Result<Self> {
|
2025-12-03 17:21:01 +08:00
|
|
|
let self_attn = NaiveAttention::new(
|
2025-11-22 23:27:14 +08:00
|
|
|
vb.pp("self_attn"),
|
|
|
|
|
config.hidden_size,
|
|
|
|
|
config.num_attention_heads,
|
|
|
|
|
config.num_key_value_heads,
|
2025-12-09 00:41:30 +08:00
|
|
|
None,
|
2025-12-03 17:21:01 +08:00
|
|
|
false,
|
2025-12-09 00:41:30 +08:00
|
|
|
None,
|
2025-11-22 23:27:14 +08:00
|
|
|
)?;
|
|
|
|
|
let mlp = if layer_id >= config.first_k_dense_replace
|
|
|
|
|
&& layer_id.is_multiple_of(config.moe_layer_freq)
|
|
|
|
|
{
|
|
|
|
|
DeepseekV2Proj::MOE(DeepseekV2MoE::new(vb.pp("mlp"), config)?)
|
|
|
|
|
} else {
|
2025-12-03 17:21:01 +08:00
|
|
|
DeepseekV2Proj::MLP(GateUpDownMLP::new(
|
2025-11-22 23:27:14 +08:00
|
|
|
vb.pp("mlp"),
|
|
|
|
|
config.hidden_size,
|
|
|
|
|
config.intermediate_size,
|
|
|
|
|
Activation::Silu,
|
2025-12-03 17:21:01 +08:00
|
|
|
false,
|
2025-11-22 23:27:14 +08:00
|
|
|
)?)
|
|
|
|
|
};
|
|
|
|
|
let input_layernorm = rms_norm(
|
|
|
|
|
config.hidden_size,
|
|
|
|
|
config.rms_norm_eps,
|
|
|
|
|
vb.pp("input_layernorm"),
|
|
|
|
|
)?;
|
|
|
|
|
let post_attention_layernorm = rms_norm(
|
|
|
|
|
config.hidden_size,
|
|
|
|
|
config.rms_norm_eps,
|
|
|
|
|
vb.pp("post_attention_layernorm"),
|
|
|
|
|
)?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
self_attn,
|
|
|
|
|
mlp,
|
|
|
|
|
input_layernorm,
|
|
|
|
|
post_attention_layernorm,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(
|
|
|
|
|
&mut self,
|
|
|
|
|
xs: &Tensor,
|
|
|
|
|
cos: &Tensor,
|
|
|
|
|
sin: &Tensor,
|
|
|
|
|
attention_mask: Option<&Tensor>,
|
|
|
|
|
) -> Result<Tensor> {
|
|
|
|
|
let residual = xs.clone();
|
|
|
|
|
let xs = self.input_layernorm.forward(xs)?;
|
|
|
|
|
|
|
|
|
|
let xs = self
|
|
|
|
|
.self_attn
|
|
|
|
|
.forward_with_cache(&xs, cos, sin, attention_mask, false)?;
|
|
|
|
|
let residual = residual.add(&xs)?;
|
|
|
|
|
let xs = self.post_attention_layernorm.forward(&residual)?;
|
|
|
|
|
let xs = self.mlp.forward(&xs)?;
|
|
|
|
|
let xs = residual.add(&xs)?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clear_kv_cache(&mut self) {
|
|
|
|
|
self.self_attn.clear_kv_cache();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct DeepseekV2Model {
|
|
|
|
|
embed_tokens: Embedding,
|
|
|
|
|
layers: Vec<DeepseekV2DecoderLayer>,
|
|
|
|
|
rope: RoPE,
|
|
|
|
|
norm: RmsNorm,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DeepseekV2Model {
|
|
|
|
|
pub fn new(vb: VarBuilder, config: DeepseekV2Config) -> Result<Self> {
|
|
|
|
|
let embed_tokens = embedding(config.vocab_size, config.hidden_size, vb.pp("embed_tokens"))?;
|
|
|
|
|
let mut layers = Vec::new();
|
|
|
|
|
let vb_layers = vb.pp("layers");
|
|
|
|
|
for i in 0..config.num_hidden_layers {
|
|
|
|
|
let layer = DeepseekV2DecoderLayer::new(vb_layers.pp(i), &config, i)?;
|
|
|
|
|
layers.push(layer);
|
|
|
|
|
}
|
|
|
|
|
let head_dim = config.hidden_size / config.num_attention_heads;
|
|
|
|
|
let rope = RoPE::new(head_dim, 10000.0, vb.device())?;
|
|
|
|
|
let norm = rms_norm(config.hidden_size, config.rms_norm_eps, vb.pp("norm"))?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
embed_tokens,
|
|
|
|
|
layers,
|
|
|
|
|
rope,
|
|
|
|
|
norm,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
pub fn forward(&mut self, xs: &Tensor, seqlen_offset: usize) -> Result<Tensor> {
|
|
|
|
|
let (bs, seq_len, _) = xs.dims3()?;
|
|
|
|
|
let (cos, sin) = self.rope.forward(seqlen_offset, seq_len, xs.device())?;
|
|
|
|
|
let attention_mask: Option<&Tensor> = {
|
|
|
|
|
if seq_len <= 1 {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some(&prepare_causal_attention_mask(bs, seq_len, 0, xs.device())?)
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let mut xs = xs.clone();
|
|
|
|
|
for layer in &mut self.layers {
|
|
|
|
|
xs = layer.forward(&xs, &cos, &sin, attention_mask)?;
|
|
|
|
|
}
|
|
|
|
|
let xs = self.norm.forward(&xs)?;
|
|
|
|
|
Ok(xs)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clear_kv_cache(&mut self) {
|
|
|
|
|
for layer in &mut self.layers {
|
|
|
|
|
layer.clear_kv_cache();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-09 15:40:29 +08:00
|
|
|
pub struct DeepseekOCRModel {
|
2025-11-22 23:27:14 +08:00
|
|
|
// config: DeepseekOCRConfig,
|
2025-11-09 15:40:29 +08:00
|
|
|
sam_model: ImageEncoderViT,
|
|
|
|
|
vision_model: VitModel,
|
2025-11-22 23:27:14 +08:00
|
|
|
projector: Linear,
|
2025-11-09 15:40:29 +08:00
|
|
|
language_model: DeepseekV2Model,
|
|
|
|
|
image_newline: Tensor,
|
|
|
|
|
view_seperator: Tensor,
|
|
|
|
|
lm_head: Linear,
|
|
|
|
|
}
|
2025-11-22 23:27:14 +08:00
|
|
|
|
|
|
|
|
impl DeepseekOCRModel {
|
|
|
|
|
pub fn new(vb: VarBuilder, config: DeepseekOCRConfig) -> Result<Self> {
|
|
|
|
|
let vb_m = vb.pp("model");
|
|
|
|
|
let sam_model = ImageEncoderViT::new(
|
|
|
|
|
vb_m.pp("sam_model"),
|
|
|
|
|
1024,
|
|
|
|
|
16,
|
|
|
|
|
3,
|
|
|
|
|
768,
|
|
|
|
|
12,
|
|
|
|
|
12,
|
|
|
|
|
4.0,
|
|
|
|
|
256,
|
|
|
|
|
true,
|
|
|
|
|
Activation::Gelu,
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
// true,
|
|
|
|
|
14,
|
|
|
|
|
config
|
|
|
|
|
.vision_config
|
|
|
|
|
.width
|
|
|
|
|
.sam_vit_b
|
|
|
|
|
.global_attn_indexes
|
|
|
|
|
.clone(),
|
|
|
|
|
)?;
|
|
|
|
|
let vision_model = VitModel::new(
|
|
|
|
|
vb_m.pp("vision_model"),
|
|
|
|
|
224,
|
|
|
|
|
14,
|
|
|
|
|
3,
|
|
|
|
|
24,
|
|
|
|
|
1024,
|
|
|
|
|
16,
|
|
|
|
|
4096,
|
|
|
|
|
1e-5,
|
|
|
|
|
)?;
|
|
|
|
|
let projector = linear(
|
|
|
|
|
config.projector_config.input_dim,
|
|
|
|
|
config.projector_config.n_embed,
|
|
|
|
|
vb_m.pp("projector.layers"),
|
|
|
|
|
)?;
|
|
|
|
|
let image_newline = vb_m.get_with_hints(1280, "image_newline", Init::Const(0.))?;
|
|
|
|
|
let view_seperator = vb_m.get_with_hints(1280, "view_seperator", Init::Const(0.))?;
|
|
|
|
|
let language_model = DeepseekV2Model::new(vb_m, config.language_config.clone())?;
|
|
|
|
|
let lm_head = linear_no_bias(config.hidden_size, config.vocab_size, vb.pp("lm_head"))?;
|
|
|
|
|
Ok(Self {
|
|
|
|
|
// config,
|
|
|
|
|
sam_model,
|
|
|
|
|
vision_model,
|
|
|
|
|
projector,
|
|
|
|
|
language_model,
|
|
|
|
|
image_newline,
|
|
|
|
|
view_seperator,
|
|
|
|
|
lm_head,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn forward(
|
|
|
|
|
&mut self,
|
|
|
|
|
input_ids: &Tensor,
|
|
|
|
|
images_ori: Option<&Tensor>,
|
|
|
|
|
image_crop: Option<&Tensor>,
|
|
|
|
|
images_seq_mask: Option<&Tensor>,
|
|
|
|
|
images_spatial_crop: Option<&Tensor>,
|
|
|
|
|
seqlen_offset: usize,
|
|
|
|
|
) -> Result<Tensor> {
|
|
|
|
|
let mut input_embeds = self.language_model.embed_tokens.forward(input_ids)?;
|
|
|
|
|
if input_ids.dim(1)? > 1
|
|
|
|
|
&& let Some(images_ori) = images_ori
|
|
|
|
|
&& let Some(image_crop) = image_crop
|
|
|
|
|
&& let Some(images_seq_mask) = images_seq_mask
|
|
|
|
|
&& let Some(images_spatial_crop) = images_spatial_crop
|
|
|
|
|
{
|
|
|
|
|
let image_num = images_ori.dim(0)?;
|
|
|
|
|
let mut last_crop_num = 0;
|
|
|
|
|
let mut images_in_this_batch = Vec::new();
|
|
|
|
|
for i in 0..image_num {
|
|
|
|
|
let image_ori_i = images_ori.i(i)?.unsqueeze(0)?;
|
|
|
|
|
let global_local_features = if image_crop
|
|
|
|
|
.sum_all()?
|
|
|
|
|
.to_dtype(candle_core::DType::F32)?
|
|
|
|
|
.to_scalar::<f32>()?
|
|
|
|
|
!= 0.0
|
|
|
|
|
{
|
|
|
|
|
let images_spatial_crop_i = images_spatial_crop.i(i)?;
|
|
|
|
|
let width_crop_num = images_spatial_crop_i.i(0)?.to_scalar::<u32>()? as usize;
|
|
|
|
|
let height_crop_num = images_spatial_crop_i.i(1)?.to_scalar::<u32>()? as usize;
|
|
|
|
|
let crop_num = width_crop_num * height_crop_num;
|
|
|
|
|
let image_crop_i = image_crop.i(last_crop_num..last_crop_num + crop_num)?;
|
|
|
|
|
last_crop_num += crop_num;
|
|
|
|
|
let local_feature_1 = self.sam_model.forward(&image_crop_i)?;
|
|
|
|
|
let local_feature_2 = self
|
|
|
|
|
.vision_model
|
|
|
|
|
.forward(&image_crop_i, Some(&local_feature_1))?;
|
|
|
|
|
let local_feature_1 = local_feature_1.flatten(2, 3)?.permute((0, 2, 1))?;
|
|
|
|
|
let local_feature_2 = local_feature_2.i((.., 1..))?;
|
|
|
|
|
let local_features =
|
|
|
|
|
Tensor::cat(&[local_feature_2, local_feature_1], D::Minus1)?
|
|
|
|
|
.contiguous()?;
|
|
|
|
|
let local_features = self.projector.forward(&local_features)?;
|
|
|
|
|
let global_features_1 = self.sam_model.forward(&image_ori_i)?;
|
|
|
|
|
let global_features_2 = self
|
|
|
|
|
.vision_model
|
|
|
|
|
.forward(&image_ori_i, Some(&global_features_1))?;
|
|
|
|
|
let global_features_1 = global_features_1.flatten(2, 3)?.permute((0, 2, 1))?;
|
|
|
|
|
let global_features_2 = global_features_2.i((.., 1..))?;
|
|
|
|
|
let global_features =
|
|
|
|
|
Tensor::cat(&[global_features_2, global_features_1], D::Minus1)?;
|
|
|
|
|
let global_features = self.projector.forward(&global_features)?;
|
|
|
|
|
let (_, hw, n_dim) = global_features.dims3()?;
|
|
|
|
|
let h = (hw as f32).sqrt() as usize;
|
|
|
|
|
let w = h;
|
|
|
|
|
let (_, hw2, n_dim2) = local_features.dims3()?;
|
|
|
|
|
let h2 = (hw2 as f32).sqrt() as usize;
|
|
|
|
|
let w2 = h2;
|
|
|
|
|
let global_features = global_features.reshape((h, w, n_dim))?;
|
|
|
|
|
let image_newline = self.image_newline.unsqueeze(0)?.unsqueeze(0)?;
|
|
|
|
|
let global_cat = image_newline.expand((h, 1, n_dim))?;
|
|
|
|
|
let global_features = Tensor::cat(&[&global_features, &global_cat], 1)?;
|
|
|
|
|
let global_features = global_features.reshape(((), n_dim))?;
|
|
|
|
|
let local_features = local_features
|
|
|
|
|
.reshape((height_crop_num, width_crop_num, h2, w2, n_dim2))?
|
|
|
|
|
.permute((0, 2, 1, 3, 4))?
|
|
|
|
|
.reshape((height_crop_num * h2, width_crop_num * w2, n_dim2))?;
|
|
|
|
|
let local_cat = image_newline.expand((height_crop_num * h2, 1, n_dim2))?;
|
|
|
|
|
let local_features = Tensor::cat(&[&local_features, &local_cat], 1)?;
|
|
|
|
|
let local_features = local_features.reshape(((), n_dim2))?;
|
|
|
|
|
Tensor::cat(
|
|
|
|
|
&[
|
|
|
|
|
local_features,
|
|
|
|
|
global_features,
|
|
|
|
|
self.view_seperator.unsqueeze(0)?,
|
|
|
|
|
],
|
|
|
|
|
0,
|
|
|
|
|
)?
|
|
|
|
|
} else {
|
|
|
|
|
let global_features_1 = self.sam_model.forward(&image_ori_i)?;
|
|
|
|
|
let global_features_2 = self
|
|
|
|
|
.vision_model
|
|
|
|
|
.forward(&image_ori_i, Some(&global_features_1))?;
|
|
|
|
|
let global_features_1 = global_features_1.flatten(2, 3)?.permute((0, 2, 1))?;
|
|
|
|
|
let global_features_2 = global_features_2.i((.., 1..))?;
|
|
|
|
|
let global_features =
|
|
|
|
|
Tensor::cat(&[global_features_2, global_features_1], D::Minus1)?;
|
|
|
|
|
let global_features = self.projector.forward(&global_features)?;
|
|
|
|
|
let (_, hw, n_dim) = global_features.dims3()?;
|
|
|
|
|
let h = (hw as f32).sqrt() as usize;
|
|
|
|
|
let w = h;
|
|
|
|
|
let global_features = global_features.reshape((h, w, n_dim))?;
|
|
|
|
|
let image_newline = self.image_newline.unsqueeze(0)?.unsqueeze(0)?;
|
|
|
|
|
let global_cat = image_newline.expand((h, 1, n_dim))?;
|
|
|
|
|
let global_features = Tensor::cat(&[&global_features, &global_cat], 1)?;
|
|
|
|
|
let global_features = global_features.reshape(((), n_dim))?;
|
|
|
|
|
Tensor::cat(&[global_features, self.view_seperator.unsqueeze(0)?], 0)?
|
|
|
|
|
};
|
|
|
|
|
images_in_this_batch.push(global_local_features);
|
|
|
|
|
}
|
|
|
|
|
let images_in_this_batch = Tensor::cat(&images_in_this_batch, 0)?;
|
|
|
|
|
input_embeds =
|
|
|
|
|
masked_scatter_dim0(&input_embeds, &images_in_this_batch, images_seq_mask)?;
|
|
|
|
|
}
|
|
|
|
|
let outputs = self.language_model.forward(&input_embeds, seqlen_offset)?;
|
|
|
|
|
let seq_len = outputs.dim(1)?;
|
|
|
|
|
let hidden_state = outputs.narrow(1, seq_len - 1, 1)?;
|
|
|
|
|
let logits = self.lm_head.forward(&hidden_state)?;
|
|
|
|
|
Ok(logits)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn clear_kv_cache(&mut self) {
|
|
|
|
|
self.language_model.clear_kv_cache();
|
|
|
|
|
}
|
|
|
|
|
}
|