mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-06 07:56:52 +08:00
refactor: 收口 V3 分层架构与插件兼容边界
This commit is contained in:
@@ -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 = {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user