M4b:ai_provider 删除手术①-⑥——神识全面接管模型出口

- ① 后端删除 app/ai_provider/(38 文件,含 anthropic/openai 格式、billing、audio、embedding)、services/ai_provider_admin.py、core/config/model_config.py、tests/ai_provider/(21 文件)
- ② 连带退役 application/agent/(旧 Agent 循环/steer/follow-up/确认注册表)、application/skill_executor.py、app/skills/(python skills 孤儿)、endpoints/audio.py、application/imports.py(ProviderManager 消费方);settings 端点收敛为生成偏好
- ③ runs.py 修剪:AgentRunRegistry/steer/follow-up/confirmations 端点退役,保留 list/get/events/cancel/stream;safety 确认改为直接落库裁决(pending→approved/denied)
- ④ 前端删除:models 页、ModelGatewayView、gateway.ts、GatewayPanel(玄关)、ModelGatewayPanel/ModelStrategyForm、audio.ts/useVoiceInput、网关类型与 mock;设置页收敛为外观/语言/通知
- ⑤ 配置收敛:config/models|providers|pricing.example.yaml 归档 shenshi/config/;.env.example 删 provider keys/MODEL_ENDPOINT_POOL/MODEL_CONFIG_PATH,收敛 SHENSHI_*
- ⑥ 验收:rg 审计灵台 Provider SDK import 与 ai_provider 引用归零;后端 528 passed(2 个预存失败经 HEAD 复跑验证与本手术无关)、前端 type-check+201 passed、神识 go vet+test、BFF 4 passed
This commit is contained in:
chenxin committed 2026-08-27 10:02:44 +08:00
1 parent 0d383725b5
commit 462d570751
129 files changed
+81 -15867

No files matched your search

+2 -91
View File
@@ -1,11 +1,8 @@
"""设置服务:模型网关状态聚合与生成偏好。
"""设置服务:生成偏好。
模型网关状态从 config/models.yaml 派生,provider 密钥按 settings 是否配置脱敏为
configured 布尔(绝不暴露值);生成偏好为本地单用户单行,无则返回默认值。
生成偏好为本地单用户单行,无则返回默认值;模型网关状态由神识承接(用户面见神识阁)。
"""
from app.ai_provider.config.loader import load_models_config
from app.ai_provider.config.models import ModelConfig
from app.core.config import settings
from app.core.time import utc_now
from app.db.session import AsyncSessionLocal
@@ -13,96 +10,10 @@ from app.models.governance import GenerationPreferences
from app.repositories import preferences as preferences_repo
from app.schemas.preferences import (
GenerationPreferencesResponse,
LogicalModel,
ModelEndpointStatus,
ModelGatewayStatus,
ProviderKeyStatus,
UpdateGenerationPreferencesRequest,
)
from app.services.ai_provider_admin import get_endpoint_overrides_cache
from app.services.serializers import generation_preferences_to_response
# provider → 持有其 API Key 的环境变量名;未登记的 provider 回退 <PROVIDER>_API_KEY。
_PROVIDER_KEY_ENV: dict[str, str] = {
"openai": "OPENAI_API_KEY",
"deepseek": "DEEPSEEK_API_KEY",
"anthropic": "ANTHROPIC_API_KEY",
"google": "GOOGLE_API_KEY",
"minimax": "MINIMAX_API_KEY",
"zhipu": "ZHIPU_API_KEY",
"tencentcloud": "TENCENTCLOUD_API_KEY",
"volcengine": "VOLCENGINE_ARK_API_KEY",
"bailian": "BAILIAN_API_KEY",
}
def provider_configured(provider: str | None) -> bool:
"""provider 的 API Key 是否已在 settings 配置(仅返回布尔,不暴露值)。"""
if not provider:
return False
env_name = _PROVIDER_KEY_ENV.get(provider, f"{provider.upper()}_API_KEY")
return bool(getattr(settings, env_name.lower(), None))
def _endpoint_status(
endpoint, model_name: str, provider: str, overrides_cache
) -> ModelEndpointStatus:
ov = overrides_cache.get((model_name, endpoint.name))
return ModelEndpointStatus(
name=endpoint.name,
provider=provider,
status=(ov.get("status") or endpoint.status) if ov else endpoint.status,
weight=endpoint.weight,
priority=endpoint.priority,
is_overridden=ov is not None,
has_url_override=bool(ov and ov.get("base_url")),
has_key_override=bool(ov and ov.get("api_key")),
base_url_env=endpoint.base_url_env,
api_key_env=endpoint.api_key_env,
)
def _logical_model(cfg: ModelConfig, overrides_cache) -> LogicalModel:
provider = cfg.provider or "unknown"
endpoints = [
_endpoint_status(ep, cfg.name, provider, overrides_cache) for ep in cfg.endpoints
] or None
return LogicalModel(
name=cfg.name,
display_name=cfg.display_name or cfg.name,
provider=provider,
capabilities=[k for k, v in cfg.resolved_capabilities().items() if v],
routing_strategy=cfg.routing_strategy,
supports_streaming=bool(cfg.supports_streaming),
supports_thinking=bool(cfg.supports_thinking),
supports_structured_output=bool(cfg.supports_structured_output),
context_window=cfg.context_window,
max_output_tokens=cfg.max_output_tokens,
endpoints=endpoints,
is_default=True if cfg.name == settings.default_model_hint else None,
)
def get_provider_gateway() -> ModelGatewayStatus:
"""从 config/models.yaml 派生模型网关总览(含 DB 覆盖标记,脱敏不回原值)。"""
models_cfg = load_models_config()
overrides_cache = get_endpoint_overrides_cache()
providers_seen: dict[str, None] = {}
logical_models: list[LogicalModel] = []
for cfg in models_cfg:
logical_models.append(_logical_model(cfg, overrides_cache))
provider = cfg.provider or "unknown"
providers_seen.setdefault(provider, None)
providers = [
ProviderKeyStatus(provider=name, configured=provider_configured(name))
for name in providers_seen
]
return ModelGatewayStatus(
models=logical_models,
providers=providers,
default_model_hint=settings.default_model_hint,
)
def _default_preferences() -> GenerationPreferences:
return GenerationPreferences(