Gemma-3-270m实战教程:Ollama + FastAPI封装为标准RESTful接口
本文介绍了如何在星图GPU平台上自动化部署Gemma-3-270m镜像,并利用Ollama与FastAPI将其封装为标准RESTful API接口。通过该服务,开发者可以轻松将模型能力集成到各类应用中,例如快速构建智能客服机器人或自动生成周报等文本生成工具,极大提升了开发效率。
Gemma-3-270m实战教程:Ollama + FastAPI封装为标准RESTful接口
你是不是已经体验过在Ollama的Web界面里和Gemma-3-270m模型聊天了?直接在页面上提问,确实很方便。但如果你想在自己的程序里调用它,比如做一个智能客服机器人、一个自动生成周报的工具,或者集成到你的App里,每次都打开网页复制粘贴,是不是太麻烦了?
这时候,我们就需要一个标准的、程序能直接调用的接口。今天,我就带你一步步把Ollama上的Gemma-3-270m模型,用FastAPI封装成一个标准的RESTful API。这样一来,任何支持HTTP请求的程序,无论是Python脚本、Java后端,还是手机App,都能轻松调用这个强大的文本生成模型了。
学完这篇教程,你将掌握:
- 如何快速搭建一个基于FastAPI的Web服务框架。
- 如何通过代码调用Ollama的API,与Gemma-3-270m模型对话。
- 如何设计一个清晰、易用的RESTful接口,并处理各种请求。
- 如何启动服务,并通过工具(如curl或Postman)测试你的接口。
整个过程就像搭积木,我们一块块来,保证你能跟上。让我们开始吧!
1. 环境准备与项目搭建
在开始写代码之前,我们需要确保电脑上已经装好了必要的工具,并创建一个干净的项目目录。
1.1 前置条件检查
首先,确认你的系统已经满足以下条件:
- Python 3.8+:这是运行FastAPI的基础。打开终端(或命令提示符),输入
python --version或python3 --version查看。 - Ollama已安装且运行:确保你已经按照之前的指引,在本地成功安装并运行了Ollama,并且已经拉取了
gemma3:270m模型。你可以在终端输入ollama list来确认模型是否存在。 - 网络通畅:确保你的开发机能访问到Ollama服务(默认在
http://localhost:11434)。
1.2 创建项目与虚拟环境
一个好的习惯是为每个项目创建独立的Python环境,避免包版本冲突。
-
打开终端,创建一个新的项目文件夹并进入:
mkdir gemma-fastapi-service cd gemma-fastapi-service -
创建Python虚拟环境:
# 对于 macOS/Linux python3 -m venv venv # 对于 Windows python -m venv venv -
激活虚拟环境:
# 对于 macOS/Linux source venv/bin/activate # 对于 Windows (CMD) venv\Scripts\activate # 对于 Windows (PowerShell) venv\Scripts\Activate.ps1激活后,你的命令行提示符前通常会显示
(venv),表示你正在虚拟环境中工作。
1.3 安装依赖包
我们只需要两个核心的Python包:fastapi 用于创建Web服务,uvicorn 是一个轻量级的ASGI服务器,用于运行FastAPI应用。requests 库用于在FastAPI服务内部调用Ollama的API。
在激活的虚拟环境中,运行以下命令安装:
pip install fastapi uvicorn requests
安装完成后,可以用 pip list 快速查看一下。
2. 核心代码编写:连接Ollama与FastAPI
现在,我们来编写最核心的部分。我们将创建两个文件:一个主应用文件,一个定义数据模型的辅助文件。
2.1 定义请求与响应模型 (models.py)
为了让我们的API接口清晰、规范,并且有自动化的数据验证,我们先定义客户端请求和我们返回响应时应该遵循的“格式”。在项目根目录下创建一个 models.py 文件。
# models.py
from pydantic import BaseModel
from typing import Optional, List
# 客户端发送给我们的请求格式
class ChatRequest(BaseModel):
prompt: str # 用户输入的提示词,比如“你好,请介绍一下你自己”
model: str = "gemma3:270m" # 指定使用的模型,默认就是我们今天的主角
stream: bool = False # 是否使用流式响应(一个字一个字输出),默认关闭
# 以下是一些可选的模型参数,用于调整生成效果
temperature: Optional[float] = 0.7 # 温度,控制随机性。越高越有创意,越低越稳定。
max_tokens: Optional[int] = 512 # 生成的最大令牌数,控制回答长度。
# 我们返回给客户端的响应格式
class ChatResponse(BaseModel):
success: bool # 请求是否成功处理
message: str # 主要的响应消息(模型生成的文本)
model_used: str # 实际使用的模型名称
prompt_tokens: Optional[int] = None # 消耗的提示词令牌数(如果Ollama返回了)
response_tokens: Optional[int] = None # 生成的响应令牌数(如果Ollama返回了)
error: Optional[str] = None # 如果出错,这里会包含错误信息
代码解释:
- 我们使用了
pydantic的BaseModel(FastAPI自带),它能让数据验证和文档生成变得非常简单。 ChatRequest定义了客户端调用我们的API时需要传递哪些信息。Optional表示这个字段是可选的,我们有提供默认值。ChatResponse定义了我们的API会返回什么信息给客户端,结构一目了然。
2.2 编写FastAPI主应用 (main.py)
接下来,创建主文件 main.py。这里是所有逻辑发生的地方。
# main.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import requests
import logging
from models import ChatRequest, ChatResponse
# 1. 创建FastAPI应用实例
app = FastAPI(
title="Gemma-3-270m API Service",
description="一个基于Ollama和FastAPI封装的Gemma-3-270m模型RESTful API服务",
version="1.0.0"
)
# 2. 添加CORS中间件(非常重要!)
# 这允许其他域的前端网页(比如你的Vue/React应用)能够调用这个API
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 在生产环境中,应该替换为具体的域名,如 ["https://your-frontend.com"]
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 3. 配置日志,方便我们查看运行情况和调试
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 4. Ollama服务的地址(默认本地11434端口)
OLLAMA_BASE_URL = "http://localhost:11434"
# 5. 健康检查端点 - 用来测试服务是否正常启动
@app.get("/")
async def root():
return {"message": "Gemma-3-270m API Service is running!"}
# 6. 核心的聊天/completions端点
@app.post("/v1/chat/completions", response_model=ChatResponse)
async def chat_completions(request: ChatRequest):
"""
处理聊天/文本生成请求。
接收用户的提示词(prompt),调用Ollama的Gemma模型,返回生成的文本。
"""
logger.info(f"收到请求: model={request.model}, prompt长度={len(request.prompt)}")
# 准备发送给Ollama API的请求体
ollama_payload = {
"model": request.model,
"prompt": request.prompt,
"stream": request.stream,
"options": { # 将可选参数放入options中,这是Ollama API要求的格式
"temperature": request.temperature,
"num_predict": request.max_tokens
}
}
try:
# 向Ollama的生成接口发起POST请求
ollama_url = f"{OLLAMA_BASE_URL}/api/generate"
response = requests.post(ollama_url, json=ollama_payload, timeout=60) # 设置60秒超时
response.raise_for_status() # 如果HTTP状态码不是200,会抛出异常
# 解析Ollama返回的JSON数据
ollama_result = response.json()
# 构建我们自己的标准响应
api_response = ChatResponse(
success=True,
message=ollama_result.get("response", "").strip(), # 提取模型生成的文本
model_used=ollama_result.get("model", request.model),
prompt_tokens=ollama_result.get("prompt_eval_count"),
response_tokens=ollama_result.get("eval_count")
)
logger.info(f"请求成功处理,生成令牌数: {api_response.response_tokens}")
return api_response
except requests.exceptions.Timeout:
error_msg = "请求Ollama服务超时,模型可能正在加载或提示词过长。"
logger.error(error_msg)
raise HTTPException(status_code=504, detail=error_msg)
except requests.exceptions.ConnectionError:
error_msg = f"无法连接到Ollama服务,请确保Ollama正在运行于 {OLLAMA_BASE_URL}。"
logger.error(error_msg)
raise HTTPException(status_code=503, detail=error_msg)
except requests.exceptions.RequestException as e:
error_msg = f"调用Ollama API时发生错误: {str(e)}"
logger.error(error_msg)
raise HTTPException(status_code=500, detail=error_msg)
except Exception as e:
error_msg = f"服务器内部错误: {str(e)}"
logger.error(error_msg)
raise HTTPException(status_code=500, detail=error_msg)
# 7. 一个简单的模型列表查询端点(可选)
@app.get("/v1/models")
async def list_models():
"""返回当前Ollama中可用的模型列表。"""
try:
response = requests.get(f"{OLLAMA_BASE_URL}/api/tags")
response.raise_for_status()
models_data = response.json()
# 简化返回格式,只提取模型名
model_list = [model_info.get("name") for model_info in models_data.get("models", [])]
return {"models": model_list}
except requests.exceptions.RequestException:
# 如果无法获取,至少返回我们默认支持的模型
return {"models": ["gemma3:270m"]}
代码关键点解析:
- CORS中间件:这是让浏览器中运行的前端应用能调用本地API的关键,务必添加。
- 端点设计:我们创建了两个端点。
/用于健康检查,/v1/chat/completions是核心的文本生成接口。路径设计模仿了OpenAI的风格,方便后续适配。 - 错误处理:我们使用
try...except块捕获了网络超时、连接错误、Ollama API错误等常见异常,并返回友好的HTTP状态码和错误信息,这对于API的健壮性至关重要。 - 日志记录:使用
logging模块记录关键信息,当出现问题时能快速定位。
3. 启动与测试你的API服务
代码写好了,让我们把它跑起来,并验证它是否工作。
3.1 启动FastAPI服务
在终端(确保还在项目目录且虚拟环境已激活),运行以下命令:
uvicorn main:app --reload --host 0.0.0.0 --port 8000
main:app:main是文件名(不含.py),app是我们在main.py中创建的FastAPI实例变量。--reload:开启热重载。当你修改代码后,服务会自动重启。生产环境不要使用此参数。--host 0.0.0.0:让服务监听所有网络接口,这样同一局域网内的其他设备也能访问。--port 8000:指定服务运行在8000端口。
看到类似下面的输出,说明服务启动成功:
INFO: Will watch for changes in these directories: ['/path/to/your/project']
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
3.2 测试API接口
服务跑起来了,我们怎么知道它好不好用呢?有几种方法:
方法一:使用自动生成的交互式文档(推荐!) FastAPI的一个超棒特性是自动生成API文档。打开你的浏览器,访问:
- Swagger UI 文档:
http://localhost:8000/docs - ReDoc 文档:
http://localhost:8000/redoc
在 http://localhost:8000/docs 页面,你可以看到我们定义的两个端点。点击 /v1/chat/completions 右边的 “Try it out” 按钮,在 Request body 里填入JSON数据,然后点击 “Execute” 就能直接测试!这是最直观的测试方式。
方法二:使用curl命令(终端测试) 打开另一个终端窗口,执行以下命令:
curl -X POST "http://localhost:8000/v1/chat/completions" \
-H "Content-Type: application/json" \
-d '{
"prompt": "用简单的语言解释一下什么是人工智能?",
"model": "gemma3:270m",
"temperature": 0.8
}'
你应该会收到一个格式工整的JSON响应,其中 message 字段就是Gemma模型生成的回答。
方法三:使用Postman或Insomnia(图形化工具) 对于更复杂的测试,可以使用这些专业的API测试工具。创建一个POST请求到 http://localhost:8000/v1/chat/completions,在Body中选择 raw 和 JSON,然后输入和上面curl例子一样的JSON数据即可发送。
3.3 一个完整的客户端调用示例
假设你有一个Python脚本想要调用我们刚建好的API,代码可以这样写:
# client_example.py
import requests
import json
api_url = "http://localhost:8000/v1/chat/completions"
payload = {
"prompt": "为一家新开的咖啡店写一句吸引人的广告语。",
"model": "gemma3:270m",
"temperature": 0.9,
"max_tokens": 100
}
headers = {
"Content-Type": "application/json"
}
try:
response = requests.post(api_url, json=payload, headers=headers)
response.raise_for_status() # 检查请求是否成功
result = response.json()
if result.get("success"):
print("生成的广告语:")
print(result.get("message"))
else:
print(f"请求失败:{result.get('error')}")
except requests.exceptions.RequestException as e:
print(f"调用API时发生错误: {e}")
保存为 client_example.py,在终端运行 python client_example.py,看看效果吧!
4. 进阶:让服务更健壮、更实用
基础功能已经实现了,但一个准备投入使用的服务还需要考虑更多。这里给你几个进阶方向:
4.1 添加请求速率限制
防止恶意用户短时间内发送大量请求拖垮你的服务。可以使用 slowapi 或 fastapi-limiter 等库。
pip install slowapi
然后在 main.py 中添加相应的限流中间件。
4.2 添加身份验证(API Key)
为你的接口增加一层安全保护,只有提供有效API Key的请求才能被处理。FastAPI内置了强大的安全工具。
from fastapi import Depends, HTTPException, status
from fastapi.security import APIKeyHeader
API_KEY_NAME = "X-API-Key"
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
# 假设你将有效的API Key存储在环境变量或数据库中
VALID_API_KEY = "your-secret-api-key-here"
async def verify_api_key(api_key: str = Depends(api_key_header)):
if api_key != VALID_API_KEY:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="无效或缺失的API Key"
)
return api_key
# 在端点函数上添加依赖
@app.post("/v1/chat/completions", response_model=ChatResponse, dependencies=[Depends(verify_api_key)])
async def chat_completions(request: ChatRequest):
# ... 原有代码不变
4.3 支持流式响应 (Streaming)
如果你希望实现像ChatGPT那样一个字一个字输出的效果,需要支持Server-Sent Events (SSE)。这需要对 main.py 中的 /v1/chat/completions 端点进行较大改造,使其能够处理 stream: true 的请求,并将Ollama返回的流式数据实时转发给客户端。这涉及到 StreamingResponse 的使用,稍微复杂一些,但能极大提升用户体验。
4.4 使用环境变量管理配置
将Ollama服务地址、API Key、端口号等敏感或易变的信息放在环境变量中,而不是硬编码在代码里。
# 在启动服务前设置环境变量(Linux/macOS)
export OLLAMA_BASE_URL="http://localhost:11434"
export API_PORT=8000
然后在代码中使用 os.getenv(“OLLAMA_BASE_URL”) 来读取。
5. 总结
恭喜你!走到这一步,你已经成功地将一个本地运行的Gemma-3-270m模型,封装成了一个具备生产环境雏形的RESTful API服务。我们来回顾一下今天的成果:
- 搭建了基础框架:我们使用FastAPI快速搭建了一个Web服务,并定义了清晰的数据模型 (
ChatRequest,ChatResponse)。 - 实现了核心逻辑:编写了
/v1/chat/completions端点,它作为“中间人”,接收客户端的请求,转发给Ollama,再将处理好的结果返回给客户端。我们加入了完善的错误处理和日志记录。 - 提供了交互文档:得益于FastAPI,我们几乎零成本获得了一个强大的交互式API文档 (
/docs),这对于前后端联调和测试非常方便。 - 探索了进阶可能:我们讨论了如何通过速率限制、API Key认证、流式响应等功能来增强服务的安全性、稳定性和用户体验。
现在,这个API已经可以作为一个独立的服务运行了。你可以:
- 将它部署到服务器上,供你的团队内部使用。
- 用它作为后端,快速开发一个聊天机器人Web界面或移动应用。
- 将它集成到自动化工作流中,比如自动生成邮件、总结文档等。
这个项目是一个坚实的起点。你可以根据实际需求,继续为它添加更多功能,比如对话历史管理、多模型切换、性能监控等。希望这篇教程能帮你打开思路,将强大的大模型能力更灵活、更便捷地应用到你的各种项目中去。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐
所有评论(0)