use rlx_ir::infer::GraphExt;
use rlx_ir::{DType, Graph, NodeId, Shape};
use crate::LoraConfig;
pub fn lora_delta_node(
g: &mut Graph,
a: NodeId,
b: NodeId,
in_features: usize,
out_features: usize,
cfg: LoraConfig,
) -> NodeId {
let _ = (in_features, out_features);
let prod = g.mm(b, a);
let s = g.full(&[1, 1], cfg.scaling() as f32, DType::F32);
g.mul(prod, s)
}
pub fn lora_delta_graph(in_features: usize, out_features: usize, cfg: LoraConfig) -> Graph {
let mut g = Graph::new("lora_delta");
let a = g.input("a", Shape::new(&[cfg.r, in_features], DType::F32));
let b = g.input("b", Shape::new(&[out_features, cfg.r], DType::F32));
let d = lora_delta_node(&mut g, a, b, in_features, out_features, cfg);
g.set_outputs(vec![d]);
g
}
pub fn ia3_graph(rows: usize, out_features: usize) -> Graph {
let mut g = Graph::new("ia3");
let y = g.input("y", Shape::new(&[rows, out_features], DType::F32));
let l = g.input("l", Shape::new(&[1, out_features], DType::F32));
let out = g.mul(y, l);
g.set_outputs(vec![out]);
g
}
pub fn adalora_delta_graph(in_features: usize, out_features: usize, cfg: LoraConfig) -> Graph {
let mut g = Graph::new("adalora_delta");
let p = g.input("p", Shape::new(&[out_features, cfg.r], DType::F32));
let lam = g.input("lambda", Shape::new(&[1, cfg.r], DType::F32));
let q = g.input("q", Shape::new(&[cfg.r, in_features], DType::F32));
let pl = g.mul(p, lam);
let prod = g.mm(pl, q);
let s = g.full(&[1, 1], cfg.scaling() as f32, DType::F32);
let d = g.mul(prod, s);
g.set_outputs(vec![d]);
g
}
pub fn dora_graph(in_features: usize, out_features: usize) -> Graph {
let mut g = Graph::new("dora");
let w = g.input("w", Shape::new(&[out_features, in_features], DType::F32));
let d = g.input(
"delta",
Shape::new(&[out_features, in_features], DType::F32),
);
let m = g.input("m", Shape::new(&[out_features, 1], DType::F32));
let v = g.add(w, d);
let sq = g.mul(v, v);
let ss = g.sum(sq, vec![1], true);
let norm = g.sqrt(ss);
let dir = g.div(v, norm);
let out = g.mul(dir, m);
g.set_outputs(vec![out]);
g
}