Ollama API 实战:Python 与 Node.js 客户端开发指南
凌晨一点,终端里敲下 ollama run gemma3,屏幕吐出第一句回复。挺爽的。
但你很快就开始琢磨:这玩意儿能不能接到自己项目里?不用 API Key,不用付钱,本地跑着,多香。
说实话,我一开始也这么想的。翻了一圈文档,发现官方直接给了 Python 和 JavaScript 的 SDK,甚至还能用 OpenAI 的 SDK 改两行代码就能对接。这事儿比想象中简单。
但简单不代表没坑。流式响应怎么累积?工具调用的 Agent Loop 怎么写?thinking 模式下推理和回答怎么分开?这些都是踩过的坑。
这篇文章就把这些坑填上。Python 和 Node.js 双语言对比,原生 SDK 和 OpenAI 兼容两种方案都讲清楚,给你一个完整的客户端开发指南。
对了,如果你还没装 Ollama,可以先看看我们系列的第一篇 LangChain + Ollama 集成实战,先把本地模型跑起来。
第一章:Ollama API 基础
先搞清楚 API 怎么跑的。
Ollama 默认在本地启动一个 REST API 服务,地址是 http://localhost:11434/api。你打开浏览器访问这个地址,会看到一句干巴巴的 “Ollama is running”——这就说明服务正常。
主要端点
两个核心端点你得记住:
| 端点 | 用途 | 特点 |
|---|---|---|
/api/chat | 多轮对话 | 支持 messages 数组,能传上下文 |
/api/generate | 单轮生成 | 简单粗暴,适合一次性任务 |
还有一个 /v1/chat/completions,这是 OpenAI 兼容端点。如果你手头有现成的 OpenAI 项目,改个 base_url 就能用,后面会细讲。
用 curl 试一把
先用最原始的方式试试 API:
curl http://localhost:11434/api/chat -d '{
"model": "gemma3",
"messages": [
{ "role": "user", "content": "天空为什么是蓝色的?" }
]
}'
终端里会吐出一堆 JSON。关键看 message.content 字段,那里面就是模型的回答。
响应结构大概是这样:
{
"model": "gemma3",
"created_at": "2026-04-18T01:23:45.678Z",
"message": {
"role": "assistant",
"content": "天空呈现蓝色主要是因为..."
},
"done": true
}
done 字段很重要。流式响应时,每个 chunk 的 done 都是 false,最后一个 chunk 才是 true。这个后面处理流式响应时会用到。
流式响应
默认情况下,API 会等模型生成完再一次性返回。但你想让用户看到”打字机效果”,就得加 stream: true:
curl http://localhost:11434/api/chat -d '{
"model": "gemma3",
"messages": [{ "role": "user", "content": "天空为什么是蓝色的?" }],
"stream": true
}'
这次终端里会一行一行蹦出 JSON。每行都是一个小 chunk,你得把它们攒起来才能凑成完整回答。
嗯,手动处理这些 chunk 确实挺麻烦。这也是为什么官方给了 SDK——帮你把这些细节都封装好了。
第二章:Python SDK 完整实战
Python 的 SDK 是官方维护的,装起来特简单:
pip install ollama
装完直接用。支持 Python 3.8+,这点挺友好的。
基础调用
最简单的调用方式,一行代码搞定:
from ollama import chat
response = chat(
model='gemma3',
messages=[{'role': 'user', 'content': '天空为什么是蓝色的?'}]
)
print(response.message.content)
就这么简单。chat() 函数是 SDK 提供的快捷方式,内部自动创建了一个默认的 Client 连接本地的 Ollama 服务。
如果你想自定义连接参数——比如 Ollama 跑在另一台机器上——可以自己创建 Client:
from ollama import Client
client = Client(host='http://192.168.1.100:11434')
response = client.chat(model='gemma3', messages=[...])
流式响应
流式响应是重点。你得让用户看到文字一点点蹦出来,而不是等半天突然全吐出来。
from ollama import chat
stream = chat(
model='gemma3',
messages=[{'role': 'user', 'content': '天空为什么是蓝色的?'}],
stream=True,
)
for chunk in stream:
print(chunk['message']['content'], end='', flush=True)
这里有个坑:chunk 返回的是字典,不是对象。所以访问方式是 chunk['message']['content'],不是 chunk.message.content。我一开始就踩了这坑,报错半天没反应过来。
异步客户端
如果你的应用是异步架构——比如用 FastAPI 或 aiohttp——就得用异步客户端:
import asyncio
from ollama import AsyncClient
async def main():
client = AsyncClient()
# 非流式
response = await client.chat(
model='gemma3',
messages=[{'role': 'user', 'content': '你好'}]
)
print(response.message.content)
# 流式
stream = await client.chat(
model='gemma3',
messages=[{'role': 'user', 'content': '天空为什么是蓝色的?'}],
stream=True,
)
async for chunk in stream:
print(chunk['message']['content'], end='', flush=True)
asyncio.run(main())
异步流式返回的是 async generator,用 async for 遍历。跟同步版本的逻辑一样,就是加了 await 和 async。
Cloud Models
有意思的是,Ollama SDK 还支持云端模型。有些大模型本地跑不动——比如那个 120B 的 gpt-oss——但云端有。
from ollama import chat
response = chat(
model='gpt-oss:120b-cloud',
messages=[{'role': 'user', 'content': '你好'}]
)
模型名带 -cloud 后缀就会走云端 API。当然你得有 Ollama 的云端账户和 API Key,配置方式跟本地不太一样,感兴趣的可以看官方文档。
说实话,这个功能挺实用的。小模型本地跑省钱,大模型云端跑省硬件。混合方案挺香。
第三章:Node.js SDK 完整实战
Node.js 的 SDK 也一样简洁:
npm i ollama
注意这包同时支持 Node.js 和浏览器环境。浏览器版本要单独导入:
// Node.js
import ollama from 'ollama'
// 浏览器
import ollama from 'ollama/browser'
基础调用
Node.js 里默认就是异步的,写起来更顺手:
import ollama from 'ollama'
const response = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: '天空为什么是蓝色的?' }],
})
console.log(response.message.content)
跟 Python 版对比一下:Python 用字典传 messages,Node.js 用对象。参数名基本一致,换语言不用重新学习概念。
流式响应
Node.js 的流式处理天生就是异步 generator:
import ollama from 'ollama'
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: '天空为什么是蓝色的?' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.message.content)
}
这里用 process.stdout.write 而不是 console.log,因为 console.log 会自动换行,你不想每蹦一个字就换行吧?
自定义配置
SDK 支持自定义 host 和 headers:
import ollama from 'ollama'
// 自定义 host
const client = new ollama.Ollama({ host: 'http://192.168.1.100:11434' })
// 或者用全局配置
ollama.setDefaultHost('http://192.168.1.100:11434')
// 添加 headers(比如认证)
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: '你好' }],
headers: { Authorization: 'Bearer xxx' },
})
headers 参数挺有用。如果你的 Ollama 服务前面加了认证代理,可以在这里传 token。
取消流式生成
有个 abort() 方法可以取消正在进行的流式生成:
import ollama from 'ollama'
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: '写一篇长文...' }],
stream: true,
})
// 用户点击了停止按钮
ollama.abort()
for await (const chunk of stream) {
// abort 后循环会提前结束
process.stdout.write(chunk.message.content)
}
这个功能做聊天界面时必用。用户不想等模型写完废话,点个按钮就能停。
浏览器版本
浏览器里用法类似,但有些差异:
import ollama from 'ollama/browser'
// 浏览器里只能用流式,因为原生 API 不支持非流式跨域请求
const stream = await ollama.chat({
model: 'gemma3',
messages: [{ role: 'user', content: '你好' }],
stream: true,
})
for await (const chunk of stream) {
document.getElementById('output').textContent += chunk.message.content
}
浏览器版本有个限制:必须用流式模式。因为 Ollama API 的非流式请求会一次性返回大 JSON,跨域请求容易超时或被拦截。流式请求是分 chunk 的,问题少很多。
这个设计挺合理的。浏览器里做聊天 UI,本来就需要流式显示效果。
第四章:工具调用实战
工具调用是做 Agent 的基础。Ollama 支持让模型调用你定义的函数,然后根据函数返回结果继续生成回答。
Python SDK 有个很方便的特性:可以直接传 Python 函数作为工具,SDK 会自动解析函数的 docstring 和参数类型。
Python 函数自动解析
def get_weather(city: str) -> str:
"""获取指定城市的天气信息
Args:
city: 城市名称,如"北京"、"上海"
Returns:
天气描述字符串
"""
# 模拟数据
weather_data = {
'北京': '晴,温度 18°C',
'上海': '多云,温度 22°C',
'广州': '雨,温度 26°C',
}
return weather_data.get(city, f'未找到 {city} 的天气数据')
from ollama import chat
response = chat(
model='qwen3',
messages=[{'role': 'user', 'content': '北京今天天气怎么样?'}],
tools=[get_weather],
)
print(response.message.content)
SDK 自动把函数转成了工具定义格式:名字从函数名取,描述从 docstring 取,参数从类型注解取。省了自己手写 JSON Schema 的麻烦。
Agent Loop 模式
但事情没那么简单。模型可能调用多个工具,或者调用工具后还想继续调用。你需要一个循环来处理。
这就是 Agent Loop:
from ollama import chat
def add(a: int, b: int) -> int:
"""加法运算"""
return a + b
def multiply(a: int, b: int) -> int:
"""乘法运算"""
return a * b
tools = [add, multiply]
tool_map = {'add': add, 'multiply': multiply}
messages = [{'role': 'user', 'content': '计算 (3 + 5) * 2'}]
while True:
response = chat(model='qwen3', messages=messages, tools=tools)
if response.message.tool_calls:
# 模型想调用工具
for call in response.message.tool_calls:
func_name = call.function.name
func_args = call.function.arguments
result = tool_map[func_name](**func_args)
# 把工具调用结果加进消息历史
messages.append({
'role': 'tool',
'content': str(result),
'tool_name': func_name,
})
else:
# 模型没调用工具,说明结束了
print(response.message.content)
break
逻辑是这样的:
- 发消息给模型,带上工具定义
- 如果模型返回了
tool_calls,就执行对应的函数 - 把函数结果塞回消息历史,再发给模型
- 循环直到模型不再调用工具
这个模式做 Agent 时必用。你定义好一堆工具函数,模型自己决定什么时候调用、调用哪些、调用顺序。
thinking 模式
有些模型——比如 qwen3——支持 thinking 模式。模型会先”思考”,再给出回答。
from ollama import chat
stream = chat(
model='qwen3',
messages=[{'role': 'user', 'content': '为什么天空是蓝色的?'}],
stream=True,
think=True,
)
thinking = ''
content = ''
for chunk in stream:
if chunk.message.thinking:
thinking += chunk.message.thinking
elif chunk.message.content:
content += chunk.message.content
print('=== 思考过程 ===')
print(thinking)
print('=== 最终回答 ===')
print(content)
thinking 模式下,chunk 里会多一个 thinking 字段。你得分别累积思考内容和最终回答。
这个功能挺有意思的。你能看到模型是怎么一步步推导出答案的。做教育类应用或者调试 Prompt 时很有用。
第五章:原生 SDK vs OpenAI 兼容 API
现在你有两种选择:
- 用 Ollama 原生 SDK(前面讲的那些)
- 用 OpenAI SDK,改个地址就能对接 Ollama
哪种更好?看你的情况。
OpenAI 兼容方案
如果你手头有现成的 OpenAI 项目,迁移成本最低的方式就是改 base_url:
from openai import OpenAI
client = OpenAI(
base_url='http://localhost:11434/v1',
api_key='ollama', # 必填,但会被忽略
)
response = client.chat.completions.create(
model='gemma3',
messages=[{'role': 'user', 'content': '天空为什么是蓝色的?'}],
)
print(response.choices[0].message.content)
就这么简单。OpenAI SDK 完全不知道背后跑的是 Ollama,它只知道自己在跟一个 “OpenAI API” 说话。
Node.js 版本也一样:
import OpenAI from 'openai'
const client = new OpenAI({
baseURL: 'http://localhost:11434/v1',
apiKey: 'ollama',
})
const completion = await client.chat.completions.create({
model: 'gemma3',
messages: [{ role: 'user', content: '天空为什么是蓝色的?' }],
})
console.log(completion.choices[0].message.content)
两种方案对比
| 方面 | 原生 SDK | OpenAI 兼容 |
|---|---|---|
| 安装 | pip install ollama | 已有 OpenAI SDK 即可 |
| 工具调用 | 自动解析函数 docstring | 手写 JSON Schema |
| 流式响应 | 字典格式 chunk | 标准 OpenAI 格式 |
| Cloud Models | 支持 | 不支持 |
| 迁移成本 | 新项目无成本 | 现有项目成本极低 |
选择建议
新项目:用原生 SDK。
理由:
- 工具调用更方便,Python 函数直接当工具传
- 支持更多特性(Cloud Models、thinking 模式)
- 文档和示例都是官方的,遇到问题容易查
现有 OpenAI 项目迁移:用 OpenAI 兼容方案。
理由:
- 改两行代码就能跑
- 不用重写任何逻辑
- 后续想切换回 OpenAI 也简单
一句话总结:原生 SDK 功能更全,OpenAI 兼容迁移更快。看你需求。
说实话,两个方案我都试过。原生 SDK 的工具调用确实省事不少——不用自己写 JSON Schema 定义,函数 docstring 写清楚就行。但如果你的项目已经跑在 OpenAI 上,没必要为了用 Ollama 全部重构。
最后
说了这么多,总结几个要点:
基础调用:Python 和 Node.js SDK 都封装得很好,几行代码就能跑。流式响应记得用 stream=True 开启。
工具调用:Agent Loop 是核心模式——循环处理 tool_calls 直到模型不再调用。Python SDK 能直接传函数当工具,省了写 JSON Schema 的麻烦。
thinking 模式:qwen3 等模型支持,能看到模型的思考过程。chunk 里要分别处理 thinking 和 content 字段。
方案选择:新项目用原生 SDK,功能更全;现有 OpenAI 项目用兼容方案,改个地址就行。
下一步建议:
- 如果你还没把 Ollama 装起来,先看系列第一篇把本地模型跑起来
- 挑一个适合你项目的方案(原生或 OpenAI 兼容),动手试一试
- 官方文档持续更新,新功能会不断加进去,有空可以翻翻看
本地跑 LLM 这事儿,门槛越来越低了。Ollama 把复杂的东西都藏在了简单 API 背后。你只需要知道怎么调用,剩下的交给它。
这就是我们这个系列的第二篇。下一篇会讲 Modelfile 定制——怎么把模型调教成你想要的样子。
Ollama API 客户端开发
使用 Python 或 Node.js SDK 调用 Ollama 本地模型 API 的完整指南
⏱️ 预计耗时: 45 分钟
- 1
步骤1: 安装 SDK 并测试基础调用
Python 用户执行 `pip install ollama`,Node.js 用户执行 `npm i ollama`。
安装完成后,用最简单的代码测试连接:
```python
from ollama import chat
response = chat(model='gemma3', messages=[{'role': 'user', 'content': '你好'}])
print(response.message.content)
```
确保 Ollama 服务已启动(默认端口 11434),且已下载对应模型。 - 2
步骤2: 实现流式响应
开启流式模式,让用户看到逐字输出效果:
```python
from ollama import chat
stream = chat(model='gemma3', messages=[...], stream=True)
for chunk in stream:
print(chunk['message']['content'], end='', flush=True)
```
注意 chunk 返回的是字典,用 `chunk['message']['content']` 访问。 - 3
步骤3: 配置工具调用(可选)
定义 Python 函数作为工具,SDK 自动解析 docstring 和类型注解:
```python
def get_weather(city: str) -> str:
"""获取城市天气信息"""
return f'{city}: 晴'
response = chat(model='qwen3', messages=[...], tools=[get_weather])
```
实现 Agent Loop 循环处理多次工具调用,直到模型返回最终答案。 - 4
步骤4: 选择原生或 OpenAI 兼容方案
新项目推荐原生 SDK,功能更全(Cloud Models、thinking 模式)。
现有 OpenAI 项目只需改两行:
```python
client = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')
```
迁移成本极低,随时切回 OpenAI。
常见问题
Ollama API 的默认端口和地址是什么?
Python SDK 流式响应返回的是什么类型?
Node.js SDK 在浏览器环境有什么限制?
什么是 Agent Loop 模式?
thinking 模式下如何分别获取思考过程和最终回答?
原生 SDK 和 OpenAI 兼容方案如何选择?
11 分钟阅读 · 发布于: 2026年4月18日 · 修改于: 2026年4月18日

评论
使用 GitHub 账号登录后即可评论