☰
MLOps-Basics 第 6 周:用 GitHub Actions 串联训练、DVC 数据版本化与 Docker 推理部署的完整实战
2026/10/3 8:19:53 网站建设 项目流程
  • 示例工程

【免费下载链接】MLOps-Basics

项目地址:https://gitcode.com/GitHub_Trending/ml/MLOps-Basics
点击查看免费下载

本篇文章以仓库 week_6_github_actions/README.md 为核心骨架,结合该目录下的train.py、convert_model_to_onnx.py、inference_onnx.py、Dockerfile、docker-compose.yml以及仓库根目录 .github/workflows/ 下的工作流定义,系统讲解在 MLOps-Basics 项目中如何从零搭建训练环境、监控训练过程、用 DVC 版本化数据与模型、导出 ONNX 并部署为 Docker 服务,最终由 GitHub Actions 完成 CI/CD 自动化。读完本文,你将能够在本地完整复现该阶段从训练到推理部署的全流程,并理解每个环节背后源码级的实现细节。

GitHub Actions 驱动的 CI/CD 流程:推送代码触发自动构建与测试,通过后合并并部署到生产环境(来源:仓库 images/basic_flow.png)


一、阶段背景:这一周要解决什么问题

MLOps-Basics 是一个循序渐进探索 MLOps 工具链的开源项目,其出发点并非追求 SOTA 模型,而是「通过实战学会使用工具」。README 开头即明确说明:

Note: The purpose of the project to explore the libraries and learn how to use them. Not to build a SOTA model.

week_6_github_actions作为整个系列的第 6 周,重点是把前几周积累的**实验管理(WandB)、配置管理(Hydra)、数据版本控制(DVC)、模型转换(ONNX)和容器化(Docker)**能力,统一收敛到GitHub Actions 自动化流水线中:当代码推送(push)到仓库时,自动触发构建与测试,进而完成模型镜像的构建与部署。

从目录结构可以清晰看到该阶段的完整技术栈:

week_6_github_actions/ ├── configs/ # Hydra 分层配置(model / processing / training) ├── dvcfiles/trained_model.dvc # DVC 跟踪的 ONNX 模型 ├── Dockerfile / docker-compose.yml # 容器化部署 ├── app.py / inference_onnx.py # FastAPI 推理服务 ├── convert_model_to_onnx.py # PyTorch → ONNX 转换 ├── train.py / data.py / model.py # 训练与数据管线 └── requirements*.txt # 训练/推理两套依赖

同时,仓库根目录 .github/workflows/basic.yaml 与 .github/workflows/build_docker_image.yaml 提供了 GitHub Actions 从入门到镜像推送的两种工作流范例,这正是本文后半部分要深入拆解的内容。


二、环境准备:Python 3.8 虚拟环境与依赖安装

2.1 创建虚拟环境

项目基于Python 3.8开发。README 建议使用 conda 创建独立的虚拟环境:

conda create --name project-setup python=3.8 conda activate project-setup

激活后安装依赖:

pip install -r requirements.txt

2.2 训练与推理的依赖分离

从源码看,该阶段刻意将依赖拆成了两份,避免推理镜像携带训练期的不必要包:

requirements.txt(训练用)包含:

  • pytorch-lightning==1.2.10:模型训练框架(train.py中pl.Trainer即来自此包)
  • datasets==1.6.2、transformers==4.5.1:数据与预训练模型
  • scikit-learn==0.24.2、torchmetrics:评估指标
  • matplotlib、seaborn:可视化
  • hydra-core、omegaconf、hydra_colorlog:Hydra 配置管理(train.py中@hydra.main装饰器依赖它们)
  • wandb:实验跟踪
  • fastapi、uvicorn:推理服务

requirements_inference.txt(推理部署用)则精简为pytorch-lightning、datasets、scikit-learn、hydra-core、omegaconf、hydra_colorlog,并额外加入onnxruntime(运行 ONNX 模型)与dvc(拉取远程模型文件)。

从 Dockerfile 可以看到,Docker 镜像构建时只安装requirements_inference.txt,而非全量训练依赖——这是镜像瘦身的直接体现。


