保存时间:2026/3/29 15:53:09
L_prev = N + (L-1) 的 “历史上下文序列”(记为 Seq_prev)。L_curr = L_prev + 1 = L 的序列(记为 Seq_curr)。L × d(L 是当前总长度,d 是模型维度),其中前 L-1 个位置是 “已知上下文的嵌入向量 + 位置编码”,第 L 个位置是 “占位嵌入向量 + 对应位置的位置编码”。Score = Q × K^T(维度 L×L)—— 这个矩阵的每一行 i,代表 “第 i 个位置的 Token” 与 “所有 L 个位置 Token” 的相似度;Score_masked = Score × Mask—— 这样一来,第 i 个位置的 Score_masked 矩阵中,“列 j> i” 的位置(未来位置)的相似度得分会被置为 0(或 -∞,避免 Softmax 后有概率);Logits = FFN_out × W_out(维度 L×vocab_size)——Logits 是 “每个位置对应词表中所有 Token 的原始得分”;Prob = Softmax(Logits[L])(维度 1×vocab_size)—— 得到词表中每个 Token 的生成概率;FFN_out 矩阵,维度是 3×d(3 是当前序列长度 L=3,d 是模型维度,比如 d=4096);W_out(可训练参数,模型训练时学到的),维度是 d×vocab_size(vocab_size 是词表大小,比如 32000,即模型能生成的所有 Token 总数);Logits[i][j] 代表:W_out = [
[1, 0.5, 0.2], # d=0维的权重
[0.8, 1.2, 0.3] # d=1维的权重
]
[4.4, 4.6, 1.3]argmax(logits)
logits 开关(比如 --logits / logits_all / return_logits),和我们前面讲的 Transformer 里的 Logits 完全是同一个东西—— 就是 FFN 输出经过 W_out 映射后、还没做 Softmax 的那一行原始得分(1 × vocab_size)。logits 开关的作用、什么时候开 / 关、和你实验(4W1H 向量匹配)的关系讲透。llama_decode() 为核心,生成一个 token 的极简流程(和 Transformer 完全对应):prompt + 已生成的 token 喂给模型,得到当前上下文序列 seq_len = L。L × dL × d 的隐藏态h = hidden[L-1, :](1 × d)W_out(d × vocab_size)→ logits = h × W_out(1 × vocab_size)→ 这就是 llama.cpp 里的 logits,和 Transformer 里的 Logits 100% 一致。logits 做处理(temperature、top-k、top-p 等)logits 开关:到底在控制什么?logits = false(默认):只返回生成的 token ID / 文本,不返回 1 × vocab_size 的原始得分。logits = true:除了 token,还把最后一步的 logits(1 × vocab_size)一起返回给你。logits_all = true:返回每一步的 logits(而不只是最后一步),适合需要逐 token 分析的场景。1 × vocab_size 的数组,给你做后续计算(比如你要的 4W1H 向量匹配、意图打分)。logits 开关会控制:拿到模型对 “某个 token 位置” 的原始得分分布,而不是只看它生成了什么 token。
logits?What 类意图:对应词表中 what、which、how 等 token 的 logits 得分;When 类:when、time、date 等;1 × vocab_size),因为:logits 默认是最后一步生成 token 时的 logits(对应上下文最后一个位置)。logits_all = true,拿到每一步的 logits,再取 prompt 对应位置的 logits。p_j = e^logits_j / sum(e^logits)),再做意图向量;LLAMA_CUDA_FP32_LOGITS(如果用 CUDA);logits 开关的 “使用场景对照表”| 场景 | 开关设置 | 得到什么 | 适合你的实验吗? |
|---|---|---|---|
| 只生成文本,不分析意图 | logits = false | 仅 token ID / 文本 | ❌ 不行,拿不到得分 |
| 分析生成的 token的意图 | logits = true | 最后一步 logits(1 × vocab_size) | ✅ 部分适合(如果意图在生成端) |
| 分析输入 prompt 中每个 token的意图 | logits_all = true | 每一步 logits(seq_len × vocab_size) | ✅ 最适合你的 4W1H 向量匹配 |
| 微调 / 训练算 loss | logits = true + 训练参数 | logits + loss | ❌ 你是推理实验,不用 |
// 1. 初始化模型,开启 logits_all
llama_context_params ctx_params = llama_context_default_params();
ctx_params.logits_all = true; // 关键:拿每一步的 logits
llama_context* ctx = llama_new_context_with_model(model, ctx_params);
// 2. 喂入 prompt,做前向传播
llama_token prompt_tokens[] = { ... }; // 你的 4W1H 相关 prompt
llama_decode(ctx, prompt_tokens, n_prompt);
// 3. 拿到所有 logits:seq_len × vocab_size
const float* all_logits = llama_get_logits(ctx);
int seq_len = llama_get_seq_len(ctx);
int vocab_size = llama_n_vocab(model);
// 4. 提取 prompt 中“关键位置”的 logits(比如第 k 个 token,对应 4W1H 关键词)
int key_pos = 5; // 假设 prompt 第 5 个 token 是意图核心
const float* logits_k = all_logits + key_pos * vocab_size; // 1 × vocab_size
// 5. 构建 4W1H 向量:取词表中对应意图的 token 的 logits 得分
float vec_4W1H[5] = {0};
// What 意图:取词表中 "what", "which", "how" 等 token 的 logits 均值/最大值
vec_4W1H[0] = (logits_k[token_what] + logits_k[token_which] + logits_k[token_how]) / 3;
// When 意图:logits_k[token_when] + logits_k[token_time]
vec_4W1H[1] = logits_k[token_when] + logits_k[token_time];
// ... 同理处理 Who, Where, How
// 6. 可选:Softmax 转概率,或归一化
// 比如对 vec_4W1H 做 L2 归一化,方便后续向量匹配
float norm = sqrt(vec_4W1H[0]*vec_4W1H[0] + ... + vec_4W1H[4]*vec_4W1H[4]);
for (int i = 0; i < 5; i++) vec_4W1H[i] /= norm;
1 × vocab_size 的原始得分,未 Softmax。logits = true:返回最后一步生成 token 的 logits。logits_all = true:返回每一步的 logits(你做 4W1H 向量匹配必须开这个)。logits_all);