命令行对话:参数、模板和多轮会话
[TOC] 能把模型跑起来只是起步(还没跑起来的先去看拉取和运行模型:pull、run 和版本标签),真正用得舒服不舒服,取决于你怎么调它。同样一个模型,参数调好了是得力助手,参数没调好可能就是一本正经的胡说机器。这篇把 Ollama 对话相关的三件事讲清楚:怎么调生成参数、怎么用模板固化模型的行为、以及多轮对话的上下文机制。内容偏操作,建议边看边在自己机器上试,每条命令都可以直接复制运行。
先理解生成参数
大模型生成文字的过程是逐字预测:根据已有的内容猜下一个字,每猜一个都带一定的随机性。生成参数就是控制这种随机性的旋钮。理解了这一点,所有参数的作用都好懂了。
第一个要认识的参数是 temperature,中文叫温度。它控制模型发散思维的程度:温度越低,输出越确定、越规整;温度越高,输出越发散、越有创意。写代码、做摘要、回答事实性问题,应该用低温度,要的是准;写小说、起标题、头脑风暴,用高温度,要的是新。
一个直观的感受是,温度接近零的时候,同一个问题问十遍答案几乎一样;温度拉高之后,同一句话能给你整出十种花样。温度本质上就是一个从刻板到奔放的旋钮,每个模型对温度的敏感度还不一样,同一个数值在不同模型上效果不同,这就是为什么参数没有标准答案,只能边用边调。
第二个是 top_p,控制候选词的范围。模型每次生成时会列出一堆候选字及概率,top_p 只保留概率累加达到设定值的那些候选,剩下的直接不考虑。它和 temperature 的效果有点像,是控制随机性的另一个旋钮。
经验上 temperature 和 top_p 调一个就行,两个一起动容易调晕。社区里流传的稳妥组合是低温度加高 top_p,既保持稳定又留一点灵活性,不妨作为起点再微调。
第三个是 num_ctx,上下文长度。它决定模型一次能看进去多少 token,直接影响长对话和长文档处理的能力。设得越大能装的上下文越多,占的显存也越多,需要按显存余量权衡。
| 参数 | 作用 | 常用取值 | 建议场景 |
|---|---|---|---|
| temperature | 控制随机性 | 0.1 到 1.2 | 低求准、高求新 |
| top_p | 候选词过滤 | 0.5 到 1.0 | 和温度二选一调 |
| num_ctx | 上下文长度 | 2048 到 32768 | 长文档才需要调大 |
| num_predict | 限制输出长度 | 100 到 2000 | 防止啰嗦超时 |
| seed | 随机种子 | 任意整数 | 复现某次输出 |
注意这些参数大多只在 API 调用时生效,交互式 run 里最方便的调法是通过 Modelfile 固化,下面具体讲。
Modelfile:把模板和参数固化下来
每次对话都重复写一遍系统提示词是很蠢的。Ollama 提供了 Modelfile 机制,你可以基于一个现有模型,派生出一个自带提示词和参数的定制版本。
写一个最简单的 Modelfile:
FROM qwen2.5:7b
SYSTEM """你是一位资深程序员,回答简洁,先给代码再解释。"""
PARAMETER temperature 0.3
PARAMETER num_predict 800
FROM 指定基础模型,SYSTEM 设定系统提示词,PARAMETER 设定生成参数。用下面的命令打包:
ollama create coder -f ./Modelfile
这条命令敲完,你会看到它先做几次校验,然后报告模型已创建。之后 ollama list 里就会多出 coder 这一项,和你从官方仓库 pull 来的模型并列在一起,没有任何区别。
打包定制模型不占额外的大量磁盘空间, 它只是基础模型的一条分支记录,存的是你的配置而非完整模型副本。所以放心造,造十个八个不同的工作模板也不心疼空间。
ollama run coder
从这一刻起,coder 这个模型永远以程序员的角色回答问题,永远先给代码再解释,输出长度被限制在 800 token 以内,全程不用你再重复任何设定。效果立竿见影。
这个机制的实际价值非常大。给团队用,可以固化每个人的工作风格;做产品,可以把输出格式锁定成 JSON 方便程序解析;教家人用,可以把模型设定成永远用通俗语言解释。所有重复性的提示工作都可以一次性写进模板里。
再往深一步,Modelfile 还能做更多事情。TEMPLATE 指令可以改写模型看到的对话拼接格式,属于进阶玩法,多数人用不到;更实用的是多条系统提示的叠加。SYSTEM 可以写很长,把角色设定、输出规范、注意事项全放进去。写得越细,模型行为越稳定。
举一个实际例子。假设你要做一个代码评审助手,SYSTEM 里可以写:你是一位严格的代码评审专家,只指出问题不夸奖,每个问题给出具体修改建议和示例代码,按严重程度从高到低排列,最后给一句总结。这样的固设,比你每次提问都写一遍同样的话,效率和稳定性都高得多。
需要注意的是 SYSTEM 的长度是有讲究的。太长了每次推理都要过一遍,既费显存又影响速度;太短了行为约束不到位。 一般控制在两三百字以内,把最重要的要求放前面,模型对开头的指令印象更深。
定期更新模板也很重要。用着用着你会不断发现新的提示技巧,把它们逐步加进 SYSTEM 里,模型的表现会肉眼可见地提升。这不叫折腾,这叫调教,是本地大模型独有的乐趣。说句题外话,云端 API 虽然也能传系统提示词,但每次请求都要带,既费 token 又容易忘,模板固化是本地特有的便利。
多轮会话的上下文怎么算
多轮对话是 run 命令默认开启的能力。你问一句话,模型回答,你再追问,模型知道你前面说过的内容。这套机制看起来神奇,原理其实很直白:每次你提问时,Ollama 把之前的全部对话原样拼接在一起,一次性发给模型。模型并没有真的记住什么,它只是从头又读了一遍聊天记录。
理解了这个原理,几个现象就好懂了。第一,对话越长每次推理的输入越长,所以长对话会越聊越慢,因为每次都要把历史重新过一遍。第二,当总长度超过上下文窗口,最早的对话会被挤出窗口,模型就忘了最开始说过什么,这不是bug是物理限制。第三,切换话题之前最好 /clear,否则模型会被无关的旧对话干扰。
理解了这三个现象,你就能对自己的聊天节奏有预判:短问答随便聊,长对话要舍得清理,严肃任务直接开新会话。养成这几个微小的习惯,日常使用的体验会平滑很多,这就是新手和老手之间的差距所在。
顺便说说多人共用的场景。如果你把 Ollama 服务开放给局域网,多个人同时和同一个模型聊天,彼此的对话是隔离的——每个人维护自己的会话上下文,不会串话。这一点不用担心,隔离机制是服务层面内置的。但要注意并发高的时候请求会排队,团队的规模大了之后,每多一个人就多一份等待, 这时候就要考虑性能调优了。
说回上下文长度参数,新手的常见误区是盲目调大它。窗口越大确实越能装,但显存占用也线性增长,而且大多数日常对话根本用不到那么长的窗口。2048 到 8192 的区间覆盖了百分之九十的场景,先从这个范围试起,遇到具体需求再加,比一上来就拉满更聪明。
清空上下文最果断的做法是 /clear。重新开始一个不相干的话题之前,养成清一下的习惯,模型的表现会更稳定。还有一个选择是直接退出重新 run,效果一样,看你哪个顺手。
为什么这件事值得单独强调?因为不清上下文最直接的表现就是模型莫名其妙地串味:你问它今天天气,它突然接上一段一小时前聊过的菜谱。这不是模型蠢了,是你给它看的聊天记录太长太杂,它被旧内容带了节奏。 /clear 一下,世界立刻清净。
API 调用做多轮对话时,上下文需要你自己维护:每次请求把完整的对话历史放在 messages 数组里发给服务。大多数客户端工具会自动帮你做这件事,但如果你自己写代码,这块逻辑要留意,漏掉了历史消息模型就会失忆,这是新手写聊天应用最常见的连环翻车点。
API 调用:让其它程序用上模型
命令行聊天只是入门,Ollama 真正的威力在于它是一个标准服务。任何能发 HTTP 请求的程序都能调用它。最简单的接口长这样:
curl http://localhost:11434/api/chat -d '{
"model": "qwen2.5:7b",
"messages": [{"role": "user", "content": "你好"}],
"stream": false
}'
返回的是一个 JSON 结构,里面包含模型生成的回复内容。role 字段区分角色,user 是用户说的,assistant 是模型说的,system 是系统提示。把多轮历史按顺序放进 messages 数组,就实现了多轮对话。
流式输出的响应格式稍有不同,开启流式后,接口会逐块返回内容,适合做打字机效果的界面。接口设计的细节可以直接对照官方文档,也可以装一个 Open-WebUI 走现成界面,省掉自己处理接口的功夫。
还有一个接口适合特别简单的场景:/api/generate,只要传一个 prompt 字符串就行,连消息数组都不用组装。要做个最简单的问答脚本,它比 chat 接口更省事。两个接口返回的内容格式略有差异,写解析代码的时候看清楚要用哪个。
做正式应用时还有两个建议。一是把请求超时设长一点,大模型生成长内容时十几秒不返回很正常,超时设短了会白白截断;二是做一层简单的重试逻辑,偶尔的请求失败重试一次往往就好了,别让用户面对一个刺眼的报错。这些都是踩过坑之后才会想起来的细节,提前注意能少走弯路。
聊天参数的实用经验
调来调去,最后落到一句大实话:参数的黄金组合因人因模型而异,没有标准答案。但确实有一些经验可以分享,帮你少走弯路。
写代码用低温度加中等输出长度,让模型稳扎稳打别发挥;写文案用中等温度,让它有点灵气但不至于跑野;事实问答把温度压到最低,最大程度压制编造倾向——前提是你用的是问答能力过关的模型,压温度救不了本身就不靠谱的模型。
如果模型回答总是太短,检查 num_predict 是不是被你或者默认值卡住了;如果长对话越来越慢,检查是不是该 /clear 了;如果同样的问题每次答案差别巨大,温度可能调高了。遇到问题先想参数,再想模型,最后才怀疑软件,这个排查顺序最高效。
最后给一条更朴素的建议:别陷入参数焦虑。绝大多数情况下,默认参数已经能满足八成需求,把时间花在把问题问清楚上比花在调参上回报高得多。参数优化是临门一脚的事,不是入场门槛。命令行玩熟了的人,最终都会回归到简单:好问题、好模板、好习惯,技术没那么重要可言。
常见问题
回答突然变慢是怎么回事
先分清是哪种慢。第一种是单次回复慢,多半是上下文太长了,每次推理要把全部历史过一遍,自然就慢,/clear 立竿见影。第二种是整个会话都慢,可能是显存被挤占、模型被部分卸载到内存, 关掉一些占显存的程序,或者重启一下服务恢复。第三种是间歇性慢,可能是机器同时在跑别的重活,错峰使用就行。
第四种慢最容易被忽略:你换了更大的模型。8B 换成 32B 之后速度肉眼可见下降, 但这是正常的成本,能力提升本来就以速度为代价。判断的依据是先 ollama ps 确认当前真的是你想跑的那个模型, 再往下排查。
模型老是忘记前面说过的话
上下文窗口就那么大,超过就被挤掉,这是物理限制不是设定问题。解决思路有三个:定期 /clear 减少无关历史;手动整理对话要点开新话题;以及换一个上下文窗口更大的模型版本。如果做的是长期的应用,把关键信息每次都放进提示词里,别指望模型自己记住,这是工程上更可靠的做法。
ollama create 报错说找不到基础模型
先 ollama list 确认基础模型名字拼写完全正确,包括冒号后面的标签。 模型不存在、缩写不对、大小写不对都会报这个错。从 list 输出里直接复制名字是最稳的做法,别凭记忆敲命令。如果确认名字没问题,再检查 Modelfile 的 FROM 行写法有没有多余空格。
怎么复现某次满意的输出
设置相同的随机种子。在 PARAMETER 里写 seed 固定下来,只要输入完全一样,输出就基本可复现。不过注意模型版本一升级,同样的种子也可能给出不同结果,想长期留痕还是把满意的回答单独存档更靠谱。
定制的模型怎么分享给别人
最简单的方式是分享你的 Modelfile。对方自己 pull 同一个基础模型,拿到你的 Modelfile 文件后执行 ollama create 就能得到一模一样的定制模型。Modelfile 是纯文本,几行字,发个消息的事就能传过去,比传几个GB的模型文件方便太多。公司团队内部共享工作模板,都走这条路。
模型回答老是带格式 markdown 符号怎么办
这其实是正常现象,模型把输出理解成给程序看的格式了。两个办法:一是在 SYSTEM 里明确要求用自然语言回答;二是把格式化输出当成能力来用,干脆在模板里固定输出格式,程序解析起来反而方便。全看你需要的是给人看还是给机器看。
