use crate::model::conv_conformer::load_simple_conv;
use crate::model::simple_conv::SimpleConvEncoder;
use crate::tensor::Tensor;
use crate::v1::bahdanau::BahdanauAttention;
use crate::v1::config::V1EncoderConfig;
use crate::weights::{get, load_safetensors, param_to_tensor, WeightStore};
pub struct SimpleConvTimeAgg {
pub conv: SimpleConvEncoder,
pub attention: BahdanauAttention,
pub hidden: usize,
}
impl SimpleConvTimeAgg {
pub fn from_config_and_weights(
cfg: &V1EncoderConfig,
store: &mut WeightStore,
prefix: &str,
) -> anyhow::Result<Self> {
anyhow::ensure!(
cfg.time_agg_out == "att",
"only Bahdanau attention (time_agg_out=att) is supported"
);
let conv = load_simple_conv(&cfg.encoder_config, store, prefix)?;
let att_prefix = format!("{prefix}time_agg_out.");
let attention = BahdanauAttention {
wa_w: param_to_tensor(get(store, &format!("{att_prefix}Wa.weight"))?),
wa_b: param_to_tensor(get(store, &format!("{att_prefix}Wa.bias"))?),
va_w: param_to_tensor(get(store, &format!("{att_prefix}Va.weight"))?),
va_b: param_to_tensor(get(store, &format!("{att_prefix}Va.bias"))?),
};
Ok(Self {
hidden: cfg.encoder_config.hidden,
conv,
attention,
})
}
pub fn from_tiny_weights(weights_path: &str) -> anyhow::Result<Self> {
let cfg = crate::v1::config::V1Config::tiny().brain_model_config;
let mut store = load_safetensors(weights_path)?;
Self::from_config_and_weights(&cfg, &mut store, "")
}
pub fn forward(&self, x: &Tensor, subject_ids: &[usize], chan_pos: Option<&Tensor>) -> Tensor {
let z = self.conv.forward(x, subject_ids, chan_pos);
let ctx = self.attention.forward(&z);
assert_eq!(ctx.shape[0], x.shape[0]);
assert_eq!(ctx.shape[1], self.hidden);
ctx.reshape(&[ctx.shape[0], self.hidden])
}
}