rlx_flow/blocks/
llama_decoder.rs1use anyhow::Result;
17use rlx_ir::op::MaskKind;
18
19use super::BlockStage;
20use crate::context::FlowCtx;
21use crate::value::FlowValue;
22#[derive(Debug, Clone)]
23pub struct LlamaDecoderStage {
24 pub layer_prefix: String,
25 pub num_heads: usize,
26 pub head_dim: usize,
27 pub num_kv_heads: usize,
28 pub eps: f32,
29 pub mask: MaskKind,
30 pub hidden_shape: rlx_ir::Shape,
31 pub rope_style: rlx_ir::RopeStyle,
32}
33
34impl LlamaDecoderStage {
35 pub fn layer(layer_idx: usize, spec: LlamaDecoderSpec) -> Self {
36 Self {
37 layer_prefix: format!("model.layers.{layer_idx}"),
38 num_heads: spec.num_heads,
39 head_dim: spec.head_dim,
40 num_kv_heads: spec.num_kv_heads,
41 eps: spec.eps,
42 mask: spec.mask,
43 hidden_shape: spec.hidden_shape,
44 rope_style: spec.rope_style,
45 }
46 }
47}
48
49#[derive(Debug, Clone)]
50pub struct LlamaDecoderSpec {
51 pub num_heads: usize,
52 pub head_dim: usize,
53 pub n_rot: usize,
56 pub num_kv_heads: usize,
57 pub eps: f32,
58 pub mask: MaskKind,
59 pub hidden_shape: rlx_ir::Shape,
60 pub rope_style: rlx_ir::RopeStyle,
62}
63
64impl BlockStage for LlamaDecoderStage {
65 fn emit(&self, ctx: &mut FlowCtx<'_>, input: FlowValue) -> Result<Option<FlowValue>> {
66 let lp = &self.layer_prefix;
67 let zero_beta = ctx
68 .state
69 .zero_beta
70 .ok_or_else(|| anyhow::anyhow!("LlamaDecoder requires ZeroBeta stage"))?;
71 let cos = ctx
72 .state
73 .rope_cos
74 .ok_or_else(|| anyhow::anyhow!("LlamaDecoder requires RopeTables stage"))?;
75 let sin = ctx
76 .state
77 .rope_sin
78 .ok_or_else(|| anyhow::anyhow!("LlamaDecoder requires RopeTables stage"))?;
79
80 let in_ln_g = ctx.load_param(&format!("{lp}.input_layernorm.weight"), false)?;
81 let q_w = ctx.load_param(&format!("{lp}.self_attn.q_proj.weight"), true)?;
82 let k_w = ctx.load_param(&format!("{lp}.self_attn.k_proj.weight"), true)?;
83 let v_w = ctx.load_param(&format!("{lp}.self_attn.v_proj.weight"), true)?;
84 let o_w = ctx.load_param(&format!("{lp}.self_attn.o_proj.weight"), true)?;
85 let post_ln_g = ctx.load_param(&format!("{lp}.post_attention_layernorm.weight"), false)?;
86 let gate_w = ctx.load_param(&format!("{lp}.mlp.gate_proj.weight"), true)?;
87 let up_w = ctx.load_param(&format!("{lp}.mlp.up_proj.weight"), true)?;
88 let down_w = ctx.load_param(&format!("{lp}.mlp.down_proj.weight"), true)?;
89
90 let id = ctx.hir().llama_decoder_block(
91 input.id,
92 in_ln_g,
93 zero_beta,
94 q_w,
95 k_w,
96 v_w,
97 o_w,
98 post_ln_g,
99 zero_beta,
100 gate_w,
101 up_w,
102 down_w,
103 cos,
104 sin,
105 None,
106 self.num_heads,
107 self.head_dim,
108 self.num_kv_heads,
109 self.eps,
110 self.mask,
111 self.rope_style,
112 self.hidden_shape.clone(),
113 );
114
115 Ok(Some(ctx.wrap(id, self.hidden_shape.clone())))
116 }
117}