StackTraces
Ollama從零跑通

從零跑通 Ollama + Qwen3 本地對話:5 步,外加 4 個容易卡住的地方

@debug_master2026-09-28

跟著這篇走完,你會在本機把 Qwen3 跑起來:先用命令行聊一輪,再用 HTTP 接口發起一次帶上下文的多輪會話。整個過程 5 步,每步都有一條命令能驗證自己做對了沒有。文中出現的 localhost:11434 是 Ollama 的預設監聽地址,模型固定用 qwen3:8b;如果你換了端口或換了 tag,把示例值替換掉即可。

前置條件

項 要求 說明
Ollama 0.34.4 或更高 本文按 0.34.4 寫,它是 2026-09 的最新穩定版;0.40.0 仍是預發佈版,不要用
磁盤 6 GB 以上空閒 qwen3:8b 的權重文件 5.2 GB,另需一點空間放運行時文件
記憶體 8 GB 以上 8B 模型按預設 Q4_K_M 量化後約 5 GB 常駐,統一記憶體或顯存都能兜住
網絡 能訪問 ollama.com 只在首次拉模型時需要下載 5.2 GB,之後可以完全離線運行

裝完或升級後先跑這條確認版本。

ollama --version

看到 ollama version is 0.34.4 就是對的。Windows 上有些版本只回顯一行版本號字符串,內容一致即可;命令直接報 command not found 說明沒裝成功,回到第一步。版本低於 0.34 時 ollama ps 和 thinking 相關參數的行為會和本文不一致,建議先升級再往下走。

第一步:安裝並啟動 Ollama

macOS 和 Linux 用同一條安裝腳本,Windows 用 PowerShell 的對應版本。不想跑腳本的話,官方下載頁 上有各平臺的圖形安裝包,裝出來是同一個東西。

# macOS / Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows(PowerShell)
irm https://ollama.com/install.ps1 | iex

裝完之後 macOS 和 Windows 上 Ollama 會常駐選單欄並自動拉起服務,Linux 上安裝腳本會註冊 systemd 服務並立即啟動。這一步不需要手動執行 ollama serve,只有 Docker 或純命令行環境才需要自己起進程。

驗證服務是否已經在監聽預設端口。

curl http://localhost:11434/api/version

返回 {"version":"0.34.4"} 說明服務在跑,可以直接進入下一步。返回 curl: (7) Failed to connect to localhost port 11434 是服務沒起或沒綁在這個地址上,先看 Ollama 進程在不在,再看是不是被 OLLAMA_HOST 改到了別的地址。

第二步:拉取 qwen3:8b

Ollama 的模型不會隨安裝包一起下發,要單獨 pull 到本地。qwen3 是倉庫名,8b 是規格 tag,寫全了才能避開歧義。

ollama pull qwen3:8b

下載 5.2 GB,速度取決於網絡。qwen3 倉庫裡還有更小和更大的規格,按機器記憶體挑一檔(完整 tag 列表見 qwen3 模型庫頁):

tag 下載體積 上下文 適合
qwen3:1.7b 1.4 GB 40K 只驗證鏈路,不追求效果
qwen3:4b 2.5 GB 256K 8 GB 記憶體以下的機器
qwen3:8b 5.2 GB 40K 本文用的檔位,16 GB 記憶體機器跑得舒服
qwen3:14b 9.3 GB 40K 32 GB 記憶體以上

驗證模型是否真的落到本地。

ollama list

輸出裡出現一行 qwen3:8b、SIZE 列顯示 5.2 GB,就算拉好了。列表裡沒有它,說明前面的 pull 中途失敗,重跑一次 ollama pull qwen3:8b 會斷點續傳。

第三步:用命令行完成一次會話

ollama run 會拉起模型並進入交互提示符,這是最快確認「模型到底能不能答」的方式。

ollama run qwen3:8b

首次執行需要把權重加載進記憶體,會等幾秒到幾十秒。加載完出現 >>> 提示符,直接敲問題回車即可。Qwen3 預設開啟 thinking,你會先看到一段推理過程,再看到正式回答。聊完輸入 /bye 退出。

會話變長以後如果發現模型開始忘掉前面的內容,是預設上下文只有 4096 token 被塞滿了。可以在會話裡臨時抬高。

>>> /set parameter num_ctx 8192

這個設置只對當前會話生效。想改所有會話的預設值,用環境變數起服務:OLLAMA_CONTEXT_LENGTH=8192 ollama serve。

驗證。

在 >>> 下輸入 用一句话解释什么是栈溢出,能看到先出一段 thinking 再給出答案;輸入 /bye 能幹淨退出回到 shell,這一步就算成了。如果一直停在 pulling manifest,那是網絡沒通,不是模型問題。

第四步:用 REST API 發一次請求

Ollama 服務同時暴露了一套 HTTP 接口,端口就是剛才驗證過的 11434。先發一條單輪請求確認接口通不通。

curl http://localhost:11434/api/chat -d '{
  "model": "qwen3:8b",
  "messages": [
    { "role": "user", "content": "用一句话说明 /api/chat 和 /api/generate 的区别" }
  ],
  "stream": false
}'

