Mindket

Ollama API:从你的代码调用本地模型

黑色横幅,标题是“本地 AI”,下面是“在自己的电脑上运行模型”。

Ollama API 是本机服务器在 http://localhost:11434/api 上提供的一组 Web 接口,不需要密钥。/api/generate 回答单个提示词,/api/chat 接收一组消息,两者默认都是流式输出。同样的模型还能在 /v1 上响应 OpenAI SDK,而 Modelfile 可以把系统提示词和参数保存成一个新的模型名。

本节内容

  • 用 curl 或几行 Python,把提示词发到你自己的电脑上。
  • 每次调用都带上历史记录,让对话接得下去。
  • 把云服务的地址换成你的笔记本,客户端代码不用重写。
  • 把常用的助手做成一个模型名,指令直接写在里面。
全部课程
本页目录
  1. 开始之前
  2. 用 curl 发出第一个请求
  3. 从 Python 调用:Ollama 的库,或者 OpenAI SDK
  4. 把系统提示词存进 Modelfile
  5. Georgi Gerganov 谈本地模型为什么看起来不好用
  6. 常见错误
  7. 自己试一试
  8. 自测一下
  9. 常见问题
  10. 资料来源

开始之前

你需要按第 1 课的做法让 Ollama 运行起来,并且硬盘上至少有一个模型。

示例用的是 gemma4,Ollama 的 API 示例大多也用它,所以先把它拉下来,或者换成你已有的任何标签。写代码还需要 Python 3 和两个包:ollama 和 openai。

这里说的 API,是一组接收 JSON、返回 JSON 的 Web 地址。本机服务器在 11434 端口上应答。来自本机的请求不需要密钥,而且服务器只监听 127.0.0.1,所以在你修改 OLLAMA_HOST 之前,别的电脑连不上它。

Ollama 没有给这个 API 做严格的版本管理。它的介绍页面说,API 预期会保持稳定、向后兼容,官方也提供了 Python 和 JavaScript 两个库。

入口有两个,选哪个决定了你能用到什么。/api 下的原生路由开放了 Ollama 的全部能力,包括单次请求的参数、keep_alive 和思考控制。/v1 路由照搬 OpenAI 的格式,为 OpenAI 写的代码和工具不用改就能跑,只是少几个字段。

同一套 API 也在 Ollama 的云端运行。调用云端模型时,基础地址换成 https://ollama.com/api,每个请求都要带 Authorization: Bearer 请求头,里面是你在账号设置里拿到的 OLLAMA_API_KEY。

这个密钥只能放在服务器上,不能写进浏览器代码,也不能提交到代码仓库。下面的内容都用本机服务器,那里根本没有密钥可以泄露。

这套 API 是一步步长出来的,每一步都在 Ollama 的博客上公布过。早于某一步写成的教程不会提到它,所以拿教程的日期对照一下这张时间线。

ollama pull gemma4
pip install ollama openai
Ollama API 各部分上线的时间
  1. OpenAI 兼容

    /v1 路由上线,为 OpenAI API 写的代码可以调用本地模型。

    来源:Ollama blog: OpenAI compatibility (2026年11月5日 查阅)

  2. 工具支持

    /api/chat 接收 tools,支持工具的模型会用 tool_calls 回应。

    来源:Ollama blog: Tool support (2026年11月5日 查阅)

  3. 结构化输出

    format 可以接收 JSON schema,回复会按你定义的结构返回。

    来源:Ollama blog: Structured outputs (2026年11月5日 查阅)

  4. 带工具调用的流式输出

    模型调用工具时,回复也能继续流式输出。

    来源:Ollama blog: Streaming responses with tool calling (2026年11月5日 查阅)

  5. Anthropic API 兼容

    从 v0.14.0 起,Claude Code 可以通过 Anthropic 风格的 Messages API 在 Ollama 上运行。

    来源:Ollama blog: Claude Code with Anthropic API compatibility (2026年11月5日 查阅)

  6. 支持 Claude Desktop

    在 Ollama 应用里选中 Claude 并打开开关,网关会自动配置好,本地模型和云端模型都能用。

    来源:Ollama blog: Claude Desktop support with Ollama (2026年11月5日 查阅)

用 curl 发出第一个请求

从最简单的接口开始。/api/generate 接收一个提示词,返回一个回答。加上 "stream": false,服务器会等生成完,只发回一个 JSON 对象,第一次看会清楚很多。/api/chat 接收的则是一组消息,每条消息都有 role 和对应的 content。

