吕梁市网站建设_网站建设公司_SSL证书_seo优化
2026/1/21 7:47:03 网站建设 项目流程

Flask快速搭建API,让别人也能调用你的模型

你已经成功部署了阿里开源的「万物识别-中文-通用领域」图像分类模型,也能本地运行推理。但如果你想让别人通过网页、手机App或其他系统来调用这个模型呢?这时候就需要把它封装成一个可远程访问的API服务

本文将手把手教你使用轻量级Web框架Flask,把本地运行的推理.py脚本改造成一个对外提供服务的 RESTful API 接口。完成后,只需发送一个HTTP请求上传图片,就能收到中文标签识别结果,真正实现“让别人也能调用你的AI模型”。

1. 为什么选择Flask?

在众多Python Web框架中(如Django、FastAPI、Tornado),Flask是最适合AI模型服务化的入门选择,原因如下:

  • 极简上手:几行代码就能启动一个Web服务
  • 轻量灵活:不强制项目结构,适合小规模模型封装
  • 生态丰富:与PyTorch、Pillow、transformers等AI库无缝集成
  • 调试友好:开发模式支持热重载和详细错误提示

⚠️ 提示:生产环境建议升级为 FastAPI + Gunicorn + Nginx 组合,但对新手来说,Flask 是最平滑的第一步。

2. 环境准备与依赖安装

确保你已处于py311wwtsConda 环境,并安装以下Web相关依赖:

conda activate py311wwts # 安装Flask pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple # 可选:安装gunicorn用于后续性能测试(非必需) pip install gunicorn

检查当前目录结构

推荐将所有文件放在/root/workspace/api_demo目录下,结构如下:

/root/workspace/api_demo/ ├── app.py # Flask主程序 ├── inference.py # 封装好的推理模块(由原推理.py改写) ├── static/ # 存放上传的图片 │ └── uploads/ └── requirements.txt # 记录完整依赖

你可以通过以下命令创建目录:

mkdir -p /root/workspace/api_demo/static/uploads cd /root/workspace/api_demo

3. 模块化改造:从脚本到可导入函数

原始的推理.py是一个独立脚本,不适合被Flask调用。我们需要将其重构为一个可复用的模块 ——inference.py

### 3.1 创建inference.py

将以下内容保存为/root/workspace/api_demo/inference.py

# -*- coding: utf-8 -*- import torch from PIL import Image from transformers import AutoModel, AutoTokenizer, CLIPProcessor import os # ================== 配置参数 ================== MODEL_NAME = "bailian/visual-classification-zh-base" DEVICE = "cuda" if torch.cuda.is_available() else "cpu" # 默认候选标签(可根据需求扩展) CANDIDATE_LABELS_ZH = [ "动物", "植物", "交通工具", "电子产品", "食物", "自然景观", "城市建筑", "人物", "书籍", "服装", "家具", "办公用品", "海洋生物", "鸟类", "昆虫", "山脉", "河流", "沙漠", "飞机", "汽车", "火车", "轮船", "自行车", "摩托车", "猫", "狗", "老虎", "大象", "熊猫", "狮子" ] # 全局缓存模型和处理器 _model = None _processor = None def _load_model(): """懒加载模型:首次调用时才加载""" global _model, _processor if _model is not None: return _model, _processor print("正在加载万物识别模型...") processor = CLIPProcessor.from_pretrained(MODEL_NAME) model = AutoModel.from_pretrained(MODEL_NAME) model.to(DEVICE) model.eval() print(f"模型加载完成,运行设备: {DEVICE}") _model, _processor = model, processor return _model, _processor def build_text_inputs(labels): """构建文本输入模板""" return [f"这是一张{label}的照片" for label in labels] def predict(image_path, custom_labels=None): """ 执行图像分类预测 Args: image_path (str): 图片文件路径 custom_labels (list): 自定义候选标签列表(可选) Returns: list: Top-5预测结果,包含label和score """ model, processor = _load_model() labels_to_use = custom_labels or CANDIDATE_LABELS_ZH text_inputs = build_text_inputs(labels_to_use) try: image = Image.open(image_path).convert("RGB") except Exception as e: raise FileNotFoundError(f"无法读取图像: {image_path}, 错误: {e}") inputs = processor( text=text_inputs, images=image, return_tensors="pt", padding=True, truncation=True ).to(DEVICE) with torch.no_grad(): outputs = model(**inputs) logits_per_image = outputs.logits_per_image probs = torch.softmax(logits_per_image, dim=-1).cpu().numpy()[0] top_indices = probs.argsort()[-5:][::-1] results = [] for idx in top_indices: label = labels_to_use[idx] score = float(probs[idx]) results.append({"label": label, "score": round(score, 4)}) return results

### 3.2 改造说明

原始问题解决方案
脚本式执行改为函数式接口predict()
模型重复加载使用全局变量实现单例模式,避免每次请求都重新加载
路径写死接收外部传入的image_path
不支持自定义标签新增custom_labels参数

4. 构建Flask应用:app.py

现在我们来编写核心的Web服务入口文件。

### 4.1 创建app.py

将以下内容保存为/root/workspace/api_demo/app.py

