File size: 17,695 Bytes
4e56b53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/* runtime/lal_concept_attn.h — Concept-Aware Attention
 *
 * 基于「理解(概念-边界) + 推理(关系演化)」框架优化的注意力机制。
 *
 * 设计原点(从框架公理推导,非抄工程现成方案):
 *   - Attention 的本职:发现概念之间真实的关系,给关系分配权重,聚合V信息。
 *   - 算力浪费根源:标准自注意力强制对全部两两概念对执行 Q-K 匹配,
 *     大量 token-pair 概念边界本身互相隔离,本来就几乎不会产生有效关系,
 *     却依然完整计算 QK^T。
 *   - 优化目标:不破坏"识别关系强弱、绑定实体"这个理解能力,
 *     砍掉大量无效概念对的匹配计算。
 *
 * 四层设计:
 *   Layer 1: 基于概念边界,区分「需要精细匹配」和「可以间接通信」的概念集
 *            - 片段内部:完整多头注意力
 *            - 片段之间:通过 segment-messenger 间接通信
 *   Layer 2: 关系强度门控,过滤本就边界隔离的概念对
 *            - 距离先验 + 粗粒度相似度快速预判
 *            - 软门控(保留极小概率回退通路,避免切断长距离指代)
 *   Layer 3: 多头的差异化算力分配(异构多头)
 *            - 局部语法头:只在局部窗口做匹配
 *            - 指代/因果头:可以访问窗口 + 信使
 *   Layer 4: 推理侧约束:区分训练阶段和推理 KV-Cache 的概念复用
 *            - 历史概念的 K/V 已编码完成,直接复用
 *            - 信使 token 也进入 KV-cache,保证间接长距离通路复用
 *
 * 与现有方案的本质区别:
 *   - Mistral 滑动窗口:单纯位置窗口,没有信使;长距离依赖能力弱。
 *   - Longformer global-token:全局固定几个 token 读取全部位置;
 *     不是每个片段动态聚合本片段语义状态的信使。
 *   - Performer 线性注意力:纯数学核近似,不关心"概念边界、关系强弱"。
 *
 * 本优化只改造理解阶段(Attention)的信息交互通路,不改动 FFN 推理演化逻辑。
 * 只要真实关系的匹配通路保留,上层推理能力就不会被破坏。
 *
 * Build: 与 lal_runtime.c 一起编译(#include "lal_concept_attn.h")
 */
#ifndef LAL_CONCEPT_ATTN_H
#define LAL_CONCEPT_ATTN_H

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ========================================================================
 * Concept-Aware Attention Configuration
 * ======================================================================== */

/* 头的访问域类型(Layer 3: 异构多头) */
typedef enum {
    HEAD_LOCAL     = 0,  /* 局部语法关系(主谓宾、修饰):强局部性,小窗口 */
    HEAD_MESSENGER = 1,  /* 指代、实体绑定、因果时序:窗口 + 信使 */
    HEAD_GLOBAL    = 2,  /* 全局兜底(少数头,访问全部历史 + 信使) */
} HeadAccessType;

/* 概念感知注意力配置 */
typedef struct {
    /* === Layer 1: 片段 + 信使 === */
    int   segment_len;          /* 语义片段长度 L(token 数)。0 = 禁用片段化 */
    int   num_messengers;       /* 每个片段的信使数目 S (S << L)。默认 4 */
    int   messenger_neighbors;  /* 邻近片段信使数(普通 token 可见的邻居片段数)。默认 2 */
    int   min_seg_len;          /* 尾部封口最小片段长度:序列末尾累积 ≥ 此值时也触发信使生成。
                                   默认 16。修复短样本(对话数据平均 11 token)信使永远不激活的 bug */

    /* === Layer 2: 关系强度门控 === */
    int   gate_enable;          /* 1 = 启用关系预筛选门控,0 = 禁用 */
    int   gate_window;           /* 门控生效的局部窗口大小(窗口内才做门控) */
    float gate_threshold;        /* 概念边界相似度阈值,低于此值判定为边界隔离 */
    float gate_fallback_prob;    /* 回退概率(极小,避免硬切断长距离指代)。默认 0.01 */
    int   gate_distance_prior;   /* 距离先验权重(>0 启用)。距离越远,门控越严 */

    /* === Layer 3: 异构多头 === */
    int   hetero_enable;         /* 1 = 启用异构多头,0 = 所有头同等访问 */
    int   n_local_heads;         /* 局部语法头数量 */
    int   n_messenger_heads;     /* 指代/因果头数量(访问窗口+信使) */
    /* 剩余头 = HEAD_GLOBAL */

    /* === Layer 4: 推理 KV-Cache === */
    int   cache_messenger;       /* 1 = 信使也进入 KV-cache(保证间接长距离通路复用) */

    /* === 主开关 === */
    int   enable;                /* 1 = 启用概念感知注意力,0 = 回退到标准 attention_forward */
} ConceptAttnConfig;

