llama.cpp Diffusion LLM 文本生成实战:llama-diffusion-cli 参数解析与源码级原理解析

发布时间:2026/9/7 17:27:58
llama.cpp Diffusion LLM 文本生成实战:llama-diffusion-cli 参数解析与源码级原理解析 llama.cpp Diffusion LLM 文本生成实战llama-diffusion-cli 参数解析与源码级原理解析【免费下载链接】llama.cppLLM inference in C/C项目地址: https://gitcode.com/GitHub_Trending/ll/llama.cpp本文围绕 llama.cpp 仓库中examples/diffusion/目录下的扩散语言模型Diffusion LLM简称 DLLM实现展开系统讲解llama-diffusion-cli的全部生成参数核心扩散参数、两类调度方式、采样参数与模型参数并结合 diffusion.cpp 源码深入剖析置信度选择 转移调度的生成算法底层机制帮助你在理解原理的同时直接上手运行 Dream、LLaDA、RND1 三类扩散架构模型。一、什么是 Diffusion LLM与自回归生成不同的范式传统 LLM 采用自回归方式从左到右逐 token 生成而 Diffusion LLM 走的是填充-去噪路线先把整段待生成序列用 mask 占位符填满然后经过多步迭代diffusion steps每一步从全部 mask 位置中挑选一部分置信度最高的位置填入真实 token其余位置继续保留 mask直到所有位置都被填充完毕。llama.cpp 的 diffusion.h 用一句话概括了这套机制的两个可调维度token 选择算法diffusion_algorithm枚举决定哪些位置先被填充转移调度方式diffusion_transfer_schedule枚举决定每一步填充多少个位置。enum diffusion_algorithm { DIFFUSION_ALGORITHM_ORIGIN 0, DIFFUSION_ALGORITHM_ENTROPY_BASED 1, DIFFUSION_ALGORITHM_MARGIN_BASED 2, DIFFUSION_ALGORITHM_RANDOM 3, DIFFUSION_ALGORITHM_CONFIDENCE_BASED 4, }; // Unified transfer scheduling methods enum diffusion_transfer_schedule { DIFFUSION_TRANSFER_SCHEDULE_TIMESTEP_BASED 0, // Dream-style: (1.0 - s/t) * remaining DIFFUSION_TRANSFER_SCHEDULE_BLOCK_BASED 1, // LLaDA-style: process in blocks with get_num_transfer_tokens };examples/diffusion/ 目录由四个文件组成CMakeLists.txt定义llama-diffusion静态库与llama-diffusion-cli可执行程序两个目标diffusion.h 声明参数结构与统一的生成入口diffusion_generate()diffusion.cpp 实现核心生成循环diffusion-cli.cpp 则是命令行入口负责解析参数、加载模型并驱动可视化。二、CLI 参数全解以下参数说明继承自 examples/diffusion/README.md并结合 common/arg.cpp 的参数注册代码与 common/common.h 中的默认值进行了补全。核心扩散参数--diffusion-steps扩散步数。README 中标注默认值为 256当前源码中 common_params_diffusion 的steps字段默认值为 128实际运行时会打印生效值两种来源的差异请以运行日志输出为准。--diffusion-algorithmtoken 选择算法取值 0–4对应diffusion_algorithm枚举0DIFFUSION_ALGORITHM_ORIGIN——按原文档 arXiv:2107.03006 描述的纯随机顺序生成源码实际以每位置独立伯努利抽样实现1DIFFUSION_ALGORITHM_ENTROPY_BASED——基于分布熵的选择2DIFFUSION_ALGORITHM_MARGIN_BASED——基于 top-1 与 top-2 概率差margin的选择3DIFFUSION_ALGORITHM_RANDOM——随机置信度4DIFFUSION_ALGORITHM_CONFIDENCE_BASED——基于被选 token 概率的置信度选择默认值common.h 中algorithm 4。--diffusion-visual开启实时可视化模式每步清屏并刷新当前部分填充的文本mask 位置以空格显示实现位于 diffusion-cli.cpp 的diffusion_step_callback。README 未列出、但源码同样注册的扩散专用参数见 common/arg.cpp--diffusion-alg-temp算法温度0.0表示确定性按置信度排序选取大于 0 时对置信度做软化分布抽样diffusion.cpp--diffusion-cfg-scaleLLaDA 的 classifier-free guidance 缩放系数。 0时每步执行两次 decode条件 输入全部 mask 的无条件按uncond (scale1) * (cond - uncond)合成 logitsdiffusion.cpp--diffusion-add-gumbel-noise当temp 0.0时向 logits 添加 Gumbel 噪声exp(logit) / gumbel见 diffusion.cpp。调度参数二选一调度方式控制每一步去噪多少个位置两种方法互斥——diffusion-cli.cpp 中有一行硬性断言GGML_ASSERT((params.diffusion.eps 0) ^ (params.diffusion.block_length 0))即--diffusion-eps与--diffusion-block-length有且只能配置一个。Timestep-based schedulingDream 风格--diffusion-epstimestep 调度的 epsilon例如0.001。Block-based schedulingLLaDA 风格--diffusion-block-length块大小例如32。采样参数--temp采样温度0.0 贪心/确定性越高越随机--top-ktop-k 过滤--top-ptop-pnucleus过滤--seed随机种子用于复现结果。模型参数-mGGUF 模型文件路径-p输入提示文本-ub最大序列长度ubatch size——注意它同时就是扩散生成的总长度上限diffusion-cli.cpp 中output_tokens直接按params.n_ubatch分配且diff_params.max_length params.n_ubatch-c上下文大小-bbatch size。三、可复制的运行示例以下三条命令分别对应 Dream、LLaDA、RND1 三类扩散架构继承自 examples/diffusion/README.md 的 Examples 小节差异点在于Dream 用 timestep 调度 随机算法LLaDA 用块调度RND1 用 timestep 调度 熵算法并搭配温度 0.5。# Dream 架构 llama-diffusion-cli -m dream7b.gguf -p write code to train MNIST in pytorch -ub 512 \ --diffusion-eps 0.001 --diffusion-algorithm 3 --diffusion-steps 256 --diffusion-visual # LLaDA 架构 llama-diffusion-cli -m llada-8b.gguf -p write code to train MNIST in pytorch -ub 512 \ --diffusion-block-length 32 --diffusion-steps 256 --diffusion-visual # RND1 架构 llama-diffusion-cli -m RND1-Base-0910.gguf -p write code to train MNIST in pytorch -ub 512 \ --diffusion-algorithm 1 --diffusion-steps 256 --diffusion-visual --temp 0.5 --diffusion-eps 0.001对应的 GGUF 模型需先用仓库根目录的转换脚本生成例如 conversion/dream.py 与 conversion/llada.py 分别处理两类架构配合根目录 convert_hf_to_gguf.py 使用。四、源码级原理剖析diffusion_generate 的完整工作流diffusion.cpp 的diffusion_generate()是全部算法的载体其执行流程与 CLI 参数一一对应1. 初始化mask 填充与双向注意力std::copy(input_tokens, input_tokens n_input, output_tokens); std::fill(output_tokens n_input, output_tokens params.max_length, params.mask_token_id); ... llama_set_causal_attn(ctx, false);输入 prompt 占据序列前部其后到max_length即-ub之间的位置全部填上 mask token由llama_vocab_mask(vocab)从词表获取CLI 侧断言其必须存在。同时llama_set_causal_attn(ctx, false)关闭因果掩码让模型在每步都能双向看到已填充与未填充位置——这是扩散架构与自回归架构最关键的上下文差异。2. 采样器链与置信度计算生成循环内构建的采样器链按顺序为top_k0 时→top_p1 时→temperature0 时→dist。这解释了 README 中采样参数的作用位置。随后每个 mask 位置的置信度由calculate_confidence()计算五种算法与 CLI 数值一一对应算法置信度定义源码 diffusion.cpp0 ORIGIN被选中 token 的概率p1 ENTROPY_BASED分布熵的相反数-Σ p·log(p)熵越高置信度越低2 MARGIN_BASEDtop-1 与 top-2 概率之差p0 - p13 RANDOM[0,1)均匀随机数4 CONFIDENCE_BASED默认被选中 token 的概率p3. 每步转移数量的两种调度公式calculate_transfer_count()diffusion.cpp实现了 README 中两类调度Timestep-based--diffusion-eps令t 1 - step/total·(1-ε)、s 1 - (step1)/total·(1-ε)转移概率p_transfer 1 - s/t最后一步强制为 1实际转移数 剩余 mask 数 × p_transfer。即前期少量、后期加速的去噪节奏Block-based--diffusion-block-length先做整除性校验——max_length % block_length 0且steps % num_blocks 0否则触发GGML_ASSERT再把每个块内的 mask 数用get_num_transfer_tokens()均匀摊到该块的所有步上余数分摊给前几步实现 LLaDA 式的定长块处理。4. 位置填充的两条分支ORIGIN 算法0对每个 mask 位置独立掷骰以p_transfer为概率决定是否用采样器链选出的 token 填充diffusion.cpp其余算法1–4先对全部 mask 位置做采样并记录置信度再按alg_temp分流——为 0 时用std::partial_sort取置信度最高的transfer_count个位置填充大于 0 时把置信度除以温度当作 logit交给独立的dist_sampler做无放回概率抽样diffusion.cpp。当mask_positions为空全部填充完毕时循环提前退出生成结束。5. 收尾与统计CLI 结束时会去掉前n_input个输入 token对剩余部分调用common_detokenize输出最终文本diffusion_generate()末尾统一打印总耗时、每步耗时与每步采样耗时total time: %0.2fms, time per step: %0.2fms, sampling time per step: %0.2fms另外模型侧还有一个隐藏行为CLI 读取 GGUF 元数据diffusion.shift_logits缺省按true处理diffusion-cli.cpp为真时位置 0 使用原始 logits、其余位置pos取pos-1行的 logits即 decode 后 logits 左移一位的适配逻辑。五、前置检查模型必须是扩散架构llama-diffusion-cli在加载模型后立即执行一道门禁if (!llama_model_is_diffusion(model)) { LOG_ERR(error: unsupported model for diffusion); ... }该检查最终落到架构判定函数src/llama-model.cpp 的llama_model_is_diffusion→llm_arch_is_diffusion(model-arch)。因此只有架构被识别为扩散模型如 Dream、LLaDA、RND1 系列的 GGUF 才能进入生成流程普通自回归模型会在加载阶段直接报错退出。六、实践要点与常见限制-ub决定一切长度总生成长度由-ububatch决定-c/-b只影响运行期上下文与批处理效率LLaDA 块调度还要求-ub能被--diffusion-block-length整除、--diffusion-steps能被块数整除否则命中GGML_ASSERT断言。调度二选一--diffusion-eps与--diffusion-block-length必须恰好指定一个同时给出或同时缺省都会触发断言。复现实验固定--seed后再调节--diffusion-algorithm/--diffusion-alg-temp可对比不同选择策略在同一随机序列下的填充顺序差异--diffusion-visual下肉眼可见。CFG 代价--diffusion-cfg-scale 0时每步两次 decode开销翻倍且无条件分支是把输入 token 全部替换为 mask 后重新前向diffusion.cpp仅对支持该机制的模型如 LLaDA有意义。可视化调试--diffusion-visual会清屏刷新进度条与当前文本适合观察先填哪里、后填哪里的位置分布直观验证五种算法的行为差异。七、延伸阅读仓库内的相关入口参数默认值与结构定义common_params_diffusion参数注册与帮助文本common/arg.cpp架构门禁include/llama.h 中声明的llama_model_is_diffusion实现在 src/llama-model.cpp模型转换conversion/dream.py、conversion/llada.py 配合根目录 convert_hf_to_gguf.py 将 HF 权重转为本 CLI 可用的 GGUF。【免费下载链接】llama.cppLLM inference in C/C项目地址: https://gitcode.com/GitHub_Trending/ll/llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考