File size: 7,980 Bytes
26d5b81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#ifndef NEUROFLOW_CAUSAL_LM_HPP
#define NEUROFLOW_CAUSAL_LM_HPP

#include <memory>
#include <string>
#include <vector>
#include "memory.hpp"
#include "model.hpp"
#include "networks.hpp"
#include "tensor.hpp"
#include "rope.hpp"
#include "swiglu.hpp"
#include "rms_norm.hpp"
#include "adamw.hpp"

#ifdef USE_CUDA
#include "cuda_kernels.hpp"
#endif

namespace neuroflow {

enum class FinishReason : uint8_t {
    EOS_TOKEN = 0,
    MAX_LENGTH = 1,
    GEN_ERROR = 2
};

struct CausalLMConfig {
    size_t vocab_size = 128000;
    size_t d_model = 512;
    size_t max_seq_len = 512;
    size_t causal_window_size = 32;
    size_t sae_k = 128;
    size_t ntm_memory_slots = 32;
    bool use_mla = true;
    size_t mla_latent_dim = 64;
    size_t mla_n_heads = 8;
    size_t mla_max_cache_len = 4096;
    bool use_quantization = false;
    bool weight_tying = true;
    bool use_rope = true;
    bool use_bridge = true;
    bool use_swiglu = true;
    size_t swiglu_intermediate_size = 0;
    bool use_qk_norm = true;
    size_t num_attn_layers = 4;
    size_t num_attn_heads = 8;
    size_t n_kv_heads = 2;
    int padding_id = -1;
    std::string pooling = "last";
};

struct CacheStats {
    size_t cache_len = 0;
    size_t memory_bytes = 0;
    float saving_ratio = 0.0f;
    size_t sliding_window_drops = 0;
};

struct GenerateOutput {
    std::string text;
    std::vector<size_t> token_ids;
    std::vector<Tensor> logits_history;
    FinishReason finish_reason = FinishReason::MAX_LENGTH;
    CacheStats cache_stats;
};

class CausalSelfAttention {
public:
    size_t n_q_heads_;
    size_t n_kv_heads_;
    size_t n_rep_;
    size_t d_model_;
    size_t head_dim_;

    std::shared_ptr<Linear> w_q;
    std::shared_ptr<Linear> w_k;
    std::shared_ptr<Linear> w_v;
    std::shared_ptr<Linear> w_out;
    std::shared_ptr<LayerNorm> norm;
    std::unique_ptr<RoPE> rope_;
    bool use_rope_;
    size_t max_seq_len_;
    bool use_qk_norm_;
    std::unique_ptr<RMSNorm> q_norm_;

    std::unique_ptr<RMSNorm> k_norm_;
    bool training_mode_ = false;
    float yarn_temp_scale_ = 1.0f;

    struct Cache {
        Tensor input;
        Tensor q_proj;
        Tensor k_proj;
        Tensor v_proj;
        Tensor attn_weights;
        Tensor attn_output;
        Tensor w_out_input;
        Tensor residual;
    };
    Cache cache_;

    CausalSelfAttention(size_t d_model, size_t n_q_heads, size_t n_kv_heads,
                        bool use_rope = true, size_t max_seq_len = 128, bool use_qk_norm = true);
    Tensor forward(const Tensor& x, const Tensor* padding_mask = nullptr);

    void train() { training_mode_ = true; }
    void eval() { training_mode_ = false; }

    struct Gradients {
        Tensor w_q_weight_grad;
        Tensor w_q_bias_grad;
        Tensor w_k_weight_grad;
        Tensor w_k_bias_grad;
        Tensor w_v_weight_grad;
        Tensor w_v_bias_grad;
        Tensor w_out_weight_grad;
        Tensor w_out_bias_grad;
        Tensor input_grad;
    };

    Gradients backward(const Tensor& output_grad);

private:
    Tensor layernorm_backward_impl(const Tensor& input, const Tensor& weight, const Tensor& output_grad, float eps = 1e-5f);
    Tensor linear_backward_weight_impl(const Tensor& input, const Tensor& output_grad);
    Tensor linear_backward_input_impl(const Tensor& output_grad, const Tensor& weight);
    Tensor bias_backward_impl(const Tensor& output_grad);
};

class CausalLMHead {
public:
    CausalLMConfig config_;