/* 默认配置(唯一路线底座:CORE/BINARY/PRUNE + 浮点 + 概念注意力)
 *
 * 这是项目唯一保留的注意力路线——不再是"可选开关"。
 * 四层优化(片段信使 / 关系门控 / 异构多头 / KV 复用)默认全开,
 * 并按审查意见固化:去中心化门控、去中心化信使、窗口对称(128)、自适应阈值。
 * 环境变量 LAL_CONCEPT_ATTN=0 仅作为调试逃生口(强制关,回退标准 attention)。 */
static inline ConceptAttnConfig concept_attn_default_config(void) {
    ConceptAttnConfig c;
    c.segment_len         = 32;    /* v21: 32 token 一个片段.
                                       原 64 在对话数据(avg~11 token, 短样本多)下填不满,
                                       信使机制空转、概念注意力收不到梯度 (探针实证).
                                       改 32 后信使候选/质量/统计片段全部恢复(见 seg_len=32 测试).
                                       注: segment_len 仍可由 LAL_CA_SEG_LEN 环境变量覆盖. */
    c.num_messengers      = 4;     /* 每片段 4 个信使 */
    c.min_seg_len        = 4;     /* 尾部封口最小片段长度:≥4 token 的短样本尾部也生成信使,
                                     避免对话数据(avg 11 token)信使永远空转、概念注意力收不到梯度 */
    c.messenger_neighbors = 2;     /* 看 2 个邻近片段的信使 */
    c.gate_enable        = 1;
    c.gate_window         = 128;   /* 窗口对称:概念路径与标准路径一致 (审查 Bug Fix 3: 32→128) */
    /* 阈值语义:固定 0.1 在塌缩表征下失效(审查 Bug 2)。
     * 运行时用门控分数分布的 P25 分位数自适应覆盖(概念注意力前向内维护 g_ca_quantile)。
     * 此处的 0.1 仅作初始/兜底值,不再作为稳定工作点。 */
    c.gate_threshold      = 0.1f;
    c.gate_fallback_prob  = 0.01f; /* 1% 回退概率,避免硬切断长距离指代 */
    c.gate_distance_prior = 1;    /* 启用距离先验(去中心化后作为相对偏差项) */
    c.hetero_enable      = 1;     /* 异构多头:局部/信使/全局分层算力 */
    c.n_local_heads       = -1;    /* -1 = 自动:n_head 的一半 */
    c.n_messenger_heads   = -1;    /* -1 = 自动:n_head 的 1/4 */
    c.cache_messenger     = 1;     /* 信使进 KV-cache,保证间接长距离通路复用 */
    c.enable              = 1;    /* 默认开启——概念注意力是基座路线,非可选 */
    return c;
}

/* ========================================================================
 * Messenger Cache (Layer 1 + Layer 4)
 * ========================================================================
 * 每层一个 MessengerCache,存储已聚合的片段信使 K/V。
 * 信使是本片段全部概念与关系状态的压缩载体。
 *
 * 内存布局:
 *   messenger_k: [segment_capacity * num_messengers * n_embd] floats
 *   messenger_v: 同上
 *   segment_filled[segment_capacity]: 该片段的信使是否已生成
 */
typedef struct {
    float     *messenger_k;       /* [segment_capacity * num_messengers * n_embd] */
    float     *messenger_v;       /* 同上 */
    uint8_t   *segment_filled;    /* [segment_capacity] 该片段信使是否已生成 */
    int        segment_capacity;  /* 最大片段数(= n_ctx / segment_len + 1) */
    int        num_messengers;    /* 每片段信使数 */
    int        n_embd;            /* 嵌入维度 */
    int        n_filled;          /* 已生成的片段数 */
} MessengerCache;

/* 分配信使缓存。在 model_load 后调用。 */
void messenger_cache_alloc(MessengerCache *mc, int segment_capacity,
                           int num_messengers, int n_embd);

/* 释放信使缓存 */
void messenger_cache_free(MessengerCache *mc);

