refactor: 收口 V3 分层架构与插件兼容边界

This commit is contained in:
jxxghp
2026-08-18 13:22:02 +08:00
parent cca99bd421
commit 8472bcff43
274 changed files with 10730 additions and 6130 deletions
+1 -18
View File
@@ -1,24 +1,7 @@
"""Agent 内部使用的 LLM 适配层,公开对象按需解析。"""
from importlib import import_module
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from app.agent.llm.capability import (
AgentCapabilityManager,
AgentCapabilityProvider,
AudioCapabilityProvider,
MiMoAudioProvider,
OpenAIAudioProvider,
OpenAIChatAudioProvider,
)
from app.agent.llm.helper import LLMHelper, LLMTestError, LLMTestTimeout
from app.agent.llm.provider import (
LLMProviderAuthError,
LLMProviderError,
LLMProviderManager,
render_auth_result_html,
)
from typing import Any
_EXPORT_MODULES = {
+1 -1
View File
@@ -799,7 +799,7 @@ class AgentCapabilityManager:
if not source:
return False
from app.runtime.extensions.service_registry import ServiceConfigHelper
from app.runtime.extensions.service_config import ServiceConfigHelper
for config in ServiceConfigHelper.get_notification_configs():
if config.name != source:
+49
View File
@@ -0,0 +1,49 @@
"""LLM helper 与 provider 实现之间的运行时端口。"""
from collections.abc import Callable
from typing import Any, Protocol
class LLMProviderRuntimePort(Protocol):
"""声明 LLM helper 所需的最小 provider 运行时能力。"""
def resolve_cached_model_metadata(self, **kwargs: Any) -> dict[str, Any] | None:
"""从本地目录缓存解析模型元数据。"""
...
async def resolve_runtime(self, **kwargs: Any) -> dict[str, Any]:
"""解析创建模型客户端所需的统一运行时参数。"""
...
def create_bedrock_client(self, *args: Any, **kwargs: Any) -> Any:
"""创建带统一认证和网络配置的 Bedrock 客户端。"""
...
async def list_models(self, **kwargs: Any) -> list[dict[str, Any]]:
"""返回 provider 可用的模型目录。"""
...
def resolve_model_list_base_url(self, **kwargs: Any) -> str | None:
"""解析兼容接口用于查询模型列表的基础地址。"""
...
LLMProviderRuntimeFactory = Callable[[], LLMProviderRuntimePort]
_provider_runtime_factory: LLMProviderRuntimeFactory | None = None
def register_llm_provider_runtime(
factory: LLMProviderRuntimeFactory | None,
) -> LLMProviderRuntimeFactory | None:
"""注册 provider 运行时工厂,并返回先前工厂供隔离测试恢复。"""
global _provider_runtime_factory
previous = _provider_runtime_factory
_provider_runtime_factory = factory
return previous
def resolve_llm_provider_runtime() -> LLMProviderRuntimePort:
"""解析已组装的 provider 运行时,未注册时给出明确边界错误。"""
if _provider_runtime_factory is None:
raise RuntimeError("LLM provider 运行时尚未由启动层完成组装")
return _provider_runtime_factory()
+6 -17
View File
@@ -10,6 +10,7 @@ from urllib.parse import urlsplit
from langchain_core.messages import AIMessage, AIMessageChunk
from app.agent.llm.gateway import resolve_llm_provider_runtime
from app.runtime.config import settings
from app.runtime.log import logger
@@ -793,9 +794,7 @@ class LLMHelper:
return None
try:
from app.agent.llm.provider import LLMProviderManager
metadata = LLMProviderManager().resolve_cached_model_metadata(
metadata = resolve_llm_provider_runtime().resolve_cached_model_metadata(
provider_id=provider_name,
model_id=model_name,
base_url=base_url if base_url is not None else settings.LLM_BASE_URL,
@@ -1197,11 +1196,7 @@ class LLMHelper:
thinking_level=thinking_level,
)
try:
# 延迟导入,避免单测在最小 stub 环境下 import `llm.py` 时被 provider
# 目录依赖链拖住。
from app.agent.llm.provider import LLMProviderManager
runtime = await LLMProviderManager().resolve_runtime(
runtime = await resolve_llm_provider_runtime().resolve_runtime(
provider_id=provider_name,
model=model_name,
api_key=api_key_value,
@@ -1328,8 +1323,6 @@ class LLMHelper:
elif runtime["runtime"] == "bedrock":
from langchain_aws import ChatBedrockConverse
from app.agent.llm.provider import LLMProviderManager
bedrock_model_cls = ChatBedrockConverse
if (
str(prompt_cache_key or "").strip()
@@ -1344,7 +1337,7 @@ class LLMHelper:
aws_auth = runtime.get("aws_auth") or {}
# Bearer 认证需要跳过 SigV4 签名并注入 Authorization 头,SigV4 认证
# 直接以 AK/SK 签名;两种方式统一由 provider 管理器构造 boto3 客户端。
bedrock_client = LLMProviderManager().create_bedrock_client(
bedrock_client = resolve_llm_provider_runtime().create_bedrock_client(
"bedrock-runtime",
region=aws_region,
credentials=aws_auth,
@@ -1558,9 +1551,7 @@ class LLMHelper:
"""
logger.info(f"获取 {provider} 模型列表...")
try:
from app.agent.llm.provider import LLMProviderManager
models = await LLMProviderManager().list_models(
models = await resolve_llm_provider_runtime().list_models(
provider_id=provider,
api_key=api_key,
base_url=base_url,
@@ -1589,10 +1580,8 @@ class LLMHelper:
base_url=base_url,
)
try:
from app.agent.llm.provider import LLMProviderManager
model_list_base_url = (
LLMProviderManager().resolve_model_list_base_url(
resolve_llm_provider_runtime().resolve_model_list_base_url(
provider_id=provider,
base_url=base_url,
base_url_preset_id=base_url_preset,
+1 -1
View File
@@ -21,7 +21,7 @@ import httpx
import jwt
from app.runtime.config import settings
from app.db.oper.systemconfig import SystemConfigOper
from app.application.configuration import get_configured_system_config as SystemConfigOper
from app.runtime.log import logger
from app.schemas.types import LlmProviderAction, SystemConfigKey
from app.foundation.singleton import Singleton