feat(#57): InferenceBackend 抽象接口定义(PRD 5.6 loadModel/infer/health/unload)

将原先内联在 gateway.py 的薄弱 InferenceBackend 提炼为正式抽象基类(ABC),
对齐 PRD 5.6「⑥ 部署底座」契约,为 #44/#45/#58/#59 各类后端提供统一接入点。

实现内容:
- 新增 core/llm-gateway/backends.py:
  · InferenceBackend(ABC):PRD 要求的四个生命周期方法 load_model / infer /
    health_check / unload(均幂等),能力声明 capabilities,并保留 generate()
    向后兼容(转发到 infer().text)
  · 值对象 BackendCapabilities(streaming/max_concurrency/on_premises/modalities)
    / BackendHealth(healthy/detail/checked_at)/ InferResult(text+审计元信息)
  · LocalBackend / CloudBackend 占位实现迁移至此并继承新 ABC,补齐生命周期
  · default_registry + build_backend:配置驱动切换后端(未知 name 报错并提示已知项)
- gateway.py:删除内联定义,改为从 backends.py 再导出,LLMGateway.ask() 调用路径不变
- __init__.py:再导出新符号(BackendCapabilities/BackendHealth/InferResult/
  build_backend/default_registry),InferenceBackend 现为 ABC

设计原则:业务代码仅依赖接口,不感知硬件;切换后端 = 换实现 + 改配置,业务零改动。

测试:core/llm-gateway 全量 97 个用例通过(新增 27 + 既有 70,零回归)。
运行:python -m unittest discover -s tests -v(在 core/llm-gateway 目录下)
This commit is contained in:
2026-08-04 21:04:00 +08:00
parent 691a812fcf
commit 03ae81a217
4 changed files with 635 additions and 63 deletions
+18 -61
View File
@@ -12,12 +12,15 @@
- `router`(SensitivityRouter):敏感度分级路由(local / cloud / block);
- `prompts`(PromptRegistry):提示词模板版本绑定(可复现);
- `guard`(HallucinationGuard):引用溯源 + 信度阈值 → 人工确认;
- `backends`(LocalBackend / CloudBackend):推理后端抽象(可注入)。
- `backends`(InferenceBackend / LocalBackend / CloudBackend):推理后端抽象
(可注入)。接口定义已提炼到 `backends.py`(Issue #57,对齐 PRD 5.6)。
设计说明:
- 本版提供**编排闭环 + 后端抽象接口**,本地 70B / 云端 API 的具体接入
由子任务 #44 / #45 实现;`LocalBackend` / `CloudBackend` 默认内置一个
最小实现(返回固定占位答案 + 回显引用),供端到端测试与演示。
- 推理后端契约(`loadModel / infer / health_check / unload`)见 `backends.py`,
本模块仅消费其 `generate` / `name`,业务代码不感知具体硬件。
测试:`python -m unittest discover -s tests -v`(在 core/llm-gateway 目录下执行)。
"""
@@ -26,71 +29,25 @@ from __future__ import annotations
import uuid
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Callable, Dict, List, Optional, Sequence
from typing import Dict, List, Optional, Sequence
from .dlp import DlpEngine
from .router import RouteDecision, RouteTarget, SensitivityRouter
from .prompts import PromptRegistry
from .hallucination import GuardVerdict, HallucinationGuard
# ---------------------------------------------------------------------------
# 推理后端抽象(Issue #44 / #45 将实现具体后端,业务代码只依赖本接口)
# ---------------------------------------------------------------------------
class InferenceBackend:
"""推理后端接口抽象(对齐 PRD 5.6 InferenceBackend 思想)。
业务代码只依赖本接口,不感知具体硬件/厂商;切换后端 = 换实现。
子任务 #44(本地 70B)、#45(云端 Qwen/DeepSeek)将各自实现本接口。
"""
name: str = "base"
def generate(self, prompt: str, context: Sequence[str]) -> str:
"""根据 prompt 与 RAG 上下文生成回答。子类实现。"""
raise NotImplementedError
class LocalBackend(InferenceBackend):
"""本地 70B 后端占位实现:数据不出厂(敏感/核心走此通道)。
子任务 #44 将替换为真实本地模型推理封装(vLLM/TGI 等)。
"""
name = "local-70b"
def __init__(self, echo_context: bool = True) -> None:
self.echo_context = echo_context
def generate(self, prompt: str, context: Sequence[str]) -> str:
head = f"[本地70B占位] {prompt[:40]}"
refs = ""
if self.echo_context:
for i, src in enumerate(context[:3], 1):
refs += f"\n[来源: {src}]"
return head + refs
class CloudBackend(InferenceBackend):
"""云端 API 后端占位实现:仅接收 DLP 放行的脱敏/通用内容。
子任务 #45 将替换为 Qwen/DeepSeek API 接入 + 安全网关。
"""
name = "cloud-api"
def __init__(self, echo_context: bool = True) -> None:
self.echo_context = echo_context
def generate(self, prompt: str, context: Sequence[str]) -> str:
head = f"[云端API占位] {prompt[:40]}"
refs = ""
if self.echo_context:
for i, src in enumerate(context[:3], 1):
refs += f"\n[来源: {src}]"
return head + refs
# 推理后端抽象(Issue #57):契约定义在 backends.py,这里仅做再导出,
# 保持 ``from .gateway import InferenceBackend/LocalBackend/CloudBackend`` 的
# 向后兼容(既有 import 路径与 ``LLMGateway`` 依赖均不变)。
from .backends import (
BackendCapabilities,
BackendHealth,
CloudBackend,
InferResult,
InferenceBackend,
LocalBackend,
build_backend,
default_registry,
)
# ---------------------------------------------------------------------------
# 网关输出