三、模型训练与 WandB 实验监控

3.1 启动训练

安装好依赖后,一条命令即可开始训练:

python train.py

3.2 训练入口的源码级拆解

从 train.py 可以看清训练的完整链路:

  1. Hydra 配置注入:main函数被@hydra.main(config_path="./configs", config_name="config")装饰,配置由 configs/config.yaml 统一入口加载,并通过defaults组合model、processing、training三组配置:
    defaults: - model: default - processing: default - training: default - override hydra/job_logging: colorlog - override hydra/hydra_logging: colorlog
  2. 配置打印:logger.info(OmegaConf.to_yaml(cfg, resolve=True))将解析后的完整配置以 YAML 形式输出,方便核对本次运行的超参数。
  3. 数据与模型装配:DataModule(cfg.model.tokenizer, cfg.processing.batch_size, cfg.processing.max_length)负责 tokenizer、batch size、序列长度;ColaModel(cfg.model.name)负责模型与 tokenizer 的加载。
  4. 回调与日志:ModelCheckpoint监控valid/loss保存最优权重到models/best-checkpoint.ckpt;EarlyStopping在valid/loss连续 3 个 epoch 不降时提前终止;WandbLogger(project="MLOps Basics")把指标同步到 WandB。
  5. 训练器配置:max_epochs、log_every_n_steps、deterministic均来自 Hydra 的training配置组。

此外,train.py 中定义了一个自定义回调SamplesVisualisationLogger:每个验证阶段结束后,对比真实标签与模型预测,将预测错误的句子整理成wandb.Table记录到实验面板,便于直观分析模型在哪些样本上出错。

3.3 监控训练日志

训练结束后,终端日志末尾会看到类似输出:

wandb: Synced 5 W&B file(s), 4 media file(s), 3 artifact file(s) and 0 other file(s) wandb: wandb: Synced proud-mountain-77: https://wandb.ai/raviraja/MLOps%20Basics/runs/3vp1twdc

这条日志中的链接即为本次实验在 WandB 上的独立运行页面(run id:3vp1twdc),包含 loss 曲线、准确率曲线、样本错误表格等全部图表。README 提示:直接点击该链接即可打开 WandB dashboard 查看所有绘图。需要说明的是,该 URL 是运行时由 WandB 服务动态生成的,仓库内不保存;在实际使用中,你也可以在WandbLogger(project="MLOps Basics")的 project 参数中替换为自己的项目名与 entity。


四、用 DVC 版本化数据与模型

4.1 初始化 DVC 与配置 Google Drive 远程存储

训练产物(模型权重、onnx 文件)不适合直接提交到 Git。本项目使用DVC + Google Drive作为远程存储。README 给出的配置序列如下:

dvc init dvc remote add -d storage gdrive://19JK5AFbqOBlrFVwDHjTrf9uvQFtS0954 dvc remote modify storage gdrive_use_service_account true dvc remote modify storage gdrive_service_account_json_file_path creds.json

逐条说明:

  • dvc init:在当前目录初始化 DVC 仓库(生成.dvc/目录);
  • dvc remote add -d storage gdrive://...:添加名为storage的远程存储,指向 Google Drive 上的指定目录(-d将其设为默认 remote);
  • dvc remote modify storage gdrive_use_service_account true:开启Google Service Account认证方式,避免人工 OAuth 授权,这是 CI 环境中拉取数据的必要前提;
  • dvc remote modify storage gdrive_service_account_json_file_path creds.json:指定 Service Account 的密钥文件路径。

其中creds.json正是创建 Service Account 时下载的 JSON 密钥文件。

4.2 DVC 跟踪的模型文件长什么样

该阶段的 ONNX 模型由 DVC 跟踪,仓库中只保留了元数据文件 dvcfiles/trained_model.dvc:

wdir: ../models outs: - md5: d82b8390fa2f09b121de4abfa094a7a9 size: 17562590 path: model.onnx

