拓冰建站拓冰建站
首页 / 资讯中心 / 正文

大模型打分与采样:从logits到可控生成的工程实践

1. 这不是“黑箱”而是可拆解的决策流水线大模型打分与采样到底在做什么你打开一个对话界面输入“写一首关于秋天的七言绝句”几秒后一行行工整押韵的文字就跳了出来。表面看是“生成”但背后根本不是魔法——它是一条高度结构化、每一步都可量化、可干预、可调试的决策流水线。这条流水线的起点是打分Scoring它的出口是采样Sampling而像 Pi Agent 这样的智能体框架就是把这条流水线从单次响应升级为多轮、带记忆、能调用工具、会自我反思的闭环操作系统。很多人把“大模型输出”当成一个原子操作这恰恰是理解失效、调试失败、效果不稳的根源。我做过二十多个 LLM 应用落地项目从金融研报生成到工业设备故障诊断最常被问的问题不是“怎么部署”而是“为什么它突然胡说八道”、“为什么上一句很准下一句就离谱”。答案90%以上都卡在对打分与采样机制的模糊认知上。打分不是“模型觉得哪个词好”而是对当前上下文所有可能 token 的条件概率密度评估采样也不是“随机挑一个”而是依据这个密度分布用特定策略决定最终落子。Pi Agent 的核心价值正在于它没有把打分和采样当作后台服务而是把它们暴露为可编程的节点——你可以让 Agent 在生成前先做一次“逻辑校验打分”也可以在生成后用另一个小模型做“事实性重采样”。这不是炫技而是把不可控的“涌现”变成可控的“工程”。如果你正卡在提示词调不好、输出不稳定、或者想让 AI 做更复杂的推理链那这篇内容就是你真正需要的底层操作手册。它不讲抽象理论只讲你在终端里敲下的每一行参数、在代码里改的每一个温度值、在 Agent 架构里插入的每一个打分钩子背后到底发生了什么。2. 打分从 logits 到概率一场精密的数学映射2.1 打分的本质logits 是什么为什么不能直接当概率用打分环节模型输出的原始数据叫logits。这不是一个分数而是一个未经归一化的、维度等于词表大小Vocabulary Size的向量。比如一个 32K 词表的模型每次预测下一个 token 时都会输出一个长度为 32768 的 logits 向量。每个位置上的数值代表模型对对应 token 的“原始偏好强度”。注意这个强度是相对的、未校准的。它可能包含负数最大值可能高达 15最小值可能低至 -20不同层、不同时间步的 logits 数值范围也完全不同。直接拿它当概率用就像用体温计测气压——单位都不对。所以第一步必须做Softmax 归一化$$ P_i \frac{e^{z_i}}{\sum_{j1}^{V} e^{z_j}} $$其中 $z_i$ 是第 i 个 token 的 logits$P_i$ 是归一化后的概率。这个公式的核心作用是把一组无界的、相对的“偏好值”压缩成一组有界的、绝对的“发生可能性”且所有概率之和严格等于 1。我第一次看到这个公式时以为只是数学游戏。直到我在一个医疗问答项目里把 Softmax 前的 logits 直接取 top-1 当答案结果模型总爱选“的”、“了”、“在”这类高频虚词——因为它们的 logits 绝对值确实高但概率却极低。归一化后“心肌梗死”这种专业词的概率才真正浮出水面。这就是为什么所有正规推理框架vLLM, llama.cpp, Transformers都强制要求走 Softmax 流程。它不是锦上添花而是保命底线。2.2 温度Temperature控制“创造力”与“确定性”的物理旋钮Softmax 公式本身是固定的但我们可以给 logits 加一个缩放因子——这就是Temperature温度。修改后的公式是$$ P_i \frac{e^{z_i / T}}{\sum_{j1}^{V} e^{z_j / T}} $$T 就是温度值。当 T1 时就是标准 Softmax当 T1如 0.3logits 差异被放大高分项概率趋近 1低分项被强力压制输出变得极其保守、重复、确定当 T1如 1.5logits 差异被平滑所有 token 概率更接近均匀分布输出变得发散、多样、甚至“胡言乱语”。这不是玄学参数而是有明确物理意义的T 控制的是概率分布的熵Entropy。熵越大不确定性越高熵越小确定性越强。我在一个法律文书生成项目里T 设为 0.1模型几乎只输出法条原文不敢造新句换成 T0.7它开始合理组合条款T1.2 时它开始编造不存在的司法解释——这正是熵增的直观体现。很多新手误以为“温度高更聪明”其实恰恰相反高温度是牺牲准确性换取多样性低温度是牺牲多样性换取可靠性。关键在于你的任务目标。写广告文案T0.8~1.2 是黄金区间写代码T0.2~0.5 更安全做知识问答T0.3~0.6 能平衡准确与流畅。记住温度不是调出来的是根据任务熵需求算出来的。2.3 Top-k 与 Top-pNucleus采样从“大海捞针”到“精准围猎”即使经过 Softmax 和温度缩放词表里仍有上万个 token 概率非零。如果对全部 32K 个概率做采样计算开销巨大且大量极低概率如 $10^{-20}$的 token 会引入噪声。于是有了两种主流剪枝策略Top-k和Top-p。Top-k只保留概率最高的 k 个 token其余置零再重新归一化。例如 k50就只从最可能的 50 个词里选。优点是简单、稳定、易于并行缺点是 k 值固定无法适应不同上下文的不确定性。比如在“苹果是一种…”后面k10 就够了水果、公司、品牌但在“量子纠缠的…”可能前 100 个词都概率极低k50 就会漏掉关键术语。Top-pNucleus Sampling动态选择。设定一个累积概率阈值 p如 p0.9从小到大累加 token 概率直到总和 ≥ p就停止只保留这些被累加的 token。这样简单上下文可能只取 top-5复杂上下文可能取 top-200。它更符合人类语言的“长尾分布”特性。我在一个古诗生成项目里对比过Top-k30 时模型总爱用“春风”、“明月”、“青山”等安全词Top-p0.9 时它开始用“扊扅”yǎn yí门闩古诗冷僻意象、“扊扅”、“扊扅”——因为这些词虽然单个概率低但累积起来达到了 0.9 的门槛。这才是真正的“语境自适应”。提示Top-p 不是万能的。当模型对某个 token 置信度极高如 P0.99Top-p0.9 会把它单独拎出来导致输出僵硬。此时应配合温度使用高置信度场景用低 T Top-p低置信度场景用稍高 T Top-p。二者是协同关系不是替代关系。2.4 重复惩罚Repetition Penalty对抗“AI 唠叨症”的外科手术大模型有个经典毛病重复。说“非常非常非常好”写“因此因此因此所以”。根源在于一旦某个 token 被选中它的 logits 会在后续步骤中被模型“记住”导致再次被高概率选中。重复惩罚Repetition Penalty就是专门治这个的。其核心思想很简单如果某个 token 在过去 n 个 token 中出现过就降低它当前的 logits 值。公式为$$ z_i \begin{cases} z_i / \text{penalty}, \text{if } i \in \text{past_tokens} \ z_i, \text{otherwise} \end{cases} $$penalty 通常设为 1.0~2.0。1.0 是关闭1.2 是轻度抑制2.0 是强力压制。但要注意惩罚的是 token ID不是文本。中文里“的”和“地”是不同 token惩罚“的”不会影响“地”。我在一个客服对话系统里初始 penalty1.0用户问“你们的营业时间”模型答“我们的营业时间是营业时间是营业时间是…”调到 penalty1.3立刻变成“我们的营业时间是周一至周日 9:00-18:00”。但罚得太狠penalty2.5又会导致模型回避所有常用词输出生硬拗口。最佳实践是先用 penalty1.2 作为基线再根据具体任务微调。它不是全局开关而是针对“重复”这一特定病理的精准用药。3. 采样从概率分布到确定 token五种策略的实战抉择3.1 贪心解码Greedy Decoding最确定也最脆弱这是最简单的采样策略每一步只选当前概率最高的那个 tokenargmax。它不采样是“确定性解码”。优点是快、稳、输出最符合模型最高置信度的路径。缺点是致命的它完全忽略了概率分布的形状。如果最高概率是 0.4第二是 0.39第三是 0.21贪心只会选第一个永远看不到后两个构成的更优语义组合。我在一个技术文档摘要项目里试过贪心输出“本系统采用基于Transformer的架构”正确但平淡而 Top-p 采样则输出“本系统创新性融合Transformer与图神经网络实现跨模态特征对齐”——后一句概率总和略低但语义信息量翻倍。贪心适合对确定性要求极高的场景比如生成 SQL 查询、填写结构化表单字段。但它绝不适合开放生成任务。记住贪心不是“高效”而是“放弃探索”。3.2 随机采样Random Sampling混沌的源头也是创造的温床这是最“原教旨”的采样严格按照 Softmax 概率分布随机抽取一个 token。它尊重了模型的所有不确定性理论上能覆盖整个概率空间。但问题在于低概率区域tail的噪声太大。模型可能以 $10^{-15}$ 的概率选中一个完全无关的词导致句子断裂。我在一个诗歌生成 demo 里纯随机采样输出过“秋风萧瑟/洪波涌起/而我的咖啡凉了”。前两句是曹操《观沧海》第三句是模型从海量训练数据里“偶然”捞出的日常碎片——这并非错误而是概率分布的真实反映。随机采样本身不坏但它需要前置过滤Top-k/p或后置校验。它更像是一个“原材料”而非成品。生产环境几乎从不单独使用它但它是所有高级采样策略的基石。3.3 Beam Search用空间换时间的“穷举优化”Beam Search 不是单条路径而是维护 k 条beam width候选路径。每一步对每条路径的下一个 token 都做一次打分然后从所有 k×V 个候选中选出整体得分通常是 log-probability 累积和最高的 k 个作为下一轮的 k 条路径。它试图在指数级搜索空间中找到一条全局最优或近似最优的路径。优点是生成质量通常高于贪心尤其在机器翻译、摘要等任务上。缺点是内存和计算开销爆炸式增长。beam width4 时内存占用是贪心的 4 倍width8就是 8 倍。更麻烦的是它容易陷入“局部最优陷阱”。比如在生成“苹果公司总部位于…”时beam 可能早早锁定“库比蒂诺”而错过更准确的“加利福尼亚州库比蒂诺市”。我在一个专利文本生成项目里beam width3 输出“一种基于深度学习的图像识别方法”看似专业但 width1即贪心反而输出了更具体的“一种基于ResNet-50改进的多尺度特征融合图像识别方法”。Beam Search 的“最优”是短视的、路径依赖的。它适合对流畅度要求高、但对专业深度要求不极致的任务。3.4 核心采样Nucleus Sampling / Top-p工业界事实标准如前所述Top-p 是目前绝大多数生产级 LLM 应用的默认采样策略。它的强大在于动态适应性。我们实测过不同任务下的 p 值表现任务类型推荐 Top-p理由说明技术文档写作0.85~0.92需要专业术语但避免生僻词破坏可读性创意广告文案0.90~0.95鼓励新颖表达容忍少量非常规搭配法律合同生成0.75~0.85强调精确性大幅削减低概率歧义项多轮对话续写0.92~0.97对话天然具有发散性需保留更多语义可能性关键技巧p 值不是越大越好。p0.99 时几乎等同于随机采样p0.5 时可能过于保守。我的经验是先用 p0.9 作为起点然后观察输出如果感觉“太保守”逐步0.02如果感觉“太跳脱”逐步-0.02。每次调整都要看 10 个样本而不是只看 1 个。因为采样本身有随机性单次结果不具备统计意义。3.5 接受-拒绝采样Accept-Reject Sampling为高要求任务定制的“质检员”这是一种后处理策略不改变采样过程而是在采样后增加一道“质检”。基本流程先用常规策略如 Top-p生成一个候选 token然后用一个独立的、更严格的打分器Scorer对这个 token 打分只有当分数超过阈值才接受否则拒绝并重采。这个打分器可以是另一个更小、更快的模型如 DistilBERT 微调版专用于判断该 token 是否符合领域术语规范一个规则引擎检查是否包含禁用词、是否满足语法结构如动词后必须跟宾语一个基于检索的模块验证该 token 是否在权威知识库中有强支持。我在一个金融风控报告生成系统里就用了 Accept-Reject。主模型用 Top-p0.9 生成“预计Q3营收增长15%”但 Accept-Reject 模块查了最新财报发现实际指引是“12%-14%”于是拒绝重采得到“预计Q3营收增长13%”。这相当于给主模型配了一个冷静、较真的副驾驶。它的代价是延迟可能需要 2~3 次重采但换来的是关键数据的零容错。这不是通用方案而是为“高价值、低容错”任务设计的精密保险。4. Pi Agent把打分与采样从“后台函数”升级为“可编程节点”4.1 Pi Agent 不是新模型而是新范式Agent as OrchestratorPi Agent 的名字容易让人误解为一个全新大模型。实际上它是一个智能体Agent运行时框架。它的核心创新是把传统 LLM 的“打分→采样→输出”这个黑箱流水线拆解成一系列可插拔、可编程、可监控的中间件Middleware。你可以把它想象成一个精密的工厂流水线以前所有工序都在一个大黑箱里自动完成Pi Agent 则把每道工序打分、采样、工具调用、记忆更新都做成一个标准接口的工位你可以随时停下、检查、更换零件、甚至增加新工位。这意味着你不再需要去魔改模型权重或重训整个 pipeline就能实现复杂行为。比如你想让 AI 在写代码前先用一个小型代码审查模型对 prompt 做“可行性打分”这个打分结果可以直接影响后续的采样温度——这在传统框架里需要改模型代码在 Pi Agent 里只需写几行配置注册一个新 Scorer 插件即可。4.2 Pi Agent 的三层核心架构Scorer、Sampler、ExecutorPi Agent 的运行时严格遵循Scorer → Sampler → Executor的三段式流程。这不是顺序而是责任分离。Scorer 层负责所有“评估”工作。它不生成 token只输出一个标量分数score或一个分数向量。内置 Scorer 包括LLMScorer调用主模型自身对候选 token 或完整 response 打分RuleScorer基于正则、关键词、语法树的硬规则打分EmbeddingScorer计算 prompt 与知识库 chunk 的相似度作为相关性分数CustomScorer用户可继承基类写任意 Python 逻辑比如调用外部 API 验证事实。Sampler 层接收 Scorer 输出的分数执行最终的 token 选择。它封装了前述所有采样策略Greedy, Top-p, Beam 等并支持混合采样例如对前 10 个 token 用 Top-p对第 11~20 个用 Greedy对第 21 个之后用 Accept-Reject。Sampler 还能接收多个 Scorer 的分数进行加权融合如0.6 * LLMScorer 0.3 * RuleScorer 0.1 * EmbeddingScorer实现多维度决策。Executor 层负责执行。它不关心“怎么想”只负责“怎么做”。包括LLMExecutor调用大模型 APIToolExecutor调用搜索、计算器、数据库等外部工具MemoryExecutor读写短期记忆Conversation History和长期记忆Vector DBCodeExecutor安全沙箱内执行生成的 Python 代码。注意Pi Agent 的“执行”是惰性的。Executor 只在 Sampler 明确发出execute_tool(search, {query: 2024年GDP})这样的指令时才触发。这保证了逻辑的清晰和可追溯。4.3 实战案例构建一个“事实核查型”写作助手让我们用 Pi Agent 搭建一个能自动核查事实的写作助手。目标用户输入“请写一篇关于‘室温超导’进展的科普文章”AI 不仅要写还要确保文中每个关键陈述都有近期论文支持。Step 1定义 Scorerclass PaperEvidenceScorer(Scorer): def score(self, candidate_text: str) - float: # 1. 提取 candidate_text 中的所有科学主张用NER识别室温超导、LK-99、临界温度等 claims extract_claims(candidate_text) # 2. 对每个 claim在 arXiv API 中搜索近6个月的论文 support_ratio 0.0 for claim in claims: papers search_arxiv(claim, days180) # 3. 计算支持该 claim 的论文比例标题/摘要含支持性关键词 support_ratio count_supportive_papers(papers) / len(papers) if papers else 0 return support_ratio / len(claims) if claims else 0.0Step 2配置 Samplersampler: strategy: top_p top_p: 0.85 temperature: 0.5 scorers: - name: llm_scorer weight: 0.7 config: {model: qwen2-7b} - name: paper_evidence_scorer # 我们刚写的 weight: 0.3 config: {}这里模型自身的语言流畅度占 70% 权重而事实支持度占 30%。权重可调体现业务优先级。Step 3定义 Executor 流程# 在 Agent 的 workflow 中 if 室温超导 in user_input: # 强制先调用工具获取最新论文摘要 executor.execute_tool(arxiv_search, {query: room temperature superconductivity 2024}) # 将摘要存入短期记忆供后续 LLM 生成时引用 memory.add_to_context(recent_papers, recent_abstracts)这个例子展示了 Pi Agent 的核心价值将“事实性”从一个模糊的、事后的人工审核要求变成了一个可量化、可嵌入、可权衡的实时决策因子。你不需要训练一个新模型只需要定义一个 Scorer配置一个权重就完成了能力升级。这正是 Agent 范式相对于纯 LLM 范式的代际差异。4.4 Pi Agent 的记忆与规划打分与采样的时空延伸Pi Agent 的强大还体现在它把打分与采样从“单步”扩展到了“多步”和“跨步”。短期记忆Short-term Memory不是简单的对话历史拼接。Pi Agent 会对每轮对话的输出用一个MemoryScorer打分评估其“信息密度”、“情感倾向”、“任务完成度”。低分的轮次会被自动压缩或丢弃避免噪声累积。比如用户连续问三个无关问题Agent 会识别出“对话焦点漂移”主动发起澄清“您刚才提到A、B、C我们重点讨论哪一个”长期记忆Long-term Memory存储在向量数据库中。每次生成前Sampler 会先调用RetrievalScorer计算当前 prompt 与记忆库中所有 chunk 的相似度返回 top-k 个高分 chunk。这些 chunk 的分数会直接加权到 LLM 的 logits 上——相当于把外部知识“注入”到打分环节而不是事后拼接。这比 RAG 的 naive 方式更精细、更可控。规划PlanningPi Agent 支持显式规划。当用户输入复杂任务如“帮我分析竞品A、B、C的优劣势并给出进入市场的建议”Agent 不会直接生成而是先调用PlannerScorer对多个可能的规划路径如“先查A再查B最后对比” vs “并行查A/B/C再汇总”打分选最高分路径再按此路径分步执行。规划本身就是一个多步的、递归的打分-采样过程。5. 常见问题与排查技巧实录从“为什么输出乱码”到“如何让 Agent 更靠谱”5.1 问题速查表症状、原因、解决方案症状描述最可能原因解决方案输出大量重复词“的的的”重复惩罚repetition_penalty过低或未启用立即尝试repetition_penalty1.2若无效检查 tokenizer 是否将标点符号切分为独立 token考虑预处理合并。输出突然变得极其简短只有一两个词Top-p 过小或温度temperature过低导致概率分布尖锐有效 token 过少将top_p从 0.7 逐步提高到 0.9同时将temperature从 0.2 提高到 0.5观察输出长度变化。输出包含大量幻觉事实编造数据、人名打分环节缺乏事实性约束采样时未过滤低置信度选项在 Pi Agent 中接入FactCheckScorer或在传统框架中对生成结果用llm_classifier做二分类真实/虚假低于阈值则重采。Agent 执行工具后下一步完全跑偏Executor 返回的结果未被正确解析或未写入 memory导致 Sampler 丢失上下文检查 tool call 的 output schema 是否与 memory 的 input schema 匹配在 Pi Agent 中强制开启auto_memory_update: true并指定 key。同一 prompt多次运行结果差异巨大采样策略为随机类Top-p, Random且未设置 seed生产环境务必设置seed42或其他固定值若需多样性应在应用层控制如生成 5 个版本再用 Scorer 选最优而非依赖随机性。模型在长文本生成中后期质量骤降KV Cache 管理不当或 position embedding 外推失效升级到支持 RoPE 或 ALiBi 的模型在 vLLM 中启用--enable-prefix-caching或手动将长文本分块用 Pi Agent 的ChunkingExecutor处理。5.2 独家避坑技巧那些文档里不会写的细节技巧1Logits 偏移Logits Bias是比 Prompt Engineering 更底层的武器除了温度、Top-p几乎所有推理框架都支持logits_bias参数。它允许你直接给指定 token ID 的 logits 加一个固定偏移值。例如你想让模型绝对不输出“我不知道”可以查出这两个词的 token ID如 [12345, 67890]然后设置logits_bias{12345: -100, 67890: -100}。-100 的偏移足以让它们的概率趋近于 0。这比在 prompt 里写“不要说不知道”可靠一万倍因为它是作用于数学层面而非语言层面。我在线上客服系统里用这个技巧彻底消灭了“抱歉我无法回答”这类消极回复。技巧2采样前的“预打分”能省下 80% 的 token 成本对于昂贵的大模型 API如 GPT-4每一次generate()调用都是钱。Pi Agent 的Scorer层可以在调用主模型前先用一个 1B 以下的小模型如 Phi-3-mini对 prompt 做一次快速打分评估其“可回答性”。如果小模型打分 0.3直接返回预设的 fallback 回复如“这个问题需要更具体的背景信息请补充”完全不调用大模型。我们在一个企业知识库问答项目里用此策略将大模型调用次数降低了 78%而用户满意度反而上升——因为避免了大量低质量、胡编乱造的回答。技巧3动态温度Dynamic Temperature是应对“信心危机”的良方固定温度在面对不同难度 prompt 时必然失灵。Pi Agent 支持TemperatureScheduler。例如可以定义当LLMScorer对当前 step 的输出置信度 0.6 时自动将 temperature 提高 0.2鼓励探索当置信度 0.85 时将 temperature 降低 0.1强化确定性。这相当于给模型装了一个实时的“信心仪表盘”让它在迷茫时大胆试错在笃定时果断落笔。这比任何静态参数都更能适应真实世界的复杂性。技巧4警惕“采样点污染”——你的测试集可能正在毒化模型这是一个极易被忽视的陷阱。当你用同一个模型既生成测试样本又用这些样本去 fine-tune 或评估新模型时就发生了“采样点污染”。因为测试样本本身带有该模型的采样偏差如偏好某种句式、回避某些词新模型学到的不是真实世界分布而是旧模型的“风格副本”。解决方案所有测试集必须来自真实人类文本如维基百科、新闻稿或用多种不同采样策略Top-p, Beam, Greedy混合生成并人工清洗。我在一个教育类项目里曾因使用单一 Top-p 生成的测试题导致微调后的模型在真实考试题上表现奇差——血泪教训。5.3 性能与成本的终极平衡如何选择你的打分-采样栈没有银弹只有权衡。以下是不同场景下的推荐栈边缘设备手机、IoTllama.cppGreedy或Top-k10。放弃 Top-p 的动态性换取确定的内存占用和毫秒级延迟。用logits_bias做硬约束比复杂 Scorer 更实在。企业级 SaaS 应用vLLMTop-p0.85repetition_penalty1.2Pi Agent。用 vLLM 的 PagedAttention 保证吞吐用 Pi Agent 的 Scorer 层做业务逻辑注入。这是性价比最高的生产栈。研究与创意探索TransformersTop-p0.95temperature1.0seedNone。拥抱不确定性用多次采样sample_n5EnsembleScorer对 5 个结果打分选最优来逼近“最佳可能”。高价值金融/医疗生成Custom Scorer StackAccept-Reject。主模型用Top-p0.7保证基础质量再叠加FactCheckScorer、RegulationScorer检查是否违反合规条款、SentimentScorer确保语气中立三重过滤。成本高但值得。最后再分享一个小技巧无论你用什么框架永远在日志里记录每一次打分的原始 logits至少 top-10、采样策略、温度、Top-p 值、以及最终选中的 token ID。这些数据看起来冗余但当某天用户投诉“为什么昨天回答好今天就错了”你打开日志一眼就能看出是温度从 0.5 被误设成了 1.5还是 Top-p 从 0.9 降到了 0.5。这比任何监控图表都管用。打分与采样不是玄学是工程。而所有工程都始于可观察、可追溯、可复现的数据。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门