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 num_kv_heads: usize,
54 pub eps: f32,
55 pub mask: MaskKind,
56 pub hidden_shape: rlx_ir::Shape,
57 pub rope_style: rlx_ir::RopeStyle,
59}
60
61impl BlockStage for LlamaDecoderStage {
62 fn emit(&self, ctx: &mut FlowCtx<'_>, input: FlowValue) -> Result<Option<FlowValue>> {
63 let lp = &self.layer_prefix;
64 let zero_beta = ctx
65 .state
66 .zero_beta
67 .ok_or_else(|| anyhow::anyhow!("LlamaDecoder requires ZeroBeta stage"))?;
68 let cos = ctx
69 .state
70 .rope_cos
71 .ok_or_else(|| anyhow::anyhow!("LlamaDecoder requires RopeTables stage"))?;
72 let sin = ctx
73 .state
74 .rope_sin
75 .ok_or_else(|| anyhow::anyhow!("LlamaDecoder requires RopeTables stage"))?;
76
77 let in_ln_g = ctx.load_param(&format!("{lp}.input_layernorm.weight"), false)?;
78 let q_w = ctx.load_param(&format!("{lp}.self_attn.q_proj.weight"), true)?;
79 let k_w = ctx.load_param(&format!("{lp}.self_attn.k_proj.weight"), true)?;
80 let v_w = ctx.load_param(&format!("{lp}.self_attn.v_proj.weight"), true)?;
81 let o_w = ctx.load_param(&format!("{lp}.self_attn.o_proj.weight"), true)?;
82 let post_ln_g = ctx.load_param(&format!("{lp}.post_attention_layernorm.weight"), false)?;
83 let gate_w = ctx.load_param(&format!("{lp}.mlp.gate_proj.weight"), true)?;
84 let up_w = ctx.load_param(&format!("{lp}.mlp.up_proj.weight"), true)?;
85 let down_w = ctx.load_param(&format!("{lp}.mlp.down_proj.weight"), true)?;
86
87 let id = ctx.hir().llama_decoder_block(
88 input.id,
89 in_ln_g,
90 zero_beta,
91 q_w,
92 k_w,
93 v_w,
94 o_w,
95 post_ln_g,
96 zero_beta,
97 gate_w,
98 up_w,
99 down_w,
100 cos,
101 sin,
102 None,
103 self.num_heads,
104 self.head_dim,
105 self.num_kv_heads,
106 self.eps,
107 self.mask,
108 self.rope_style,
109 self.hidden_shape.clone(),
110 );
111
112 Ok(Some(ctx.wrap(id, self.hidden_shape.clone())))
113 }
114}