Files
MoviePilot/app/application/agent.py

132 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Agent 编排服务门面。
chain 层需要触发 Agent 后台任务、渲染提示词、查询模型能力时统一经本模块调用。
具体实现由 startup 组合根注册,形成依赖倒置:
chain -> application.agent <- startup -> agent
门面保存 provider 而非重量级实现对象,注册本身不会物化 Agent、LLM 或工具树。
本模块禁止静态或函数内导入 app.agent,否则会重新形成跨层循环依赖。
"""
from typing import Any, Callable, Optional
Provider = Callable[[], Any]
# provider 注册表由 startup/initializers/agent.py 在组合根装配。
_agent_manager_provider: Optional[Provider] = None
_running_agent_manager_provider: Optional[Provider] = None
_prompt_manager_provider: Optional[Provider] = None
_agent_capability_manager_provider: Optional[Provider] = None
_llm_helper_provider: Optional[Provider] = None
_manual_redo_prompt_builder_provider: Optional[Provider] = None
def register_agent_service_providers(
*,
agent_manager_provider: Provider,
running_agent_manager_provider: Provider,
prompt_manager_provider: Provider,
capability_manager_provider: Provider,
llm_helper_provider: Provider,
manual_redo_prompt_builder_provider: Provider,
) -> None:
"""注册 Agent 服务 provider,保持组合根装配阶段零重量实现导入。"""
global _agent_manager_provider, _running_agent_manager_provider
global _prompt_manager_provider, _agent_capability_manager_provider
global _llm_helper_provider, _manual_redo_prompt_builder_provider
_agent_manager_provider = agent_manager_provider
_running_agent_manager_provider = running_agent_manager_provider
_prompt_manager_provider = prompt_manager_provider
_agent_capability_manager_provider = capability_manager_provider
_llm_helper_provider = llm_helper_provider
_manual_redo_prompt_builder_provider = manual_redo_prompt_builder_provider
def register_agent_services(
agent_manager: Any,
prompt_manager: Any,
capability_manager: Any,
llm_helper: Any,
manual_redo_prompt_builder: Optional[Callable[[Any], str]] = None,
) -> None:
"""兼容直接对象注入;生产组合根应注册惰性 provider。"""
register_agent_service_providers(
agent_manager_provider=lambda: agent_manager,
running_agent_manager_provider=lambda: agent_manager,
prompt_manager_provider=lambda: prompt_manager,
capability_manager_provider=lambda: capability_manager,
llm_helper_provider=lambda: llm_helper,
manual_redo_prompt_builder_provider=lambda: manual_redo_prompt_builder,
)
def _resolve(provider: Optional[Provider], service_name: str) -> Any:
"""解析已注册服务;缺少组合根装配时给出稳定错误。"""
if provider is None:
raise RuntimeError(
f"Agent 服务 {service_name} 未注册:"
"请先导入 app.startup.initializers.agent 完成组合根装配"
)
return provider()
def get_agent_manager() -> Any:
"""返回 canonical AgentManager;调用可能触发实现物化。"""
return _resolve(_agent_manager_provider, "agent_manager")
def get_running_agent_manager() -> Any | None:
"""返回已进入 RUNNING 的 AgentManager,不触发实现物化。"""
return _resolve(_running_agent_manager_provider, "running_agent_manager")
def get_prompt_manager() -> Any:
"""按需返回提示词管理器。"""
return _resolve(_prompt_manager_provider, "prompt_manager")
def supports_image_input(
provider: Optional[str] = None,
model: Optional[str] = None,
base_url: Optional[str] = None,
base_url_preset: Optional[str] = None,
) -> bool:
"""判断当前模型是否启用了图片输入能力。"""
llm_helper = _resolve(_llm_helper_provider, "llm_helper")
return llm_helper.supports_image_input(
provider=provider,
model=model,
base_url=base_url,
base_url_preset=base_url_preset,
)
def is_audio_input_available() -> bool:
"""判断语音输入能力是否可用。"""
capability_manager = _resolve(
_agent_capability_manager_provider,
"agent_capability_manager",
)
return capability_manager.is_audio_input_available()
def transcribe_audio(content: bytes, filename: str = "input.ogg") -> Optional[str]:
"""把音频内容转写为文本。"""
capability_manager = _resolve(
_agent_capability_manager_provider,
"agent_capability_manager",
)
return capability_manager.transcribe_audio(content, filename=filename)
def build_manual_redo_prompt(history: Any) -> str:
"""构造整理记录 AI 重新整理提示词(builder 由 agent 层注册)。"""
builder = _resolve(
_manual_redo_prompt_builder_provider,
"manual_redo_prompt_builder",
)
if builder is None:
raise RuntimeError("整理记录重新整理提示词构建器未注册")
return builder(history)