FastAPI是基于Starlette和Pydantic构建。pydantic能利用Python的类型提示(Type Hints)实现自动的数据校验和转换,极大减少了繁琐的参数验证代码。 能根据代码自动生成API文档,方便开发者直接在页面上调试。 同时充分利用了async/await等现代python特性。
一、 环境准备
FastAPI[all]包含了FastAPI本身以及运行它需要的ASGI服务器uvicorn
pip install `fastapi[all]`
uvicorn 是一个高性能的 ASGI (Asynchronous Server Gateway Interface) 服务器,用于在生产环境中运行 FastAPI 应用。ASGI 是现代 Python Web 框架用于与 Web 服务器通信的标准接口
二、 Ner任务部署
# code/C14/NerPredictor/main.py
import logging
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from predict import NerPredictor
# --- 全局配置 ---
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
MODEL_DIR = "./checkpoints"
# --- 数据模型定义 ---
class NerRequest(BaseModel):
text: str
# --- FastAPI 应用初始化 ---
app = FastAPI(
title="命名实体识别 API",
description="部署 NER 模型",
version="1.0.0"
)
# --- 模型加载 ---
@app.on_event("startup")
async def startup_event():
logger.info(f"开始加载模型,来源: {MODEL_DIR}")
app.state.predictor = NerPredictor(model_dir=MODEL_DIR)
logger.info("模型加载成功!")
# --- API 路由定义 ---
@app.post("/predict/ner")
async def predict_ner(request: NerRequest):
"""
接收文本,返回命名实体识别结果。
"""
try:
text = request.text.strip()
if not text:
raise HTTPException(status_code=400, detail="输入文本不能为空")
logger.info(f"接收到NER请求: '{text}'")
predictor = app.state.predictor
entities = predictor.predict(text)
logger.info(f"识别出实体: {entities}")
return {
"code": 0,
"message": "成功",
"data": {
"text": text,
"entities": entities
}
}
except Exception as e:
logger.error(f"NER预测时发生错误: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"服务器内部错误: {e}")
@app.get("/health")
async def health_check():
return {"status": "ok"}
@app.get("/")
async def root():
return {"message": "欢迎使用命名实体识别 (NER) API"}
其中:
- 请求参数使用的Pydantic的BaseModel -> NerRequest
- 模型加载: 在app.on_event('startup')时候启动, 初始化时会将NerPredictor实例存储在app.state对象里。这种方式模型只会在启动时创建一次。
@app.on_event("startup") 启动前置方法; app.on_event("shutdown") 服务结束后置方法
- 实体识别api使用的是post方法, 参数是NerRequest.。异常通过HttpException抛出
- 服务健康状态 @app.get("/health")
- 根服务 @app.get("/health")
- /docs 是FastAPI自动生成的交互式API文档
三、启动与测试
启动,使用的uvicorn
uvicorn main:app --reload
测试,使用curl 测试
curl -X POST "http://127.0.0.1:8000/predict/ner" -H "Content-Type: application/json" -d "{\"text\":\"患者自述发热、咳嗽,伴有轻微头痛。\"}"
JSON响应:
{
"code": 0,
"message": "成功",
"data": {
"text": "患者自述发热、咳嗽,伴有轻微头痛。",
"entities": [
{
"text": "发热",
"type": "sym",
"start": 4,
"end": 6
},
{
"text": "咳嗽",
"type": "sym",
"start": 7,
"end": 9
},
{
"text": "头",
"type": "bod",
"start": 14,
"end": 15
}
]
}
}
四、生产服务
开发时使用的是uvicorn main:app --reload来启动服务。默认只允许本地访问。如果希望云服务器上测试,比如制定--host 0.0.0.0,这种方式不够健壮。
Gunicorn 是一个成熟的 Python HTTP 服务器和进程管理器,通过 -k uvicorn.workers.UvicornWorker 可以以多进程方式托管 FastAPI 这样的 ASGI 应用。Uvicorn 负责异步处理请求,Gunicorn 负责监听端口、管理 worker 进程和日志,这是常见且稳定的生产部署组合。
gunicorn -w 3 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000
- -w 3: 启动 3 个工作进程(worker)。Gunicorn 官方文档推荐的通用设置是 2 * CPU核心数 + 1。但对于我们所使用的 UvicornWorker 这种异步工作进程,由于其高效的并发处理能力,通常设置为 CPU核心数 + 1 就足够了。我们的服务器是 2 核 CPU,所以设置为 3。
- -k uvicorn.workers.UvicornWorker: 指定 Gunicorn 使用 Uvicorn 的工作进程类,以便支持 asyncio。
- --bind 0.0.0.0:8000: 绑定到 0.0.0.0,意味着服务器将监听所有可用的 IP 地址上的 8000 端口,从而允许外网访问。
使用Systemd 持久化服务
gunicorn 命令, 一旦关闭SSH连接,服务就会中断。为了让我们的API服务能在后台长期运行,并在服务器重启后能自动启动,需要使用systemd --- Linux系统标准服务器管理。
(1)创建systemd 服务文件
sudo nano /etc/systemd/system/ner_api.service
(2) 编写服务配置
[Unit]
Description=NER API Service
After=network.target
[Service]
User=root
Group=root
# 工作目录
WorkingDirectory=/root/ner_deployment
# 启动服务的完整命令,务必使用gunicorn绝对路径
ExecStart=/root/ner_deployment/.venv/bin/gunicorn -w 3 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000
# 失败自动重启
Restart=on-failure
RestartSec=5s
# 定义服务安装信息,表示服务器以多用户模式启动时启用
[Install]
WantedBy=multi-user.target
(3)管理服务
- 重新加载systemd配置:
sudo systemctl daemon-reload
- 启动服务
sudo systemctl start ner_api
- 设置开机自启
sudo systemctl enable ner_api
- 查看服务状态
sudo systemctl status ner_api
- 查看实时日志
sudo journalctl -u ner_api -f
五、DockerCompose部署
5.1 Docker与DockerCompose
Docker 让软件变成集装箱模式,允许开发者将应用及其所有依赖项打包到一个轻量级、可抑制的容器中。
这个容器可以再任何安装了Docker的机器上运行。
DockerCompose 是通过定义和运行多容器Docker应用的工具,通过docker-compose.yaml的YAML文件,可以配置应用所需的所有服务。
docker compose up -> 启动了所有服务
5.2 NER 服务的镜像相关文件
Dockerfile
# ner_deployment/Dockerfile
# 基础镜像
FROM python:3.10-slim
# 关闭python输出缓冲、禁止生成.pyc文件,让容器中的日志更适合调试、镜像内容更简洁
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# 容器内荣做目录
WORKDIR /app
# 设置 PyPI 镜像源,加速依赖安装
RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
RUN pip install --no-cache-dir uv
# 文件复制到镜像
COPY pyproject.toml ./
RUN uv pip install --system --no-cache .
COPY . .
# 用户
RUN useradd -m appuser
USER appuser
# 暴露端口
EXPOSE 8000
CMD ["gunicorn", "-w", "3", "-k", "uvicorn.workers.UvicornWorker", "main:app", "--bind", "0.0.0.0:8000"]
docker-compose.yml
# ner_deployment/docker-compose.yml
services:
ner_api:
build: .
container_name: ner_api_service
ports:
- "8000:8000"
restart: always
5.3 部署与测试
启动
sudo docker compose up --build -d
查看日志
# 查看正在运行的容器
sudo docker compose ps
# 实时查看服务日志
sudo docker compose logs -f