两个接口都不记得之前的调用。用 /api/chat 时,每次都要发送整段对话:之前的问题、助手之前的回答,最后是新问题。漏掉哪一轮,模型就看不到哪一轮。每多一轮,提示词就更长一些,每次回复里的 prompt_eval_count 会显示它在增长。

两个接口能接收的不只是文字。options 对象放的是单次请求的设置:temperature、top_p、让输出可复现的 seed、stop 停止序列、限制回复长度的 num_predict,以及上下文长度 num_ctx。能看图的模型,可以在 images 里传入一组 base64 编码的文件。

思考型模型还多一个字段。用 think 可以要求模型给出推理过程,也可以关掉它。有些模型,比如 gpt-oss,接受的是 "low" 这样的档位,而不是 true 或 false。推理内容放在单独的 thinking 字段里,和回答分开。某个模型接受哪些值,可以问 /api/show。

只带模型名、别的什么都不带的请求也有用。它会载入模型但不生成内容,这样第一个真正的问题就不用等载入。

# is the server up, and which models does it have?
curl http://localhost:11434/api/tags

# one prompt, one answer
curl http://localhost:11434/api/generate -d '{
  "model": "gemma4",
  "prompt": "Why is the sky blue?",
  "stream": false
}'

# a conversation: send the messages so far
curl http://localhost:11434/api/chat -d '{
  "model": "gemma4",
  "messages": [
    {
      "role": "user",
      "content": "why is the sky blue?"
    }
  ],
  "stream": false
}'
  1. 运行 /api/tags 那条命令。它返回一个 models 列表,里面有每个模型的名字、以字节计的硬盘占用,以及 parameter_size 和 quantization_level 等详情。这一步报错,说明服务器没在运行。
  2. 运行 /api/generate 请求。回答在 response 字段里,done 为 true。
  3. 运行 /api/chat 请求。回答这次在 message.content 里,role 是 assistant。
  4. 把这条助手消息和一个追问追加到 messages 里,再发一次请求。模型现在能引用它自己的第一个回答了。
  5. 从任一请求里删掉 "stream": false,再运行一次。回复会分成很多行到达,每行一个 JSON 对象,各带一段文字。
出自 Ollama 的 generate 和 chat 参考文档,2026 年 11 月 5 日阅读。
/api/generate/api/chat
你发送什么prompt,一个字符串messages,由 role 和 content 组成的列表
系统提示词system 字段一条 role 为 system 的消息
之前的回合没有,每次调用各自独立你在 messages 里放了多少历史,就有多少
回答在哪里responsemessage.content
额外输入suffix 用于中间填充模型,raw 跳过提示词模板tools 用于函数调用,结果用 tool 消息发回

从 Python 调用:Ollama 的库,或者 OpenAI SDK

官方 Python 库包装的是同一批接口。chat() 接收模型名和一组消息。加上 stream=True,调用返回的是一段段数据块,而不是一个完整回答,每块的 message.content 里是回复的下一段。

下面的循环一收到就打印,所以模型还没写完,前面的字就已经出来了。

流式输出是服务器的默认行为,格式是按行分隔的 JSON:每行一个完整的 JSON 对象,一有新文字就发出来。普通的数据块带着一段回答和 done: false。最后一块是 done: true,带有 stop 这样的 done_reason,以及整次运行的统计数据,流式输出页面有示例。

速度方面的问题,大多能从这些统计里找到答案。所有时长都以纳秒计。常说的每秒 token 数,等于 eval_count 除以 eval_duration,再乘以十亿。token 是一小段文字,常常是半个词。

generate 参考文档完整列出了一次回复作为示例。它来自 gemma4,结尾是 done_reason: stop、prompt_eval_count: 11 和 eval_count: 18,也就是那个提示词用了十一个输入 token,回答用了十八个。

chat 只是众多调用之一。这个库还有 generate、list、show、create、copy、delete、pull、push、embed 和 ps,覆盖了命令行能做的事,所以脚本可以先拉取模型再使用它。

要连其他地址上的服务器,就自己建一个客户端:Client(host='http://localhost:11434') 可以传入地址和额外的请求头。

很多工具本来就用 OpenAI 的 API,而 Ollama 在 /v1 下应答同样的请求。你只改 base URL,其余代码照旧。客户端没有 API 密钥就不肯启动,Ollama 又会忽略你传的值,所以随便填一个字符串就行。

