refactor: introduce transport-neutral connection runtime

This commit is contained in:
caixypromise
2026-07-27 02:05:26 +08:00
parent f5ed1aaec8
commit 0c582ed3b6
56 changed files with 9931 additions and 237 deletions
@@ -0,0 +1,116 @@
from typing import Any, Dict
from core.components.component_manager import Component, ComponentType, ComponentFactory
from core.utils import asr
from core.utils.modules_initialize import initialize_asr
from config.logger import setup_logging
logger = setup_logging()
TAG = __name__
class ASRAdapter(Component):
"""
ASR组件适配器:将现有ASR组件包装为新的组件接口
支持两种模式:
1. 共享实例模式:使用 SharedASRManager 的全局共享实例
2. 独立实例模式:每个连接创建独立的 ASR 实例(原有逻辑)
"""
def __init__(self, config: Dict[str, Any]):
super().__init__(ComponentType.ASR, config)
self._asr_instance = None
self._delete_audio = config.get("delete_audio", True)
self._using_shared = False # 是否使用共享实例
self._shared_owner = None
async def _do_initialize(self, context: Any) -> None:
"""初始化ASR组件"""
try:
# 获取ASR配置
selected_module = self.config.get("selected_module", {}).get("ASR")
if not selected_module:
raise ValueError("未配置ASR模块")
# 检查是否有全局共享 ASR 管理器
shared_manager = getattr(context, 'shared_asr_manager', None)
acquired_manager = None
if shared_manager and hasattr(shared_manager, "acquire_for_config"):
acquired_manager = await shared_manager.acquire_for_config(
self.config
)
elif (
shared_manager
and shared_manager.is_ready()
and shared_manager.matches_config(self.config)
):
acquired_manager = shared_manager
if acquired_manager is not None:
# 使用共享实例模式
logger.bind(tag=TAG).info(f"使用共享 ASR 实例: {selected_module}")
from core.providers.asr.shared_asr_proxy import SharedASRProxy
self._asr_instance = SharedASRProxy(acquired_manager)
self._using_shared = True
self._shared_owner = shared_manager
else:
# 使用独立实例模式(原有逻辑)
if shared_manager and shared_manager.is_ready():
logger.bind(tag=TAG).info(
f"连接ASR配置与共享实例不匹配,使用独立实例: {selected_module}"
)
logger.bind(tag=TAG).info(f"使用独立 ASR 实例: {selected_module}")
self._asr_instance = initialize_asr(self.config)
self._using_shared = False
# Legacy providers inspect conn.asr while handling stream state.
context.asr = self._asr_instance
# 打开音频通道(如果需要)
if hasattr(self._asr_instance, 'open_audio_channels'):
await self._asr_instance.open_audio_channels(context)
logger.bind(tag=TAG).info(
f"ASR组件初始化完成: {selected_module}, "
f"共享模式: {self._using_shared}"
)
except Exception as e:
logger.bind(tag=TAG).error(f"ASR组件初始化失败: {e}")
raise
async def _do_cleanup(self) -> None:
"""清理ASR组件"""
if self._asr_instance:
instance = self._asr_instance
if self._using_shared:
await self._close_resource(instance)
if self._shared_owner and hasattr(
self._shared_owner, "release_for_config"
):
await self._shared_owner.release_for_config(instance.manager)
logger.bind(tag=TAG).debug("共享 ASR 代理已释放")
else:
await self._close_resource(instance)
if hasattr(instance, 'cleanup_audio_files'):
instance.cleanup_audio_files()
logger.bind(tag=TAG).info("ASR组件清理完成")
self._asr_instance = None
self._using_shared = False
self._shared_owner = None
@property
def asr_instance(self):
"""获取ASR实例"""
return self._asr_instance
class ASRFactory(ComponentFactory):
"""ASR组件工厂"""
def create(self, config: Dict[str, Any]) -> Component:
return ASRAdapter(config)
def get_component_type(self) -> ComponentType:
return ComponentType.ASR
@@ -0,0 +1,92 @@
from typing import Any, Dict
from core.components.component_manager import Component, ComponentType, ComponentFactory
from core.utils import intent, llm
from config.logger import setup_logging
logger = setup_logging()
class IntentAdapter(Component):
"""Intent组件适配器:将现有Intent组件包装为新的组件接口"""
def __init__(self, config: Dict[str, Any]):
super().__init__(ComponentType.INTENT, config)
self._intent_instance = None
self._owned_llm_instance = None
async def _do_initialize(self, context: Any) -> None:
"""初始化Intent组件"""
try:
# 获取Intent配置
selected_module = self.config.get("selected_module", {}).get("Intent")
if not selected_module:
raise ValueError("未配置Intent模块")
# 获取Intent类型
intent_type = (
selected_module
if "type" not in self.config["Intent"][selected_module]
else self.config["Intent"][selected_module]["type"]
)
# 创建Intent实例
self._intent_instance = intent.create_instance(
intent_type,
self.config["Intent"][selected_module],
)
# intent_llm 可配置独立模型;未配置时回退主 LLM。
if intent_type == "intent_llm":
llm_component = None
if getattr(context, "component_manager", None):
llm_component = await context.component_manager.get_component(ComponentType.LLM, context)
main_llm = getattr(llm_component, "llm_instance", None)
intent_config = self.config["Intent"][selected_module]
dedicated_llm_name = intent_config.get("llm")
selected_llm = main_llm
if (
dedicated_llm_name
and dedicated_llm_name in self.config.get("LLM", {})
):
dedicated_config = self.config["LLM"][dedicated_llm_name]
dedicated_type = dedicated_config.get("type", dedicated_llm_name)
self._owned_llm_instance = llm.create_instance(
dedicated_type, dedicated_config
)
selected_llm = self._owned_llm_instance
logger.info(f"为意图识别创建专用LLM: {dedicated_llm_name}")
if selected_llm and hasattr(self._intent_instance, "set_llm"):
self._intent_instance.set_llm(selected_llm)
logger.info(f"Intent组件初始化完成: {intent_type}")
except Exception as e:
logger.error(f"Intent组件初始化失败: {e}")
raise
async def _do_cleanup(self) -> None:
"""清理Intent组件"""
if self._intent_instance:
instance = self._intent_instance
await self._close_resource(instance)
self._intent_instance = None
logger.info("Intent组件清理完成")
if self._owned_llm_instance:
instance = self._owned_llm_instance
await self._close_resource(instance)
self._owned_llm_instance = None
@property
def intent_instance(self):
"""获取Intent实例"""
return self._intent_instance
class IntentFactory(ComponentFactory):
"""Intent组件工厂"""
def create(self, config: Dict[str, Any]) -> Component:
return IntentAdapter(config)
def get_component_type(self) -> ComponentType:
return ComponentType.INTENT
@@ -0,0 +1,64 @@
from typing import Any, Dict
from core.components.component_manager import Component, ComponentType, ComponentFactory
from core.utils import llm
from config.logger import setup_logging
logger = setup_logging()
class LLMAdapter(Component):
"""LLM组件适配器:将现有LLM组件包装为新的组件接口"""
def __init__(self, config: Dict[str, Any]):
super().__init__(ComponentType.LLM, config)
self._llm_instance = None
async def _do_initialize(self, context: Any) -> None:
"""初始化LLM组件"""
try:
# 获取LLM配置
selected_module = self.config.get("selected_module", {}).get("LLM")
if not selected_module:
raise ValueError("未配置LLM模块")
# 获取LLM类型
llm_type = (
selected_module
if "type" not in self.config["LLM"][selected_module]
else self.config["LLM"][selected_module]["type"]
)
# 创建LLM实例
self._llm_instance = llm.create_instance(
llm_type,
self.config["LLM"][selected_module],
)
logger.info(f"LLM组件初始化完成: {llm_type}")
except Exception as e:
logger.error(f"LLM组件初始化失败: {e}")
raise
async def _do_cleanup(self) -> None:
"""清理LLM组件"""
if self._llm_instance:
instance = self._llm_instance
await self._close_resource(instance)
self._llm_instance = None
logger.info("LLM组件清理完成")
@property
def llm_instance(self):
"""获取LLM实例"""
return self._llm_instance
class LLMFactory(ComponentFactory):
"""LLM组件工厂"""
def create(self, config: Dict[str, Any]) -> Component:
return LLMAdapter(config)
def get_component_type(self) -> ComponentType:
return ComponentType.LLM
@@ -0,0 +1,103 @@
from typing import Any, Dict
from core.components.component_manager import Component, ComponentType, ComponentFactory
from core.utils import llm, memory
from config.logger import setup_logging
logger = setup_logging()
class MemoryAdapter(Component):
"""Memory组件适配器:将现有Memory组件包装为新的组件接口"""
def __init__(self, config: Dict[str, Any]):
super().__init__(ComponentType.MEMORY, config)
self._memory_instance = None
self._owned_llm_instance = None
async def _do_initialize(self, context: Any) -> None:
"""初始化Memory组件"""
try:
# 获取Memory配置
selected_module = self.config.get("selected_module", {}).get("Memory")
if not selected_module:
raise ValueError("未配置Memory模块")
# 获取Memory类型
memory_type = (
selected_module
if "type" not in self.config["Memory"][selected_module]
else self.config["Memory"][selected_module]["type"]
)
# 创建Memory实例
self._memory_instance = memory.create_instance(
memory_type,
self.config["Memory"][selected_module],
self.config.get("summaryMemory", None),
)
# 初始化记忆模块
main_llm = None
if hasattr(self._memory_instance, 'init_memory'):
# 需要LLM实例来初始化记忆
llm_component = None
if getattr(context, "component_manager", None):
llm_component = await context.component_manager.get_component(ComponentType.LLM, context)
if llm_component and hasattr(llm_component, 'llm_instance'):
main_llm = llm_component.llm_instance
self._memory_instance.init_memory(
role_id=context.device_id,
llm=main_llm,
summary_memory=self.config.get("summaryMemory", None),
save_to_file=not self.config.get("read_config_from_api", False),
)
memory_config = self.config["Memory"][selected_module]
dedicated_llm_name = memory_config.get("llm")
if (
memory_type == "mem_local_short"
and dedicated_llm_name
and dedicated_llm_name in self.config.get("LLM", {})
):
dedicated_config = self.config["LLM"][dedicated_llm_name]
dedicated_type = dedicated_config.get("type", dedicated_llm_name)
self._owned_llm_instance = llm.create_instance(
dedicated_type, dedicated_config
)
self._memory_instance.set_llm(self._owned_llm_instance)
logger.info(f"为记忆总结创建专用LLM: {dedicated_llm_name}")
elif main_llm and hasattr(self._memory_instance, "set_llm"):
self._memory_instance.set_llm(main_llm)
logger.info(f"Memory组件初始化完成: {memory_type}")
except Exception as e:
logger.error(f"Memory组件初始化失败: {e}")
raise
async def _do_cleanup(self) -> None:
"""清理Memory组件"""
if self._memory_instance:
instance = self._memory_instance
await self._close_resource(instance)
self._memory_instance = None
logger.info("Memory组件清理完成")
if self._owned_llm_instance:
instance = self._owned_llm_instance
await self._close_resource(instance)
self._owned_llm_instance = None
@property
def memory_instance(self):
"""获取Memory实例"""
return self._memory_instance
class MemoryFactory(ComponentFactory):
"""Memory组件工厂"""
def create(self, config: Dict[str, Any]) -> Component:
return MemoryAdapter(config)
def get_component_type(self) -> ComponentType:
return ComponentType.MEMORY
@@ -0,0 +1,76 @@
from typing import Any, Dict
from core.components.component_manager import Component, ComponentType, ComponentFactory
from core.utils import tts
from config.logger import setup_logging
logger = setup_logging()
class TTSAdapter(Component):
"""TTS组件适配器:将现有TTS组件包装为新的组件接口"""
def __init__(self, config: Dict[str, Any]):
super().__init__(ComponentType.TTS, config)
self._tts_instance = None
self._delete_audio = config.get("delete_audio", True)
async def _do_initialize(self, context: Any) -> None:
"""初始化TTS组件"""
try:
# 获取TTS配置
selected_module = self.config.get("selected_module", {}).get("TTS")
if not selected_module:
raise ValueError("未配置TTS模块")
# 获取TTS类型
tts_type = (
selected_module
if "type" not in self.config["TTS"][selected_module]
else self.config["TTS"][selected_module]["type"]
)
# 创建TTS实例
self._tts_instance = tts.create_instance(
tts_type,
self.config["TTS"][selected_module],
str(self._delete_audio).lower() in ("true", "1", "yes"),
)
# 打开音频通道
if hasattr(self._tts_instance, 'open_audio_channels'):
await self._tts_instance.open_audio_channels(context)
# 设置兼容属性(用于向后兼容)
if hasattr(context, 'tts'):
context.tts = self._tts_instance
logger.info(f"TTS组件初始化完成: {tts_type}")
except Exception as e:
logger.error(f"TTS组件初始化失败: {e}")
raise
async def _do_cleanup(self) -> None:
"""清理TTS组件"""
if self._tts_instance:
instance = self._tts_instance
await self._close_resource(instance)
if hasattr(instance, 'cleanup_audio_files'):
instance.cleanup_audio_files()
self._tts_instance = None
logger.info("TTS组件清理完成")
@property
def tts_instance(self):
"""获取TTS实例"""
return self._tts_instance
class TTSFactory(ComponentFactory):
"""TTS组件工厂"""
def create(self, config: Dict[str, Any]) -> Component:
return TTSAdapter(config)
def get_component_type(self) -> ComponentType:
return ComponentType.TTS
@@ -0,0 +1,64 @@
from typing import Any, Dict
from core.components.component_manager import Component, ComponentType, ComponentFactory
from core.utils import vad
from config.logger import setup_logging
logger = setup_logging()
class VADAdapter(Component):
"""VAD组件适配器:将现有VAD组件包装为新的组件接口"""
def __init__(self, config: Dict[str, Any]):
super().__init__(ComponentType.VAD, config)
self._vad_instance = None
async def _do_initialize(self, context: Any) -> None:
"""初始化VAD组件"""
try:
# 获取VAD配置
selected_module = self.config.get("selected_module", {}).get("VAD")
if not selected_module:
raise ValueError("未配置VAD模块")
# 获取VAD类型
vad_type = (
selected_module
if "type" not in self.config["VAD"][selected_module]
else self.config["VAD"][selected_module]["type"]
)
# 创建VAD实例
self._vad_instance = vad.create_instance(
vad_type,
self.config["VAD"][selected_module],
)
logger.info(f"VAD组件初始化完成: {vad_type}")
except Exception as e:
logger.error(f"VAD组件初始化失败: {e}")
raise
async def _do_cleanup(self) -> None:
"""清理VAD组件"""
if self._vad_instance:
instance = self._vad_instance
await self._close_resource(instance)
self._vad_instance = None
logger.info("VAD组件清理完成")
@property
def vad_instance(self):
"""获取VAD实例"""
return self._vad_instance
class VADFactory(ComponentFactory):
"""VAD组件工厂"""
def create(self, config: Dict[str, Any]) -> Component:
return VADAdapter(config)
def get_component_type(self) -> ComponentType:
return ComponentType.VAD