本文详解在 pyvespa 中部署 onnx 模型时常见的路径引用错误,重点说明为何不能在应用包中直接引用宿主机或 docker 卷中的 onnx 文件,并提供可落地的解决方案:将模型文件嵌入 zip 包、正确配置 schema 与 model 定义、确保资源分配充足。
本文详解在 pyvespa 中部署 onnx 模型时常见的路径引用错误,重点说明为何不能在应用包中直接引用宿主机或 docker 卷中的 onnx 文件,并提供可落地的解决方案:将模型文件嵌入 zip 包、正确配置 schema 与 model 定义、确保资源分配充足。
在使用 pyvespa 将 ONNX 模型集成至 Vespa 向量数据库时,一个高频报错是:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
该错误表面看是 JSON 解析失败,但根源往往在于 ONNX 模型文件路径配置不当。Vespa 的应用包(.zip)在部署时会被完整上传并解压到容器内运行;它不支持从外部挂载卷(如 Docker volume)或宿主机绝对路径中动态加载模型文件。也就是说,以下写法是无效的:
# ❌ 错误示例:引用本地/卷路径(部署时不可达)
self.app_package.schema.add_model(
Model(
name="finance_onnx",
model_file="/path/on/host/model.onnx", # ← Vespa 容器内根本不存在此路径!
input="input.1",
output="output.1"
)
)
✅ 正确做法是:将 ONNX 文件作为资源纳入应用包,并使用相对路径引用。具体步骤如下:
- 将 .onnx 文件置于项目目录下(如 models/finance_model.onnx)
- 在 app_package.schema.add_model() 中使用相对于 schema.sd 的路径(即包内路径)
- 确保 pyvespa 构建 ZIP 时包含该文件(默认会自动包含同目录及子目录下的二进制资源)
示例代码(修正后):
from vespa.package import ApplicationPackage, Schema, Document, Field, RankProfile, Model
def create_finance_app(self):
self.app_package = ApplicationPackage(name="finance")
# 定义文档结构(含 embedding 字段)
self.app_package.schema = Schema(
name="finance_doc",
document=Document(
fields=[
Field(name="title", type="string"),
Field(name="embedding", type="tensor(x[1024])"),
]
)
)
# 添加 ONNX 模型(路径为包内相对路径)
self.app_package.schema.add_model(
Model(
name="finance_onnx",
model_file="models/finance_model.onnx", # ✅ 必须存在于项目目录中,且会被打包进 .zip
input="input.1",
output="output.1"
)
)
# 添加 rank profile,调用模型生成 embedding 或打分
self.app_package.schema.add_rank_profile(
RankProfile(
name="default",
first_phase="closeness(field, embedding)",
# 若需用 ONNX 做 query encoding,可配合 query pipeline + function
functions=[
Function(
name="query_embedding",
expression="onnx(model, \"finance_onnx\", {\"input.1\": query(query_tensor)})"
)
],
inputs=[("query(query_tensor)", "tensor(x[1024])")]
)
)
self.app_package.schema.mode = "streaming"
return self.app_package
? 关键注意事项:
- ✅ model_file 必须是相对于 application/ 根目录的路径(如 models/xxx.onnx),且该文件必须物理存在于你的 Python 项目目录中;
- ✅ 部署前请确认 pyvespa 构建的 ZIP 包已包含该 ONNX 文件(可通过 unzip -l app.zip 验证);
- ⚠️ Docker 环境下需为 Vespa 容器分配足够内存(ONNX 推理需额外资源),建议至少 --memory=4g;
- ⚠️ ONNX 模型输入/输出张量名、维度必须与 Vespa schema 和 query tensor 定义严格一致,否则 runtime 报错;
- ? 若仍报 JSON 解析错误,请检查 deploy_app() 中是否误传了空/非法 JSON(如未正确初始化 Vespa() 实例或 deploy() 参数异常)。
总结:Vespa 的模型部署是“静态打包”范式——所有依赖(包括 ONNX、词典、配置)必须内嵌于应用包。理解并遵守这一约束,是成功集成机器学习模型的第一步。