摘要:LLM是概率引擎,每个词都是从概率分布中抽出来的。temperature控制发散度,TopK限制候选池,两者配合决定输出是严谨还是创意。本文用LangChain搭双链条同一主题两套参数,直观对比真实效果。
目录
- [LLM 怎么"随机"说话?](#LLM 怎么"随机"说话? "#%E4%B8%80llm-%E6%80%8E%E4%B9%88%E9%9A%8F%E6%9C%BA%E8%AF%B4%E8%AF%9D")
- [temperature:从 0 到 1 的发散控制](#temperature:从 0 到 1 的发散控制 "#%E4%BA%8Ctemperature%E4%BB%8E-0-%E5%88%B0-1-%E7%9A%84%E5%8F%91%E6%95%A3%E6%8E%A7%E5%88%B6")
- [Top K:给候选池圈个范围](#Top K:给候选池圈个范围 "#%E4%B8%89top-k%E7%BB%99%E5%80%99%E9%80%89%E6%B1%A0%E5%9C%88%E4%B8%AA%E8%8C%83%E5%9B%B4")
- [实战:用 LangChain 搭建双链条对比](#实战:用 LangChain 搭建双链条对比 "#%E5%9B%9B%E5%AE%9E%E6%88%98%E7%94%A8-langchain-%E6%90%AD%E5%BB%BA%E5%8F%8C%E9%93%BE%E6%9D%A1%E5%AF%B9%E6%AF%94")
- 总结
一、LLM 怎么"随机"说话?
LLM 的工作方式本质上是"根据上文预测下一个词"。给定前文"你好",模型会输出一张概率分布表:
python
"你好" 之后下一个词的概率分布:
────────────────────────────
吗 0.60 ████████████████████████████████
啊 0.15 ████████
呀 0.10 █████
美 0.05 ██
坏 0.05 ██
... (词表中有数万个候选词,都分配了微小的概率)
问题是:模型每次都选概率最高的"吗"吗?如果是这样,所有对话都将千篇一律。但如果纯随机抽,又可能抽到"坏"让对话跑偏。
真实答案是:每次生成都从概率分布中采样,但通过两个参数控制采样的"纪律"。 这就是 temperature 和 Top K 的用武之地。
二、temperature:从 0 到 1 的发散控制
temperature 的值在 0 到 1 之间,它调整的是概率分布的"陡峭度":
| temperature | 效果 | 概率分布形态 | 适用场景 |
|---|---|---|---|
| 0.2 | 低随机,高概率词被极度放大 | 陡峭------"吗"几乎稳中 | 代码生成、法律合同、翻译 |
| 0.8 | 高随机,中低概率词被拉起来 | 平缓------"呀"也有机会 | 散文创作、AI 漫剧、头脑风暴 |
数学上,temperature 作用在 softmax 之前:将 logits 除以 temperature。当 T < 1 时,高概率词被放大,分布变陡;当 T → 1 时,分布趋近原始形态。
同一个"你好",不同 temperature 下的实际表现:
ini
temperature = 0.2 → "你好吗?最近怎么样?" (安全、常见)
temperature = 0.8 → "你好呀,今天的风吹得人很舒服" (发散、有画面感)
三、Top K:给候选池圈个范围
Top K 是第二道闸门:只保留概率最高的前 K 个候选词,其余的全部清零。
| Top K | 效果 | 适用场景 |
|---|---|---|
| K = 4 | 只从概率前 4 的词里抽,限制跑偏 | 需要一定创意但不想失控 |
| K = 8 | 候选池更大,信息更完整 | 需要保证表达丰富性的严谨写作 |
Top K 和 temperature 是一个先过滤、再调整的两阶段流程:
css
原始概率分布(数万个词)
↓ Top K:只保留前 K 个得分最高的候选
缩小后的候选池(K 个词)
↓ temperature:调节这 K 个词的分布陡峭度
最终采样分布 → 随机抽一个 → 输出
黄金组合
两个参数不可能都太大(那等于完全随机),也不可能都太小(那等于退化到最大概率选择,丧失多样性)。最佳实践:
| 组合 | temperature | Top K | 效果 |
|---|---|---|---|
| 精准 + 完整 | 低(0.2) | 高(8) | 准确且不失信息丰富性,适合正式写作 |
| 创意 + 靠谱 | 高(0.8) | 低(4) | 有创意但不跑偏,适合文学创作 |
四、实战:用 LangChain 搭建双链条对比
理论讲完,用代码让效果一目了然。LangChain 提供了一套将 LLM、Prompt、输出解析器串联成**工作链(Chain)**的抽象。
两条模型,两套参数
javascript
import { ChatOpenAI } from '@langchain/openai';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { PromptTemplate } from '@langchain/core/prompts';
// 创意写作模型:高发散 + 小候选池
const creativeModel = new ChatOpenAI({
model: 'deepseek-v4-pro',
temperature: 0.8, // 增强创意发散
topK: 4, // 仅从前4候选抽,防止彻底跑偏
maxToken: 600,
apiKey: process.env.DEEPSEEK_API_KEY,
configuration: { baseURL: 'https://api.deepseek.com' }
});
// 严谨写实模型:低发散 + 大候选池
const preciseModel = new ChatOpenAI({
model: 'deepseek-v4-pro',
temperature: 0.2, // 保守严谨
topK: 8, // 更大候选池,保证表达丰富
maxToken: 600,
apiKey: process.env.DEEPSEEK_API_KEY,
configuration: { baseURL: 'https://api.deepseek.com' }
});
可复用的 Prompt 模板
LangChain 的 PromptTemplate 将 Prompt 从硬编码字符串变为可复用、可传参的模板:
javascript
const storyPrompt = PromptTemplate.fromTemplate(`
请写一篇短篇散文,主题{theme}
风格温柔治愈,篇幅200字左右,不要分段,文字细腻有画面感。
`);
同一个模板,传入不同的 theme 就能生成不同主题的散文------Prompt 不再散落在代码各处,而是集中管理、按需调用。
链条组装:.pipe() 串联一切
javascript
const outputParser = new StringOutputParser();
// 创意链条
const creativeChain = storyPrompt
.pipe(creativeModel) // PromptTemplate → LLM
.pipe(outputParser); // LLM 输出 → 纯文本
// 严谨链条
const preciseChain = storyPrompt
.pipe(preciseModel)
.pipe(outputParser);
同一主题,两种文风
javascript
async function runWriteDemo() {
const theme = '秋日山野晚风';
console.log('创意写作模式');
const creativeText = await creativeChain.invoke({ theme });
console.log(creativeText);
// 可能输出:夕阳把山野染成了橘色,晚风在林间跳着自由的舞...
console.log('严谨写实模式');
const preciseText = await preciseChain.invoke({ theme });
console.log(preciseText);
// 可能输出:秋天的山野笼罩在暮色中,晚风拂过灌木丛,发出沙沙的响声...
}
runWriteDemo().catch(err => console.error(err));
同一个主题 {theme: '秋日山野晚风'},同一个 Prompt 模板,唯一区别是 temperature 和 Top K 的参数不同------输出就是两篇风格截然不同的散文。创意链的句子更长更跳跃,用词更大胆;严谨链的表达更工整,逻辑更连贯。
chain.invoke({theme}) 是整个工作流的启动点------把参数塞进链条,PromptTemplate 自动填充模板,发给 LLM 生成结果,StringOutputParser 提取出纯文本,一条龙完成。
为什么需要 Chain?
| 不用 Chain | 用 Chain | |
|---|---|---|
| Prompt 管理 | 硬编码在代码各处 | PromptTemplate 集中管理,变量参数化 |
| 输出处理 | 手动从 response 中取 choices[0].message.content |
StringOutputParser 自动提取纯文本 |
| 可复用性 | 换一个模型要改多处代码 | .pipe() 链式组装,换模型只改一个节点 |
| 可维护性 | 业务逻辑和调用代码杂糅 | 每个节点职责单一,链条清晰可追踪 |
AI 应用开发的核心矛盾是"既要可控又要有创意"。Chain 的价值就是把"不可控的生成过程"封装进"可控的工作流"------temperature 和 Top K 让你知道它在怎么随机,PromptTemplate 让你知道它收到了什么指令,链条结构让你知道数据是怎么流转的。黑盒变成了透明的流水线。
五、总结
- LLM 的概率本质:每个词都是从概率分布中采样出来的。默认选择最高概率词会让输出千篇一律,纯随机又会让内容失控。
- temperature 是发散旋钮:0.2 放大高概率词(严谨),0.8 拉平分布(创意)。底层原理是 softmax 前的 logits 缩放。
- Top K 是候选围栏:只保留前 K 个得分最高的候选,其余清零。和 temperature 是两步流水线------先过滤、再调节。
- 黄金组合:温度低 + K 高 = 精准且丰富(正式写作);温度高 + K 低 = 创意不跑偏(文学创作)。
- LangChain 三步搭链条 :
PromptTemplate管输入、带参数的 model 管生成、StringOutputParser管输出。.pipe()串联所有节点。 - 同一主题两套参数 = 两篇不同文章:想控制 LLM 的"胡说"程度,就调 temperature 和 Top K 两个旋钮。
------ LLM 的随机是可控的,钥匙就在 temperature 和 Top K 两个旋钮上。