mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-29 05:53:55 +08:00
refactor: introduce transport-neutral connection runtime
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user