Files
iAOP/core/inference-backend/factory.py
T

69 lines
2.6 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""推理后端工厂:按配置选择后端实现(可插拔适配层)。
PRD 5.6「配置点:资源配额、推理后端选择、灰度发布策略」——
`backend: gpu|npu` 即推理后端选择;业务代码只调用 `build_backend()`
返回的接口对象,不感知具体硬件。
"""
import os
from inference_backend.base import InferenceBackend
from inference_backend.gpu_backend import NvidiaGpuBackend
from inference_backend.npu_backend import AscendNpuBackend
#: 可插拔后端注册表:配置名 -> 实现类。新增硬件只需注册新类。
BACKEND_REGISTRY = {
"gpu": NvidiaGpuBackend, # NVIDIA 5090(Triton/ONNX)
"npu": AscendNpuBackend, # 华为昇腾(ACL/CANN)
}
def build_backend(config: dict) -> InferenceBackend:
"""依据配置构建推理后端实例(切换后端仅改配置,业务代码零改动)。
Args:
config: 后端配置字典(见 config/backends.template.yaml),
至少包含 ``backend`` 键(gpu | npu)。
Returns:
实现了 :class:`InferenceBackend` 接口的后端实例。
Raises:
ValueError: 配置缺失或指定了未注册的后端。
"""
if not isinstance(config, dict) or not config.get("backend"):
raise ValueError("推理后端配置缺失:需要 backend: gpu|npu")
name = str(config["backend"]).lower()
if name not in BACKEND_REGISTRY:
raise ValueError(
f"未注册的推理后端: {name!r},可用: {sorted(BACKEND_REGISTRY)}"
)
cls = BACKEND_REGISTRY[name]
inf = config.get("inference", {}) or {}
kwargs = dict(
endpoint=inf.get("endpoint", ""),
model=inf.get("model", "iaop-default"),
timeout_seconds=float(inf.get("timeout_seconds", 10)),
)
# 空值/缺省不覆盖后端类默认(如昇腾 npu 默认 mindie / ascend-910b / CANN 8.0),
# 保证「切换后端仅改 backend 字段」时硬件相关参数落到正确的默认值。
for key in ("runtime", "device", "cann_version"):
value = inf.get(key)
if value:
kwargs[key] = value
return cls(**kwargs)
def load_backend_config(path: str) -> dict:
"""从 YAML 配置资产加载后端配置(模板可覆盖资产)。"""
import yaml
with open(path, "r", encoding="utf-8") as fh:
return yaml.safe_load(fh) or {}
def default_config_path() -> str:
"""返回本模块模板配置资产的默认路径。"""
return os.path.join(os.path.dirname(os.path.abspath(__file__)),
"config", "backends.template.yaml")