stream 預設是 true,會把響應切成一行一個 JSON 分片推回來。這裡顯式寫成 false,一次拿到完整 JSON,便於確認鏈路。想看流式效果就把它打開,同時給 curl 加上 -N 關掉輸出緩衝。

curl -N http://localhost:11434/api/chat -d '{
  "model": "qwen3:8b",
  "messages": [{ "role": "user", "content": "从 1 数到 5" }],
  "stream": true
}'

驗證。

拿第一個請求的返回體,同時滿足三條就算通了:"done": true、message.content 非空、eval_count 大於 0。eval_count 是這次實際生成的 token 數,它是 0 就說明模型沒產出內容,通常是模型名寫錯或顯存不夠導致加載失敗。total_duration 和 eval_duration 單位都是納秒,順手除一下能得到每秒 token 數。

第五步:把會話接下去

/api/chat 是無狀態的,它不記得你上一次請求過什麼。所謂多輪會話,就是每輪都把歷史消息按順序拼進 messages 再發一遍。下面這條把第一輪的問和答都帶了進去。

curl http://localhost:11434/api/chat -d '{
  "model": "qwen3:8b",
  "messages": [
    { "role": "user", "content": "我叫阿禾,在做支付网关的限流。" },
    { "role": "assistant", "content": "<上一轮真实的回答原文>" },
    { "role": "user", "content": "我刚才说我在做什么?" }
  ],
  "stream": false
}'

第二條 assistant 消息要填上一輪返回的 message.content 原文,不能自己編一句。這一段就是你以後寫客戶端時要維護的會話狀態:一個按 role 和 content 累積的陣列,越聊越長,直到撞上 num_ctx 上限再考慮截斷或摘要。

驗證。

返回的 message.content 裡出現「支付網關」或「限流」,說明上下文真的被帶進去了。如果答非所問,先檢查 messages 陣列裡有沒有漏掉 assistant 那一條——只塞 user 消息等於把上一輪的答案抹掉,模型自然接不上話。

核心概念

概念 是什麼 類比
Ollama 把權重文件、運行參數和推理引擎(llama.cpp / MLX)打包成本地常駐服務的運行時 像本地的數據庫服務,裝好就有一個進程守在 11434 端口
模型 tag 仓库名:规格 形式的模型標識,如 qwen3:8b、qwen3:4b 像鏡像 tag,同一個倉庫下不同規格
量化 把權重壓到 4 bit 左右再存,預設 Q4_K_M,體積能小到三分之一上下 像給圖片降碼率,體積大降、質量損失有限
num_ctx 一次請求能看到的 token 上限,預設 4096,超出的歷史會被截掉 相當於工作臺面積,放不下的材料只能推到地上
/api/chat 無狀態的對話接口,歷史會話完全由調用方自己拼 和 HTTP 一樣天然無狀態,服務端不替你記 session

常見問題

curl: (7) Failed to connect to localhost port 11434

現象:命令行 curl 或客戶端都連不上 11434,報 Connection refused,不是超時。

原因:Ollama 服務沒起來,或者只綁在別的地址上(容器裡最常見,容器內的 localhost 不是宿主機)。

相關文章:Spring AI 接 Ollama 報 Connection refused

model "qwen3:9b" not found, try pulling it first

現象:請求發出去了,Ollama 回一句 model not found 並讓你先 pull。

原因:服務是通的,只是本地庫裡沒有這個名字——tag 寫錯、規格不存在,或者壓根沒拉過。

相關文章:Spring AI 接 Ollama 報 model not found

多輪對話到後面報 400,或者模型開始忘掉開頭的內容

現象:前幾輪正常,聊長了以後要麼被服務端拒絕,要麼回答裡丟掉早先的設定。

原因:歷史消息越堆越長,撞上了 num_ctx;預設 4096,條數沒超但 token 早就爆了。

相關文章:Spring AI 報 400 context_length_exceeded

Java 客戶端裡模型名寫錯,拋的是 NullPointerException

現象:服務端明明只是「沒這個模型」,客戶端棧裡卻是 NPE,連模型名都不提。

原因:Ollama 對不存在的模型返回 404、響應體為空,客戶端解析空響應體時炸在 HTTP 層。

相關文章:LangChain4j Ollama 模型名寫錯拋 NullPointerException

下一步

把本地模型接進 Spring Boot

qwen3:8b 拉好之後,服務端只要把 Ollama starter 的 base-url 指到 11434 就能用,裝配不上多半是 starter 沒引或模型名拼錯。

Spring AI 報 No qualifying bean of type ChatModel

改成流式輸出

把 stream 打開只是第一步,接進 Web 層還要處理 SSE 的連接生命週期和超時。

Spring AI 流式輸出:stream 與 SseEmitter

管好長會話的上下文

會話越長越要主動截斷或摘要,別等報 400 才回頭加。

Spring AI 報 400 context_length_exceeded

卡在哪一步了?

從零跑通的過程中撞到報錯?把命令和輸出記下來,幫助下一個剛起步的人。

貢獻一條解法