第二段代码就是兼容性页面自己的示例,只把模型换成了 gemma4。页面列出的路由有 /v1/chat/completions、/v1/completions、/v1/models、/v1/embeddings 和 /v1/responses,另外还有语音合成、转写和翻译的音频路由。

有几样功能不支持。Chat completions 不处理 logprobs、tool_choice、logit_bias、user 和 n,图片只能是 base64 数据,不能是 URL。Responses 路由是无状态的,所以 previous_response_id 和 conversation 用不了,每次都要重新发送历史。

OpenAI 的 API 也没有设置上下文长度的字段。变通办法是用 Modelfile 建一个 num_ctx 更大的新模型,任何 OpenAI 客户端都能在 model 里写上它的名字。

JavaScript 也一样。那边的 OpenAI 客户端用 baseURL: "http://localhost:11434/v1/" 和 apiKey: "ollama",调用的其余部分都不用改。

为 Claude 写的代码也有路可走。Ollama 支持 Anthropic Messages API 的一部分,所以把 Anthropic 客户端的 base URL 设成 http://localhost:11434 就能用,客户端会自己在地址后面加上 /v1/messages。

from ollama import chat

stream = chat(
  model='gemma4',
  messages=[{'role': 'user', 'content': 'Why is the sky blue?'}],
  stream=True,
)

for chunk in stream:
  print(chunk['message']['content'], end='', flush=True)

# the same model through the OpenAI SDK
from openai import OpenAI

client = OpenAI(
    base_url='http://localhost:11434/v1/',
    api_key='ollama',  # required but ignored
)

chat_completion = client.chat.completions.create(
    messages=[
        {
            'role': 'user',
            'content': 'Say this is a test',
        }
    ],
    model='gemma4',
)
print(chat_completion.choices[0].message.content)
响应字段出自 generate 参考文档,时长以纳秒计。
字段含义
prompt_eval_count提示词里的输入 token 数
prompt_eval_cached_count直接从缓存读取、没有重新处理的提示词 token 数
eval_count模型生成的 token 数
load_duration载入模型花的时间,冷启动时会体现在这里
prompt_eval_duration处理未缓存的提示词 token 花的时间
eval_duration生成回答花的时间
total_duration整个请求花的时间

把系统提示词存进 Modelfile

Modelfile 是一个简短的文本文件,用你已有的模型构建一个新模型。FROM 指定基础模型。PARAMETER 设置选项,比如以 token 计的上下文长度 num_ctx,以及控制措辞随机程度的 temperature。SYSTEM 写的是系统提示词,发给新模型的每个请求都会带上它。

ollama create 读取这个文件并注册新名字。之后,凡是能写模型名的地方,新模型都能用:ollama run、/api/chat,还有 OpenAI SDK。SYSTEM 那一行和别的提示词没什么两样,提示词工程课程里的系统提示词那一课讲了怎样写好它。

从 Hugging Face 拉取的模型,用另一种方式做同样的设置:仓库里名为 system 的文件设定系统提示词,名为 params 的 JSON 文件设定参数。

Modelfile 参考文档还列了其他指令:TEMPLATE 设置完整的提示词模板,MESSAGE 写入消息历史,LICENSE 写许可证,REQUIRES 指定所需的最低 Ollama 版本。

FROM gemma4
PARAMETER num_ctx 8192
PARAMETER temperature 0.3
SYSTEM You answer questions about the user's notes in plain English. If the notes do not say, answer that you do not know.
  1. 把上面四行保存成一个空目录里的 Modelfile。
  2. 运行 ollama create notes-helper -f ./Modelfile。
  3. 运行 ollama run notes-helper,问一个你的笔记里不会有答案的问题。
  4. 用 ollama show --modelfile notes-helper 打印你刚建好的模型。对 gemma4 运行同一条命令,能看到你的文件继承了哪些模板和参数。

Georgi Gerganov 谈本地模型为什么看起来不好用

Georgi Gerganov 在构建 ggml-org,也就是 llama.cpp 所在的 GitHub 组织,同时是 Hugging Face 的工程师。三月,他在 X 上的一条回复里回答了一个关于本地模型的问题。

他推荐 Qwen 3.5,因为它的尺寸覆盖面广。接着他提醒,人们遇到的大多数问题并不在模型本身,而在运行框架、对话模板和提示词的拼法上。

