1. 从一次“密钥散落”的推理环境搭建说起
ONNX Runtime 是微软推出的跨平台推理引擎,能直接加载.onnx模型文件,在 CPU、GPU 上跑前向计算,适合做模型部署、批量推理和端侧验证。它本身不依赖训练框架,PyTorch、TensorFlow 导出的 ONNX 模型都能吃进来,对刚接触推理优化的同学来说,是比 TensorRT、OpenVINO 更容易上手的一站。但真正从零搭环境时,麻烦往往不在 ONNX Runtime 本身,而在“周边配套”:模型下载、辅助脚本生成、文档查询、多工具调用时,每个环节都要单独配一份 Key,散落在settings.json、config.toml、环境变量里,改一处忘一处,排查起来很费时间。
这篇就聚焦这个场景:用 TaoToken 的统一 Key 和 API 通道,把 ONNX Runtime 推理环境搭建过程中涉及的模型获取、配置生成、请求验证串起来。你会拿到两份可直接复制的配置骨架——settings.json和config.toml,再跟着做一次模型加载与推理请求,确认通道连通。适合刚装完onnxruntime、还没跑通第一条推理命令的初学者,也适合手里有多个工具、想统一管理密钥的开发者。
我试过把模型下载、配置生成、推理验证拆成三步走,每步只改一个地方,出错时定位会快很多。下面按这个节奏来。
2. TaoToken 前置:统一 Key 与 API 通道准备
TaoToken 在这里扮演的角色是“统一入口”:你不需要为每个工具单独申请一套凭证,而是用同一个 Key 走同一个 API 通道,配置里只维护一份。对 ONNX Runtime 场景来说,它主要覆盖两类动作——拉取模型或辅助资源、调用模型对话类接口做结果校验。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 根地址是 https://taotoken.net/api (这个不加 UTM,直接填进配置)。
开始前你需要准备三样东西:一个可用的 TaoToken Key、Python 3.8 以上的环境、以及onnxruntime包。Key 的获取走控制台,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,登录后在 API Keys 页面创建,具体页面在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。创建完先复制到本地临时文件,别直接贴进代码仓库。
注意:Key 只显示一次,创建后立刻保存。后面
settings.json和config.toml里都引用同一个值,不要写两份不同的。
环境侧先装依赖,命令如下:
python -m venv ort-env source ort-env/bin/activate # Windows 用 ort-env\Scripts\activate pip install onnxruntime numpy requests如果你要用 GPU,把onnxruntime换成onnxruntime-gpu,并确认 CUDA 版本匹配。装完用python -c "import onnxruntime as rt; print(rt.__version__)"确认版本号能打印出来,这一步过了再往下走。
3. 可复制配置:settings.json 与 config.toml 骨架
配置分两份,职责不同。settings.json放运行时参数和通道地址,config.toml放模型路径、provider 选择和请求超时。两份都只引用同一个 Key 变量,避免硬编码。
先建目录结构:
mkdir -p ort-demo/config ort-demo/models cd ort-demosettings.json骨架如下,放在config/下:
{ "api_base": "https://taotoken.net/api", "api_key_env": "TAOTOKEN_API_KEY", "default_model": "gpt-4o-mini", "request_timeout": 30, "log_level": "INFO" }这里api_key_env指向环境变量名,而不是把 Key 写死。运行时用export TAOTOKEN_API_KEY=你的Key注入,配置文件和代码都不落明文。
config.toml骨架如下,同样放config/下:
[model] path = "models/resnet50.onnx" input_name = "input" input_shape = [1, 224, 224, 3] output_names = ["output"] [runtime] providers = ["CPUExecutionProvider"] intra_op_num_threads = 4 graph_optimization_level = "ORT_ENABLE_ALL" [request] timeout = 30 retry = 2两份配置的对应关系用表格对照更清楚:
| 配置项 | 所在文件 | 作用 | 是否引用 Key |
|---|---|---|---|
| api_base | settings.json | 统一 API 根地址 | 否 |
| api_key_env | settings.json | 指向环境变量名 | 间接 |
| path | config.toml | ONNX 模型文件路径 | 否 |
| providers | config.toml | 推理后端选择 | 否 |
| timeout | 两份都有 | 请求超时秒数 | 否 |
提示:
providers先写CPUExecutionProvider,确认跑通后再换CUDAExecutionProvider。换后端时只改这一行,其他不动。
配置写完后,用一条命令校验 JSON 和 TOML 语法:
python -c "import json, tomllib; json.load(open('config/settings.json')); tomllib.load(open('config/config.toml','rb')); print('config ok')"打印config ok说明两份骨架都没语法问题。
4. 验证请求:一次模型加载与推理动作
配置就绪后,做一次最小验证:加载 ONNX 模型、跑一次前向推理、再用统一通道发一个校验请求。先准备一个测试模型,如果你手头没有.onnx文件,可以用下面的脚本从 ONNX Runtime 官方示例导出一个小的:
import numpy as np import onnx from onnx import helper, TensorProto input_tensor = helper.make_tensor_value_info("input", TensorProto.FLOAT, [1, 3, 224, 224]) output_tensor = helper.make_tensor_value_info("output", TensorProto.FLOAT, [1, 1000]) node = helper.make_node("GlobalAveragePool", ["input"], ["output"]) graph = helper.make_graph([node], "demo", [input_tensor], [output_tensor]) model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 13)]) onnx.save(model, "models/resnet50.onnx") print("model saved")跑完会在models/下生成resnet50.onnx。接着写推理脚本infer.py:
import json import os import time import numpy as np import onnxruntime as rt import tomllib with open("config/settings.json") as f: settings = json.load(f) with open("config/config.toml", "rb") as f: cfg = tomllib.load(f) api_key = os.environ.get(settings["api_key_env"]) assert api_key, "TAOTOKEN_API_KEY 未设置" sess = rt.InferenceSession( cfg["model"]["path"], providers=cfg["runtime"]["providers"], ) input_name = sess.get_inputs()[0].name dummy = np.random.randn(*cfg["model"]["input_shape"]).astype(np.float32) t0 = time.perf_counter() out = sess.run(cfg["model"]["output_names"], {input_name: dummy}) cost = time.perf_counter() - t0 print(f"inference ok, cost={cost:.6f}s, out_shape={out[0].shape}")执行:
export TAOTOKEN_API_KEY=你的Key python infer.py预期输出类似inference ok, cost=0.003421s, out_shape=(1, 1000)。这一步证明模型加载和推理链路通了。接着验证统一通道,用requests发一个最小请求:
import os, requests, json settings = json.load(open("config/settings.json")) key = os.environ[settings["api_key_env"]] resp = requests.post( f"{settings['api_base']}/v1/chat/completions", headers={"Authorization": f"Bearer {key}"}, json={"model": settings["default_model"], "messages": [{"role": "user", "content": "ping"}]}, timeout=settings["request_timeout"], ) print(resp.status_code, resp.json()["choices"][0]["message"]["content"][:40])返回200且打印出内容片段,说明 Key 和通道都正常。想直接在网页端确认模型可用性,可以走模型对话页面 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite ,发一条消息看是否有回复。
5. 本篇常见错排查
报错一:ModuleNotFoundError: No module named 'onnxruntime'原因通常是虚拟环境没激活,或者装到了全局 Python。先which python确认路径在ort-env下,再pip install onnxruntime。GPU 版装onnxruntime-gpu,两者不要同时装。
报错二:InvalidGraph: No Op registered for GlobalAveragePool with domain_version of 13opset 版本和 ONNX Runtime 版本不匹配。用python -c "import onnxruntime as rt; print(rt.__version__)"看版本,低于 1.10 的把导出脚本里的opset降到 11。
报错三:TAOTOKEN_API_KEY 未设置环境变量没导出,或者settings.json里api_key_env写成了别的名字。检查echo $TAOTOKEN_API_KEY是否有值,再核对配置里的变量名是否一致。
报错四:请求返回401Key 失效或复制时带了空格。重新在 API Keys 页面生成一个,注意复制完整字符串。如果用的是 Coding Plan 相关额度,确认套餐状态,页面在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。
报错五:providers写CUDAExecutionProvider但报找不到CUDA 或 cuDNN 版本不匹配。先用CPUExecutionProvider跑通,再按 ONNX Runtime 官方矩阵核对 CUDA 版本,别直接改配置硬上。
报错六:TOML 解析报KeyError: 'model'config.toml里 section 名拼错,或者文件路径不对。用第 3 节的校验命令先过语法,再确认tomllib.load打开的是同一个文件。
6. 后续接入与通道选择
跑通上面这套之后,配置骨架基本不用大改。如果你要长期做编码类任务、把 ONNX Runtime 推理接进 Agent 流程,可以看 Coding Plan 的接入方式,地址是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它适合需要持续调用、额度稳定的场景。如果只是偶尔验证模型输出,走模型对话页面更轻量。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有各语言 SDK 的调用示例,配置字段和本篇的settings.json能对上。
Claude Code 这类工具如果也要接同一通道,参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 的说明,Key 还是同一个,不用再申请。实际用下来,把 Key 收敛到一处之后,改配置的次数明显少了,排查时也只需要盯一个环境变量。