可以看到:DVC 记录的不是二进制模型本身,而是其md5 校验和与大小,path: model.onnx配合wdir: ../models表明实际文件位于models/model.onnx。真实模型文件通过dvc pull从远程存储拉取。在 Dockerfile 中正是通过这一机制在镜像构建阶段拉取训练好的模型(见第六节)。

关于 DVC 各命令更细化的原理说明(如dvc add、dvc push、dvc pull的工作流),原 README 建议参考作者撰写的《MLOps-DVC》博客;本文以仓库内的trained_model.dvc元数据与 Dockerfile 中的拉取实践为据展开,不展开外部内容。


五、Google Service Account 创建与凭据落地

DVC 要能在无人值守环境(GitHub Actions / Docker build)中访问 Google Drive,必须使用Google Service Account而非个人账号 OAuth。

README 要求按官方步骤创建 Service Account,并将下载的 JSON 密钥保存为creds.json。需要特别提醒两点工程细节:

  1. 凭据文件不能入库:creds.json属于敏感凭据,应通过 GitHub Actions 的Secrets或本地文件注入,绝不能提交进 Git 仓库;
  2. 格式转换场景:若 CI 或本地环境中拿到的凭据是单行字符串文本而非标准 JSON 文件,仓库提供了辅助脚本 parse_json.py 演示如何读取creds.txt、用eval还原为 Python 字典并写回标准 JSON 文件test.json(该脚本同时注释了json.loads(strict=False)的另一种解析思路),供凭据格式适配时参考。

配置完成后,凡是在包含.dvc/config的目录中执行dvc pull,DVC 便会使用该 Service Account 从 Google Drive 远程存储拉取被跟踪的模型文件。


六、把 PyTorch 模型导出为 ONNX

6.1 执行导出

训练完成后,执行以下命令将 checkpoint 转换为 ONNX 格式:

python convert_model_to_onnx.py

6.2 导出脚本的源码级细节

convert_model_to_onnx.py 的核心逻辑:

  1. 加载权重:从models/best-checkpoint.ckpt通过ColaModel.load_from_checkpoint(model_path)恢复训练时保存的最优模型;
  2. 构造输入样例:初始化DataModule并从训练集取一个 batch,抽取input_ids与attention_mask作为导出时的示例输入;
  3. 执行导出:调用torch.onnx.export,关键参数如下:
    • opset_version=10:目标 ONNX opset 版本;
    • input_names=["input_ids", "attention_mask"]、output_names=["output"]:为 I/O 张量命名,供 ONNX Runtime 按名字喂入数据;
    • dynamic_axes={"input_ids": {0: "batch_size"}, ...}:将 batch 维度声明为动态,允许推理时一次处理任意数量的样本;
  4. 输出文件:转换产物保存在models/model.onnx。

导出后的 ONNX 模型正是第四节中 DVC 所跟踪的model.onnx(大小约 17.5MB)。


七、两种推理方式:PyTorch 原生与 ONNX Runtime

7.1 PyTorch 原生推理

python inference.py

inference.py 中的ColaPredictor封装了完整推理链路:加载 checkpoint →model.eval()+model.freeze()→ 用DataModule对输入文本做 tokenize → 前向传播得到 logits →Softmax归一化 → 输出unacceptable(不可接受)与acceptable(可接受)两类各自的置信度。所有预测调用都被@timing装饰器记录耗时。

7.2 ONNX Runtime 推理

python inference_onnx.py

inference_onnx.py 中的ColaONNXPredictor展示了一条完全不同的推理路径:

  • 用ort.InferenceSession(model_path)加载 ONNX 模型,不再依赖 PyTorch 运行时;
  • 将 tokenize 结果按导出时声明的名字构造ort_inputs = {"input_ids": ..., "attention_mask": ...};
  • 调用ort_session.run(None, ort_inputs)执行推理,再经scipy.special.softmax得到置信度分布。

对比两条路径可以发现:ONNX 版本只依赖onnxruntime与numpy等轻量库,无需加载整个 PyTorch 推理栈,这正是把模型用于 Docker 服务化部署的意义所在。


