同一段文字如何变成模型输入,下一段文字又如何从分数中产生?先沿“文本 → token ID → logits → 概率 → 选取”走一遍,再比较温度与候选截断。这里的数值例子只解释解码机制;参数好坏要由具体任务验证。
从文本到 token ID
token 是词表单位,不等于字符或单词
文本模型通常把字符串编码成整数序列,每个整数对应词表中的一个 token。一个 token 可以表示完整词、词的一部分、标点、空格组合或字节片段。一个 Unicode 字符也可能跨多个 token;反过来,多个字符可能合成一个 token。因此不能靠“汉字数乘二”计算所有模型的输入。
BPE 是常见的子词构造方法。训练时从较小单位开始,根据语料统计反复合并相邻单位;编码时使用已经训练好的词表与合并规则,而不是对每次输入重新训练。例如,假设 已学到按序合并 (l,o)→lo、(lo,w)→low,l o w e r 就可得到 low e r。这只是机制示例,不代表任何现成模型对 lower 的实际切分。
byte-level BPE 使用可覆盖字节的基础表示,可以避免纯字符词表缺少某个字符的问题,但“BPE”这个名字本身不保证字节回退。分词还可能使用 Unigram、WordPiece 等方法,配置中的规范化、预切分、特殊 token 也会影响最终结果。Tokenizers 模型类型
为什么只计算正文还不够
聊天系统需要把角色和消息边界编码进模型输入。工具定义、结构化内容、图像等也可能产生额外计数。用户看到的字符串长度与模型输入长度属于不同表示层:先确定完整请求如何构造,再计算其 token 数。
例如,两条用户消息与把两段文本合成一条消息,正文字符可以完全相同,但消息边界可能不同。若 tokenizer 含规范化处理,外观相同或近似的 Unicode 字符序列也可能产生不同结果;不能假设所有 tokenizer 都保留或都消除这种差异。分词流水线
服务端计数应使用目标模型对应的接口,并用真实响应 usage 校准。Claude 的计数文档也说明计数结果是估计,模型换代后应重新计数;不存在对所有中文、代码和工具 schema 都成立的跨模型换算倍率。Claude Token counting
从 logits 到概率
标准自回归文本生成在当前前缀条件下预测下一个 token。模型输出词表各位置的分数 logits;解码器再依据配置选一个 ID,将它接到前缀后继续。实际推理引擎可以使用批处理或推测解码优化执行,但条件生成的语义仍可用这个逐步过程理解。
当前 token 序列 提示 + 已生成内容 模型前向计算 输出下一位置 logits 处理与选择 温度、过滤、采样 选中的 token ID 解码后逐步形成可见文本 一次自回归生成:分数、候选集合与选择是不同步骤 停止条件由结束标记、长度限制或接口规则决定;可见文本块不一定等于一个 token。
对正温度 T,softmax 的一个数值稳定写法是:
pᵢ = exp((zᵢ − max(z))/T) / Σⱼ exp((zⱼ − max(z))/T)
减去最大值不会改变归一化后的概率,却能避免直接计算巨大指数。设只有 A、B、C 三个候选,logits 为 [2, 1, 0]:
温度 A B C
T=1 66.52% 24.47% 9.00%
T=0.5 86.68% 11.73% 1.59%
T = 1 A 66.52% B 24.47% C 9.00% T = 0.5 A 86.68% B 11.73% C 1.59% 降温没有新增证据,也没有提高模型知识;它使已有高分候选更容易被选中。 相同 logits = [2, 1, 0],温度改变概率集中程度
降温放大相对分数差异,升温使分布更平坦。这改变选择的随机性,不是“正确率旋钮”:若错误答案本来分数最高,降温会更稳定地选择它。整个回答也不是抽样一次后写出,早期 token 的变化会改变后续条件分布。
候选截断:top-k 与 top-p
top-k 保留分数最高的 k 个候选;top-p 先按概率排序,保留累计概率首次达到阈值 p 的最小前缀,然后在保留集合内重新归一化。后者的集合大小会随分布改变。
对上面的 T=1 分布,top-p=0.8 时 A 单独只有 0.6652,不够;加入 B 后达到约 0.9100,因此保留 A、B,丢弃 C。再归一化得到 A≈0.7311、B≈0.2689。top-p=0.8 不是保留 80% 的词表,也不是让最高候选拥有 80% 概率。
在 T=0.5 时,A 一项已超过 0.8,同样阈值就只保留 A。因此温度与过滤顺序会共同影响结果。不同引擎还可能组合惩罚、最小保留数量和其他过滤器;要核对具体实现的顺序,不能把不同服务上的同名参数视为完全相同。Transformers 生成配置
下面的独立例子复现表中的数值,并明确采用“温度后再做 top-p”的顺序;无需下载模型。
import math
def softmax ( logits , temperature = 1. 0 ) :
if not logits or temperature <= 0 :
raise ValueError ( " 需要非空 logits 和正温度" )
peak = max ( logits )
weights = [ math . exp ( ( z - peak ) / temperature ) for z in logits ]
total = sum ( weights )
return [ w / total for w in weights ]
def nucleus ( probs , threshold ) :
if not 0 < threshold <= 1 :
raise ValueError ( " 阈值应在 (0, 1] 内" )
kept , mass = [ ] , 0. 0
for i in sorted ( range ( len ( probs ) ) , key = lambda i : ( - probs [ i ] , i ) ) :
kept . append ( i )
mass += probs [ i ]
if mass >= threshold :
break
return { i : probs [ i ] / mass for i in kept }
p = softmax ( [ 2 , 1 , 0 ] )
q = nucleus ( p , 0. 8 )
assert list ( q ) == [ 0 , 1 ]
assert math . isclose ( q [ 0 ] , 1 / ( 1 + math . exp ( - 1 ) ) )
assert nucleus ( softmax ( [ 2 , 1 , 0 ] , 0. 5 ) , 0. 8 ) == { 0 : 1. 0 }
assert math . isclose ( sum ( p ) , 1. 0 )
assert len ( nucleus ( p , 1. 0 ) ) == 3
print ( [ round ( x , 4 ) for x in p ] )
print ( { i : round ( v , 4 ) for i , v in q . items ( ) } )
这个实验验证概率变换,不证明某个阈值在实际任务上更好。nucleus sampling 的原始研究讨论了开放文本生成中概率尾部与退化问题;其结果不能直接推出翻译、代码、分类等所有任务都该采用同一解码方式。The Curious Case of Neural Text Degeneration
候选概率怎样变成一次选择?
把概率看成 [0,1) 上的区间,抽样就是定位 u 落在哪段。过滤后必须重新分配这些区间;删去 C 却不归一化,会留下没有候选的空隙。变化的是给定分数下的选择机制,图中没有“正确答案概率”的含义。
p i = ∑ j e ( z j − m a x z ) / T e ( z i − m a x z ) / T
正在呈现知识画面 重新加载
候选概率怎样变成一次选择? top-p 保留累计质量达到阈值的最小前缀,再归一化;抽样位置决定本次落入哪一项。
{"id":"ai-sampling-mass","title":"候选概率怎样变成一次选择?","summary":"top-p 保留累计质量达到阈值的最小前缀,再归一化;抽样位置决定本次落入哪一项。","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"temp\" data-i18n=\"temp\"></label><output for=\"temp\" id=\"temp-value\"></output><input id=\"temp\" type=\"range\" min=\"0.1\" max=\"2\" value=\"1\" step=\"0.1\"></div><div class=\"control\"><label for=\"p\" data-i18n=\"p\"></label><output for=\"p\" id=\"p-value\"></output><input id=\"p\" type=\"range\" min=\"0.05\" max=\"1\" value=\"0.8\" step=\"0.05\"></div><div class=\"control\"><label for=\"u\" data-i18n=\"u\"></label><output for=\"u\" id=\"u-value\"></output><input id=\"u\" type=\"range\" min=\"0\" max=\"0.99\" value=\"0.7\" step=\"0.01\"></div><div class=\"track-row\"><span data-i18n=\"raw\"></span><div id=\"names\" class=\"track\"></div></div><div id=\"raw\"></div><div id=\"filtered\"></div><div class=\"metrics\"><div><span data-i18n=\"kept\"></span><strong id=\"kept\"></strong></div><div><span data-i18n=\"chosen\"></span><strong id=\"chosen\"></strong></div></div><div class=\"copy\"><p id=\"explanation\" role=\"status\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"explain\"></p></div><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control output{color:var(--accent);text-align:right;font-variant-numeric:tabular-nums;min-width:4em}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1;min-width:0;overflow-wrap:anywhere;font-size:13px;min-height:44px}.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin:16px 0}.actions button{min-width:0;min-height:44px;font-size:13px;overflow-wrap:anywhere}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0;overflow-wrap:anywhere}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:18px 0}.metrics>div{border-left:2px solid var(--accent);padding:0 6px 0 10px;min-width:0}.metrics span{display:block;min-height:3.6em;color:var(--muted);font-size:12px;overflow-wrap:anywhere}.metrics strong{font-size:21px;display:block;min-height:2em;font-weight:550;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.check{display:flex;align-items:center;gap:9px;font-size:13px;margin:14px 0}.check input{width:18px;height:18px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:14px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:44px}.panel{padding:14px;border:1px solid var(--rule);border-radius:9px;margin:16px 0;min-width:0}.panel>header{font-size:13px;font-weight:600;margin-bottom:12px;color:var(--muted)}.panel>div{overflow-wrap:anywhere}.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:8px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:56px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:6px 3px;font-size:12px;overflow-wrap:anywhere}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.table{display:grid;gap:5px;font-size:12px}.tr{display:grid;gap:5px}.tr>div{background:var(--surface);border-radius:4px;padding:9px 6px;min-width:0;min-height:5em;overflow-wrap:anywhere;display:flex;align-items:center}.tr>.gold{background:var(--second-soft)}.tr>.on{background:var(--accent-soft)}.formula,.source{font:13px/1.8 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:16px 0}.formula{border-top:1px solid var(--rule);padding-top:12px;min-height:7.2em}.source{min-height:8em;background:var(--surface);padding:12px;border-radius:8px}.intervals{margin:16px 0}.interval{position:relative;height:38px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/38px ui-monospace,monospace;padding-left:7px}.bars{display:grid;gap:10px;margin:16px 0}.bar-row{display:grid;grid-template-columns:44px minmax(0,1fr) 62px;gap:8px;align-items:center;font:12px ui-monospace,monospace}.bar-track{height:24px;background:var(--surface);border-radius:4px;overflow:hidden}.bar-track i{display:block;height:100%;background:var(--accent);transition:width .2s}.bar-track i.gold{background:var(--second)}.bar-track i.empty{opacity:.2}.bar-row output{text-align:right}.diagram{display:block;width:100%;height:auto;margin:18px 0}.diagram text{font:13px ui-monospace,monospace;fill:var(--ink)}.node{fill:var(--surface);stroke:var(--rule)}.node.on{fill:var(--accent-soft);stroke:var(--accent)}.node.gold{fill:var(--second-soft);stroke:var(--second)}.edge{stroke:var(--rule);stroke-width:2;fill:none}.edge.on{stroke:var(--accent)}.matrix{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;margin:16px 0}.matrix button{min-width:0;min-height:44px;font:13px ui-monospace,monospace}.matrix button[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent)}.matrix button.masked{opacity:.35}.legend{font-size:12px;color:var(--muted);min-height:3.6em;overflow-wrap:anywhere}.numeric{font-variant-numeric:tabular-nums}.scope p{line-break:strict}@media(max-width:480px){.presets button,.actions button{font-size:12px}.panel{padding:12px}.metrics{gap:10px}.metrics strong{font-size:19px}.bar-row{grid-template-columns:34px minmax(0,1fr) 58px;gap:6px}}@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n\n.panel>h3{font-size:13px;font-weight:600;margin:0 0 12px;color:var(--muted)}\n\n.bar-row{grid-template-columns:44px minmax(0,1fr) 82px}.bar-row output{white-space:nowrap}@media(max-width:480px){.bar-row{grid-template-columns:34px minmax(0,1fr) 76px}}\n\n","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';row.style.gridTemplateColumns='repeat('+r.length+',minmax(0,1fr))';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}function plot(id,series,xr,yr,opts={}){const e=$('#'+id),X=x=>42+(x-xr[0])/(xr[1]-xr[0])*298,Y=y=>175-(y-yr[0])/(yr[1]-yr[0])*148;let out='<defs><clipPath id=\"clip-'+id+'\"><rect x=\"42\" y=\"27\" width=\"298\" height=\"148\"/></clipPath></defs>';for(let i=0;i<3;i++){let x=xr[0]+i*(xr[1]-xr[0])/2,y=yr[0]+i*(yr[1]-yr[0])/2;out+='<path class=\"gridline\" d=\"M '+X(x)+' 27V175M42 '+Y(y)+'H340\"/><text x=\"'+X(x)+'\" y=\"194\" text-anchor=\"middle\">'+esc(opts.xfmt?opts.xfmt(x):Number(x.toFixed(2)))+'</text><text x=\"36\" y=\"'+(Y(y)+4)+'\" text-anchor=\"end\">'+esc(opts.yfmt?opts.yfmt(y):Number(y.toFixed(2)))+'</text>';}out+='<g clip-path=\"url(#clip-'+id+')\">';for(const s of series){out+='<path fill=\"none\" stroke=\"'+(s.color||'var(--accent)')+'\" stroke-width=\"2.5\" '+(s.dash?'stroke-dasharray=\"5 4\"':'')+' d=\"'+s.pts.map((p,i)=>(i?'L':'M')+X(p[0]).toFixed(2)+','+Y(p[1]).toFixed(2)).join(' ')+'\"/>';}for(const p of opts.points||[])out+='<circle cx=\"'+X(p[0])+'\" cy=\"'+Y(p[1])+'\" r=\"4\" fill=\"var(--second)\" stroke=\"var(--paper)\" stroke-width=\"1.5\"/>';if(opts.cursor!==undefined)out+='<path d=\"M'+X(opts.cursor)+' 27V175\" stroke=\"var(--muted)\" stroke-dasharray=\"3 3\"/>';e.innerHTML=out+'</g>';e.dataset.curves=JSON.stringify(series.map(s=>s.pts));}const curve=(fn,lo,hi,n=120)=>Array.from({length:n+1},(_,i)=>{const x=lo+(hi-lo)*i/n;return[x,fn(x)]});function inputs(draw){document.querySelectorAll('input,select').forEach(e=>{e.addEventListener('input',draw);e.addEventListener('change',draw)});draw()}const n=id=>+$('#'+id).value;const show=(id,v,d=3)=>set(id,Number(v.toFixed(d)));function bars(id,values,max=1){$('#'+id).className='bars';$('#'+id).innerHTML=values.map(v=>'<div class=\"bar-row\"><span>'+esc(v.label)+'</span><div class=\"bar-track\"><i class=\"'+(v.cls||'')+'\" style=\"width:'+Math.max(0,Math.min(100,v.value/max*100))+'%\"></i></div><output>'+esc(v.text??(v.value*100).toFixed(1)+'%')+'</output></div>').join('')}function softmax(z,T=1){let max=Math.max(...z),w=z.map(x=>Math.exp((x-max)/T)),sum=w.reduce((a,b)=>a+b,0);return w.map(x=>x/sum)}function draw(){let T=n('temp'),p=n('p'),u=n('u'),a=softmax([2,1,0],T),mass=0,k=0;while(k<3&&(mass<p-1e-12||k===0))mass+=a[k++];let b=a.map((v,i)=>i<k?v/mass:0),c=0,sum=b[0];while(c<2&&u>=sum){c++;sum+=b[c]}['temp','p','u'].forEach(x=>set(x+'-value',n(x).toFixed(2)));cells('names',['A','B','C'].map((text,i)=>({text,cls:i===c?'gold':i<k?'on':'empty'})));bars('raw',a.map((value,i)=>({label:'ABC'[i],value})));bars('filtered',b.map((value,i)=>({label:'ABC'[i],value,cls:i===c?'gold':''})));set('kept',k);set('chosen','ABC'[c]);set('explanation',t('explain'));document.body.dataset.probabilities=JSON.stringify(b);document.body.dataset.raw=JSON.stringify(a);}inputs(draw);","audio":false,"strings":{"chosen":"选中 token","explain":"调到 T=1、p=0.8,A 和 B 被保留;降低到 T=0.5,A 单独即可达到阈值。","filtered":"保留并归一化","heading":"候选概率怎样变成一次选择?","intro":"调整温度、top-p 和抽样位置,比较过滤前后的概率。","kept":"候选数量","p":"累计概率阈值","raw":"原概率","reset":"重置","scope":"固定三项 logits=[2,1,0],先温度后 top-p,平局按 A/B/C;抽样位置由你指定,不调用模型。","scopeLabel":"模型范围与约定","temp":"温度 T","u":"抽样位置 u"}}
贪心选择与确定性
greedy 每一步取最高分候选。T=0 时上面的除法公式无定义;一些接口把零温度约定为贪心解码,另一些要求通过单独参数关闭采样。应区分数学极限与接口约定。
贪心只保证局部选择。假设第一步 A=0.6、B=0.4,选 A 后最佳下一步概率是 0.5,选 B 后最佳下一步是 0.9,那么两条候选路径概率分别为 0.30 与 0.36。逐步贪心会先选 A,却没有得到这两条路径中概率更大的那条。beam search 会保留多条候选来缓解这类问题,但仍受搜索宽度、长度偏置和评分目标限制;序列概率最高也不等于事实最正确。
对完全相同的 logits,固定平局处理的 argmax 是确定的;真实服务是否能再次产生完全相同的 logits,则取决于模型版本、精度、内核、批处理和确定性设置。固定 seed 也只控制相应随机数过程,不能锁住全部执行条件。低温度不能单独承诺逐字节复现,低 effort 更不是确定性的替代设置。
对审计或回归测试,保存完整输入、模型与生成配置、服务版本信息以及原始输出。若必须重现之前展示的内容,应读取那次的保存结果;这与重新运行模型得到同一答案是两种保证。
每一步最大,整条路径也最大吗?
局部选择只比较当前前缀下的候选。把 B 的后续概率移过 0.75,观察完整路径的排序反转,而贪心首步仍为 A。这里只比较概率目标,不能进一步推断哪条回答更真实。
正在呈现知识画面 重新加载
每一步最大,整条路径也最大吗? 首步 A=0.6 大于 B=0.4;当 B 的后续概率超过 0.75,B 的最佳两步路径反而更高。
{"id":"ai-greedy-path","title":"每一步最大,整条路径也最大吗?","summary":"首步 A=0.6 大于 B=0.4;当 B 的后续概率超过 0.75,B 的最佳两步路径反而更高。","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"next\" data-i18n=\"next\"></label><output for=\"next\" id=\"next-value\"></output><input id=\"next\" type=\"range\" min=\"0.5\" max=\"1\" value=\"0.9\" step=\"0.01\"></div><div id=\"paths\"></div><div class=\"metrics\"><div><span data-i18n=\"greedy\"></span><strong id=\"greedy\"></strong></div><div><span data-i18n=\"best\"></span><strong id=\"best\"></strong></div></div><div id=\"math\" class=\"formula\"></div><div class=\"copy\"><p id=\"explanation\" role=\"status\"></p><p class=\"reserve\" aria-hidden=\"true\" data-i18n=\"explain\"></p></div><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control output{color:var(--accent);text-align:right;font-variant-numeric:tabular-nums;min-width:4em}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1;min-width:0;overflow-wrap:anywhere;font-size:13px;min-height:44px}.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin:16px 0}.actions button{min-width:0;min-height:44px;font-size:13px;overflow-wrap:anywhere}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0;overflow-wrap:anywhere}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:18px 0}.metrics>div{border-left:2px solid var(--accent);padding:0 6px 0 10px;min-width:0}.metrics span{display:block;min-height:3.6em;color:var(--muted);font-size:12px;overflow-wrap:anywhere}.metrics strong{font-size:21px;display:block;min-height:2em;font-weight:550;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.check{display:flex;align-items:center;gap:9px;font-size:13px;margin:14px 0}.check input{width:18px;height:18px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:14px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:44px}.panel{padding:14px;border:1px solid var(--rule);border-radius:9px;margin:16px 0;min-width:0}.panel>header{font-size:13px;font-weight:600;margin-bottom:12px;color:var(--muted)}.panel>div{overflow-wrap:anywhere}.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:8px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:56px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:6px 3px;font-size:12px;overflow-wrap:anywhere}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.table{display:grid;gap:5px;font-size:12px}.tr{display:grid;gap:5px}.tr>div{background:var(--surface);border-radius:4px;padding:9px 6px;min-width:0;min-height:5em;overflow-wrap:anywhere;display:flex;align-items:center}.tr>.gold{background:var(--second-soft)}.tr>.on{background:var(--accent-soft)}.formula,.source{font:13px/1.8 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:16px 0}.formula{border-top:1px solid var(--rule);padding-top:12px;min-height:7.2em}.source{min-height:8em;background:var(--surface);padding:12px;border-radius:8px}.intervals{margin:16px 0}.interval{position:relative;height:38px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/38px ui-monospace,monospace;padding-left:7px}.bars{display:grid;gap:10px;margin:16px 0}.bar-row{display:grid;grid-template-columns:44px minmax(0,1fr) 62px;gap:8px;align-items:center;font:12px ui-monospace,monospace}.bar-track{height:24px;background:var(--surface);border-radius:4px;overflow:hidden}.bar-track i{display:block;height:100%;background:var(--accent);transition:width .2s}.bar-track i.gold{background:var(--second)}.bar-track i.empty{opacity:.2}.bar-row output{text-align:right}.diagram{display:block;width:100%;height:auto;margin:18px 0}.diagram text{font:13px ui-monospace,monospace;fill:var(--ink)}.node{fill:var(--surface);stroke:var(--rule)}.node.on{fill:var(--accent-soft);stroke:var(--accent)}.node.gold{fill:var(--second-soft);stroke:var(--second)}.edge{stroke:var(--rule);stroke-width:2;fill:none}.edge.on{stroke:var(--accent)}.matrix{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;margin:16px 0}.matrix button{min-width:0;min-height:44px;font:13px ui-monospace,monospace}.matrix button[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent)}.matrix button.masked{opacity:.35}.legend{font-size:12px;color:var(--muted);min-height:3.6em;overflow-wrap:anywhere}.numeric{font-variant-numeric:tabular-nums}.scope p{line-break:strict}@media(max-width:480px){.presets button,.actions button{font-size:12px}.panel{padding:12px}.metrics{gap:10px}.metrics strong{font-size:19px}.bar-row{grid-template-columns:34px minmax(0,1fr) 58px;gap:6px}}@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n\n.panel>h3{font-size:13px;font-weight:600;margin:0 0 12px;color:var(--muted)}\n\n.bar-row{grid-template-columns:44px minmax(0,1fr) 82px}.bar-row output{white-space:nowrap}@media(max-width:480px){.bar-row{grid-template-columns:34px minmax(0,1fr) 76px}}\n\n","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';row.style.gridTemplateColumns='repeat('+r.length+',minmax(0,1fr))';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}function plot(id,series,xr,yr,opts={}){const e=$('#'+id),X=x=>42+(x-xr[0])/(xr[1]-xr[0])*298,Y=y=>175-(y-yr[0])/(yr[1]-yr[0])*148;let out='<defs><clipPath id=\"clip-'+id+'\"><rect x=\"42\" y=\"27\" width=\"298\" height=\"148\"/></clipPath></defs>';for(let i=0;i<3;i++){let x=xr[0]+i*(xr[1]-xr[0])/2,y=yr[0]+i*(yr[1]-yr[0])/2;out+='<path class=\"gridline\" d=\"M '+X(x)+' 27V175M42 '+Y(y)+'H340\"/><text x=\"'+X(x)+'\" y=\"194\" text-anchor=\"middle\">'+esc(opts.xfmt?opts.xfmt(x):Number(x.toFixed(2)))+'</text><text x=\"36\" y=\"'+(Y(y)+4)+'\" text-anchor=\"end\">'+esc(opts.yfmt?opts.yfmt(y):Number(y.toFixed(2)))+'</text>';}out+='<g clip-path=\"url(#clip-'+id+')\">';for(const s of series){out+='<path fill=\"none\" stroke=\"'+(s.color||'var(--accent)')+'\" stroke-width=\"2.5\" '+(s.dash?'stroke-dasharray=\"5 4\"':'')+' d=\"'+s.pts.map((p,i)=>(i?'L':'M')+X(p[0]).toFixed(2)+','+Y(p[1]).toFixed(2)).join(' ')+'\"/>';}for(const p of opts.points||[])out+='<circle cx=\"'+X(p[0])+'\" cy=\"'+Y(p[1])+'\" r=\"4\" fill=\"var(--second)\" stroke=\"var(--paper)\" stroke-width=\"1.5\"/>';if(opts.cursor!==undefined)out+='<path d=\"M'+X(opts.cursor)+' 27V175\" stroke=\"var(--muted)\" stroke-dasharray=\"3 3\"/>';e.innerHTML=out+'</g>';e.dataset.curves=JSON.stringify(series.map(s=>s.pts));}const curve=(fn,lo,hi,n=120)=>Array.from({length:n+1},(_,i)=>{const x=lo+(hi-lo)*i/n;return[x,fn(x)]});function inputs(draw){document.querySelectorAll('input,select').forEach(e=>{e.addEventListener('input',draw);e.addEventListener('change',draw)});draw()}const n=id=>+$('#'+id).value;const show=(id,v,d=3)=>set(id,Number(v.toFixed(d)));function bars(id,values,max=1){$('#'+id).className='bars';$('#'+id).innerHTML=values.map(v=>'<div class=\"bar-row\"><span>'+esc(v.label)+'</span><div class=\"bar-track\"><i class=\"'+(v.cls||'')+'\" style=\"width:'+Math.max(0,Math.min(100,v.value/max*100))+'%\"></i></div><output>'+esc(v.text??(v.value*100).toFixed(1)+'%')+'</output></div>').join('')}function softmax(z,T=1){let max=Math.max(...z),w=z.map(x=>Math.exp((x-max)/T)),sum=w.reduce((a,b)=>a+b,0);return w.map(x=>x/sum)}function draw(){let v=n('next'),a=.6*.5,b=.4*v;set('next-value',v.toFixed(2));bars('paths',[{label:'A',value:a},{label:'B',value:b,cls:'gold'}]);set('greedy','A');set('best',Math.abs(a-b)<1e-10?'A = B':a>b?'A':'B');set('math','A: 0.6 × 0.5 = 0.30\\nB: 0.4 × '+v.toFixed(2)+' = '+b.toFixed(3));set('explanation',t('explain'));}inputs(draw);","audio":false,"strings":{"best":"较高的路径","explain":"先固定 A 的局部优势,再改变 B 后续条件。序列概率要乘每一步的条件概率。","greedy":"贪心首步","heading":"每一步最大,整条路径也最大吗?","intro":"调整 B 分支的后续概率,对照逐步贪心与完整路径乘积。","next":"B 的后续概率","paths":"两条路径概率","reset":"重置","scope":"固定两步、等长序列,A 的后续概率为 0.5;只比较分支最优路径,不代表事实正确性。","scopeLabel":"模型范围与约定"}}
输出停止与格式约束
控制 它约束什么 没有保证什么
EOS 或结束标记 模型选择结束 任务已经正确完成
最大生成长度 输出规模上限 JSON、代码块一定完整
stop sequence 指定边界处停止 不会误截断正文中的同样字符串
格式或 schema 约束 允许的语法、字段或类型范围 字段值在业务上真实、合法
重复惩罚 调整已出现 token 的分数 所有重复都不必要
例如,生成订单 JSON 时,schema 可以要求 quantity 是整数,却未必知道仓库实际只剩 2 件。输出 {"quantity": 5} 可以语法有效而业务无效。客户端仍要检查停止原因、完整解析、执行字段校验,并在业务层验证库存和权限。
重复惩罚也有场景代价:代码中的变量名、JSON 字段或固定术语本就需要反复出现,过强惩罚可能破坏一致性。选择采样参数前,先确认输出协议与任务约束,结构化输出的完整流程见 提示工程与结构化输出 。
迁移时重新建立基线
换模型时分别确认 tokenizer、聊天模板、支持的生成参数及其默认值,再在相同任务集上比较长度、格式通过率、任务正确率和结果波动。不要根据“本地”或“托管”就推断它一定支持或不支持某个参数;以具体模型和端点为准。Claude 迁移指南
如果新接口不再提供 temperature,先移除不支持的字段,再用清晰任务约束和评估确认输出行为。effort 调整推理投入,temperature 调整采样分布,两者不能数值映射。 要求“给四个不同方案”能表达输出目标,但不等价于升温;要求“只输出一个标签”也不等价于降低 effort。推理投入的独立权衡见 推理与 thinking 。
继续阅读:注意力、前馈网络与 MoE 。