来源:互联网 更新时间:2026-07-26 07:29
第一次给大模型传参 temperature: 0.8 时,很多人会把它理解成“把创造力调到 80%”。这个说法好记,但确实不准确。温度并不会给模型增加知识,也不能保证文章更有创意。它真正改变的是模型从候选 token 中取样时的概率分布。

这篇文章会通过一个可以直接运行的小实验,来完成两条写作链:它们接收相同主题和相同提示词,唯一的不同就是温度。我们借此看清提示词如何进入模型、pipe() 如何连接处理步骤,以及 await chain.invoke() 到底等待了什么。
大模型并不是先想好整段文字再一次性输出。生成过程中,它会根据已有的上下文反复预测下一个 token。token 是模型处理文本的基本单位,可能是一个字、一个词的一部分,也可能是标点。
假设模型在“秋天的晚风很”后面给出了几个候选 token。为了便于理解,下面的数字只是示意:
轻柔0.55清凉0.25安静0.12滚烫0.08
这些概率构成一个分布,总和为 1。程序的做法通常不是每次都选第一名,而是按照分布来抽样。于是,同一个提示词执行多次,结果也可能不同。
temperature 会在抽样前调整这个分布:
所以,低温不等于“绝对正确”,高温也不等于“必然有创意”。模型已有的知识、提示词质量、上下文和服务商的采样实现都会影响结果。不同 API 对温度的允许范围也可能不同,不应把它固定理解为 0~1。
另一个常见参数是 top_k:它先保留概率最高的 K 个候选,再从中抽样。不过,并非所有 OpenAI 兼容接口都支持 top_k,LangChain 的某个模型封装接受一个字段,也不代表上游服务一定会使用它。为了让下面的例子适用于更多兼容接口,我们只比较 temperature。如果服务商支持 top_k 或 top_p,应以它的接口文档为准,并尽量一次只调整一个采样参数,否则很难判断究竟是谁造成了变化。
本文使用 Node.js 20 或更高版本。新建目录后安装三个依赖:
npm init -ynpm install @langchain/core @langchain/openai dotenv
它们各司其职:
@langchain/openai 提供 ChatOpenAI,用于访问 OpenAI API 或兼容接口。@langchain/core 提供提示词模板、输出解析器等通用组件。dotenv 把 .env 中的配置加载到 process.env。创建 .env,记得不要把真实密钥提交到 Git:
LLM_API_KEY=your_api_keyLLM_MODEL=your_model_nameLLM_BASE_URL=https://your-provider.example/v1
LLM_MODEL 必须填写服务商真实提供的模型 ID。LLM_BASE_URL 需要指向兼容接口的 API 根地址;不同服务商是否包含 /v1 并不统一。如果直接使用 OpenAI,也可以采用其官方环境变量和默认地址,并相应简化初始化配置。
将程序保存为 main.mjs。.mjs 告诉 Node.js 这是一个 ES 模块,因此可以直接使用 import。
模型对象保存的不只是“模型名称”,还包含请求鉴权、接口地址和生成参数。先写一个创建模型的函数,避免两套配置重复:
import "dotenv/config";import { ChatOpenAI } from "@langchain/openai";function createModel(temperature) {return new ChatOpenAI({model: process.env.LLM_MODEL,temperature,maxTokens: 500,apiKey: process.env.LLM_API_KEY,configuration: {baseURL: process.env.LLM_BASE_URL,},});}const creativeModel = createModel(0.8);const preciseModel = createModel(0.2);
调用 createModel(0.8) 时,实参 0.8 传给形参 temperature,函数再把它放入配置对象,并返回一个 ChatOpenAI 实例。两个变量因此指向两个配置不同的客户端,但还没有向模型发送请求。
maxTokens 限制模型最多生成多少 token,它不是精确字数。中文字符与 token 通常也不是一一对应,所以“约 300 字”仍要在提示词中表达,maxTokens 只负责给输出设置上限。
接下来定义提示词:
import { PromptTemplate } from "@langchain/core/prompts";const storyPrompt = PromptTemplate.fromTemplate("请围绕{theme}写一篇约300字的短篇散文。" +"风格温柔、克制,有具体画面,不要分段。");
{theme} 是占位符。提示词模板的意义其实不只是少写几次字符串拼接:它明确了调用方必须提供哪些输入,也让固定规则和动态数据分离。稍后传入 { theme: "秋日山野晚风" } 时,模板才会被格式化为真正发送给模型的文本。
聊天模型返回的通常是一个消息对象,其中除了正文还可能包含响应元数据。若后续代码只需要字符串,可以添加 StringOutputParser:
import { StringOutputParser } from "@langchain/core/output_parsers";const outputParser = new StringOutputParser();const creativeChain = storyPrompt.pipe(creativeModel).pipe(outputParser);const preciseChain = storyPrompt.pipe(preciseModel).pipe(outputParser);
pipe() 可以理解为连接流水线,但它并不会立即执行请求。每条链都定义了三步数据转换:
{ theme: "..." }↓PromptTemplate:生成完整提示词↓ChatOpenAI:调用模型并得到消息对象↓StringOutputParser:取出文本内容
前一步的输出会成为后一步的输入。这样,调用代码不必自己拆解消息对象,链最终返回的就是普通字符串。
下面加入环境变量校验、顺序调用和统一错误处理。为了让实验更容易观察,两次请求使用同一个主题,并且顺序执行,终端输出不会交错。
// main.mjsimport "dotenv/config";import { ChatOpenAI } from "@langchain/openai";import { PromptTemplate } from "@langchain/core/prompts";import { StringOutputParser } from "@langchain/core/output_parsers";const requiredEnvNames = ["LLM_API_KEY", "LLM_MODEL", "LLM_BASE_URL"];for (const name of requiredEnvNames) {if (!process.env[name]) {throw new Error(`缺少环境变量:${name}`);}}function createModel(temperature) {return new ChatOpenAI({model: process.env.LLM_MODEL,temperature,maxTokens: 500,apiKey: process.env.LLM_API_KEY,configuration: {baseURL: process.env.LLM_BASE_URL,},});}const storyPrompt = PromptTemplate.fromTemplate("请围绕{theme}写一篇约300字的短篇散文。" +"风格温柔、克制,有具体画面,不要分段。");const outputParser = new StringOutputParser();function createStoryChain(temperature) {const model = createModel(temperature);return storyPrompt.pipe(model).pipe(outputParser);}const creativeChain = createStoryChain(0.8);const preciseChain = createStoryChain(0.2);async function runWritingExperiment() {const input = { theme: "秋日山野晚风" };console.log("--- 较高温度:0.8 ---");const creativeText = await creativeChain.invoke(input);console.log(creativeText);console.log("n--- 较低温度:0.2 ---");const preciseText = await preciseChain.invoke(input);console.log(preciseText);}runWritingExperiment().catch((error) => {console.error("生成失败:", error);process.exitCode = 1;});
运行命令:
node main.mjs
这里没有用某一次输出证明“0.8 一定比 0.2 更好”。生成本身带有随机性,更合理的观察方法是每组重复运行多次,再比较用词多样性、跑题比例和要求遵循情况。
以第一条链为例,完整过程如下:
dotenv/config 将 .env 写入 process.env。runWritingExperiment() 被调用,局部变量 input 保存参数对象 { theme: "秋日山野晚风" }。creativeChain.invoke(input) 启动第一条链。模板从对象中读取与占位符同名的 theme,生成完整提示词。ChatOpenAI 使用模型名、密钥和接口地址发起 HTTP 请求。这个异步操作返回 Promise,它表示“未来才会得到的结果”。runWritingExperiment 声明为 async,函数内部可以使用 await。await 暂停的是当前异步函数后续语句;Ja vaScript 运行时仍可处理其他任务,并不是整个进程被冻结。StringOutputParser,解析器取出文本并把字符串作为整条链的结果。creativeText 接收这个字符串并输出。随后第二条链才以 0.2 的温度执行相同过程。invoke() 返回的 Promise 会被拒绝。异常沿着 await 传播,使 runWritingExperiment() 返回一个被拒绝的 Promise,末尾的 .catch() 负责打印错误并设置非零退出码。注意,invoke() 的参数必须是对象,因为模板要按属性名查找变量。把主题直接写成字符串会让模板找不到 theme。
常见现象是 404、model not found,或者服务商返回“模型不存在”。模型 ID 不能凭产品名称猜测,兼容 OpenAI 的请求格式也不意味着模型名相同。
排查时,一步步来确认:
.env 中的 LLM_MODEL 是否是账号实际可用的模型 ID。LLM_BASE_URL 是否为 API 地址,而不是服务商官网首页。/v1,以及账号所在地域是否使用不同域名。模板中使用 {theme},调用时却传入 { topic: "秋风" },通常会收到缺少变量的错误。正确写法是让两个名字严格一致:
const text = await creativeChain.invoke({ theme: "秋风" });
对象中的 theme 是属性名,字符串 "秋风" 是属性值。这里也使用了对象属性简写:若已有变量 const theme = "秋风",那么 { theme } 等价于 { theme: theme }。
下面拿到的不是最终文章,而是一个 Promise:
const text = creativeChain.invoke({ theme: "秋风" });console.log(text);
应在 async 函数中等待它:
const text = await creativeChain.invoke({ theme: "秋风" });console.log(text);
若 Promise 被拒绝而程序又没有 .catch() 或 try...catch,错误可能变成未处理的 Promise rejection,排查信息也会更零散。
先确认入口顶部存在 import "dotenv/config";,.env 位于执行命令所对应项目的正确位置,并检查变量名是否完全一致。还要注意,环境变量的值都是字符串。
线上排查时,不要用 console.log(process.env.LLM_API_KEY),这会把密钥写入终端或日志。更安全的方式是只输出布尔值:
console.log("是否读取到密钥:", Boolean(process.env.LLM_API_KEY));
一个接口接受 temperature,不代表它也支持 topK;有的推理模型甚至会忽略或限制温度。遇到“改了参数但输出没有明显变化”时,应检查服务商文档、响应警告和实际请求体,再做多轮对照测试。不要仅凭一次生成结果下结论。
当前程序适合学习数据流,但还不是严谨的模型评测。可以沿着三个方向继续改进。
第一,控制变量并重复采样。保持模型、提示词和主题不变,每个温度运行 10 次,保存结果。除了主观阅读,还可以记录格式遵循率、事实错误数和重复表达比例。这样得到的是趋势,而不是一次抽样带来的错觉。
第二,根据任务选参数,而不是按标签套数值。创意写作可以尝试较高温度;信息抽取、分类和代码修改通常从较低温度开始。但只要任务依赖事实,就还需要可靠上下文、检索、校验或测试。RAG 能为模型提供外部资料,却不能承诺彻底消除幻觉。
第三,补上工程保护。生产环境应设置请求超时和重试策略,记录不含密钥的错误上下文,并限制并发与成本。如果返回内容必须是 JSON,不要只在提示词里写“请返回 JSON”,应优先使用模型支持的结构化输出能力,再用 Schema 校验结果。
temperature 控制的是候选 token 概率分布的形状,不是知识量、正确率或创造力的百分比。LangChain 的价值则体现在流程组合:PromptTemplate 把动态输入变成提示词,ChatOpenAI 完成异步模型调用,StringOutputParser 再把消息对象变成业务代码容易使用的字符串。
真正有效的参数调试,需要固定其他条件、重复运行并按任务指标比较。先弄清数据如何穿过整条链,再讨论“哪个温度最好”,会比记住一组看似通用的推荐值更可靠。
问卷星官方网站入口地址 问卷星网页版在线使用
币安Binance官方中文网站 币安App最新版下载及新手注册指南
为何比特币BTC价格跌破7.3万美元?一文拆解影响近期比特币行情的五大原因
豆包AI专业版使用教程【新手必看】
摩托车活塞环性能如何
ThinkBook系列最新价格全解析:2026年选购避坑与实时询价指南
迷你网名古风男生霸气(精选100个)
文雅简易网名男生可爱(精选100个)
GPT5.6惨遭切脑,Fable 5回归要变弱鸡版?
陈姓和杨姓网名大全男生(精选100个)
网名开头英文名字男生(精选100个)
区块链存储板块是什么?有哪些?一文详解
暗黑4S14野蛮人终局BD攻略
Ondo将于今日上线股票永续合约
免费网络收音机软件有哪些?高评分收音机APP推荐
时隔一个多月,Dify v1.15.0终于发布了!
郑好办app如何查询档案 郑好办app查询档案方法
电视剧《罗曼诺夫后裔》剧情介绍
迅雷云盘如何下载到本地速度最快
如何在火狐浏览器中彻底禁用自动更新功能?
手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc