4. 基本推理:使用 main 命令加载模型进行对话与文本生成
既然咱们已经把 llama.cpp 编译好了,也拿到了量化后的模型文件,接下来就该让它真正跑起来了。这一章我带你手把手地用 main 这个命令行工具完成最基本的推理——说白了就是让模型开口说话。
我个人习惯把 main 称为 llama.cpp 的“瑞士军刀”。它能加载模型、处理 prompt、控制生成参数,甚至还能开启交互模式跟你聊天。我们一步一步来。
4.1 main 命令长什么样?
先别急着敲命令。我们看看 main 的基本调用结构:
./main [选项] -m 模型路径 -p "你的提示词"
绝大多数参数都有默认值。你最少只需要指定 -m 和 -p 就能跑一句生成。但如果你想做点有质量的事,下面的参数你必须熟悉。
| 参数 | 作用 | 我的常用值 |
|---|---|---|
-m | 模型文件路径 | ./models/qwen2-3b-q4_k_m.gguf |
-p | 初始提示词 | "请写一首关于春天的诗" |
-n | 生成的最大 token 数 | 512 |
--temp | 温度(随机性) | 0.7 |
--top-p | 核采样概率阈值 | 0.9 |
--top-k | 保留最高概率的 K 个 token | 40 |
--repeat-penalty | 重复惩罚系数 | 1.1 |
--ctx-size | 上下文窗口大小 | 2048 |
-i | 交互模式(可连续对话) | 无默认值 |
-n 128 限制一下输出长度,确认模型加载无误再放开。这样能快速排查路径问题或模型兼容性问题。
4.2 第一次对话:生成文本
假设你现在有一个 Qwen2-3B 的 GGUF 文件,放在 ./models/ 目录下。我通常会这样测试:
./main -m ./models/qwen2-3b-q4_k_m.gguf -p "你好,请用一句话介绍你自己。" -n 128 --temp 0.7
你会看到终端开始刷 log:加载模型、分配内存、然后模型开始“思考”。几秒后输出文本。嗯,这里要注意——第一次加载可能因为内存不足而报错,尤其是当你用 7B 以上模型时。我做项目时遇到过一次机器只有 8GB 内存,结果直接 OOM 了。后来我改用 --mlock 并限制 --ctx-size 1024 才勉强跑起来。
输出格式默认长这样:
...
你好!我是 Qwen,一个基于 Transformer 架构的语言模型。我可以帮助你回答问题、写作、编程等。
...
看到模型回复了?恭喜,你的 llama.cpp 基本推理已经通了。
4.3 对话模式:用 -i 实现多轮交互
光跑一次可不够。真正的对话需要多轮上下文。llama.cpp 的 -i 参数开启交互模式:
./main -m ./models/qwen2-3b-q4_k_m.gguf -i --interactive-first -n 512 --temp 0.8
加上 --interactive-first 之后,程序启动后不会立即生成,而是等待你输入第一句话。输入后回车,模型回复;然后继续等你下一句。退出用 Ctrl+C。
交互模式背后其实是一次性把历史对话拼接成 prompt 送给模型。所以上下文越长,推理越慢。我建议你在多轮对话时手动增加 --ctx-size,比如 4096,否则历史会被截断。
--ctx-size,结果聊到第 5 轮以后模型突然失忆,回答完全跑偏。后来才发现默认上下文只有 512,根本装不下几轮对话。把 --ctx-size 设为 2048 或更大就正常了。
4.4 控制生成质量的几个关键参数
你可能会发现同样的 prompt,每次输出都不一样。这是因为采样参数在起作用。下面这三个我几乎每次都会调:
--temp(温度):低温度(0.2~0.5)让输出稳定、可预测,适合代码生成;高温度(0.8~1.2)让输出更有创意,适合写故事。我个人写文案时喜欢用 0.9。--top-p:动态调整候选词的数量。设置成 0.9 意味着只保留累积概率达到 90% 的那些词。通俗地讲,它像一把“滤网”,把那些极其不靠谱的词过滤掉。--top-k:只从概率最高的 K 个词里采样。我一般保持 40,如果你发现模型重复太多,可以降到 20。
你可以把它们组合调试。比如:
./main -m model.gguf -p "写一段关于夏天的比喻" -n 200 --temp 0.9 --top-p 0.92 --top-k 50
效果会比默认的 --temp 0.8 --top-p 0.95 更奔放一些。
4.5 避坑指南与效率小建议
- 模型加载慢?试试
--mlock将模型锁在物理内存中,能减少 I/O 抖动。 - 输出全是乱码?检查模型文件是否完整,或者
--seed是不是设成了固定值导致采样异常。 - 显存不够?使用
-ngl 0把 GPU 卸载,纯 CPU 运行——虽然慢但至少能跑。 - 想要流式输出?
--stream参数可以从终端实时看到 token 一个接一个吐出来,体验很好。
4.6 核心推理流程图
下面这张图把 main 命令发起一次完整推理的流程串了起来。你站在高处看一遍,心里就有底了。
你看,整个流程很直白:从我敲下命令到模型给出回复,中间经过了参数解析、模型加载、token 化、采样生成这几个主要步骤。交互模式不过是在生成完一次后,重新回到“用户输入”那个节点而已。
4.7 完整示例:让模型写一份周报
最后给你一个能直接运行的组合示例。假设你想让模型帮你写周报:
./main \
-m ./models/qwen2-3b-q4_k_m.gguf \
-p "帮我写一份本周工作总结周报,包含以下内容:\n1. 完成需求评审\n2. 修复线上 bug\n3. 搭建测试环境" \
-n 300 \
--temp 0.5 \
--top-p 0.9 \
--ctx-size 4096 \
--repeat-penalty 1.1
等它输出完,你就能看到一份格式工整的周报。如果觉得太死板,把 --temp 调高到 0.8 再跑一次,语气就会更自然。
main 命令是学习 llama.cpp 的基石。后期你接触 server 模式、绑定库、batch 推理时,这些参数和概念都会反复出现。所以这一章的基础一定要打牢。
好了,拿起你的终端,选一个模型,跑一句试试看。有问题不要紧,多试几次参数,慢慢就摸清脾性了。