LLM采样:top-p如何筛选token
top-p 不是“随机程度为80%”,也不是“只保留80%的词”。它按照下一 token 的概率排序,留下累计概率达到阈值的一小组候选,再在这组里面采样。候选数量会随当前分布改变。
0.8到底保留了什么
用四个虚构token说明:A、B、C、D的概率是0.50、0.30、0.15、0.05。top-p=0.8时,A与B累计达到0.8,因此只保留它们。重新归一化后,A的采样概率为0.50/0.80=0.625,B为0.375。被删掉的0.2概率质量并没有变成“生成错误的概率”。
Hugging Face的官方生成文档将top-p描述为保留累计概率达到阈值的最小高概率集合。若分布已经很尖锐,候选可能很少;若分布较平坦,则可能很多。所以同一个参数在不同问题、不同生成位置上的效果并不相同。
边界用代码复算
以下函数实现独立的概率筛选示例,已执行并通过归一化、候选列表及阈值1的断言。它没有调用Transformers,也没有模拟完整文本生成;真实库可能采用不同的边界或并列处理细节。
from math import log, exp, isclose
def nucleus(probabilities, threshold):
if not 0 < threshold <= 1 or not probabilities:
raise ValueError('invalid input')
if min(probabilities) < 0 or not isclose(sum(probabilities), 1):
raise ValueError('expected a probability distribution')
ordered = sorted(range(len(probabilities)), key=lambda i: (-probabilities[i], i))
keep, mass = [], 0.0
for i in ordered:
keep.append(i); mass += probabilities[i]
if mass >= threshold: break
return keep, {i: probabilities[i]/mass for i in keep}
p = [.5, .3, .15, .05]
keep, result = nucleus(p, .8)
assert keep == [0, 1] and isclose(sum(result.values()), 1)
assert isclose(result[0], .625) and isclose(result[1], .375)
assert nucleus(p, 1)[0] == [0, 1, 2, 3]
print('kept tokens:', keep)
print('conditional probabilities:', result)
返回候选[0,1],概率约为0.625与0.375。计算必须包括让累计概率跨过阈值的那个候选,不能在跨越之前停下。这里同概率按索引排序,只是为了让示例可复现。参数越小并不等于答案越真实:错误token也可能被模型赋予最高概率。
与temperature怎样一起判断
temperature改变采样分布的形状,top-p截取分布的尾部。两者都启用时,处理顺序会影响最后保留的候选,应检查使用的服务和版本。不要仅凭同一数值就认为不同服务输出一致。
若使用不采样的解码路径,采样参数也不一定产生预想的作用。工程排查要同时记录模型版本、解码模式、参数、输入与输出长度。选择参数时,用任务质量与重复生成的稳定性评估,而不是把较低top-p当成可靠性保证。
需要机器读取的结果,还应保留结构化输出校验。采样配置不能替代格式、业务关系或来源证据检查。
参考资料
补发说明:实际补发日期为北京时间2026年10月10日,文章日期保留原计划2026年10月09日19:00。代码为原创教学验证,没有运行真实模型性能测试。
支持
如果这篇文章对你有帮助,欢迎支持本站。
二维码可点击放大。更多支持方式见支持页面。


