Ollama 编程语言调用
本篇系统梳理调用 Ollama 的四条代码路线:Python 官方库、JavaScript 官方库、原生 HTTP、以及 OpenAI / Anthropic 兼容 SDK,并用两个实战项目把它们串起来。
官方 SDK:Python 与 JavaScript
官方提供两个一手维护的库,接口设计保持一致,会一个就等于会两个。
安装
# Python
pip install ollama
# JavaScript / TypeScript
npm install ollama两个库的核心方法对照:
| 方法 | 用途 | 关键参数 |
|---|---|---|
| chat | 多轮对话(主力方法) | model、messages、stream、tools、think、format、options |
| generate | 单轮文本生成 | model、prompt、stream、suffix |
| embed | 向量嵌入 | model、input(单条或数组) |
| list | 列出本地模型 | 无 |
| pull | 拉取模型(可监听进度) | model、stream |
Python 中一次带全参数的 chat 调用,覆盖前面几篇学过的大部分能力:
实例
from ollama import chat
from pydantic import BaseModel
# 定义结构化输出的 schema
class Answer(BaseModel):
site: str
free: bool
response = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': '介绍 RUNOOB 菜鸟教程'}],
stream=False, # 流式开关
think=False, # 思考模式开关
format=Answer.model_json_schema(), # 结构化输出 schema
options={'temperature': 0.3, 'num_ctx': 8192}, # 生成参数
)
print(Answer.model_validate_json(response.message.content))JavaScript 中的等价写法:
实例
import ollama from 'ollama'
// 流式对话示例
const stream = await ollama.chat({
model: 'qwen3.5',
messages: [{ role: 'user', content: '用三句话介绍 RUNOOB' }],
stream: true,
})
// 逐块输出
let content = ''
for await (const chunk of stream) {
process.stdout.write(chunk.message.content)
content += chunk.message.content
}连接非默认地址(如远程服务器或 Ollama Cloud)时,用 host 与 headers 指定:
实例
import os
from ollama import Client
# 连接远程 Ollama 或 Ollama Cloud(Bearer 认证)
client = Client(
host='https://ollama.com',
headers={'Authorization': 'Bearer ' + os.environ.get('OLLAMA_API_KEY')},
)
response = client.chat(model='qwen3.5', messages=[
{'role': 'user', 'content': '用一句话介绍 RUNOOB'}
])原生 HTTP:curl 速查
写脚本、调试接口、排查问题时,curl 是最快的工具。
| 场景 | 命令 |
|---|---|
| 单轮生成(非流式) | curl http://localhost:11434/api/generate -d '{"model":"qwen3.5","prompt":"你好","stream":false}' |
| 对话 | curl http://localhost:11434/api/chat -d '{"model":"qwen3.5","messages":[...],"stream":false}' |
| 向量嵌入 | curl http://localhost:11434/api/embed -d '{"model":"embeddinggemma","input":"文本"}' |
| 列出模型 | curl http://localhost:11434/api/tags |
| 模型详情 | curl http://localhost:11434/api/show -d '{"model":"qwen3.5"}' |
| 拉取模型 | curl http://localhost:11434/api/pull -d '{"model":"qwen3.5:4b"}' |
| 删除模型 | curl -X DELETE http://localhost:11434/api/delete -d '{"model":"qwen3.5:4b"}' |
复用 OpenAI / Anthropic SDK
已有项目迁移时,兼容层比重写省事得多。
JavaScript 项目里用 OpenAI SDK 接入本地模型:
实例
import OpenAI from "openai"
// 只改 base_url,api_key 随意填写
const openai = new OpenAI({
baseURL: "http://localhost:11434/v1",
apiKey: "ollama",
})
const res = await openai.chat.completions.create({
model: "qwen3.5",
messages: [{ role: "user", content: "用一句话介绍 RUNOOB" }],
})
console.log(res.choices[0].message.content)Python 项目里用 Anthropic SDK 同理:
实例
import anthropic
# base_url 指向本地,key 随意填写
client = anthropic.Anthropic(
base_url='http://localhost:11434',
api_key='ollama',
)
message = client.messages.create(
model='qwen3.5',
max_tokens=1024,
messages=[{'role': 'user', 'content': '用一句话介绍 RUNOOB'}],
)
print(message.content[0].text)选择建议:新项目直接用官方 SDK(能力最全);存量项目按现有 SDK 走兼容层(改动最小);被某个只认 OpenAI 协议的框架集成时,兼容层是唯一通路。
实战一:命令行聊天脚本
用不到 40 行 Python,把前面学的 chat、流式、历史管理拼成一个可用的终端聊天工具。
实例
# 文件路径:cli_chat.py
# 运行:python cli_chat.py
from ollama import chat
MODEL = 'qwen3.5:4b'
# 会话历史:system 定角色,后续追加对话
messages = [{
'role': 'system',
'content': '你是 RUNOOB 的编程助手,回答简洁并给出示例代码。',
}]
print(f'开始对话(模型 {MODEL}),输入 exit 退出。')
while True:
user_input = input('\n你:').strip()
if user_input.lower() == 'exit':
break
if not user_input:
continue
# 追加用户消息并发起流式请求
messages.append({'role': 'user', 'content': user_input})
stream = chat(model=MODEL, messages=messages, stream=True)
# 逐块打印,同时累积完整回答
print('助手:', end='', flush=True)
reply = ''
for chunk in stream:
reply += chunk.message.content
print(chunk.message.content, end='', flush=True)
# 关键:把本轮回答追加回历史,模型才能"记住"上文
messages.append({'role': 'assistant', 'content': reply})$ python cli_chat.py
开始对话(模型 qwen3.5:4b),输入 exit 退出。
你:什么是 Python 的切片?
助手:切片是用 [start:stop:step] 从序列中取子序列的语法,
例如 s[1:3] 取索引 1 到 2 的元素。
你:给个 RUNOOB 风格的例子
助手:s = "RUNOOB"
print(s[1:4]) # 输出 UNO
你:exit核心只有一处:每轮把 user 消息和 assistant 完整回答都 append 进 messages。模型本身无状态,"记忆"完全来自这个列表。
实战二:带记忆的多轮对话 Web 应用
把同样的思路搬上浏览器,需要一个后端居中协调:管理会话历史、调用 Ollama、把流式结果转发给前端。
后端:Flask 封装 Ollama 流式接口
实例
# 文件路径:server.py
# 安装依赖:pip install flask ollama
from flask import Flask, request, Response, stream_with_context
from ollama import chat
app = Flask(__name__)
# 会话历史暂存内存:真实项目应换成数据库
sessions = {}
@app.route('/chat')
def do_chat():
session_id = request.args.get('session', 'default')
user_input = request.args.get('q', '')
if not user_input:
return {'error': '缺少 q 参数'}
# 取出(或初始化)该会话的历史
history = sessions.setdefault(session_id, [
{'role': 'system', 'content': '你是 RUNOOB 的编程助手。'}
])
history.append({'role': 'user', 'content': user_input})
# 流式生成,NDJSON 格式逐行转发给前端
def generate():
reply = ''
stream = chat(model='qwen3.5:4b', messages=history, stream=True)
for chunk in stream:
reply += chunk.message.content
yield chunk.message.content + '\n'
# 关键:把完整回答写回历史,形成记忆
history.append({'role': 'assistant', 'content': reply})
return Response(
stream_with_context(generate()),
mimetype='application/x-ndjson',
)
if __name__ == '__main__':
app.run(port=5000)前端:fetch 流式读取
实例
// 浏览器端:逐行读取 NDJSON 并实时渲染
async function ask(question) {
const resp = await fetch(
`/chat?session=demo&q=${encodeURIComponent(question)}`
)
const reader = resp.body.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
// 每读到一块就追加到页面,实现打字机效果
document.getElementById('answer').textContent +=
decoder.decode(value)
}
}运行与验证
实例
# 启动后端
python server.py
# 模拟两次连续请求,验证记忆
curl "http://localhost:5000/chat?session=demo&q=什么是Python切片"
curl "http://localhost:5000/chat?session=demo&q=再给个RUNOOB风格的例子"第二次请求中模型能顺着"切片"话题继续作答,说明服务端管理的会话历史生效了;换一个 session 参数则是一个全新会话,互不干扰。
这个几十行的骨架已经覆盖了类 ChatGPT 应用的三大要素:会话隔离(session 参数)、流式体验(NDJSON 转发)、记忆持久(历史写回)。加上数据库存储和多会话列表,就是完整实战项目的雏形,Web 应用实战章节会继续扩展它。
AI 思考中...