    Tensor w_embed_;
    Tensor w_pos_;
    Tensor dw_kernel_;
    std::shared_ptr<Linear> pw_conv_;
    std::shared_ptr<Linear> sae_w_encode_;
    std::shared_ptr<Linear> sae_w_decode_;
    std::shared_ptr<Linear> ntm_w_read_;
    std::shared_ptr<Linear> ntm_w_write_;
    std::shared_ptr<Linear> ntm_w_erase_;
    Tensor ntm_memory_;
    Tensor shadow_memory_;
    bool training_mode_ = false;
    bool mode_set_ = false;
    std::shared_ptr<Linear> w_proj_;
    std::shared_ptr<Linear> bridge_;
    std::shared_ptr<Linear> w_out_;
    std::shared_ptr<LayerNorm> ln_;
    std::shared_ptr<LatentKVCache> kv_cache_;
    Tensor last_hidden_;
    Tensor last_projected_;
    std::vector<std::unique_ptr<CausalSelfAttention>> attn_layers_;
    std::unique_ptr<SwiGLUFFN> swiglu_;

    struct TrainingCache {
        std::vector<size_t> input_ids;
        Tensor x_embed;
        Tensor x_pos;
        std::vector<Tensor> attn_inputs;
        std::vector<Tensor> attn_outputs;
        Tensor x_gate_in;
        Tensor x_gate_pre_sigmoid;
        Tensor x_after_gate;
        Tensor x_after_swiglu;
        Tensor x_sae_encoded;
        Tensor x_after_sae;
        Tensor x_ntm_read_weights;
        Tensor x_ntm_read_content;
        Tensor x_ntm_h;
        Tensor x_ntm_erase;
        Tensor x_ntm_write;
        Tensor x_after_ntm;
        Tensor x_after_ln;
        Tensor x_pooled;
        Tensor x_bridge;
        Tensor x_projected;
    };
    TrainingCache train_cache_;

    size_t sliding_window_drops_;

    void tie_weights();

    CausalLMHead(const CausalLMConfig& config);

    void train();
    void eval();
    bool is_training() const { return training_mode_; }
    void set_yarn_scale(float scale_factor);

    Tensor embed_lookup(const std::vector<size_t>& ids);
    Tensor positional_encode(const Tensor& x, size_t offset = 0);
    Tensor causal_window_gate(const Tensor& x);
    Tensor sae_sparse(const Tensor& x);
    Tensor ntm_memory_access(const Tensor& x);
    Tensor last_token_pool(const Tensor& x);
    Tensor mean_pool(const Tensor& x);
    Tensor pool(const Tensor& x);

    Tensor make_padding_mask(const std::vector<size_t>& token_ids) const;

    Tensor forward(const std::vector<size_t>& token_ids);
    Tensor forward_step(size_t token_id, size_t pos);
    Tensor forward_for_training(const std::vector<size_t>& token_ids);

    struct LMGradients {
        std::vector<CausalSelfAttention::Gradients> attn_grads;
        Tensor w_proj_weight_grad;
        Tensor w_proj_bias_grad;
        Tensor bridge_weight_grad;
        Tensor bridge_bias_grad;
        Tensor w_out_weight_grad;
        Tensor w_out_bias_grad;
        Tensor embed_grad;
        std::vector<size_t> used_token_ids;
        Tensor ln_weight_grad;
        Tensor ln_bias_grad;
        Tensor ntm_read_weight_grad;
        Tensor ntm_write_weight_grad;
        Tensor ntm_erase_weight_grad;
        Tensor sae_encode_weight_grad;
        Tensor sae_decode_weight_grad;
        Tensor dw_kernel_grad;
        Tensor pw_conv_weight_grad;
        Tensor pw_conv_bias_grad;
        SwiGLUFFN::Gradients swiglu_grads;
    };

    LMGradients backward_from_logits(const Tensor& logits_grad);
    void apply_lm_gradients(LMGradients& grads, float lr);

    // 将所有可训练参数注册到 AdamW 优化器(按 weight/bias 分组)
    // 注意:不注册 attn.norm(backward_from_logits 不计算其梯度),不注册 w_embed_/w_out_(weight_tying 下共享,由 embed_grad 单独处理)
    void register_trainable_params(AdamW& opt, float lr, float weight_decay);
    // 按 register_trainable_params 的注册顺序,将 lm_grads 中的梯度填入优化器的 param_groups_[].grads
    void assign_grads_to_optimizer(AdamW& opt, LMGradients& grads);

    void clear_cache();
    CacheStats cache_stats() const;

private:
    Tensor ln_backward_impl(const Tensor& input, const Tensor& weight, const Tensor& output_grad, float eps = 1e-5f);
    Tensor lm_head_linear_backward_input(const Tensor& output_grad, const Tensor& weight);
    Tensor lm_head_linear_backward_weight(const Tensor& input, const Tensor& output_grad);
    Tensor lm_head_bias_backward(const Tensor& output_grad);
};

} // namespace neuroflow

#endif // NEUROFLOW_CAUSAL_LM_HPP