数据分类接口项目实战 · 第1章 项目概述与技术选型

1.1 项目背景与需求分析

我们团队接到一个客户需求:构建一个在线数据分类接口。客户每天要处理几万条评本,需要自动判断情感倾向——正面、负面还是中性。说白了,就是把自然语言分类能力封装成一个RESTful API,让前端或第三方系统直接调用。

我翻了一下需求文档,核心痛点在于:

  • 实时性要求高 —— 单条请求必须在200ms以内返回
  • 模型可替换 —— 今天用逻辑回归,明天可能换XGBoost,接口不能跟着改
  • 部署运维要轻量 —— 团队没有专门的DevOps,最好一个Docker就能跑起来
  • 支持批量预测 —— 一次可以传入几十条文本,降低网络开销

我在上一家公司做过类似的情感分析项目,当时选的是Flask+scikit-learn,后来并发上来就扛不住了。嗯,这次不能再走老路。FastAPI在这个场景下非常合适——异步处理、自动校验、交互式文档,都是刚需。

项目核心约束:
· 请求量预计峰值300 QPS
· 模型文件不超过50MB
· 接口必须支持多标签分类(不止二分类)
· 输出格式统一为JSON,包含预测标签和置信度

1.2 技术栈选型思考

我选技术栈有个习惯:先列候选,再比优劣势。下表是我当时做的对比:

组件 候选 最终选择 理由
编程语言 Python / Java / Go Python 团队熟练度最高,生态成熟
Web框架 Flask / FastAPI / Django FastAPI 异步、Pydantic校验、OpenAPI文档、性能好
机器学习库 scikit-learn / TensorFlow / PyTorch scikit-learn 线性模型和SVM在文本分类上够用,部署轻量
序列化 pickle / joblib / ONNX joblib 对scikit-learn模型兼容最好,压缩率高
部署工具 Docker / uvicorn / gunicorn uvicorn + Docker FastAPI原生用uvicorn,Docker封装环境

你想想看,如果选Flask,得自己写异步支持、手动解析请求体、再手撸Swagger文档——太累了。FastAPI把这些都内置了,开箱即用。我选scikit-learn还有一个个人原因:它的Pipeline对象把预处理和模型打包在一起,部署时一个joblib文件就搞定。我曾经因为预处理和模型分开导致线上环境特征不一致,踩了个大坑。

避坑提示: 千万不要在生产环境用pickle加载不受信任的模型文件。joblib虽好,也要验证模型来源。我在一个金融项目里遇到过有人替换模型文件导致预测结果异常,后来我们都加了校验哈希。

1.3 开发环境搭建

环境搭建我建议按这个来。我个人习惯用虚拟环境隔离项目,避免依赖冲突:

  1. 安装Python 3.10+(推荐3.11,性能更好)
  2. 创建虚拟环境:python -m venv .venv && source .venv/bin/activate
  3. 安装核心依赖:
    pip install "fastapi[standard]" uvicorn scikit-learn joblib pandas
  4. 验证安装:启动一个最小FastAPI应用

下面是你的第一个hello world——虽然是demo,但已经包含了接口的基本骨架:

from fastapi import FastAPI

app = FastAPI(title="数据分类接口")

@app.get("/")
def root():
    return {"message": "分类接口已启动"}

@app.post("/predict")
def predict(texts: list[str]):
    # 这里是占位,后续替换为真实模型
    return {"predictions": ["neutral"] * len(texts)}

用 uvicorn main:app --reload 跑起来,打开浏览器访问 http://127.0.0.1:8000/docs,就能看到FastAPI自动生成的交互式文档页面。我当初第一次看到这个功能时觉得太香了——调试接口再也不用Postman来回截图了。

注意: Laptop内存低于8GB的话,训练模型时可能卡。建议用云开发环境或提前升级硬件。我在4GB的旧Mac上跑过一次网格搜索,风扇直接起飞。

下图画出了整个项目的架构和数据流,你可以直观感受一下每个环节的位置:

数据分类接口项目架构图 客户端 FastAPI 服务 预处理 Scikit-learn 模型 JSON 响应 说明: 请求 → 预测 → 返回 全部异步非阻塞

这张图把项目拆成了五个核心节点:客户端发送请求 → FastAPI接收并路由 → 预处理(特征提取、清洗) → 加载scikit-learn模型做推理 → 返回JSON。箭头是单向数据流,清晰明了。

思考题: 如果模型文件需要热加载(不重启服务就更新模型),应该在哪一层做改动?我在一个项目里用了FastAPI的lifespan事件,启动时加载模型文件到全局变量,再监听文件变化自动reload——后面章节会详细讲这个技巧。