/* 重置信使缓存(推理新会话开始时调用) */
void messenger_cache_reset(MessengerCache *mc);

/* ========================================================================
 * Layer 1: Segment Messenger Generation
 * ========================================================================
 * 在每个 segment 内部,基于本片段全部 V,聚合生成少量信使向量。
 * 信使是本片段全部概念与关系状态的压缩载体。
 *
 * 聚合策略:对片段内 V 做均匀分桶 + 均值池化
 *   - 将片段内 V[0..seg_len-1] 均匀分成 num_messengers 个桶
 *   - 每个桶内做均值池化,得到一个信使向量
 *   - 信使的 K = 信使的 V(自关联,简化)
 *
 * 数学复杂度:O(seg_len * n_embd),远小于注意力本身
 *
 * 语义意义:远方片段的整体语义,由信使代为表达。
 *          普通token通过信使间接获得远方概念集合的状态,
 *          而不是挨个访问每一个远方概念。
 *
 * 参数:
 *   v_seg:     [seg_len * n_embd] — 本片段的 V 缓存
 *   seg_len:   片段长度
 *   out_k:     [num_messengers * n_embd] — 输出信使 K
 *   out_v:     [num_messengers * n_embd] — 输出信使 V
 */
void generate_segment_messengers(const float *v_seg, int seg_len, int n_embd,
                                 int num_messengers,
                                 float *out_k, float *out_v);

/* ========================================================================
 * Layer 2: Concept Boundary Gate (关系强度门控)
 * ========================================================================
 * 给定 token-i(Q侧)、token-j(K侧),利用距离先验 + 粗粒度相似度
 * 快速预判:如果预判两个概念边界隔离,潜在关系极弱,
 * 直接把该位置置 -inf,不参与完整内积计算。
 *
 * 注意:不是简单按位置距离硬截断;是"概念边界是否可能产生关系"的软判断。
 * 避免错误切断长距离指代这种真实强关系。
 *
 * 门控公式(软门控,保留回退通路):
 *   sim_coarse = <Q_i, K_j> / (||Q_i|| * ||K_j|| + eps)   // 粗粒度余弦相似度
 *   dist_prior = exp(-distance / tau)                     // 距离先验
 *   gate_score = sim_coarse * (1 + gate_distance_prior * dist_prior)
 *   if gate_score < gate_threshold:
 *       以 (1 - gate_fallback_prob) 概率置 -inf
 *       以 gate_fallback_prob 概率保留(回退通路)
 *
 * 参数:
 *   q_i:       [head_dim] — 当前 token 的 Q(某头)
 *   k_j:       [head_dim] — 候选 token 的 K(某头)
 *   distance:  i 和 j 的位置距离
 *   cfg:       概念感知注意力配置
 * 返回:1 = 保留(参与完整 QK 计算),0 = 屏蔽(置 -inf)
 */
int concept_boundary_gate(const float *q_i, const float *k_j,
                          int head_dim, int distance,
                          const ConceptAttnConfig *cfg);

/* ========================================================================
 * Layer 3: Heterogeneous Head Access Configuration
 * ========================================================================
 * 不同类型关系本身就有不同的"概念交互范围",不需要统一全序列扫描。
 *   - 头A:局部语法关系(主谓宾、修饰):强局部性,适合小窗口。
 *   - 头B:指代、实体绑定:偶尔需要长距离跳跃。
 *   - 头C:因果、时序关系:中等范围依赖。
 *
 * 配置:根据 n_head 自动分配头的访问域
 *   - 前 n_local_heads 个头 = HEAD_LOCAL
 *   - 接下来 n_messenger_heads 个头 = HEAD_MESSENGER
 *   - 剩余 = HEAD_GLOBAL
 */
HeadAccessType get_head_access_type(int head_idx, int n_head,
                                   const ConceptAttnConfig *cfg);

/* 获取某头的实际访问窗口大小 */
int get_head_window(int head_idx, int n_head, int base_window,
                    const ConceptAttnConfig *cfg);

/* 某头是否可以访问信使 */
int head_can_access_messenger(int head_idx, int n_head,
                              const ConceptAttnConfig *cfg);