他的建议是:先用你的硬件装得下的全精度模型,并弄清楚你的运行框架到底做了什么。他写道,把 Claude Code 或 Codex 接到一个本地模型上就指望奇迹发生,是行不通的。等效果出来了,再为速度去做量化。他自己测试时,大多数模型都选了 Q8_0 版本,以保住大部分原始质量。

这套 API 把模板交到了你手里。/api/chat 会把模型自己的对话模板套在你的消息上,而 /api/generate 的 raw 会跳过模板,所以除非你自己重建模板,否则别开 raw。ollama show --modelfile 会打印模型用的模板。本地模型做不好某个任务时,先读一读这个模板和你的客户端发出的请求,再去怪模型。

我认为大家的共识是,Qwen3.5 是一次跨越,所以目前我会推荐去试试它,因为它的尺寸范围适合各种设备。

Georgi Gerganov, 构建 ggml-org,Hugging Face 工程师,引文为译文 · X (2026年11月5日 查阅)
Georgi Gerganov(@ggerganov)2026 年 3 月 30 日在 X 上回复本地模型的问题:他认为 Qwen3.5 是一次跨越,尺寸适合各种设备,接着开始讲人们在本地模型上遇到的主要问题。
Georgi Gerganov 在 X 上,2026 年 3 月 30 日

X 官方嵌入卡片的截图,拍摄于 2026 年 11 月 5 日,时间为 UTC。X 用“Show more”截断了这条帖子。点击截图可到 X 上打开原帖。

常见错误

  • 把流式回复当成一个 JSON 文档来解析。没有 "stream": false 时,响应体是很多个对象,每行一个,要逐行读取。
  • 只把最新一条消息发给 /api/chat。服务器不保存对话,你漏掉哪一轮,模型就忘了哪一轮。
  • 在网页或浏览器扩展里调用 API,结果被拦下。Ollama 默认只接受来自 127.0.0.1 和 0.0.0.0 的浏览器请求,其他来源要加进 OLLAMA_ORIGINS,比如 chrome-extension://*。
  • 不看 done_reason。被 num_predict 限住的回复可能停在半句话上,而 done_reason 正是说明回复为什么结束的字段。
  • 批量任务跑到一半,模型被卸载了。每个请求都可以带 keep_alive:负数让模型一直驻留,0 让它在回答后马上卸载。
  • 把云端密钥放进桌面应用或网页里。调用 https://ollama.com/api 需要 OLLAMA_API_KEY,所以要从你自己的服务器发这些请求。
  • 只在提示词里要求输出 JSON,然后碰运气。把 format 设成 "json",或者设成一个 JSON schema 对象,回复就会按这个结构返回。
  • 在 /v1 代码里写了一个 ollama ls 列表里没有的模型名。本机服务器只能运行硬盘上的模型,所以解决办法是 ollama pull,而不是换一个密钥。

自己试一试

  • 把同一个提示词发给 /api/generate 两次,一次带 "stream": false,一次不带。流式回复一共有多少行?
  • 用某次响应里的 eval_count 和 eval_duration 算出每秒 token 数。
  • 在 Python 里用库的 list 调用列出你的模型,并打印每个名字。
  • 把 OpenAI 示例里的 base_url 在 Ollama 和某个云服务之间来回切换。哪几行变了?
  • 在 Modelfile 里加上 PARAMETER num_ctx,重新创建模型,运行时看看 ollama ps 的 CONTEXT 列。
  • 在请求里带上 "keep_alive": 0,看模型在回答之后马上从 ollama ps 里消失。
  • 对一个思考型模型,把 think 分别打开和关掉,问同一个问题,对比 thinking 字段和回答。

接下来:LM Studio 在一个桌面应用里运行同样的本地服务器,自带模型浏览器,也有自己的 OpenAI 兼容接口。第 3 课会把它装好,并拿它的 lms 命令行和你现在熟悉的 Ollama 命令做对比。

自测一下

  1. 非流式的 /api/chat 响应里,回答在哪里?

    查看答案

    B. message.content chat 接口返回的是一条助手消息,所以文字在 message.content 里,/api/generate 用的才是 response。

  2. 第二次调用 /api/chat 时,模型不记得第一个问题了,缺了什么?

    查看答案

    C. messages 列表里之前的回合 服务器不保存对话,模型要看到的历史,每次调用都得带上。

  3. 用 OpenAI SDK 连 Ollama 时,API 密钥填什么?

    查看答案

    A. 随便一个字符串,Ollama 会忽略它 客户端要求必须有一个值,而本机服务器会忽略它。

  4. 怎样让 OpenAI 风格的客户端用上更长的上下文窗口?

    查看答案

    D. 用带 PARAMETER num_ctx 的 Modelfile 建一个模型 OpenAI 的 API 没有上下文长度字段,所以这个设置要放进一个客户端能指定名字的新模型里。

