1. detectron2 部署为什么总在环境这一步翻车
detectron2 是 Meta 开源的目标检测与实例分割框架,能直接加载 Mask R-CNN、RetinaNet 这类模型做推理和微调,适合做视觉算法落地、模型导出、服务封装的开发者。它最让人头疼的地方不是模型本身,而是部署链路太长:CUDA 版本、PyTorch 版本、编译器版本、Python 版本四者必须对齐,错一个就在pip install或import阶段直接崩掉。
我见过最多的场景是这样的:本地用 conda 装好了 torch,pip install detectron2一跑就报编译错误;好不容易装完,加载权重时又提示KeyError: 'non-existent config key';想导出 ONNX 给 TensorRT 用,结果onnx.optimizer这个模块在新版 onnx 里已经被删了,脚本直接 import 失败。这些问题单独看都不难,但串在一起就足够耗掉一整天。
这篇内容聚焦 detectron2 在本地与云端的部署全流程,覆盖 CUDA/PyTorch 版本匹配、依赖冲突排查、模型权重加载、ONNX/Caffe2 导出这几类高频报错。我会给出可复制的环境配置清单、Dockerfile 模板和推理脚本,同时演示怎么用 TaoToken 统一管理多模型调用的 API 凭证——当你同时跑 detectron2 推理服务和几个大模型接口时,Key 分散在各处很容易乱,统一通道会省很多事。
适合谁看:已经跑通过 PyTorch 基础训练、准备把 detectron2 推到生产或半生产环境的同学;以及被版本冲突卡住、想找一份能直接抄的配置清单的人。下面从环境开始,一步步来。
2. 环境配置与版本匹配:detectron2 安装依赖冲突排查
detectron2 官方推荐用预编译 wheel 安装,但 wheel 只覆盖特定 torch + CUDA + Python 组合。一旦你的组合不在列表里,就得从源码编译,而源码编译对 gcc、nvcc、torch 的 C++ ABI 都有要求。所以第一步不是急着装,而是先把版本对齐。
先确认你的 CUDA 驱动能支持到哪个 runtime 版本:
nvidia-smi输出右上角的CUDA Version: 12.1表示驱动最高支持 CUDA 12.1 runtime,你装的 torch 只要不超过这个版本就行。接着确认 Python 版本,detectron2 对 3.8–3.11 支持较好,3.12 部分依赖还没跟上。
我实测下来比较稳的一组组合是:Python 3.10 + PyTorch 2.1.2 + CUDA 11.8 + detectron2 0.6。安装命令如下:
conda create -n d2 python=3.10 -y conda activate d2 pip install torch==2.1.2 torchvision==0.16.2 --index-url https://download.pytorch.org/whl/cu118 python -m pip install 'git+https://github.com/facebookresearch/detectron2.git'如果你不想从源码编译,可以先用官方 wheel 索引试:
python -m pip install detectron2 -f \ https://dl.fbaipublicfiles.com/detectron2/wheels/cu118/torch2.1/index.html装完之后立刻验证,别等到跑模型才发现问题:
python -c "import torch, detectron2; print(torch.__version__, torch.cuda.is_available(), detectron2.__version__)"预期输出类似2.1.2 True 0.6。如果torch.cuda.is_available()是 False,说明 CUDA 和 torch 没对上,回到上一步换 cu118 或 cu121 的 torch。
依赖冲突里最常见的两个坑:一是graphviz和pydot,导出 Caffe2 图的时候会用到,缺了会报ExecutableNotFound: failed to execute ['dot'],解决方式是系统层装 graphviz:
sudo apt-get install -y graphviz pip install graphviz pydot二是onnx.optimizer被移除的问题。新版 onnx 把onnx.optimizer拆成了独立的onnxoptimizer包,老脚本里import onnx.optimizer会直接失败。解决办法是装onnxoptimizer并改 import,或者把 onnx 降到 1.12 以下。我建议前者,因为降版本会牵连其他依赖。
云端部署时,我一般直接用 Docker 固定环境,避免机器之间漂移。下面这份 Dockerfile 模板可以直接用:
FROM nvidia/cuda:11.8.0-cudnn8-devel-ubuntu22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y \ python3.10 python3-pip git graphviz libgl1 libglib2.0-0 \ && rm -rf /var/lib/apt/lists/* RUN ln -s /usr/bin/python3.10 /usr/bin/python RUN pip install --no-cache-dir torch==2.1.2 torchvision==0.16.2 \ --index-url https://download.pytorch.org/whl/cu118 RUN pip install --no-cache-dir 'git+https://github.com/facebookresearch/detectron2.git' \ opencv-python-headless onnx onnxoptimizer WORKDIR /workspacelibgl1和libglib2.0-0是 opencv 在无桌面环境下的依赖,漏了会报ImportError: libGL.so.1。opencv-python-headless比完整版更适合服务端,省掉 GUI 依赖。
构建并进入容器:
docker build -t d2-env:0.1 . docker run --gpus all -it -v $(pwd):/workspace d2-env:0.1 bash进容器后再跑一次验证命令,确认torch.cuda.is_available()为 True。这一步过了,环境基本就稳了。
3. 可复制配置:detectron2 推理脚本与 TaoToken 统一 Key 接入
环境好了之后,先跑通一个最小推理,再谈导出和服务化。detectron2 的推理入口是DefaultPredictor,配置通过get_cfg()加载 yaml 再 merge。下面这份脚本可以直接复制,用官方 balloon 数据集做演示,避免依赖 COCO 的类别配置。
import cv2 import random from detectron2 import model_zoo from detectron2.config import get_cfg from detectron2.engine import DefaultPredictor from detectron2.utils.visualizer import Visualizer, ColorMode from detectron2.data import MetadataCatalog cfg = get_cfg() cfg.merge_from_file( model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml") ) cfg.MODEL.WEIGHTS = "output/model_final.pth" cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7 cfg.MODEL.DEVICE = "cuda" predictor = DefaultPredictor(cfg) metadata = MetadataCatalog.get("balloon_train") im = cv2.imread("balloon/val/1489853209_29b3e5f0d3_k.jpg") outputs = predictor(im) print(outputs["instances"].pred_classes, outputs["instances"].scores) v = Visualizer(im[:, :, ::-1], metadata=metadata, scale=0.5, instance_mode=ColorMode.IMAGE_BW) out = v.draw_instance_predictions(outputs["instances"].to("cpu")) cv2.imwrite("result.jpg", out.get_image()[:, :, ::-1])注意cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1必须和训练时一致,否则加载权重会报 shape mismatch。cfg.freeze()在导出脚本里要注释掉,因为导出过程需要改配置。
现在说 TaoToken 的接入。当你同时跑 detectron2 推理服务和几个大模型接口(比如做结果描述、做多模态校验),每个服务一套 Key 很难管。TaoToken 提供统一的 API 通道,把多模型调用凭证收敛到一个 Key 上。它的 Base URL 是https://taotoken.net/api,控制台在https://taotoken.net/console,API Key 在https://taotoken.net/api-keys生成。
我一般用一个settings.json或.env来管理,避免硬编码。下面是一个可复制的配置片段,路径放在项目根目录:
{ "taotoken": { "base_url": "https://taotoken.net/api", "api_key": "sk-你的key", "default_model": "claude-sonnet-4-5", "timeout": 60 }, "detectron2": { "config_file": "COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml", "weights": "output/model_final.pth", "num_classes": 1, "score_thresh": 0.7, "device": "cuda" } }读取配置的代码:
import json, os with open("settings.json", "r", encoding="utf-8") as f: conf = json.load(f) os.environ["TAOTOKEN_BASE_URL"] = conf["taotoken"]["base_url"] os.environ["TAOTOKEN_API_KEY"] = conf["taotoken"]["api_key"]如果你用 Cline 或 Claude Code 这类工具做辅助开发,它们的配置里同样需要三件套:Base URL、API Key、Model ID。以 Cline 的 MCP 配置为例,在cline_mcp_settings.json里写:
{ "mcpServers": { "taotoken": { "command": "npx", "args": ["-y", "@taotoken/mcp-server"], "env": { "TAOTOKEN_BASE_URL": "https://taotoken.net/api", "TAOTOKEN_API_KEY": "sk-你的key", "TAOTOKEN_MODEL": "claude-sonnet-4-5" } } } }Codex 用户则在~/.codex/auth.json里配置:
{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的key", "model": "claude-sonnet-4-5" }三件套缺一不可:Base URL 决定请求打到哪,API Key 决定身份,Model ID 决定调哪个模型。少任何一个都会在请求阶段报错。配置好之后,detectron2 的推理结果可以直接送给大模型做后处理,比如让模型根据检测框生成描述,整条链路只用一个 Key。
4. 验证请求与成功结果:detectron2 导出 ONNX 并跑通推理
配置写好了,接下来验证两件事:detectron2 推理能出结果,TaoToken 通道能通。先验证 detectron2。
导出 ONNX 是部署到 TensorRT、NCNN 的前置步骤。detectron2 自带export_model.py,但新版 onnx 删了onnx.optimizer,需要改 import。把脚本里的import onnx.optimizer改成import onnxoptimizer,或者直接装onnxoptimizer包。另外setup_cfg里的cfg.freeze()要注释掉,否则导出时改配置会报错。
导出命令:
python export_model.py \ --config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ --output ./output \ --export-method caffe2_tracing \ --format onnx \ MODEL.WEIGHTS output/model_final.pth \ MODEL.DEVICE cpu预期输出会在./output下生成model.onnx,同时打印输入输出 schema:
Inputs schema: [{'image': ...}] Outputs schema: [{'instances': ...}]如果报ModuleNotFoundError: No module named 'onnx.optimizer',就是前面说的版本问题,装onnxoptimizer即可。如果报RuntimeError: Exporting to ONNX is not supported for this model,检查--export-method是否用了caffe2_tracing,tracing 方式对某些模型支持不全。
导出 Caffe2 同理,把--format换成caffe2:
python export_model.py \ --config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ --output ./output \ --export-method caffe2_tracing \ --format caffe2 \ MODEL.WEIGHTS output/model_final.pth \ MODEL.DEVICE cpu成功后./output下会有model.pb和model.svg,svg 是计算图可视化,用浏览器打开能看结构。
再验证 TaoToken 通道。用 curl 发一个最小请求:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的key" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-5", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 16 }'预期返回 JSON,包含choices字段和模型回复。如果返回 401,说明 Key 不对或没带Bearer前缀;如果返回 404,检查 Base URL 是不是写成了https://taotoken.net/api(不要多加/v1之外的路径)。
把 detectron2 推理结果接上大模型做描述生成,完整链路大概是这样:
import requests def describe_detection(classes, scores): prompt = f"检测到类别 {classes},置信度 {scores},用一句话描述这张图。" resp = requests.post( "https://taotoken.net/api/v1/chat/completions", headers={"Authorization": f"Bearer {os.environ['TAOTOKEN_API_KEY']}"}, json={ "model": "claude-sonnet-4-5", "messages": [{"role": "user", "content": prompt}], "max_tokens": 128 }, timeout=60 ) return resp.json()["choices"][0]["message"]["content"] print(describe_detection(outputs["instances"].pred_classes.tolist(), outputs["instances"].scores.tolist()))跑通后你会看到类似「图中检测到 2 个气球,置信度分别为 0.92 和 0.88」的输出。这一步过了,说明 detectron2 推理和 TaoToken 通道都正常。
5. 本篇常见报错排查:401、local proxy failed、reading choices、OAuth
部署过程中报错集中在几类,我按真实错误信息对照着说。
401 Unauthorized:TaoToken 请求返回 401,九成是 Key 问题。检查三点:Key 是否从https://taotoken.net/api-keys正确复制(别带空格)、请求头是否是Authorization: Bearer sk-xxx、Key 是否已过期。如果用的是环境变量,打印出来确认没被覆盖:
echo $TAOTOKEN_API_KEYlocal proxy failed:这个报错通常出现在本地起了代理但没配对,或者环境变量HTTP_PROXY/HTTPS_PROXY指向了不可用的地址。先清掉代理环境变量再试:
unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy如果公司网络必须走代理,确认代理地址可达,并且 TaoToken 的域名在放行列表里。注意不要用任何非正规的网络工具,合规网络环境下直接访问即可。
Error reading choices:请求返回了 JSON 但没有choices字段,常见原因是模型名写错,或者请求体格式不对。检查model字段是否是有效 Model ID,messages是否是数组且每条有role和content。用 curl 复现时加-v看完整响应:
curl -v -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的key" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hi"}]}'OAuth 相关报错:如果你用 Claude Code 或类似工具,报 OAuth 失败通常是因为工具默认走官方登录流程,而你要用 API Key 模式。在工具的配置里显式指定 Base URL 和 API Key,关掉 OAuth 登录。Claude Code 的配置在~/.claude/settings.json,写入:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的key" } }detectron2 权重加载报 KeyError:多半是NUM_CLASSES和权重不匹配。训练时cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1,推理时也必须设成 1。如果加载的是 COCO 预训练权重做微调,先设成 80 加载,再改回 1 继续训练。
CUDA out of memory:推理时显存不够,把cfg.MODEL.DEVICE = "cpu"先跑通,或者调小输入尺寸。导出 ONNX 时用MODEL.DEVICE cpu避免占显存。
ImportError: libGL.so.1:容器里缺 opencv 的系统依赖,装libgl1和libglib2.0-0,或者直接用opencv-python-headless。
排查顺序建议:先确认环境(torch + cuda),再确认配置(yaml + 权重路径),最后确认网络(Key + Base URL)。大部分问题在前两步就能定位。
6. 长期跑 detectron2 服务,凭证和通道怎么管
detectron2 推理服务一旦上线,往往不是跑一次就完,而是要长期驻留、批量处理、对接下游。这时候两个东西最容易出问题:一是环境漂移,二是凭证散落。
环境方面,我建议把 Dockerfile 和依赖锁文件一起进版本控制。pip freeze > requirements.lock固定住所有版本,下次重建镜像时用pip install -r requirements.lock,避免某天某个包升级导致编译失败。detectron2 从源码装的话,把 commit hash 记下来,别用main分支,否则重建时可能拉到不兼容的代码。
凭证方面,如果你只跑 detectron2,一个 Key 无所谓;但当你同时接了大模型做后处理、接了其他视觉服务、接了 Agent 做自动化,Key 就会散落在各个脚本、各个容器、各个 CI 配置里。TaoToken 的价值在这里体现:所有模型调用走同一个 Base URL 和同一个 Key,换 Key 只改一处,审计也只查一处。
长期编码和 Agent 场景,可以考虑用 Coding Plan,把日常开发里的模型调用也收敛进来。控制台里能看到用量和调用记录,排查问题时比翻日志快。
最后给一个实用技巧:把 detectron2 的推理封装成 FastAPI 服务,健康检查接口里同时探一下 TaoToken 通道,这样任何一个环节挂了都能第一时间发现。
from fastapi import FastAPI import requests, os app = FastAPI() @app.get("/health") def health(): try: r = requests.post( "https://taotoken.net/api/v1/chat/completions", headers={"Authorization": f"Bearer {os.environ['TAOTOKEN_API_KEY']}"}, json={"model": "claude-sonnet-4-5", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 4}, timeout=10 ) llm_ok = r.status_code == 200 except Exception: llm_ok = False return {"detectron2": "ok", "llm_channel": llm_ok}启动后访问/health,两个都是 ok 就说明整条链路健康。这套组合我用了挺久,环境固定 + 凭证统一,后面加模型、换模型都不用动推理代码,只改配置就行。