/* ========================================================================
 * Layer 4: Concept-Aware Attention Forward (主入口)
 * ========================================================================
 * 概念感知注意力前向传播。整合四层优化:
 *
 *   1. 切成语义片段(segment_len)
 *   2. 片段内部:完整 QKV,充分做片段内概念理解
 *   3. 生成本片段信使:聚合本片段全部概念-关系状态
 *   4. 本片段普通 token:只和【局部窗口 + 本片段信使 + 邻近片段信使】做匹配
 *   5. 关系门控:过滤边界隔离的概念对(Layer 2)
 *   6. 异构多头:不同头不同访问域(Layer 3)
 *   7. KV-Cache:历史 K/V 直接复用,信使也进 cache(Layer 4)
 *
 * 参数:
 *   attn_out:   [n_embd]      — 输出
 *   qkv:        [3 * n_embd]  — Q | K | V 拼接,单 token
 *   n_embd, n_head:           — 维度与头数
 *   seq_pos:                   — 当前序列位置
 *   k_cache, v_cache:         — [n_ctx * n_embd] KV 缓存
 *   n_ctx:                     — 上下文长度
 *   cfg:                       — 概念感知注意力配置
 *   mc:                        — 信使缓存(可为 NULL,则不使用信使)
 *
 * 因果性:seq_pos 只关注 0..seq_pos(含)。
 * 多头:head_dim = n_embd / n_head(必须整除)。
 */
void attention_forward_concept(float *attn_out, const float *qkv,
                               int n_embd, int n_head, int seq_pos,
                               float *k_cache, float *v_cache,
                               int n_ctx,
                               const ConceptAttnConfig *cfg,
                               MessengerCache *mc);

/* ========================================================================
 * Layer 4: Concept-Aware Attention Backward
 * ========================================================================
 * 概念感知注意力反向传播。计算当前 token 的 Q/K/V 梯度。
 * 缓存的 K/V(位置 0..seq_pos-1)视为常量(与 attention_backward 一致)。
 *
 * 参数:
 *   grad_qkv:       [3 * n_embd] — 输出梯度(Q|K|V)
 *   grad_attn_out:   [n_embd]    — 来自上层的 attn_out 梯度
 *   qkv:            [3 * n_embd] — 前向时用的 Q|K|V
 *   n_embd, n_head, seq_pos
 *   k_cache, v_cache, n_ctx
 *   cfg, mc
 */
void attention_backward_concept(float *grad_qkv, const float *grad_attn_out,
                                const float *qkv, int n_embd, int n_head,
                                int seq_pos,
                                const float *k_cache, const float *v_cache,
                                int n_ctx,
                                const ConceptAttnConfig *cfg,
                                MessengerCache *mc);

/* ========================================================================
 * Transformer Layer Forward Integration
 * ========================================================================
 * trans_layer_forward 的实现包含比例缩放、残差归一化等复杂逻辑,
 * 完整复制易引入 bug。推荐集成方式:
 *
 *   在现有 trans_layer_forward() 中,将 attention_forward 调用替换为:
 *     if (g_concept_attn_cfg.enable && g_messenger_caches) {
 *         attention_forward_concept(act->attn_out, qkv_ptr,
 *                                    n, cfg->n_head, abs_pos,
 *                                    tl->kv_k, tl->kv_v, cfg->n_ctx,
 *                                    &g_concept_attn_cfg,
 *                                    &g_messenger_caches[layer_idx]);
 *     } else {
 *         attention_forward(act->attn_out, qkv_ptr, n, cfg->n_head,
 *                            abs_pos, tl->kv_k, tl->kv_v);
 *     }
 *
 *   反向传播同理:将 attention_backward 替换为 attention_backward_concept。
 *   通过 model_set_concept_attn() 在运行时配置,无需修改模型结构。
 */

/* ========================================================================
 * Global Config (便于全局开关,无需改 ModelConfig)
 * ========================================================================
 * 全局概念感知注意力配置。设为 enable=1 即启用。
 * 优先级:ModelConfig 中的 concept_cfg > 全局 g_concept_attn_cfg。
 */
extern ConceptAttnConfig g_concept_attn_cfg;

/* 全局信使缓存(每层一个,按 layer_idx 索引)。
 * 在 model_load 时分配,model_free 时释放。 */
extern MessengerCache *g_messenger_caches;  /* [n_layer] */

/* Model-dependent functions (declared in lal_runtime.h after Model is defined):
 *   void model_messenger_caches_alloc(Model *m, const ConceptAttnConfig *cfg);
 *   void model_messenger_caches_free(void);
 *   void model_messenger_caches_reset(void);
 *   void model_set_concept_attn(Model *m, const ConceptAttnConfig *cfg);
 */

#ifdef __cplusplus
}
#endif

#endif /* LAL_CONCEPT_ATTN_H */