3. Ollama API接口:RESTful API详解、API认证与安全、API调用示例
聊到Ollama的API接口,我得先说说我的真实感受。刚开始接触时,我以为就是个简单的HTTP调用,后来在生产环境踩了几个坑,才发现这里面的门道不少。今天我把这些经验掰开揉碎了讲给你听。
3.1 RESTful API 核心端点
Ollama暴露的API其实很简洁,核心就几个端点。我个人习惯把它们分成三类:模型管理、推理服务、系统监控。
| 端点 | 方法 | 功能 | 我常用的场景 |
|---|---|---|---|
/api/generate |
POST | 文本生成(非流式/流式) | 对话补全、代码生成 |
/api/chat |
POST | 多轮对话 | 聊天机器人、客服系统 |
/api/embed |
POST | 文本向量化 | RAG检索、语义搜索 |
/api/tags |
GET | 列出本地模型 | 模型管理面板 |
/api/pull |
POST | 下载模型 | 自动化部署脚本 |
/api/delete |
DELETE | 删除模型 | 清理磁盘空间 |
你想想看,最常用的其实就是 /api/generate 和 /api/chat。这两个端点支撑了90%以上的业务场景。
3.2 API认证与安全
嗯,这里要注意。Ollama默认是不开启认证的。我在项目中遇到过,有人直接把Ollama暴露在公网上,结果被挖矿程序盯上了。说白了,这就是个定时炸弹。
我建议至少做三层防护:
- 网络层: 绑定内网IP,用防火墙限制来源
- 应用层: 加一层反向代理,比如Nginx做IP白名单
- 认证层: 自己实现Token校验
我曾经帮一个客户排查问题,发现他的Ollama服务被外部IP疯狂调用,一晚上跑了200万次请求。后来我们加了个简单的API Key校验,问题就解决了。
下面是我常用的Nginx反向代理配置,带API Key校验:
# /etc/nginx/conf.d/ollama.conf
server {
listen 443 ssl;
server_name ollama.yourdomain.com;
location / {
# API Key 校验
if ($http_x_api_key != "your-secret-key-here") {
return 401;
}
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# 流式响应必须关闭缓冲
proxy_buffering off;
proxy_cache off;
}
}
envsubst 或者配置管理工具注入,安全又灵活。
3.3 API调用示例
光说不练假把式。咱们直接上代码,看看实际怎么调。
3.3.1 文本生成(非流式)
curl -X POST http://localhost:11434/api/generate \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.2",
"prompt": "用Python写一个快速排序",
"stream": false,
"options": {
"temperature": 0.7,
"top_p": 0.9
}
}'
返回结果长这样:
{
"model": "llama3.2",
"created_at": "2024-01-15T10:30:00Z",
"response": "def quick_sort(arr):\n if len(arr) <= 1:\n return arr\n pivot = arr[len(arr)//2]\n ...",
"done": true,
"total_duration": 2345678900,
"load_duration": 123456789,
"prompt_eval_count": 15,
"eval_count": 120,
"eval_duration": 2000000000
}
看到 eval_duration 了吗?这个字段很有用。我在做性能压测时,就是靠它来算每秒钟能处理多少个token。
3.3.2 流式生成(推荐)
为什么推荐流式?你想想看,用户等一个完整的回复可能要好几秒,但流式返回能让用户看到文字一个字一个字蹦出来,体验好太多了。
import requests
import json
def stream_generate(model, prompt):
url = "http://localhost:11434/api/generate"
payload = {
"model": model,
"prompt": prompt,
"stream": True
}
response = requests.post(url, json=payload, stream=True)
for line in response.iter_lines():
if line:
data = json.loads(line)
if data.get("done"):
print(f"\n\n✅ 生成完成,耗时: {data['total_duration']/1e9:.2f}s")
break
print(data.get("response", ""), end="", flush=True)
# 调用示例
stream_generate("llama3.2", "解释一下什么是分布式系统")
关键点: 流式模式下,每一行都是一个独立的JSON对象。记得用 stream=True 和 iter_lines() 逐行读取。
3.3.3 多轮对话
做聊天机器人时,得用 /api/chat 端点。它支持传入历史消息,保持上下文连贯。
curl -X POST http://localhost:11434/api/chat \
-H "Content-Type: application/json" \
-d '{
"model": "llama3.2",
"messages": [
{"role": "system", "content": "你是一个Python专家"},
{"role": "user", "content": "Python的GIL是什么?"},
{"role": "assistant", "content": "GIL是全局解释器锁..."},
{"role": "user", "content": "那怎么绕过GIL?"}
],
"stream": false
}'
这里有个坑,我曾经踩过。如果你传的消息列表太长,模型会丢失前面的上下文。我一般限制在10轮对话以内,或者用滑动窗口策略。
3.3.4 文本向量化
做RAG(检索增强生成)时,这个端点就派上用场了。
curl -X POST http://localhost:11434/api/embed \
-H "Content-Type: application/json" \
-d '{
"model": "nomic-embed-text",
"input": "今天天气真不错"
}'
返回的向量是768维的浮点数数组。我一般把它存到向量数据库里,比如ChromaDB或Milvus,方便后续做相似度检索。
3.4 错误处理与重试策略
API调用不可能永远一帆风顺。我在生产环境总结了一套重试策略:
| HTTP状态码 | 含义 | 我的处理方式 |
|---|---|---|
| 200 | 成功 | 正常处理 |
| 400 | 请求参数错误 | 检查payload,不重试 |
| 401 | 认证失败 | 检查API Key,不重试 |
| 429 | 请求过载 | 等待1秒后重试,最多3次 |
| 500 | 服务端错误 | 等待2秒后重试,最多5次 |
| 503 | 服务不可用 | 等待5秒后重试,最多3次 |
3.5 性能监控指标
每次API调用返回的元数据里,藏着很多性能信息。我习惯把这些数据采集到Prometheus里:
total_duration:总耗时,包括加载模型的时间load_duration:模型加载时间,第一次调用时特别长prompt_eval_count:输入token数eval_count:输出token数eval_duration:推理耗时
通过这些指标,我能算出 tokens_per_second,也就是每秒生成多少个token。这个指标直接决定了用户体验好不好。
这张图展示了一个完整的API调用链路。从客户端发起请求,经过反向代理校验,再到Ollama服务加载模型推理,最后返回结果。同时监控系统在背后默默采集着性能数据。
总结一下: Ollama的API设计得很简洁,但安全防护不能省。流式调用能提升用户体验,错误重试要用指数退避。把这些都做好了,你的AI服务才算真正能上生产环境。