69 lines
2.6 KiB
Python
69 lines
2.6 KiB
Python
# -*- 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")
|