# -*- coding: utf-8 -*- from flask import Flask, request, jsonify, render_template from inference import predict import os import uuid from werkzeug.utils import secure_filename app = Flask(__name__) # 配置上传目录 UPLOAD_FOLDER = 'static/uploads' os.makedirs(UPLOAD_FOLDER, exist_ok=True) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER # 允许的图片格式 ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'bmp', 'gif'} def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/') def index(): """主页:提供简单的HTML上传界面""" return ''' <h2>📷 万物识别-中文通用模型 API 测试页</h2> <p>上传一张图片,获取AI生成的中文标签</p> <form method="POST" action="/predict" enctype="multipart/form-data"> <input type="file" name="image" required><br><br> <button type="submit">开始识别</button> </form> ''' @app.route('/predict', methods=['POST']) def api_predict(): """API接口:接收图片并返回识别结果""" if 'image' not in request.files: return jsonify({"error": "未上传图片"}), 400 file = request.files['image'] if file.filename == '': return jsonify({"error": "文件名为空"}), 400 if not allowed_file(file.filename): return jsonify({"error": "不支持的文件类型"}), 400 # 生成唯一文件名防止冲突 ext = file.filename.rsplit('.', 1)[1].lower() unique_filename = f"{uuid.uuid4().hex}.{ext}" filepath = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename) try: file.save(filepath) results = predict(filepath) return jsonify({ "success": True, "results": results }) except Exception as e: return jsonify({"error": str(e)}), 500 finally: # 可选:识别后删除图片以节省空间 # if os.path.exists(filepath): # os.remove(filepath) pass if __name__ == '__main__': print("🚀 启动Flask服务...") print("👉 访问 http://<你的IP>:5000 查看测试页面") app.run(host='0.0.0.0', port=5000, debug=True)

### 4.2 关键功能解析

功能实现方式
文件上传使用request.files获取上传图片
安全校验allowed_file()过滤非法扩展名
唯一命名uuid.uuid4()防止文件名冲突
JSON响应jsonify()返回标准API格式
异常处理try-except捕获推理错误
调试模式debug=True开启自动重启和错误追踪

5. 启动API服务并测试

### 5.1 运行Flask应用

进入项目目录并启动服务:

cd /root/workspace/api_demo python app.py

你会看到输出:

🚀 启动Flask服务... 👉 访问 http://0.0.0.0:5000 查看测试页面 * Running on http://0.0.0.0:5000 (Press CTRL+C to quit)

### 5.2 如何访问服务?

  • 如果你在本地Jupyter或PAI平台运行,可通过端口转发内网穿透访问。
  • 若有公网IP,直接浏览器打开http://<公网IP>:5000
  • 大多数平台会自动映射URL,例如https://xxxxx.cloud.com/

### 5.3 测试API接口

方法一:使用网页表单(适合新手)

打开http://<IP>:5000,点击“选择文件”上传一张图片(如猫、风景、汽车),提交后即可看到返回的Top-5中文标签。

方法二:使用curl命令(适合开发者)
curl -X POST http://127.0.0.1:5000/predict \ -F "image=@/root/workspace/cat.jpg" \ | python -m json.tool

预期返回示例:

{ "success": true, "results": [ {"label": "动物", "score": 0.9872}, {"label": "猫", "score": 0.9645}, {"label": "宠物", "score": 0.8721}, {"label": "哺乳动物", "score": 0.7633}, {"label": "家具", "score": 0.1023} ] }

6. 实际应用场景举例

一旦API上线,它可以被各种系统轻松调用:

场景调用方式
智能相册分类移动App上传照片 → 获取中文标签 → 自动归类“宠物”、“旅行”等相册
内容审核辅助后台管理系统上传用户图片 → 判断是否含“敏感物品”、“违规场景”
教育辅助工具学生拍照植物 → 返回“银杏叶”、“向日葵”等名称 → 辅助自然课学习
无障碍识别视障人士拍摄周围环境 → 语音播报“前方是公交车站”

7. 常见问题与优化建议

### 7.1 常见问题排查

问题现象解决方法
OSError: [WinError 10013]Windows需改为host='127.0.0.1';Linux保持0.0.0.0
上传大图卡顿inference.py中添加图像缩放预处理
多次请求变慢确保_load_model()只执行一次(检查全局变量)
中文乱码文件保存为 UTF-8 编码,Flask默认支持中文JSON输出

### 7.2 性能优化建议

  1. 限制图片大小
    app.pyapi_predict中加入尺寸检查:

    from PIL import Image as PILImage # 添加前: img = PILImage.open(file.stream) if max(img.size) > 2048: return jsonify({"error": "图片尺寸过大,请上传小于2048px的图片"}), 400
  2. 启用GPU批处理(进阶)
    修改predict()函数支持批量图片编码,提升吞吐量。

  3. 增加缓存机制
    对相同图片MD5值的结果进行缓存,避免重复计算。

  4. 部署为后台服务
    使用nohup python app.py &systemd守护进程防止中断。

8. 总结:从本地脚本到可用API的完整跃迁

## 8.1 本教程核心收获

  • ✅ 成功将推理.py脚本模块化为可复用的inference.py
  • ✅ 使用 Flask 快速搭建了一个支持图片上传的 Web API
  • ✅ 实现了/predict接口,支持 JSON 格式返回识别结果
  • ✅ 掌握了模型服务化的基本流程:加载 → 接收 → 推理 → 返回
  • ✅ 学会了如何测试和调用自己的AI服务

## 8.2 下一步可以做什么?

  1. 接入前端页面:用HTML+CSS美化上传界面,实时显示识别结果
  2. 支持Base64输入:允许前端直接传base64字符串,无需上传文件
  3. 添加身份验证:使用Token控制API访问权限
  4. 部署到云服务器:将服务发布到公网,供他人长期使用
  5. 结合数据库:记录每次请求日志,便于分析使用情况

你现在不仅拥有一个强大的中文图像识别模型,更掌握了让它“走出去”的能力 —— 把AI能力变成真正的生产力工具。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询