八、Docker 化部署:把 ONNX 模型包装成 FastAPI 服务

8.1 FastAPI 推理接口

app.py 定义了一个极简的推理 API:

  • GET /:返回示例主页;
  • GET /predict?text=...:接收文本参数,调用ColaONNXPredictor("./models/model.onnx")返回预测结果。

8.2 构建镜像

按 README 的两种方式任选其一:

方式一:先 build 再 run

docker build -t inference:latest . docker run -p 8000:8000 --name inference_container inference:latest

方式二:docker-compose 一键启动

docker-compose up

docker-compose.yml 的内容如下:

version: "3" services: prediction_api: build: . container_name: "inference_container" ports: - "8000:8000"

8.3 Dockerfile 逐层解读:镜像内如何获取模型

Dockerfile 是本阶段最值得逐行研读的文件,它把 DVC + ONNX + FastAPI 完整串在了一起:

FROM huggingface/transformers-pytorch-cpu:latest COPY ./ /app WORKDIR /app # 安装 DVC 的 gdrive 扩展与推理依赖 RUN pip install "dvc[gdrive]" RUN pip install -r requirements_inference.txt # 在镜像内初始化 DVC 并配置 Google Drive 远程 RUN dvc init --no-scm RUN dvc remote add -d storage gdrive://19JK5AFbqOBlrFVwDHjTrf9uvQFtS0954 RUN dvc remote modify storage gdrive_use_service_account true RUN dvc remote modify storage gdrive_service_account_json_file_path creds.json RUN cat .dvc/config # 在构建阶段拉取训练好的模型 RUN dvc pull dvcfiles/trained_model.dvc ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 EXPOSE 8000 CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

关键设计点:

  1. 基础镜像选用huggingface/transformers-pytorch-cpu,自带 HuggingFace 生态与 PyTorch CPU 环境;
  2. 模型不进镜像仓库、构建时拉取:镜像内重新dvc init --no-scm、配置与本地一致的 Google Drive remote,然后dvc pull dvcfiles/trained_model.dvc把model.onnx拉进镜像——训练产物以数据版本控制的方式注入镜像,而非把大文件塞进 Git;
  3. 启动即服务:CMD直接以 uvicorn 启动 FastAPI 应用,暴露 8000 端口。

需要留意的前置条件:由于镜像构建阶段要执行dvc pull,必须保证creds.json在构建上下文中可用(通过 build arg、挂载或 CI Secrets 注入),否则该步骤会因认证失败而中断。


九、GitHub Actions:把上述流程全部自动化

week_6_github_actions的进阶目标,是把以上「训练 → 版本化 → 转换 → 部署」的流程交给 GitHub Actions 自动执行。仓库中提供了两个层级的范例。

9.1 入门级:事件、Runner 与上下文变量

.github/workflows/basic.yaml 是理解 GitHub Actions 运行模型的最佳最小示例:

name: GitHub Actions Basic Flow on: [push] jobs: Basic-workflow: runs-on: ubuntu-latest steps: - name: Basic Information run: | echo "🎬 The job was automatically triggered by a ${{ github.event_name }} event." echo "💻 This job is now running on a ${{ runner.os }} server hosted by GitHub!" echo "🎋 Workflow is running on the branch ${{ github.ref }}" - name: Checking out the repository uses: actions/checkout@v2 - name: List files in the repository run: | ls ${{ github.workspace }} - run: echo "🍏 This job's status is ${{ job.status }}."

该工作流揭示了三个核心概念:

  • 触发器:on: [push]——每次推送代码都会触发,这与 README「推送即自动化」的定位一致;
  • Runner 与上下文:runs-on: ubuntu-latest指定执行环境;${{ github.event_name }}、${{ runner.os }}、${{ github.ref }}、${{ github.repository }}、${{ job.status }}等是 GitHub Actions 提供的运行时上下文变量,分别对应触发事件、操作系统、分支引用、仓库名与任务最终状态;
  • checkout:actions/checkout@v2把仓库克隆到 Runner,之后ls ${{ github.workspace }}即可看到克隆下来的代码。

