Ollama: Python SDK集成
Python SDK 是打开本地 AI 大门的钥匙——三行代码,从脚本到应用无缝衔接。
💡 提示:Python SDK(
ollama 库)本质上是对Ollama REST API的封装——chat() 方法封装了 /api/chat 端点,generate() 封装了 /api/generate,list() 封装了 /api/tags。理解这层关系有助于排查问题:当SDK报错时,可以用curl直接调API确认是SDK问题还是Ollama服务问题。
📋 前置知识:需要先掌握以下内容
- 第5课:REST API入门
1. 你将学到
- ollama Python 库安装与同步/异步 API
- / / 用法
- 异步流式响应实现实时输出
- Python 类型注解与错误处理
- Alice 的 SupportBot V1 Python 封装
2. 一个 SaaS 创业者的真实故事
⚠️ 警告: Python SDK 直接调用 Ollama API 时,Ollama 无内置认证。如果你的 Ollama 绑定了
0.0.0.0,SDK 连接信息(如 http://your-server:11434)可能被他人利用。生产环境务必添加认证层。
(1) 痛点:Shell 脚本不够用
Alice 用 curl 搭建了 SupportBot 原型,但 Shell 脚本难以维护对话状态、处理错误、集成到 Web 服务。她需要一个正式的编程语言来构建生产级应用。
(2) 解法:Python SDK 三行集成
PYTHON
import ollama
response = ollama.chat(model='qwen2.5', messages=[
{'role': 'user', 'content': 'Hello'}
])
print(response['message']['content'])
3. 安装与 API 概览
ℹ️ 信息:
ollama Python SDK 默认连接 http://localhost:11434,无需额外配置。若 Ollama 运行在其他地址,可通过设置环境变量 OLLAMA_HOST 或在代码中指定 Client(host='http://...') 来覆盖。
💡 提示: Python SDK 的
chat() 方法比 generate() 更推荐——chat 支持多轮对话(messages 数组),generate 仅支持单轮。即使是单次提问,chat 的角色区分(system/user/assistant)也能获得更好的输出质量。
(1) 安装与连接验证
BASH
# Install the ollama Python package
pip install ollama
# Verify connection to Ollama server
python3 -c "import ollama; print(ollama.list())"
(2) 同步 vs 异步 API 对比
⚠️ 注意:使用异步API(
AsyncClient)时,所有调用必须加 await 关键字,如 await client.chat(...)。忘记 await 会导致返回协程对象而非实际结果,程序不会报错但得不到正确输出。在FastAPI等异步框架中必须用异步API,否则会阻塞事件循环影响并发性能。
| 维度 | 同步 API | 异步 API |
|---|---|---|
| 模块 | (AsyncClient) | |
| 调用方式 | ||
| 阻塞 | 阻塞当前线程 | 非阻塞,可并发 |
| 适用场景 | 脚本、简单工具 | Web 服务、并发处理 |
| 流式支持 |
▶ 示例 1: 同步与异步基本调用
PYTHON
import ollama
import asyncio
# Synchronous call
def sync_chat():
response = ollama.chat(
model='qwen2.5',
messages=[{'role': 'user', 'content': 'Hello!'}]
)
print(response['message']['content'])
# Asynchronous call
async def async_chat():
client = ollama.AsyncClient()
response = await client.chat(
model='qwen2.5',
messages=[{'role': 'user', 'content': 'Hello!'}]
)
print(response['message']['content'])
sync_chat()
asyncio.run(async_chat())
输出:
TEXT
📖 仅展示
# 函数定义成功
4. 核心方法详解
(1) chat() 方法
| 参数 | 类型 | 说明 |
|---|---|---|
| str | 模型名称 | |
| list[dict] | 消息列表,每条含 role/content | |
| bool | 是否流式输出 | |
| str | 输出格式: | |
| dict | 推理参数(temperature 等) | |
| str | 模型驻留时间 |
(2) generate() 方法
| 参数 | 类型 | 说明 |
|---|---|---|
| str | 模型名称 | |
| str | 提示文本 | |
| str | System Prompt | |
| bool | 是否流式 | |
| dict | 推理参数 |
▶ 示例 2: chat 与 generate 对比
PYTHON
import ollama
# chat(): multi-turn with message history
response = ollama.chat(
model='qwen2.5',
messages=[
{'role': 'system', 'content': 'You are a SQL expert.'},
{'role': 'user', 'content': 'Write a query for top 5 customers'}
],
stream=False,
options={'temperature': 0.3}
)
print('chat:', response['message']['content'])
# generate(): single-shot text generation
response = ollama.generate(
model='qwen2.5',
prompt='Write a haiku about debugging',
system='You are a poet.',
stream=False
)
print('generate:', response['response'])
输出:
TEXT
📖 仅展示
chat:
generate:
5. 流式响应实现
(1) 流式输出原理
sequenceDiagram
participant P as Python App
participant O as Ollama Server
P->>O: chat(stream=True)
loop Each token chunk
O-->>P: chunk {"content": "word"}
P->>P: print(word, end="")
end
O-->>P: chunk {"done": true}
▶ 示例 3: 同步流式输出
PYTHON
import ollama
# Stream chat response in real-time
stream = ollama.chat(
model='qwen2.5',
messages=[{'role': 'user', 'content': 'Explain RAG in 3 sentences'}],
stream=True
)
for chunk in stream:
content = chunk['message']['content']
print(content, end='', flush=True)
print() # newline at end
输出:
TEXT
📖 仅展示
# 执行成功
▶ 示例 4: 异步流式输出
PYTHON
import ollama
import asyncio
async def stream_chat():
client = ollama.AsyncClient()
stream = await client.chat(
model='qwen2.5',
messages=[{'role': 'user', 'content': 'Tell me about Ollama'}],
stream=True
)
async for chunk in stream:
content = chunk['message']['content']
print(content, end='', flush=True)
print()
asyncio.run(stream_chat())
输出:
TEXT
📖 仅展示
# 函数定义成功
6. 错误处理与类型注解
(1) 常见错误类型
| 错误 | 触发条件 | 处理方式 |
|---|---|---|
| Ollama 服务未运行 | 启动服务或重试 | |
| 模型不存在/参数错误 | 检查模型名和参数 | |
| 推理超时 | 减小 num_ctx 或增大超时 | |
| format=json 输出异常 | 加 JSON 校验和重试 |
▶ 示例 5: 完善的错误处理
PYTHON
import ollama
import json
from typing import Optional
def safe_chat(
model: str,
messages: list[dict],
temperature: float = 0.3,
max_retries: int = 3
) -> Optional[str]:
"""Chat with error handling and retries."""
for attempt in range(max_retries):
try:
response = ollama.chat(
model=model,
messages=messages,
stream=False,
options={'temperature': temperature}
)
return response['message']['content']
except ConnectionError:
print(f"Connection failed (attempt {attempt + 1})")
if attempt == max_retries - 1:
return None
except ollama.ResponseError as e:
print(f"API error: {e.error}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
if attempt == max_retries - 1:
return None
return None
# Usage
result = safe_chat('qwen2.5', [
{'role': 'user', 'content': 'What is your return policy?'}
])
if result:
print(result)
else:
print("Failed to get response")
输出:
TEXT
📖 仅展示
Failed to get response
7. 综合示例:SupportBot V1 Python 封装
PYTHON
# ============================================
# Comprehensive: SupportBot V1
# Python wrapper for e-commerce customer service
# ============================================
import ollama
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class SupportBot:
model: str = "qwen2.5"
temperature: float = 0.4
max_history: int = 10
system_prompt: str = (
"You are SupportBot, an e-commerce customer service agent. "
"Be polite, concise, and helpful. "
"If unsure, say 'Let me connect you with a human agent.'"
)
messages: list[dict] = field(default_factory=list)
def __post_init__(self):
self.messages = [
{"role": "system", "content": self.system_prompt}
]
def chat(self, user_input: str) -> str:
self.messages.append({"role": "user", "content": user_input})
try:
response = ollama.chat(
model=self.model,
messages=self.messages[-self.max_history:],
stream=False,
options={"temperature": self.temperature}
)
assistant_msg = response["message"]["content"]
self.messages.append({"role": "assistant", "content": assistant_msg})
return assistant_msg
except Exception as e:
self.messages.pop() # Remove failed user message
return f"Error: {str(e)}"
def stream_chat(self, user_input: str):
self.messages.append({"role": "user", "content": user_input})
full_response = []
try:
stream = ollama.chat(
model=self.model,
messages=self.messages[-self.max_history:],
stream=True,
options={"temperature": self.temperature}
)
for chunk in stream:
content = chunk["message"]["content"]
full_response.append(content)
print(content, end="", flush=True)
print()
self.messages.append({"role": "assistant", "content": "".join(full_response)})
except Exception as e:
print(f"\nError: {e}")
def reset(self):
self.messages = [{"role": "system", "content": self.system_prompt}]
# Usage
if __name__ == "__main__":
bot = SupportBot(model="qwen2.5", temperature=0.4)
print("=== SupportBot V1 ===")
print(bot.chat("Where is my order #12345?"))
print()
print(bot.chat("It has been 7 days since I ordered."))
print()
print(bot.chat("Can I get a refund instead?"))
💻 输出:
TEXT
📖 仅展示
=== SupportBot V1 ===
I'd be happy to check on your order #12345. Based on our records, your order is currently in transit and expected to arrive within 2-3 business days. You can track it at our website.
I understand your concern. If you'd prefer a refund instead of waiting, I can initiate that for you. Our refund policy covers orders that haven't been delivered within the estimated timeframe.
Yes, I can process a full refund for order #12345. The refund will be credited to your original payment method within 3-5 business days. Would you like me to proceed?
❓ 常见问题
Q pip install ollama 报错怎么办?
A 确保 Python >= 3.8 且 pip 已更新:。网络问题可用镜像:。
Q 同步和异步 API 怎么选?
A 脚本和简单工具用同步(更简单)。Web 服务(FastAPI/Django)用异步(不阻塞事件循环)。单用户场景两者差异不大。
Q 流式输出在 Jupyter Notebook 中不显示怎么办?
A Jupyter 对 支持有限。用 配合循环更新,或改用非流式模式。
Q 如何指定 Ollama 服务地址?
A 默认连接 localhost:11434。可通过环境变量 修改,或在代码中实例化 。
Q messages 列表太长会怎样?
A 超出模型上下文窗口(num_ctx)会被截断。建议实现滑动窗口,只保留最近 N 轮对话,或对早期对话做摘要压缩。
Q 如何获取推理速度等统计信息?
A 非流式响应中包含 、、 等字段。流式响应的最后一个 chunk 包含这些统计。
📖 小节
- 一行安装,同步异步两套 API 可选
- 适合多轮对话, 适合单轮生成
- 流式输出通过 + 迭代 chunk 实现,实时显示
- 异步流式用 遍历,适合 Web 服务并发场景
- 错误处理需覆盖 ConnectionError、ResponseError、TimeoutError
- SupportBot V1 用 dataclass 封装对话历史和推理参数
📝 作业
- 基础题(难度⭐):用 Python SDK 实现 和 各一次,对比输出差异。
- 进阶题(难度⭐⭐):实现一个流式聊天函数,带滑动窗口(保留最近 5 轮对话),并在对话超过 5 轮时自动丢弃最早消息。
- 挑战题(难度⭐⭐⭐):构建一个带错误重试、超时控制、JSON 格式输出的 SupportBot V1+,能将客服对话保存到文件并统计每次推理耗时。