use std::collections::HashMap;
use anyhow::Result;
use rlx_ir::Graph;
use rlx_ir::quant::QuantScheme;
use crate::config::GemmaConfig;
use crate::multimodal::{GemmaMultimodalConfig, fuse_multimodal_embeddings};
use crate::multimodal_mask::{build_vision_bidirectional_mask_2d, expand_attn_bias};
use crate::qat_loader::GemmaQatLoader;
type PackedWeightMap = HashMap<String, (Vec<u8>, QuantScheme, Vec<usize>)>;
pub fn e2b_fused_inputs_embeds_prescale(
loader: &GemmaQatLoader,
cfg: &GemmaConfig,
mm_cfg: &GemmaMultimodalConfig,
token_ids: &[u32],
image_embeds: &[f32],
audio_embeds: &[f32],
video_embeds: &[f32],
) -> Result<Vec<f32>> {
let h = cfg.hidden_size;
let (mut embeds, dim) =
loader.dequant_embedding_rows("model.embed_tokens.weight", token_ids)?;
anyhow::ensure!(dim == h, "embed dim {dim} != hidden {h}");
let inv = 1.0f32 / (h as f32).sqrt();
let scale = |v: &[f32]| -> Vec<f32> { v.iter().map(|x| x * inv).collect() };
fuse_multimodal_embeddings(
&mut embeds,
token_ids,
h,
mm_cfg,
&scale(image_embeds),
&scale(audio_embeds),
&scale(video_embeds),
)?;
Ok(embeds)
}
pub fn e2b_media_attn_bias(
token_ids: &[u32],
cfg: &GemmaConfig,
mm_cfg: &GemmaMultimodalConfig,
batch: usize,
) -> Vec<f32> {
let mask2d = build_vision_bidirectional_mask_2d(token_ids, mm_cfg);
expand_attn_bias(&mask2d, batch, cfg.num_attention_heads, token_ids.len())
}
pub fn embed_lazy_marker_with(cfg: &GemmaConfig, media_bias: bool) -> PackedWeightMap {
let mut m = PackedWeightMap::new();
m.insert(
"model.embed_tokens.weight".to_string(),
(
Vec::new(),
QuantScheme::Int8Block { block_size: 32 },
vec![cfg.vocab_size, cfg.hidden_size],
),
);
if media_bias {
m.insert(
"__media_bias__".to_string(),
(
Vec::new(),
QuantScheme::Int8Block { block_size: 32 },
vec![],
),
);
}
m
}
pub fn embed_lazy_marker(cfg: &GemmaConfig) -> PackedWeightMap {
embed_lazy_marker_with(cfg, false)
}
pub fn build_e2b_multimodal_prefill(
cfg: &GemmaConfig,
loader: &mut GemmaQatLoader,
batch: usize,
seq: usize,
) -> Result<(Graph, HashMap<String, Vec<f32>>)> {
build_e2b_multimodal_prefill_ext(cfg, loader, batch, seq, false)
}
pub fn build_e2b_multimodal_prefill_ext(
cfg: &GemmaConfig,
loader: &mut GemmaQatLoader,
batch: usize,
seq: usize,
media_bias: bool,
) -> Result<(Graph, HashMap<String, Vec<f32>>)> {
let marker = embed_lazy_marker_with(cfg, media_bias);
let mut packed = HashMap::new();
crate::builder::build_gemma_graph_sized_packed_ext(
cfg,
loader,
batch,
seq,
true,
false,
false,
&mut packed,
Some(&marker),
None,
)
}