(model-serving-intro)=
# 引言：训练完模型之后

你在{doc}`../pytorch-practice/train-workflow`中完成了模型的训练，在{doc}`../cnn-ablation-study/index`中验证了各组件的贡献，在{doc}`../unet-image-segmentation/index`中用UNet处理了具体的图像分割任务——模型在测试集上跑出了不错的准确率，一切都很好。但现在有一个更现实的问题：**这个模型怎么给别人用？**

让模型真正产生价值，不是训练完就结束了。你需要考虑的事情比训练多得多：别人怎么调用它？它能同时处理多少个请求？如果图片不是28×28的怎么办？别人会不会把它搞崩溃？这些问题没有一个是训练的loss曲线能回答的。

## 从训练到服务的跨越

想象一下，你训练了一个手写数字识别模型，想做一个"拍照识数"的App。这个场景下，模型需要：

1. **接收一张照片**，而不是训练时用的28×28张量
2. **在几十毫秒内给出结果**，用户没有耐心等
3. **同时响应几百个人的请求**，不是一个人调一次
4. **对恶意调用有防护**，不能被人搞崩溃

这就是从"训练模型"到"服务模型"的跨越。训练时你关注的是loss曲线和准确率，服务时你关注的是延迟、吞吐量、可用性和安全性。

```{list-table} 训练环境 vs 生产环境
:header-rows: 1

* - **维度**
  - **训练环境**
  - **生产环境**
* - 核心关注
  - 准确率、loss
  - 延迟、吞吐量
* - 输入来源
  - 预设数据集
  - 用户上传/数据流
* - 并发量
  - 单用户、顺序执行
  - 多用户、高并发
* - 运行时长
  - 几小时到几天
  - 7×24不间断
* - 资源限制
  - GPU、大内存
  - 未必有GPU
* - 安全要求
  - 无（学术环境）
  - 鉴权、限流、审计
```

## 模型服务面临的三个核心挑战

### 挑战一：格式兼容性

PyTorch训练出来的模型是`.pth`或`.pt`文件，这些文件依赖PyTorch的运行时环境。如果部署环境没有PyTorch（或者版本不一致），模型就跑不起来。更麻烦的是，如果想让模型在移动端、浏览器或边缘设备上运行怎么办？某些场景下甚至可能要用C++或者JavaScript来加载模型。

ONNX（Open Neural Network Exchange）就是为了解决这个问题而出现的标准格式。它定义了一套统一的中间表示，让模型可以在不同框架之间无缝迁移。{doc}`onnx-export`会详细讲解如何将PyTorch模型导出为ONNX。

### 挑战二：架构选择

模型要做成API服务，第一个问题是"该用同步还是异步？"

**同步推理**就像打电话——你问一句，对方当场回答。适合轻量模型、低延迟场景。但是如果有100个人同时打电话呢？电话线不够用就会排队等待。

**异步推理**就像发邮件——你发出去，对方处理完再通知你。适合大模型、耗时长的推理任务。缺点是实现更复杂，需要任务队列和回调机制。

{doc}`serving-architecture`会详细分析这两种模式各自的适用场景和架构设计。

### 挑战三：运维复杂度

模型服务上线后，你还需要：管理模型的版本（新模型上线怎么不中断旧服务？）、控制访问权限（不能让任何人都能调你的API）、监控推理延迟（模型变慢了怎么预警）、处理故障（服务挂了怎么恢复）——这些都是运维上的挑战。

{doc}`deployment-practice`会用Ferrinx这个具体的推理服务来展示如何应对这些挑战。

## Ferrinx：一个简化的教学工具

Ferrinx是一个用Rust编写的轻量级ONNX推理服务。它不像TensorFlow Serving或TorchServe那样功能丰富，但正因为简单，它更适合用来学习模型部署的核心概念。

Ferrinx采用axum作为Web框架、ort作为ONNX Runtime绑定，支持SQLite和PostgreSQL两种数据库后端。它提供两种运行模式：简单模式（单进程，无需任何外部依赖）和分布式模式（添加Redis后支持异步推理和多Worker扩展）。这种设计让读者可以循序渐进地理解模型服务的各个层次。

在{doc}`deployment-practice`中，我们将实际操作Ferrinx的部署流程，包括编译、配置、模型注册、推理调用等完整的生命周期管理。

## 本章路线图

```{mermaid}
graph LR
    A[PyTorch模型<br/>训练产物] --> B[ONNX导出<br/>跨平台格式]
    B --> C[服务架构<br/>同步 vs 异步]
    C --> D[Ferrinx实践<br/>部署与操作]
    D --> E[安全与运维<br/>鉴权限流]
```

本章的目标不是让你成为模型部署专家，而是让你理解"从训练到生产"这个链路中的关键环节，建立完整的MLOps思维框架。当你以后训练出一个好模型时，你不仅知道"这个模型很准"，还知道"怎么让它真正跑起来"。

## 下一步

从{doc}`onnx-export`开始，我们学习如何把PyTorch训练的模型导出为标准ONNX格式。这个过程需要处理一些细节：如何正确处理输入输出命名、如何处理动态batch维度、如何验证导出后的模型和原始模型输出一致——有意思的是，这些细节中的许多都跟{doc}`../cnn-ablation-study/experiment-design`中"控制变量"的思维方式相通：每次只改一个参数，确保结果可复现。
