add hunyuan_ocr
This commit is contained in:
@@ -0,0 +1,621 @@
|
||||
use anyhow::{Result, anyhow};
|
||||
use candle_core::{D, IndexOp, Tensor};
|
||||
use candle_nn::{
|
||||
Conv2d, Embedding, Init, LayerNorm, Linear, Module, RmsNorm, VarBuilder, embedding, linear,
|
||||
linear_no_bias, rms_norm,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
models::{
|
||||
common::{
|
||||
GateUpDownMLP, NaiveAttention, TwoLinearMLP, eager_attention_forward, get_conv2d,
|
||||
get_layer_norm,
|
||||
},
|
||||
hunyuan_ocr::config::{HunYuanVLConfig, HunYuanVLVisionConfig},
|
||||
},
|
||||
position_embed::rope::{RoPE, apply_rotary_pos_emb, get_xd_cos_sin},
|
||||
utils::tensor_utils::{
|
||||
interpolate_bilinear, masked_scatter_dim0, prepare_causal_attention_mask, split_tensor,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct HunYuanVisionPatchEmbed {
|
||||
patch_embedding: Conv2d,
|
||||
// position_embedding: Embedding,
|
||||
num_channels: usize,
|
||||
patch_size: usize,
|
||||
// num_positions: usize,
|
||||
// position_edge: usize,
|
||||
embed_dim: usize,
|
||||
patch_pos_embed: Tensor,
|
||||
}
|
||||
|
||||
impl HunYuanVisionPatchEmbed {
|
||||
pub fn new(vb: VarBuilder, config: &HunYuanVLVisionConfig) -> Result<Self> {
|
||||
let patch_embedding = get_conv2d(
|
||||
vb.pp("patch_embedding"),
|
||||
config.num_channels,
|
||||
config.hidden_size,
|
||||
config.patch_size,
|
||||
0,
|
||||
config.patch_size,
|
||||
1,
|
||||
1,
|
||||
true,
|
||||
)?;
|
||||
let num_channels = config.num_channels;
|
||||
let patch_size = config.patch_size;
|
||||
let position_edge = config.max_image_size / patch_size;
|
||||
let num_positions = (position_edge).pow(2) + 1;
|
||||
let embed_dim = config.hidden_size;
|
||||
let position_embedding = embedding(num_positions, embed_dim, vb.pp("position_embedding"))?;
|
||||
let patch_pos_embed = position_embedding
|
||||
.embeddings()
|
||||
.i(1..)?
|
||||
.reshape((1, position_edge, position_edge, embed_dim))?
|
||||
.permute((0, 3, 1, 2))?;
|
||||
Ok(Self {
|
||||
patch_embedding,
|
||||
// position_embedding,
|
||||
num_channels,
|
||||
patch_size,
|
||||
// num_positions,
|
||||
// position_edge,
|
||||
embed_dim,
|
||||
patch_pos_embed,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn forward(&self, pixel_values: &Tensor, grid_thw: &Tensor) -> Result<Tensor> {
|
||||
let (num_patches, _) = pixel_values.dims2()?;
|
||||
let pixel_values = pixel_values.reshape((
|
||||
num_patches,
|
||||
self.num_channels,
|
||||
self.patch_size,
|
||||
self.patch_size,
|
||||
))?;
|
||||
let patch_embeds = self.patch_embedding.forward(&pixel_values)?;
|
||||
let patch_embeds = patch_embeds
|
||||
.squeeze(D::Minus1)?
|
||||
.squeeze(D::Minus1)?
|
||||
.unsqueeze(0)?;
|
||||
let mut patch_pos_embed_list = vec![];
|
||||
let img_num = grid_thw.dim(0)?;
|
||||
for i in 0..img_num {
|
||||
let grid_i = grid_thw.i(i)?;
|
||||
let grid_h = grid_i.i(1)?.to_scalar::<u32>()? as usize;
|
||||
let grid_w = grid_i.i(2)?.to_scalar::<u32>()? as usize;
|
||||
let patch_pos_embed_ =
|
||||
interpolate_bilinear(&self.patch_pos_embed, (grid_h, grid_w), Some(false))?;
|
||||
let patch_pos_embed_ = patch_pos_embed_
|
||||
.reshape((self.embed_dim, ()))?
|
||||
.transpose(0, 1)?
|
||||
.unsqueeze(0)?;
|
||||
patch_pos_embed_list.push(patch_pos_embed_);
|
||||
}
|
||||
let patch_pos_embed = Tensor::cat(&patch_pos_embed_list, 1)?;
|
||||
let embedding = patch_embeds.add(&patch_pos_embed)?;
|
||||
Ok(embedding)
|
||||
}
|
||||
}
|
||||
pub struct HunYuanVisionBlock {
|
||||
self_attn: NaiveAttention,
|
||||
mlp: TwoLinearMLP,
|
||||
input_layernorm: LayerNorm,
|
||||
post_attention_layernorm: LayerNorm,
|
||||
}
|
||||
|
||||
impl HunYuanVisionBlock {
|
||||
pub fn new(vb: VarBuilder, config: &HunYuanVLVisionConfig) -> Result<Self> {
|
||||
let self_attn = NaiveAttention::new(
|
||||
vb.pp("self_attn"),
|
||||
config.hidden_size,
|
||||
config.num_attention_heads,
|
||||
config.num_attention_heads,
|
||||
true,
|
||||
)?;
|
||||
let mlp = TwoLinearMLP::new(
|
||||
vb.pp("mlp"),
|
||||
config.hidden_size,
|
||||
config.intermediate_size,
|
||||
config.hidden_act,
|
||||
true,
|
||||
"dense_h_to_4h",
|
||||
"dense_4h_to_h",
|
||||
)?;
|
||||
|
||||
let input_layernorm = get_layer_norm(
|
||||
vb.pp("input_layernorm"),
|
||||
config.rms_norm_eps,
|
||||
config.hidden_size,
|
||||
)?;
|
||||
let post_attention_layernorm = get_layer_norm(
|
||||
vb.pp("post_attention_layernorm"),
|
||||
config.rms_norm_eps,
|
||||
config.hidden_size,
|
||||
)?;
|
||||
Ok(Self {
|
||||
self_attn,
|
||||
mlp,
|
||||
input_layernorm,
|
||||
post_attention_layernorm,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn forward(&self, xs: &Tensor) -> Result<Tensor> {
|
||||
let residual = xs.clone();
|
||||
let xs = self.input_layernorm.forward(xs)?;
|
||||
let xs = self.self_attn.forward(&xs, None, None, None, 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 struct HunYuanVisionPatchMerger {
|
||||
proj_0: Conv2d,
|
||||
proj_2: Conv2d,
|
||||
mlp: Linear,
|
||||
image_newline: Tensor,
|
||||
image_begin: Tensor,
|
||||
image_end: Tensor,
|
||||
// image_sep: Tensor,
|
||||
before_rms: RmsNorm,
|
||||
after_rms: RmsNorm,
|
||||
}
|
||||
|
||||
impl HunYuanVisionPatchMerger {
|
||||
pub fn new(vb: VarBuilder, config: &HunYuanVLVisionConfig) -> Result<Self> {
|
||||
let proj_0 = get_conv2d(
|
||||
vb.pp("proj.0"),
|
||||
config.hidden_size,
|
||||
config.hidden_size * 2,
|
||||
config.spatial_merge_size,
|
||||
0,
|
||||
config.spatial_merge_size,
|
||||
1,
|
||||
1,
|
||||
true,
|
||||
)?;
|
||||
let proj_2 = get_conv2d(
|
||||
vb.pp("proj.2"),
|
||||
config.hidden_size * 2,
|
||||
config.hidden_size * 4,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
true,
|
||||
)?;
|
||||
let mlp = linear(config.hidden_size * 4, config.out_hidden_size, vb.pp("mlp"))?;
|
||||
let image_newline =
|
||||
vb.get_with_hints(config.hidden_size * 4, "image_newline", Init::Const(0.))?;
|
||||
let image_begin =
|
||||
vb.get_with_hints(config.out_hidden_size, "image_begin", Init::Const(0.))?;
|
||||
let image_end = vb.get_with_hints(config.out_hidden_size, "image_end", Init::Const(0.))?;
|
||||
// let image_sep = vb.get_with_hints(config.out_hidden_size, "image_sep", Init::Const(0.))?;
|
||||
let before_rms = rms_norm(config.hidden_size, config.rms_norm_eps, vb.pp("before_rms"))?;
|
||||
let after_rms = rms_norm(
|
||||
config.out_hidden_size,
|
||||
config.rms_norm_eps,
|
||||
vb.pp("after_rms"),
|
||||
)?;
|
||||
Ok(Self {
|
||||
proj_0,
|
||||
proj_2,
|
||||
mlp,
|
||||
image_newline,
|
||||
image_begin,
|
||||
image_end,
|
||||
// image_sep,
|
||||
before_rms,
|
||||
after_rms,
|
||||
})
|
||||
}
|
||||
pub fn forward(&self, xs: &Tensor, size: (usize, usize)) -> Result<Tensor> {
|
||||
let xs = self.before_rms.forward(xs)?;
|
||||
let (h, w) = size;
|
||||
let xs = xs.permute((0, 2, 1))?.reshape((xs.dim(0)?, (), h, w))?;
|
||||
let xs = self.proj_0.forward(&xs)?.gelu()?;
|
||||
let xs = self.proj_2.forward(&xs)?;
|
||||
let (b, c, h, _) = xs.dims4()?;
|
||||
let image_newline = self
|
||||
.image_newline
|
||||
.reshape((1, c, 1, 1))?
|
||||
.broadcast_as((b, c, h, 1))?
|
||||
.to_dtype(xs.dtype())?;
|
||||
let xs = Tensor::cat(&[xs, image_newline], D::Minus1)?;
|
||||
let xs = xs.reshape((b, c, ()))?.permute((0, 2, 1))?;
|
||||
let xs = self.mlp.forward(&xs)?;
|
||||
let begin = self
|
||||
.image_begin
|
||||
.reshape((1, 1, ()))?
|
||||
.broadcast_as((b, 1, xs.dim(D::Minus1)?))?
|
||||
.to_dtype(xs.dtype())?;
|
||||
let end = self
|
||||
.image_end
|
||||
.reshape((1, 1, ()))?
|
||||
.broadcast_as((b, 1, xs.dim(D::Minus1)?))?
|
||||
.to_dtype(xs.dtype())?;
|
||||
let xs = Tensor::cat(&[begin, xs, end], 1)?;
|
||||
let xs = self.after_rms.forward(&xs)?;
|
||||
Ok(xs)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HunYuanVisionTransformer {
|
||||
embeddings: HunYuanVisionPatchEmbed,
|
||||
layers: Vec<HunYuanVisionBlock>,
|
||||
perceive: HunYuanVisionPatchMerger,
|
||||
}
|
||||
|
||||
impl HunYuanVisionTransformer {
|
||||
pub fn new(vb: VarBuilder, config: &HunYuanVLVisionConfig) -> Result<Self> {
|
||||
let embeddings = HunYuanVisionPatchEmbed::new(vb.pp("embeddings"), config)?;
|
||||
let mut layers = vec![];
|
||||
let vb_layers = vb.pp("layers");
|
||||
for i in 0..config.num_hidden_layers {
|
||||
let layer_i = HunYuanVisionBlock::new(vb_layers.pp(i), config)?;
|
||||
layers.push(layer_i);
|
||||
}
|
||||
let perceive = HunYuanVisionPatchMerger::new(vb.pp("perceive"), config)?;
|
||||
Ok(Self {
|
||||
embeddings,
|
||||
layers,
|
||||
perceive,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn forward(&self, xs: &Tensor, grid_thw: &Tensor) -> Result<Tensor> {
|
||||
let mut hidden_states = self.embeddings.forward(xs, grid_thw)?;
|
||||
for layer in &self.layers {
|
||||
hidden_states = layer.forward(&hidden_states)?;
|
||||
}
|
||||
let mut cu_seqlens = vec![];
|
||||
for i in 0..grid_thw.dim(0)? {
|
||||
let [_, h, w] = grid_thw.i(i)?.to_vec1::<u32>()?[..] else {
|
||||
return Err(anyhow!(format!("grid_thw Expected exactly 3 elements")));
|
||||
};
|
||||
cu_seqlens.push((h * w) as usize);
|
||||
}
|
||||
let split_items = split_tensor(&hidden_states, &cu_seqlens, 1)?;
|
||||
let mut processed_item = vec![];
|
||||
for i in 0..grid_thw.dim(0)? {
|
||||
let [_, h, w] = grid_thw.i(i)?.to_vec1::<u32>()?[..] else {
|
||||
return Err(anyhow!(format!("grid_thw Expected exactly 3 elements")));
|
||||
};
|
||||
let processed = self
|
||||
.perceive
|
||||
.forward(&split_items[i], (h as usize, w as usize))?;
|
||||
processed_item.push(processed);
|
||||
}
|
||||
let xs = Tensor::cat(&processed_item, 1)?;
|
||||
Ok(xs)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HunYuanVLAttention {
|
||||
q_proj: Linear,
|
||||
k_proj: Linear,
|
||||
v_proj: Linear,
|
||||
o_proj: Linear,
|
||||
query_layernorm: RmsNorm,
|
||||
key_layernorm: RmsNorm,
|
||||
num_attention_heads: usize,
|
||||
num_key_value_heads: usize,
|
||||
num_kv_groups: usize,
|
||||
head_dim: usize,
|
||||
scaling: f64,
|
||||
kv_cache: Option<(Tensor, Tensor)>,
|
||||
}
|
||||
|
||||
impl HunYuanVLAttention {
|
||||
pub fn new(
|
||||
vb: VarBuilder,
|
||||
hidden_size: usize,
|
||||
head_dim: usize,
|
||||
num_attention_heads: usize,
|
||||
num_key_value_heads: usize,
|
||||
attention_bias: bool,
|
||||
rms_norm_eps: f64,
|
||||
) -> Result<Self> {
|
||||
let num_kv_groups = num_attention_heads / num_key_value_heads;
|
||||
let scaling = 1f64 / f64::sqrt(head_dim as f64);
|
||||
let (q_proj, k_proj, v_proj, o_proj) = if attention_bias {
|
||||
let q_proj = linear(hidden_size, num_attention_heads * head_dim, vb.pp("q_proj"))?;
|
||||
let k_proj = linear(hidden_size, num_key_value_heads * head_dim, vb.pp("k_proj"))?;
|
||||
let v_proj = linear(hidden_size, num_key_value_heads * head_dim, vb.pp("v_proj"))?;
|
||||
let o_proj = linear(num_attention_heads * head_dim, hidden_size, vb.pp("o_proj"))?;
|
||||
(q_proj, k_proj, v_proj, o_proj)
|
||||
} else {
|
||||
let q_proj =
|
||||
linear_no_bias(hidden_size, num_attention_heads * head_dim, vb.pp("q_proj"))?;
|
||||
let k_proj =
|
||||
linear_no_bias(hidden_size, num_key_value_heads * head_dim, vb.pp("k_proj"))?;
|
||||
let v_proj =
|
||||
linear_no_bias(hidden_size, num_key_value_heads * head_dim, vb.pp("v_proj"))?;
|
||||
let o_proj =
|
||||
linear_no_bias(num_attention_heads * head_dim, hidden_size, vb.pp("o_proj"))?;
|
||||
(q_proj, k_proj, v_proj, o_proj)
|
||||
};
|
||||
let query_layernorm = rms_norm(head_dim, rms_norm_eps, vb.pp("query_layernorm"))?;
|
||||
let key_layernorm = rms_norm(head_dim, rms_norm_eps, vb.pp("key_layernorm"))?;
|
||||
Ok(Self {
|
||||
q_proj,
|
||||
k_proj,
|
||||
v_proj,
|
||||
o_proj,
|
||||
query_layernorm,
|
||||
key_layernorm,
|
||||
num_attention_heads,
|
||||
num_key_value_heads,
|
||||
num_kv_groups,
|
||||
head_dim,
|
||||
scaling,
|
||||
kv_cache: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn forward(
|
||||
&mut self,
|
||||
xs: &Tensor,
|
||||
cos: &Tensor,
|
||||
sin: &Tensor,
|
||||
attention_mask: Option<&Tensor>,
|
||||
) -> Result<Tensor> {
|
||||
let (b_sz, q_len, _) = xs.dims3()?;
|
||||
let query_states = self
|
||||
.q_proj
|
||||
.forward(xs)?
|
||||
.reshape((b_sz, q_len, self.num_attention_heads, self.head_dim))?
|
||||
.transpose(1, 2)?;
|
||||
|
||||
let key_states = self
|
||||
.k_proj
|
||||
.forward(xs)?
|
||||
.reshape((b_sz, q_len, self.num_key_value_heads, self.head_dim))?
|
||||
.transpose(1, 2)?;
|
||||
let value_states = self.v_proj.forward(xs)?;
|
||||
let value_states = value_states
|
||||
.reshape((b_sz, q_len, self.num_key_value_heads, self.head_dim))?
|
||||
.transpose(1, 2)?;
|
||||
let (query_states, key_states) =
|
||||
apply_rotary_pos_emb(&query_states, &key_states, cos, sin, false)?;
|
||||
let query_states = self.query_layernorm.forward(&query_states)?;
|
||||
let key_states = self.key_layernorm.forward(&key_states)?;
|
||||
let (key_states, value_states) = match &self.kv_cache {
|
||||
None => (key_states, value_states),
|
||||
Some((prev_k, prev_v)) => {
|
||||
let key_states = Tensor::cat(&[prev_k, &key_states], 2)?;
|
||||
let value_states = Tensor::cat(&[prev_v, &value_states], 2)?;
|
||||
(key_states, value_states)
|
||||
}
|
||||
};
|
||||
self.kv_cache = Some((key_states.clone(), value_states.clone()));
|
||||
let attn_output = eager_attention_forward(
|
||||
&query_states,
|
||||
&key_states,
|
||||
&value_states,
|
||||
Some(self.num_kv_groups),
|
||||
attention_mask,
|
||||
self.scaling,
|
||||
)?;
|
||||
let attn_output =
|
||||
attn_output.reshape((b_sz, q_len, self.num_attention_heads * self.head_dim))?;
|
||||
let attn_output = attn_output.apply(&self.o_proj)?;
|
||||
Ok(attn_output)
|
||||
}
|
||||
|
||||
pub fn clear_kv_cache(&mut self) {
|
||||
self.kv_cache = None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HunYuanVLDecoderLayer {
|
||||
self_attn: HunYuanVLAttention,
|
||||
mlp: GateUpDownMLP,
|
||||
input_layernorm: RmsNorm,
|
||||
post_attention_layernorm: RmsNorm,
|
||||
}
|
||||
|
||||
impl HunYuanVLDecoderLayer {
|
||||
pub fn new(config: &HunYuanVLConfig, vb: VarBuilder) -> Result<Self> {
|
||||
let self_attn = HunYuanVLAttention::new(
|
||||
vb.pp("self_attn"),
|
||||
config.hidden_size,
|
||||
config.head_dim,
|
||||
config.num_attention_heads,
|
||||
config.num_key_value_heads,
|
||||
config.attention_bias,
|
||||
config.rms_norm_eps,
|
||||
)?;
|
||||
let mlp = GateUpDownMLP::new(
|
||||
vb.pp("mlp"),
|
||||
config.hidden_size,
|
||||
config.intermediate_size,
|
||||
config.hidden_act,
|
||||
false,
|
||||
)?;
|
||||
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(&xs, cos, sin, attention_mask)?;
|
||||
let xs = residual.add(&xs)?;
|
||||
let residual = xs.clone();
|
||||
let xs = self.post_attention_layernorm.forward(&xs)?;
|
||||
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 HunYuanVLTextModel {
|
||||
embed_tokens: Embedding,
|
||||
layers: Vec<HunYuanVLDecoderLayer>,
|
||||
norm: RmsNorm,
|
||||
rope: RoPE,
|
||||
xdrope_section: Vec<usize>,
|
||||
}
|
||||
|
||||
impl HunYuanVLTextModel {
|
||||
pub fn new(vb: VarBuilder, config: &HunYuanVLConfig) -> Result<Self> {
|
||||
let embed_tokens = embedding(config.vocab_size, config.hidden_size, vb.pp("embed_tokens"))?;
|
||||
let mut layers = vec![];
|
||||
let vb_layers = vb.pp("layers");
|
||||
for i in 0..config.num_hidden_layers {
|
||||
let layer = HunYuanVLDecoderLayer::new(config, vb_layers.pp(i))?;
|
||||
layers.push(layer);
|
||||
}
|
||||
let norm = rms_norm(config.hidden_size, config.rms_norm_eps, vb.pp("norm"))?;
|
||||
let base = config.rope_theta
|
||||
* config
|
||||
.rope_scaling
|
||||
.alpha
|
||||
.powf(config.head_dim as f64 / (config.head_dim - 2) as f64);
|
||||
let rope = RoPE::new(config.head_dim, base as f32, vb.device())?;
|
||||
let xdrope_section = config.rope_scaling.xdrope_section.clone();
|
||||
Ok(Self {
|
||||
embed_tokens,
|
||||
layers,
|
||||
norm,
|
||||
rope,
|
||||
xdrope_section,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn forward(
|
||||
&mut self,
|
||||
inputs_embeds: &Tensor,
|
||||
position_ids: Option<&Tensor>,
|
||||
seqlen_offset: usize,
|
||||
) -> Result<Tensor> {
|
||||
let (b_size, seq_len, _) = inputs_embeds.dims3()?;
|
||||
|
||||
// let position_ids = match position_ids {
|
||||
// Some(ids) => ids.clone(),
|
||||
// None => Tensor::arange(
|
||||
// seqlen_offset as u32,
|
||||
// (seq_len + seqlen_offset) as u32,
|
||||
// inputs_embeds.device(),
|
||||
// )?
|
||||
// .unsqueeze(0)?,
|
||||
// };
|
||||
let attention_mask: Option<&Tensor> = {
|
||||
if seq_len <= 1 {
|
||||
None
|
||||
} else {
|
||||
Some(&prepare_causal_attention_mask(
|
||||
b_size,
|
||||
seq_len,
|
||||
0,
|
||||
inputs_embeds.device(),
|
||||
)?)
|
||||
}
|
||||
};
|
||||
|
||||
let (cos, sin) = self
|
||||
.rope
|
||||
.forward(seqlen_offset, seq_len, inputs_embeds.device())?;
|
||||
let mut xs = inputs_embeds.clone();
|
||||
for (i, layer) in self.layers.iter_mut().enumerate() {
|
||||
if i == 0
|
||||
&& let Some(position_ids) = position_ids
|
||||
{
|
||||
let (cos, sin) =
|
||||
get_xd_cos_sin(&cos, &sin, position_ids, self.xdrope_section.clone())?;
|
||||
xs = layer.forward(&xs, &cos, &sin, attention_mask)?;
|
||||
} else {
|
||||
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 self.layers.iter_mut() {
|
||||
layer.clear_kv_cache()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HunyuanVLModel {
|
||||
// config: HunYuanVLConfig,
|
||||
vit: HunYuanVisionTransformer,
|
||||
model: HunYuanVLTextModel,
|
||||
lm_head: Linear,
|
||||
}
|
||||
|
||||
impl HunyuanVLModel {
|
||||
pub fn new(vb: VarBuilder, config: HunYuanVLConfig) -> Result<Self> {
|
||||
let vit = HunYuanVisionTransformer::new(vb.pp("vit"), &config.vision_config)?;
|
||||
let model = HunYuanVLTextModel::new(vb.pp("model"), &config)?;
|
||||
let lm_head = Linear::new(model.embed_tokens.embeddings().clone(), None);
|
||||
Ok(Self {
|
||||
// config,
|
||||
vit,
|
||||
model,
|
||||
lm_head,
|
||||
})
|
||||
}
|
||||
pub fn forward(
|
||||
&mut self,
|
||||
input_ids: &Tensor,
|
||||
pixel_values: Option<&Tensor>,
|
||||
image_grid_thw: Option<&Tensor>,
|
||||
image_mask: Option<&Tensor>,
|
||||
position_ids: Option<&Tensor>,
|
||||
seqlen_offset: usize,
|
||||
) -> Result<Tensor> {
|
||||
let mut inputs_embeds = self.model.embed_tokens.forward(input_ids)?;
|
||||
if let Some(pixel_values) = pixel_values
|
||||
&& let Some(grid_thw) = image_grid_thw
|
||||
&& let Some(image_mask) = image_mask
|
||||
{
|
||||
let image_embeds = self.vit.forward(pixel_values, grid_thw)?.squeeze(0)?;
|
||||
inputs_embeds = masked_scatter_dim0(&inputs_embeds, &image_embeds, image_mask)?;
|
||||
}
|
||||
let outputs = self
|
||||
.model
|
||||
.forward(&inputs_embeds, position_ids, 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.model.clear_kv_cache();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user