常见问题

怎样在 PowerShell 里调用 Ollama API?

用 Invoke-WebRequest,Windows 页面的写法是:(Invoke-WebRequest -method POST -Body '{"model":"llama3.2", "prompt":"Why is the sky blue?", "stream": false}' -uri http://localhost:11434/api/generate ).Content | ConvertFrom-json。把 llama3.2 换成你拉取过的模型。请求体里要保留 "stream": false,因为 ConvertFrom-json 要的是一个 JSON 对象,而不是每行一个。

局域网里的其他电脑能用我的 Ollama API 吗?

能。用 OLLAMA_HOST=0.0.0.0:11434 让它绑定所有网卡,这个变量要设在应用或服务读取环境的地方,然后重启 Ollama。之后谁能连上这个端口,谁就能发请求,所以要加一条只放行你自己机器的防火墙规则。

Ollama API 支持工具调用吗?

支持,通过 /api/chat。在 tools 里传入函数定义,回复里出现 tool_calls 时,运行对应的函数,再用 role 为 tool 的消息把结果发回去。chat 参考文档用 qwen3 和一个 get_current_weather 函数演示了这个过程。模型只是提出调用请求,要不要真的运行,由你的代码决定。

Ollama API 能生成嵌入向量吗?

能。先拉取 embeddinggemma 这样的嵌入模型,再把文字发给 /v1/embeddings,或者调用 Python 库里的 embed。每段文字都会变成一串数字,这正是搜索索引存储的形式,RAG 课程就建立在它之上。

资料来源

  1. Ollama Docs: API introduction (2026年11月5日 查阅)https://docs.ollama.com/api/introduction
  2. Ollama Docs: Generate a response (2026年11月5日 查阅)https://docs.ollama.com/api/generate
  3. Ollama Docs: Generate a chat message (2026年11月5日 查阅)https://docs.ollama.com/api/chat
  4. Ollama Docs: List models (2026年11月5日 查阅)https://docs.ollama.com/api/tags
  5. Ollama Docs: Streaming (2026年11月5日 查阅)https://docs.ollama.com/api/streaming
  6. Ollama Docs: OpenAI compatibility (2026年11月5日 查阅)https://docs.ollama.com/api/openai-compatibility
  7. Ollama Docs: Anthropic compatibility (2026年11月5日 查阅)https://docs.ollama.com/api/anthropic-compatibility
  8. Ollama Docs: Modelfile reference (2026年11月5日 查阅)https://docs.ollama.com/modelfile
  9. Ollama Docs: FAQ (2026年11月5日 查阅)https://docs.ollama.com/faq
  10. Ollama Docs: Windows (2026年11月5日 查阅)https://docs.ollama.com/windows
  11. GitHub: ollama/ollama-python (2026年11月5日 查阅)https://github.com/ollama/ollama-python
  12. Ollama blog: OpenAI compatibility (2026年11月5日 查阅)https://ollama.com/blog/openai-compatibility
  13. Ollama blog: Tool support (2026年11月5日 查阅)https://ollama.com/blog/tool-support
  14. Ollama blog: Structured outputs (2026年11月5日 查阅)https://ollama.com/blog/structured-outputs
  15. Ollama blog: Streaming responses with tool calling (2026年11月5日 查阅)https://ollama.com/blog/streaming-tool
  16. Ollama blog: Claude Code with Anthropic API compatibility (2026年11月5日 查阅)https://ollama.com/blog/claude
  17. Ollama blog: Claude Desktop support with Ollama (2026年11月5日 查阅)https://ollama.com/blog/claude-desktop
  18. Georgi Gerganov on X: the main issues with local models (2026年11月5日 查阅)https://x.com/ggerganov/status/2038674698809102599

分享本节课

给本地模型接上工具

在 Mindket 浏览 MCP 服务器和它们的设置说明,再通过支持 MCP 的应用,把它们接到本地模型上。

浏览 MCP 服务器

本节课的 Markdown 版本 · 本地 AI 课程:在自己的电脑上运行 AI 模型 · 全部课程