Rust in Everything
基于 candle 0.11.0

动手

前面各章用的都是 candle_transformers::models::llama,每页只对照其中一件事。这一部分把它拿掉:只用 candle-core 和 candle-nn 的张量运算和 Linear,自己读 config.json、自己写 RmsNorm、RoPE、GQA 注意力、因果 mask、SwiGLU、共享权重的 lm_head 和 KV 缓存,再拿 transformers 的输出和库里的实现来对。页末是能直接复制运行的完整程序。

  1. 从头写 Llama:约 310 行的单文件程序。logits 和 transformers 差 3.67e-5(CPU)/ 4.10e-5(Metal),20 个贪心 token 全同;把 RoPE 的配对写成交错的,差到 7.89、只剩 2 个 token 相同。和 llama.rs 比,logits 的差别只来自 lm_head 算几行、RmsNorm 和 RoPE 用不用融合算子,换成一样就逐位相同;Metal 上手写的版本 decode 慢一倍。
flowchart TB
  cfg["config.json"] --> own["自己的 Config"]
  st["safetensors"] --> vb["VarBuilder"]
  own --> model["手写的 Model"]
  vb --> model
  model --> cmp1["对 transformers"]
  model --> cmp2["对 llama.rs"]

每个零件在 transformers 和 llama.rs 里的对应关系见 06 搬一个 LLM,这一部分不重讲,只讲自己写的时候要做的选择。

💬 关联讨论

发起讨论
加载中...