90 lines
2.7 KiB
Python
90 lines
2.7 KiB
Python
"""
|
||
商业大模型 API 适配器抽象基类
|
||
============================
|
||
|
||
架构引用: HLDP-ARCH-002 §三 · factory/inference/README.md §四
|
||
作者: 铸渊 · 2026-05-01
|
||
|
||
设计原则:
|
||
- 所有商业 API(DeepSeek / Qwen-Max / Kimi / 文心 / 豆包)实现同一接口
|
||
- 1.5B MP 路由器无感切换、按需替换、按价比选择
|
||
- 每个调用都可被 syslog 审计 + 计费追踪
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
from abc import ABC, abstractmethod
|
||
from dataclasses import dataclass, field
|
||
from typing import Any, AsyncIterator, Optional
|
||
|
||
|
||
@dataclass
|
||
class ChatMessage:
|
||
role: str # 'system' | 'user' | 'assistant'
|
||
content: str
|
||
|
||
|
||
@dataclass
|
||
class CallResult:
|
||
content: str
|
||
usage: dict = field(default_factory=dict) # { prompt_tokens, completion_tokens, total_tokens }
|
||
finish_reason: str = "stop"
|
||
raw: Optional[dict] = None # 提供商原始响应(debug 用)
|
||
|
||
|
||
@dataclass
|
||
class CallOptions:
|
||
temperature: float = 0.7
|
||
max_tokens: int = 2048
|
||
top_p: float = 0.95
|
||
stream: bool = False
|
||
timeout_s: int = 60
|
||
extra: dict = field(default_factory=dict) # 提供商特有参数
|
||
|
||
|
||
class APIAdapter(ABC):
|
||
"""商业大模型 API 统一适配接口。"""
|
||
|
||
@property
|
||
@abstractmethod
|
||
def name(self) -> str:
|
||
"""提供商唯一名(如 'deepseek-r1', 'qwen-max', 'kimi-k2')"""
|
||
|
||
@abstractmethod
|
||
def cost_per_1k_tokens(self, direction: str) -> float:
|
||
"""
|
||
当前定价(人民币 / 1K tokens)
|
||
direction: 'in' (prompt) | 'out' (completion)
|
||
"""
|
||
|
||
@abstractmethod
|
||
def call(self, messages: list[ChatMessage], options: CallOptions) -> CallResult:
|
||
"""同步调用。"""
|
||
|
||
async def stream(
|
||
self, messages: list[ChatMessage], options: CallOptions
|
||
) -> AsyncIterator[str]:
|
||
"""
|
||
流式调用。子类可选实现;默认抛 NotImplementedError。
|
||
"""
|
||
raise NotImplementedError(f"{self.name} 暂未实现 stream")
|
||
|
||
@abstractmethod
|
||
def health(self) -> bool:
|
||
"""连通性 + 配额状态检查。"""
|
||
|
||
# 通用辅助方法(子类可不重写)
|
||
def estimate_cost(self, prompt_tokens: int, completion_tokens: int) -> float:
|
||
return (
|
||
prompt_tokens / 1000.0 * self.cost_per_1k_tokens("in")
|
||
+ completion_tokens / 1000.0 * self.cost_per_1k_tokens("out")
|
||
)
|
||
|
||
def soul_marker(self) -> dict:
|
||
"""每次调用前注入的灵魂印记(写入 syslog)。"""
|
||
return {
|
||
"system_root": "SYS-GLW-0001",
|
||
"sovereign": "TCS-0002∞",
|
||
"copyright": "国作登字-2026-A-00037559",
|
||
"adapter": self.name,
|
||
}
|