Qwen3.8-27B 官方推荐的采样参数,配置文件里一个都找不到

2026-08-16

看 model card 的时候有个习惯动作:读到「我们建议这样设置」这类句子,就顺手去随仓的配置文件里对一遍,看推荐值是不是已经写进默认值了。Qwen3.8-27B 这一遍对下来,结果比预想的要干净——干净到有点反直觉:Best Practices 里点名的六个采样参数,只有三个能在配置文件里找到,另外三个在整个仓库的配置文件里连一次 grep 命中都没有。

下面把这条落差摊开写清楚:它出现在哪两层、每一层的原文是什么、怎么自己核一遍,以及它不能说明什么。本文所有事实来自 Hugging Face 仓库 Qwen/Qwen3.8-27B 的 model card 与随仓文本文件,核对日 2026-08-16。

一、先把 generation_config.json 整个摊开

这个文件小得有点意外:202 字节、13 行。以下是它的全部字段,没有省略:

字段位置
bos_token_id248044generation_config.json:2
do_sampletruegeneration_config.json:3
eos_token_id[248046, 248044]generation_config.json:4-7
pad_token_id248044generation_config.json:8
temperature1.0generation_config.json:9
top_k20generation_config.json:10
top_p0.95generation_config.json:11

对照 tokenizer_config.jsonadded_tokens_decoder248044<|endoftext|>tokenizer_config.json:4),248046<|im_end|>tokenizer_config.json:20)。

跟采样有关的键,就 do_sampletemperaturetop_ktop_p 四个。max_new_tokensmax_lengthmin_ppresence_penaltyrepetition_penaltynum_beams 这些常见字段,一个都没有。

这一步不用相信我,一行就能自己数清楚有几个键:

python -c "import json,io;print(json.load(io.open('generation_config.json',encoding='utf-8')))"

输出就是上表列出的那些字段,再没有别的。作为对照,同一个仓库里 README.md 是 65,012 字节、583 行,chat_template.jinja 是 8,952 字节、170 行——文档和模板都不算小,唯独承载采样默认值的这个文件只有 202 字节。这不是什么问题,只是提醒一件事:这份仓库里真正被写死的采样默认值,就只有那么几个,其余的都得由调用侧或者推理框架来给。

二、model card 推荐的是六个,不是三个

Best Practices 第 1 条(README.md:500-505)给的是两组值,注意是两组,按模式分:

  • Thinking Mode(README.md:502):temperature=1.0top_p=0.95top_k=20min_p=0.0presence_penalty=0.0repetition_penalty=1.0
  • Instruct(non-thinking)mode(README.md:503):temperature=0.7top_p=0.80top_k=20min_p=0.0presence_penalty=1.5repetition_penalty=1.0

同样这两组数值,在 README.md:250-255 的提示框里又出现了一次,内容完全相同。以上都是 model card 自述的建议,我们没有验证过,本文也不在此之外追加任何调参建议。

把这两组和上一节的表拼在一起看,两件事就出来了:

第一件事:generation_config.json 的默认值只对应上面那一组。 temperature 1.0 / top_p 0.95 / top_k 20 与 Thinking Mode 那组逐字相同;而 Instruct 那组的 0.7 / 0.80 / presence_penalty 1.5,在配置文件里没有任何落点。想用第二组,值只能从调用侧传——model card 的 Instruct 示例(README.md:454-459)也正是这么写的:temperature=0.7top_p=0.8presence_penalty=1.5,再加 extra_body={"top_k": 20, "chat_template_kwargs": {"enable_thinking": False}}

第二件事:min_ppresence_penaltyrepetition_penalty 这三个词,在配置文件里一次都没出现过。

三、这条 grep 自己跑一遍就有

判定动作很简单,一条 Python 就够,八个文本文件逐个数词频:

python - <<'PY'
import io
files=['config.json','generation_config.json','preprocessor_config.json','video_preprocessor_config.json','tokenizer_config.json','chat_template.jinja','LICENSE','README.md']
for kw in ['min_p','presence_penalty','repetition_penalty','max_new_tokens']:
    print(kw, [(f, io.open(f,encoding='utf-8',errors='replace').read().count(kw)) for f in files])
PY

结果:min_ppresence_penaltyrepetition_penalty 三个词在 config.jsongeneration_config.jsonpreprocessor_config.jsonvideo_preprocessor_config.jsontokenizer_config.jsonchat_template.jinjaLICENSE全部为 0 命中,只在 README.md 正文里出现(min_prepetition_penalty 落在 502、503 行那两组建议里,presence_penalty 除这两行外还出现在 505 行那句说明中)。max_new_tokens 更彻底,八个文件全是 0。

需要说清楚的是,上面这类统计都是对随仓文本文件做的静态读取:这是一个模型权重仓,没有可运行的工程代码,我们也没有下载权重、没有加载模型、没有推理过一个 token。文中出现的每个值都只代表「文件里写着什么」,不代表任何一套推理链路上实际生效的值;model card 与配置文件本身也会随上游更新变动,以官方最新内容为准。