9.2 实战级:构建 Docker 镜像并推送 ECR、更新 Lambda

.github/workflows/build_docker_image.yaml 演示了将 Docker 化推理服务自动部署到 AWS 的完整流水线(该工作流位于仓库根目录,其working-directory指向./week_9_monitoring,展示了后续周次对同一模式的复用):

  1. actions/checkout@v2检出代码;
  2. aws-actions/configure-aws-credentials@v1用 Secrets 中的AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY配置 AWS 凭证,region 为us-west-2;
  3. docker build通过--build-arg传入AWS_ACCOUNT_ID等 Secret;
  4. jwalton/gh-ecr-push@v1将镜像推送到 Amazon ECR;
  5. aws lambda update-function-code用新镜像更新 Lambda 函数。

这个示例给出了 GitHub Actions 在 MLOps 场景的标准姿势:Secrets 管理云凭证、工作流编排构建步骤、最终产物直接进入云原生部署链路,与第六节 Docker 化本地部署形成「本地验证 → CI 自动化」的闭环。


十、运行实验 Notebook 的虚拟环境绑定

仓库中保留了 experimental_notebooks/data_exploration.ipynb 供数据探索使用。README 特别提醒了一个虚拟环境陷阱:在 conda 虚拟环境中直接运行jupyter lab,内核不一定会使用当前虚拟环境。为确保 Notebook 与训练代码共用同一解释器,需要先执行:

conda install ipykernel python -m ipykernel install --user --name project-setup pip install ipywidgets
  • conda install ipykernel:安装 Jupyter 内核支持;
  • python -m ipykernel install --user --name project-setup:把当前虚拟环境注册为名为project-setup的 Jupyter kernel;
  • pip install ipywidgets:保证 Notebook 中的交互组件(如进度条)可用。

之后启动jupyter lab,在 Notebook 内核选择器中选中project-setup,即可确保所有依赖(transformers、pytorch-lightning、hydra等)与训练脚本保持一致。


十一、全流程串起来:一条可复现的 MLOps 闭环

至此,week_6_github_actions阶段覆盖的完整链路可以归纳为:

  1. 准备:conda create -n project-setup python=3.8+pip install -r requirements.txt;
  2. 训练与监控:python train.py,经 Hydra 注入配置、PyTorch Lightning 训练,指标与误判样本实时同步 WandB(train.py);
  3. 模型版本化:dvc init+ 配置 Google Drive Service Account 远程,模型元数据交由 dvcfiles/trained_model.dvc 跟踪;
  4. 格式转换:python convert_model_to_onnx.py产出models/model.onnx(convert_model_to_onnx.py);
  5. 双路推理验证:python inference.py(PyTorch)与python inference_onnx.py(ONNX Runtime)交叉验证产物正确性;
  6. 容器化:docker build -t inference:latest .或docker-compose up,镜像内dvc pull拉取模型并以 uvicorn 启动 FastAPI 服务(Dockerfile);
  7. CI/CD 自动化:由 .github/workflows/ 中的工作流在每次 push 时自动构建、测试、推送镜像。

这套链路的价值在于:模型产物、依赖环境、云凭证、部署目标都以声明式文件(DVC 元数据、Dockerfile、workflow yaml)固化在仓库中,任何开发者 clone 后都能按 README 的步骤一比一复现,而这正是 MLOps 区别于普通「训练脚本」的核心——可复现、可追踪、可自动化。

说明:文中 WandB 日志中的运行链接与部分外部教程链接为运行时动态生成的占位信息,实际使用时请以自己运行输出与官方文档为准;本文全部命令与配置均以当前仓库 week_6_github_actions 目录下的真实文件为据。

  • 示例工程

【免费下载链接】MLOps-Basics

项目地址:https://gitcode.com/GitHub_Trending/ml/MLOps-Basics
点击查看免费下载

相关推荐

上一篇:Boss直聘时间插件:四大招聘平台职位发布时间智能展示工具
下一篇:scaffdog深度解析:为什么Markdown驱动的脚手架工具是开发者的新宠

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询