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:
1 parent
0d383725b5
commit
462d570751
129 files changed
+81
-15867
No files matched your search
@@ -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(
|
||||
|
||||
Reference in new issue
Block a user