顺带提一句为什么要连 chat_template.jinja 一起数:这个模板文件在本仓里承担了不少控制逻辑,reasoning_effortpreserve_thinkingenable_thinking 三个思考控制变量的唯一实现处就在它里面(chat_template.jinjatokenizer_config.jsonchat_template 字段字节级完全一致,8,952 字节)。所以「某个开关在本仓有没有实现」这个问题,模板文件是必须扫的一站。但采样这三个词在模板里同样是 0 命中——它们不在模板层。

四、这条差异摆在哪一层

把上面的结果按层归一下位,就是这么一张关系:

参数model card 推荐值出现在随仓配置文件里
temperature / top_p / top_kREADME.md:502-503(两组)generation_config.json:9-11,值与 Thinking 那组相同
min_p / presence_penalty / repetition_penaltyREADME.md:502-503无任何字段,grep 0 命中
enable_thinking / reasoning_effort / preserve_thinkingREADME.md 多处只在 chat_template.jinjatokenizer_config.json 的模板字段里

也就是说,这六个推荐参数被分在了三层上:一半写进了随仓默认值,一半只存在于 model card 的文字里,而模式切换那几个开关又落在模板层。三层各说各的,谁也不覆盖谁。

model card 对这件事其实留了一句话——README.md:255 原文写:采样参数的支持情况因推理框架而异(Please note that the support for sampling parameters varies according to inference frameworks.)。这句话我们照抄,不做延伸解读。另外 README.md:505 写:对支持的框架,可以把 presence_penalty 在 0 到 2 之间调整以减少无休止的重复;但用更高的值有时会导致语言混杂(language mixing)与模型表现的轻微下降。同样是 model card 自述,我们没有复现过。

按这批的规矩,我只陈述差异、标出两处位置,不推断哪一处「才是对的」,也不推断为什么两处没同步。这里想强调的只有一个操作层面的事实:你在配置文件里找不到 presence_penalty,不代表这个参数在你的链路上不存在,也不代表它一定可用——它落不落地取决于你用的那套推理框架,而那不是本仓文件能回答的问题。

五、顺手多看两眼:generation_config.json 与另外两处的 token id 也没对齐

既然已经把这个文件打开了,还有三处口径值得记一笔,都是同一类「同一件事在不同文件里写法不同」:

  1. eos_token_id 三处不同。 generation_config.json:4-7 是数组 [248046, 248044]tokenizer_config.json:287eos_token<|im_end|>(对应 248046);config.json:14 顶层与 text_config 里的 eos_token_id 都是单值 248044(对应 <|endoftext|>),不是数组。
  2. bos_token 的有无不同。 tokenizer_config.json:284"bos_token": null:294"add_bos_token": false;而 generation_config.json:2config.json:12 都写了 bos_token_id: 248044
  3. pad_token_id 不同。 generation_config.json:8248044tokenizer_config.json:290pad_token<|endoftext|>;而 config.json:101text_config 内)是 "pad_token_id": null

同样只记录差异与位置,不做等价性判断,也不据此评价什么。列在这里的用处很实际:如果你要写一段自动读取配置的加载脚本,这三处决定了你从哪个文件读到的值会不一样,值得先把口径定死再动手。

六、什么情况说明不是这回事

最后这一步别省,不然这篇就成了「差异大全」:

  • 如果你的目标只是复现 Thinking Mode 那组值,那这条差异跟你没关系——temperature 1.0 / top_p 0.95 / top_k 20 本来就在 generation_config.json 里,不用额外传。
  • 如果你要的是 Instruct 那组,配置文件里没有第二组数值这件事就是你要处理的:值只能从调用侧给。另外注意模式切换本身不在采样参数里,enable_thinking 是模板变量,走的是另一条路。
  • 如果你走的是 Qwen Cloud 的 API,传法在 model card 里还有单独的说明:README.md:466README.md:493 明写,那边要直接传 "enable_thinking": False / "preserve_thinking": False,而不是包在 chat_template_kwargs 里。顺便说明一下,README.md:15-16 提到 Qwen3.8-27B 的托管版本时,原文写的是该服务 coming soonStay tuned for updates.,即按 model card 自述尚未上线。这里只中立记录其存在。
  • 如果你观察到的是框架侧某个参数不被接受、或者行为与预期不同,本文这条差异解释不了——它只说明「这个值不来自本仓的配置文件」,不说明任何框架的实现行为。要查那类问题,得去对应框架的文档和源码里找,本仓的八个文本文件里没有答案。

说到底,这篇想留下的只是一个很小的检查习惯:读到 model card 的「we recommend」时,顺手把随仓配置 grep 一遍,看推荐值到底是「已经是默认值」还是「需要你自己传」。这两件事在阅读体验上差别不大,在接线的时候差别很大。

延伸阅读


本文依据 Hugging Face 仓库 Qwen/Qwen3.8-27B 的 model card 与随仓配置文件 (config.jsongeneration_config.jsonpreprocessor_config.jsonchat_template.jinja 等)整理, 核对日 2026-08-16,对应仓库快照 1d4bf0f。 本文内容为 model card 与配置文件口径,我们没有下载权重、没有部署、也没有推理过这个模型, 因此不涉及生成质量、推理速度与显存占用的任何描述;文中所有评测数字均为 model card 自述,我们没有复现。 模型仓库内容随上游更新而变动,请以官方最新说明为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。