mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
refactor: 移除 Python 后端源码,全面迁移至 Rust gateway 架构
- 删除全部 Python 源码 (src/) 及 Alembic 迁移脚本,归档至 _deprecated_py_src/ - 重构 Rust gateway ai_pipeline: 拆分 planner/finalize 模块,新增 contracts/adaptation 层 - 重组 handlers 模块为 admin/public/proxy/internal/shared 子模块结构 - 新增 executor 模块,引入 Rust 原生数据库迁移 (aether-data/migrations) - 简化 CI/Docker 构建流程,移除 base image 二级构建,统一为单一 app image - 移除 Python 相关基础设施文件 (entrypoint.sh, gunicorn_conf.py, Dockerfile.base)
This commit is contained in:
129
_deprecated_py_src/services/billing/rule_templates.py
Normal file
129
_deprecated_py_src/services/billing/rule_templates.py
Normal file
@@ -0,0 +1,129 @@
|
||||
"""
|
||||
Billing rule templates (config-file mode).
|
||||
|
||||
Goal:
|
||||
- Developers define billing rules in code as templates ("模式一/二/三/四/五 ...").
|
||||
- Adding a new billing template should only require adding a new `*.py` file under
|
||||
`src.services.billing.rule_defs` (no DB / no UI).
|
||||
|
||||
How it works:
|
||||
- Each module under `rule_defs/` exports `TEMPLATES: list[CodeBillingRuleTemplate]`.
|
||||
- We dynamically discover all templates at runtime and pick the best one by:
|
||||
- task_type match
|
||||
- optional match(ctx) predicate
|
||||
- highest priority wins
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import pkgutil
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, Iterable
|
||||
|
||||
from src.models.database import GlobalModel, Model
|
||||
from src.services.billing.default_rules import VirtualBillingRule
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RuleTemplateContext:
|
||||
global_model: GlobalModel
|
||||
model: Model | None
|
||||
provider_id: str | None
|
||||
model_name: str
|
||||
task_type: str
|
||||
|
||||
|
||||
MatchFn = Callable[[RuleTemplateContext], bool]
|
||||
BuildFn = Callable[[RuleTemplateContext], VirtualBillingRule]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CodeBillingRuleTemplate:
|
||||
"""
|
||||
A code-defined billing template.
|
||||
|
||||
Notes:
|
||||
- `task_types` are billing-domain task types ("cli" is normalized to "chat" by rule_service).
|
||||
- `build()` must return a VirtualBillingRule-like object (VirtualBillingRule is used here).
|
||||
"""
|
||||
|
||||
name: str
|
||||
description: str
|
||||
task_types: set[str]
|
||||
priority: int = 0
|
||||
match: MatchFn | None = None
|
||||
build: BuildFn | None = None
|
||||
|
||||
def supports(self, task_type: str) -> bool:
|
||||
return (task_type or "").lower() in {t.lower() for t in (self.task_types or set())}
|
||||
|
||||
|
||||
def _iter_modules() -> Iterable[str]:
|
||||
try:
|
||||
pkg = importlib.import_module("src.services.billing.rule_defs")
|
||||
pkg_path = getattr(pkg, "__path__", None)
|
||||
if not pkg_path:
|
||||
return []
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
out: list[str] = []
|
||||
for mod in pkgutil.iter_modules(pkg_path):
|
||||
if mod.ispkg:
|
||||
continue
|
||||
out.append(f"src.services.billing.rule_defs.{mod.name}")
|
||||
return out
|
||||
|
||||
|
||||
def discover_rule_templates() -> list[CodeBillingRuleTemplate]:
|
||||
templates: list[CodeBillingRuleTemplate] = []
|
||||
for mod_name in _iter_modules():
|
||||
try:
|
||||
m = importlib.import_module(mod_name)
|
||||
except Exception:
|
||||
continue
|
||||
items = getattr(m, "TEMPLATES", None)
|
||||
if not isinstance(items, list):
|
||||
continue
|
||||
for t in items:
|
||||
if isinstance(t, CodeBillingRuleTemplate):
|
||||
templates.append(t)
|
||||
# higher priority first, stable within same module import order
|
||||
templates.sort(key=lambda x: int(getattr(x, "priority", 0) or 0), reverse=True)
|
||||
return templates
|
||||
|
||||
|
||||
class CodeBillingRuleTemplateService:
|
||||
@staticmethod
|
||||
def resolve_rule(
|
||||
*,
|
||||
global_model: GlobalModel,
|
||||
model: Model | None,
|
||||
provider_id: str | None,
|
||||
model_name: str,
|
||||
task_type: str,
|
||||
) -> VirtualBillingRule | None:
|
||||
ctx = RuleTemplateContext(
|
||||
global_model=global_model,
|
||||
model=model,
|
||||
provider_id=provider_id,
|
||||
model_name=model_name,
|
||||
task_type=(task_type or "").lower(),
|
||||
)
|
||||
for t in discover_rule_templates():
|
||||
if not t.supports(ctx.task_type):
|
||||
continue
|
||||
if t.match is not None:
|
||||
try:
|
||||
if not bool(t.match(ctx)):
|
||||
continue
|
||||
except Exception:
|
||||
continue
|
||||
if t.build is None:
|
||||
continue
|
||||
try:
|
||||
return t.build(ctx)
|
||||
except Exception:
|
||||
continue
|
||||
return None
|
||||
Reference in New Issue
Block a user