mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-26 00:53:54 +08:00
update:优化日志对象
This commit is contained in:
@@ -18,6 +18,8 @@ from core.utils.util import (
|
|||||||
get_string_no_punctuation_or_emoji,
|
get_string_no_punctuation_or_emoji,
|
||||||
extract_json_from_string,
|
extract_json_from_string,
|
||||||
initialize_modules,
|
initialize_modules,
|
||||||
|
check_vad_update,
|
||||||
|
check_asr_update,
|
||||||
)
|
)
|
||||||
from concurrent.futures import ThreadPoolExecutor, TimeoutError
|
from concurrent.futures import ThreadPoolExecutor, TimeoutError
|
||||||
from core.handle.sendAudioHandle import sendAudioMessage
|
from core.handle.sendAudioHandle import sendAudioMessage
|
||||||
@@ -52,7 +54,9 @@ class ConnectionHandler:
|
|||||||
_intent,
|
_intent,
|
||||||
server=None,
|
server=None,
|
||||||
):
|
):
|
||||||
self.config = config
|
self.common_config = config
|
||||||
|
self.config = copy.deepcopy(config)
|
||||||
|
self.session_id = str(uuid.uuid4())
|
||||||
self.logger = setup_logging()
|
self.logger = setup_logging()
|
||||||
self.auth = AuthMiddleware(config)
|
self.auth = AuthMiddleware(config)
|
||||||
self.server = server # 保存server实例的引用
|
self.server = server # 保存server实例的引用
|
||||||
@@ -66,7 +70,6 @@ class ConnectionHandler:
|
|||||||
self.device_id = None
|
self.device_id = None
|
||||||
self.client_ip = None
|
self.client_ip = None
|
||||||
self.client_ip_info = {}
|
self.client_ip_info = {}
|
||||||
self.session_id = None
|
|
||||||
self.prompt = None
|
self.prompt = None
|
||||||
self.welcome_msg = None
|
self.welcome_msg = None
|
||||||
self.max_output_size = 0
|
self.max_output_size = 0
|
||||||
@@ -87,8 +90,10 @@ class ConnectionHandler:
|
|||||||
self.tts_report_thread = None
|
self.tts_report_thread = None
|
||||||
|
|
||||||
# 依赖的组件
|
# 依赖的组件
|
||||||
self.vad = _vad
|
self.vad = None
|
||||||
self.asr = _asr
|
self.asr = None
|
||||||
|
self._asr = _asr
|
||||||
|
self._vad = _vad
|
||||||
self.llm = _llm
|
self.llm = _llm
|
||||||
self.tts = _tts
|
self.tts = _tts
|
||||||
self.memory = _memory
|
self.memory = _memory
|
||||||
@@ -166,7 +171,6 @@ class ConnectionHandler:
|
|||||||
# 认证通过,继续处理
|
# 认证通过,继续处理
|
||||||
self.websocket = ws
|
self.websocket = ws
|
||||||
self.device_id = self.headers.get("device-id", None)
|
self.device_id = self.headers.get("device-id", None)
|
||||||
self.session_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
# 启动超时检查任务
|
# 启动超时检查任务
|
||||||
self.timeout_task = asyncio.create_task(self._check_timeout())
|
self.timeout_task = asyncio.create_task(self._check_timeout())
|
||||||
@@ -176,9 +180,9 @@ class ConnectionHandler:
|
|||||||
await self.websocket.send(json.dumps(self.welcome_msg))
|
await self.websocket.send(json.dumps(self.welcome_msg))
|
||||||
|
|
||||||
# 获取差异化配置
|
# 获取差异化配置
|
||||||
private_config = self._initialize_private_config()
|
self._initialize_private_config()
|
||||||
# 异步初始化
|
# 异步初始化
|
||||||
self.executor.submit(self._initialize_components, private_config)
|
self.executor.submit(self._initialize_components)
|
||||||
# tts 消化线程
|
# tts 消化线程
|
||||||
self.tts_priority_thread = threading.Thread(
|
self.tts_priority_thread = threading.Thread(
|
||||||
target=self._tts_priority_thread, daemon=True
|
target=self._tts_priority_thread, daemon=True
|
||||||
@@ -233,13 +237,17 @@ class ConnectionHandler:
|
|||||||
elif isinstance(message, bytes):
|
elif isinstance(message, bytes):
|
||||||
await handleAudioMessage(self, message)
|
await handleAudioMessage(self, message)
|
||||||
|
|
||||||
def _initialize_components(self, private_config):
|
def _initialize_components(self):
|
||||||
"""初始化组件"""
|
"""初始化组件"""
|
||||||
if private_config is not None:
|
self.prompt = self.config["prompt"]
|
||||||
self._initialize_models(private_config)
|
self.change_system_prompt(self.prompt)
|
||||||
else:
|
self.logger.bind(tag=TAG).info(f"初始化组件: prompt成功 {self.prompt[:50]}...")
|
||||||
self.prompt = self.config["prompt"]
|
|
||||||
self.change_system_prompt(self.prompt)
|
"""初始化本地组件"""
|
||||||
|
if self.vad is None:
|
||||||
|
self.vad = self._vad
|
||||||
|
if self.asr is None:
|
||||||
|
self.asr = self._asr
|
||||||
"""加载记忆"""
|
"""加载记忆"""
|
||||||
self._initialize_memory()
|
self._initialize_memory()
|
||||||
"""加载意图识别"""
|
"""加载意图识别"""
|
||||||
@@ -286,54 +294,21 @@ class ConnectionHandler:
|
|||||||
self.logger.bind(tag=TAG).error(f"获取差异化配置失败: {e}")
|
self.logger.bind(tag=TAG).error(f"获取差异化配置失败: {e}")
|
||||||
private_config = {}
|
private_config = {}
|
||||||
|
|
||||||
init_tts = False
|
init_llm, init_tts, init_memory, init_intent = (
|
||||||
if private_config.get("TTS", None) is not None:
|
|
||||||
init_tts = True
|
|
||||||
self.config["TTS"] = private_config["TTS"]
|
|
||||||
self.config["selected_module"]["TTS"] = private_config["selected_module"][
|
|
||||||
"TTS"
|
|
||||||
]
|
|
||||||
|
|
||||||
try:
|
|
||||||
modules = initialize_modules(
|
|
||||||
self.logger,
|
|
||||||
private_config,
|
|
||||||
False,
|
|
||||||
False,
|
|
||||||
False,
|
|
||||||
init_tts,
|
|
||||||
False,
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.bind(tag=TAG).error(f"初始化组件失败: {e}")
|
|
||||||
modules = {}
|
|
||||||
if modules.get("tts", None) is not None:
|
|
||||||
self.tts = modules["tts"]
|
|
||||||
if modules.get("prompt", None) is not None:
|
|
||||||
self.change_system_prompt(modules["prompt"])
|
|
||||||
private_config["prompt"] = None
|
|
||||||
return private_config
|
|
||||||
|
|
||||||
def _initialize_models(self, private_config):
|
|
||||||
init_vad, init_asr, init_llm, init_memory, init_intent = (
|
|
||||||
False,
|
|
||||||
False,
|
False,
|
||||||
False,
|
False,
|
||||||
False,
|
False,
|
||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
if private_config.get("VAD", None) is not None:
|
|
||||||
init_vad = True
|
init_vad = check_vad_update(self.common_config, private_config)
|
||||||
self.config["VAD"] = private_config["VAD"]
|
init_asr = check_asr_update(self.common_config, private_config)
|
||||||
self.config["selected_module"]["VAD"] = private_config["selected_module"][
|
|
||||||
"VAD"
|
if private_config.get("TTS", None) is not None:
|
||||||
]
|
init_tts = True
|
||||||
if private_config.get("ASR", None) is not None:
|
self.config["TTS"] = private_config["TTS"]
|
||||||
init_asr = True
|
self.config["selected_module"]["TTS"] = private_config["selected_module"][
|
||||||
self.config["ASR"] = private_config["ASR"]
|
"TTS"
|
||||||
self.config["selected_module"]["ASR"] = private_config["selected_module"][
|
|
||||||
"ASR"
|
|
||||||
]
|
]
|
||||||
if private_config.get("LLM", None) is not None:
|
if private_config.get("LLM", None) is not None:
|
||||||
init_llm = True
|
init_llm = True
|
||||||
@@ -353,8 +328,11 @@ class ConnectionHandler:
|
|||||||
self.config["selected_module"]["Intent"] = private_config[
|
self.config["selected_module"]["Intent"] = private_config[
|
||||||
"selected_module"
|
"selected_module"
|
||||||
]["Intent"]
|
]["Intent"]
|
||||||
|
if private_config.get("prompt", None) is not None:
|
||||||
|
self.config["prompt"] = private_config["prompt"]
|
||||||
if private_config.get("device_max_output_size", None) is not None:
|
if private_config.get("device_max_output_size", None) is not None:
|
||||||
self.max_output_size = int(private_config["device_max_output_size"])
|
self.max_output_size = int(private_config["device_max_output_size"])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
modules = initialize_modules(
|
modules = initialize_modules(
|
||||||
self.logger,
|
self.logger,
|
||||||
@@ -362,13 +340,15 @@ class ConnectionHandler:
|
|||||||
init_vad,
|
init_vad,
|
||||||
init_asr,
|
init_asr,
|
||||||
init_llm,
|
init_llm,
|
||||||
False,
|
init_tts,
|
||||||
init_memory,
|
init_memory,
|
||||||
init_intent,
|
init_intent,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.bind(tag=TAG).error(f"初始化组件失败: {e}")
|
self.logger.bind(tag=TAG).error(f"初始化组件失败: {e}")
|
||||||
modules = {}
|
modules = {}
|
||||||
|
if modules.get("tts", None) is not None:
|
||||||
|
self.tts = modules["tts"]
|
||||||
if modules.get("vad", None) is not None:
|
if modules.get("vad", None) is not None:
|
||||||
self.vad = modules["vad"]
|
self.vad = modules["vad"]
|
||||||
if modules.get("asr", None) is not None:
|
if modules.get("asr", None) is not None:
|
||||||
@@ -446,10 +426,12 @@ class ConnectionHandler:
|
|||||||
processed_chars = 0 # 跟踪已处理的字符位置
|
processed_chars = 0 # 跟踪已处理的字符位置
|
||||||
try:
|
try:
|
||||||
# 使用带记忆的对话
|
# 使用带记忆的对话
|
||||||
future = asyncio.run_coroutine_threadsafe(
|
memory_str = None
|
||||||
self.memory.query_memory(query), self.loop
|
if self.memory is not None:
|
||||||
)
|
future = asyncio.run_coroutine_threadsafe(
|
||||||
memory_str = future.result()
|
self.memory.query_memory(query), self.loop
|
||||||
|
)
|
||||||
|
memory_str = future.result()
|
||||||
|
|
||||||
self.logger.bind(tag=TAG).debug(f"记忆内容: {memory_str}")
|
self.logger.bind(tag=TAG).debug(f"记忆内容: {memory_str}")
|
||||||
llm_responses = self.llm.response(
|
llm_responses = self.llm.response(
|
||||||
@@ -510,7 +492,7 @@ class ConnectionHandler:
|
|||||||
future = self.executor.submit(
|
future = self.executor.submit(
|
||||||
self.speak_and_play, segment_text, text_index
|
self.speak_and_play, segment_text, text_index
|
||||||
)
|
)
|
||||||
self.tts_queue.put(future)
|
self.tts_queue.put((future, text_index))
|
||||||
|
|
||||||
self.llm_finish_task = True
|
self.llm_finish_task = True
|
||||||
self.dialogue.put(Message(role="assistant", content="".join(response_message)))
|
self.dialogue.put(Message(role="assistant", content="".join(response_message)))
|
||||||
@@ -537,10 +519,12 @@ class ConnectionHandler:
|
|||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
# 使用带记忆的对话
|
# 使用带记忆的对话
|
||||||
future = asyncio.run_coroutine_threadsafe(
|
memory_str = None
|
||||||
self.memory.query_memory(query), self.loop
|
if self.memory is not None:
|
||||||
)
|
future = asyncio.run_coroutine_threadsafe(
|
||||||
memory_str = future.result()
|
self.memory.query_memory(query), self.loop
|
||||||
|
)
|
||||||
|
memory_str = future.result()
|
||||||
|
|
||||||
# self.logger.bind(tag=TAG).info(f"对话记录: {self.dialogue.get_llm_dialogue_with_memory(memory_str)}")
|
# self.logger.bind(tag=TAG).info(f"对话记录: {self.dialogue.get_llm_dialogue_with_memory(memory_str)}")
|
||||||
|
|
||||||
@@ -685,7 +669,7 @@ class ConnectionHandler:
|
|||||||
future = self.executor.submit(
|
future = self.executor.submit(
|
||||||
self.speak_and_play, segment_text, text_index
|
self.speak_and_play, segment_text, text_index
|
||||||
)
|
)
|
||||||
self.tts_queue.put(future)
|
self.tts_queue.put((future, text_index))
|
||||||
|
|
||||||
# 存储对话内容
|
# 存储对话内容
|
||||||
if len(response_message) > 0:
|
if len(response_message) > 0:
|
||||||
@@ -747,7 +731,7 @@ class ConnectionHandler:
|
|||||||
text = result.response
|
text = result.response
|
||||||
self.recode_first_last_text(text, text_index)
|
self.recode_first_last_text(text, text_index)
|
||||||
future = self.executor.submit(self.speak_and_play, text, text_index)
|
future = self.executor.submit(self.speak_and_play, text, text_index)
|
||||||
self.tts_queue.put(future)
|
self.tts_queue.put((future, text_index))
|
||||||
self.dialogue.put(Message(role="assistant", content=text))
|
self.dialogue.put(Message(role="assistant", content=text))
|
||||||
elif result.action == Action.REQLLM: # 调用函数后再请求llm生成回复
|
elif result.action == Action.REQLLM: # 调用函数后再请求llm生成回复
|
||||||
text = result.result
|
text = result.result
|
||||||
@@ -780,7 +764,7 @@ class ConnectionHandler:
|
|||||||
text = result.result
|
text = result.result
|
||||||
self.recode_first_last_text(text, text_index)
|
self.recode_first_last_text(text, text_index)
|
||||||
future = self.executor.submit(self.speak_and_play, text, text_index)
|
future = self.executor.submit(self.speak_and_play, text, text_index)
|
||||||
self.tts_queue.put(future)
|
self.tts_queue.put((future, text_index))
|
||||||
self.dialogue.put(Message(role="assistant", content=text))
|
self.dialogue.put(Message(role="assistant", content=text))
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
@@ -801,7 +785,7 @@ class ConnectionHandler:
|
|||||||
if future is None:
|
if future is None:
|
||||||
continue
|
continue
|
||||||
text = None
|
text = None
|
||||||
opus_datas, tts_file = [], None
|
opus_datas, tts_file = [], None
|
||||||
try:
|
try:
|
||||||
self.logger.bind(tag=TAG).debug("正在处理TTS任务...")
|
self.logger.bind(tag=TAG).debug("正在处理TTS任务...")
|
||||||
tts_timeout = int(self.config.get("tts_timeout", 10))
|
tts_timeout = int(self.config.get("tts_timeout", 10))
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ import queue
|
|||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
async def handleAbortMessage(conn):
|
async def handleAbortMessage(conn):
|
||||||
logger.bind(tag=TAG).info("Abort message received")
|
conn.logger.bind(tag=TAG).info("Abort message received")
|
||||||
# 设置成打断状态,会自动打断llm、tts任务
|
# 设置成打断状态,会自动打断llm、tts任务
|
||||||
conn.client_abort = True
|
conn.client_abort = True
|
||||||
conn.clear_queues()
|
conn.clear_queues()
|
||||||
# 打断客户端说话状态
|
# 打断客户端说话状态
|
||||||
await conn.websocket.send(json.dumps({"type": "tts", "state": "stop", "session_id": conn.session_id}))
|
await conn.websocket.send(
|
||||||
|
json.dumps({"type": "tts", "state": "stop", "session_id": conn.session_id})
|
||||||
|
)
|
||||||
conn.clearSpeakStatus()
|
conn.clearSpeakStatus()
|
||||||
logger.bind(tag=TAG).info("Abort message received-end")
|
conn.logger.bind(tag=TAG).info("Abort message received-end")
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from plugins_func.register import FunctionRegistry, ActionResponse, Action, Tool
|
|||||||
from plugins_func.functions.hass_init import append_devices_to_prompt
|
from plugins_func.functions.hass_init import append_devices_to_prompt
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionHandler:
|
class FunctionHandler:
|
||||||
@@ -40,7 +39,9 @@ class FunctionHandler:
|
|||||||
for func in self.functions_desc:
|
for func in self.functions_desc:
|
||||||
func_names.append(func["function"]["name"])
|
func_names.append(func["function"]["name"])
|
||||||
# 打印当前支持的函数列表
|
# 打印当前支持的函数列表
|
||||||
logger.bind(tag=TAG).info(f"当前支持的函数列表: {func_names}")
|
self.conn.logger.bind(tag=TAG, session_id=self.conn.session_id).info(
|
||||||
|
f"当前支持的函数列表: {func_names}"
|
||||||
|
)
|
||||||
return func_names
|
return func_names
|
||||||
|
|
||||||
def get_functions(self):
|
def get_functions(self):
|
||||||
@@ -79,7 +80,9 @@ class FunctionHandler:
|
|||||||
func = funcItem.func
|
func = funcItem.func
|
||||||
arguments = function_call_data["arguments"]
|
arguments = function_call_data["arguments"]
|
||||||
arguments = json.loads(arguments) if arguments else {}
|
arguments = json.loads(arguments) if arguments else {}
|
||||||
logger.bind(tag=TAG).debug(f"调用函数: {function_name}, 参数: {arguments}")
|
self.conn.logger.bind(tag=TAG).debug(
|
||||||
|
f"调用函数: {function_name}, 参数: {arguments}"
|
||||||
|
)
|
||||||
if (
|
if (
|
||||||
funcItem.type == ToolType.SYSTEM_CTL
|
funcItem.type == ToolType.SYSTEM_CTL
|
||||||
or funcItem.type == ToolType.IOT_CTL
|
or funcItem.type == ToolType.IOT_CTL
|
||||||
@@ -94,6 +97,6 @@ class FunctionHandler:
|
|||||||
action=Action.NOTFOUND, result="没有找到对应的函数", response=""
|
action=Action.NOTFOUND, result="没有找到对应的函数", response=""
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"处理function call错误: {e}")
|
self.conn.logger.bind(tag=TAG).error(f"处理function call错误: {e}")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import random
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
WAKEUP_CONFIG = {
|
WAKEUP_CONFIG = {
|
||||||
"dir": "config/assets/",
|
"dir": "config/assets/",
|
||||||
@@ -75,7 +74,7 @@ async def wakeupWordsResponse(conn):
|
|||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
wait_max_time -= 1
|
wait_max_time -= 1
|
||||||
if wait_max_time <= 0:
|
if wait_max_time <= 0:
|
||||||
logger.bind(tag=TAG).error("连接对象没有llm")
|
conn.logger.bind(tag=TAG).error("连接对象没有llm")
|
||||||
return
|
return
|
||||||
|
|
||||||
"""唤醒词响应"""
|
"""唤醒词响应"""
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ from core.handle.sendAudioHandle import send_stt_message
|
|||||||
from core.handle.helloHandle import checkWakeupWords
|
from core.handle.helloHandle import checkWakeupWords
|
||||||
from core.utils.util import remove_punctuation_and_length
|
from core.utils.util import remove_punctuation_and_length
|
||||||
from core.utils.dialogue import Message
|
from core.utils.dialogue import Message
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
async def handle_user_intent(conn, text):
|
async def handle_user_intent(conn, text):
|
||||||
@@ -36,7 +34,7 @@ async def check_direct_exit(conn, text):
|
|||||||
cmd_exit = conn.cmd_exit
|
cmd_exit = conn.cmd_exit
|
||||||
for cmd in cmd_exit:
|
for cmd in cmd_exit:
|
||||||
if text == cmd:
|
if text == cmd:
|
||||||
logger.bind(tag=TAG).info(f"识别到明确的退出命令: {text}")
|
conn.logger.bind(tag=TAG).info(f"识别到明确的退出命令: {text}")
|
||||||
await send_stt_message(conn, text)
|
await send_stt_message(conn, text)
|
||||||
await conn.close()
|
await conn.close()
|
||||||
return True
|
return True
|
||||||
@@ -46,7 +44,7 @@ async def check_direct_exit(conn, text):
|
|||||||
async def analyze_intent_with_llm(conn, text):
|
async def analyze_intent_with_llm(conn, text):
|
||||||
"""使用LLM分析用户意图"""
|
"""使用LLM分析用户意图"""
|
||||||
if not hasattr(conn, "intent") or not conn.intent:
|
if not hasattr(conn, "intent") or not conn.intent:
|
||||||
logger.bind(tag=TAG).warning("意图识别服务未初始化")
|
conn.logger.bind(tag=TAG).warning("意图识别服务未初始化")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 对话历史记录
|
# 对话历史记录
|
||||||
@@ -55,7 +53,7 @@ async def analyze_intent_with_llm(conn, text):
|
|||||||
intent_result = await conn.intent.detect_intent(conn, dialogue.dialogue, text)
|
intent_result = await conn.intent.detect_intent(conn, dialogue.dialogue, text)
|
||||||
return intent_result
|
return intent_result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"意图识别失败: {str(e)}")
|
conn.logger.bind(tag=TAG).error(f"意图识别失败: {str(e)}")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ async def process_intent_result(conn, intent_result, original_text):
|
|||||||
# 检查是否有function_call
|
# 检查是否有function_call
|
||||||
if "function_call" in intent_data:
|
if "function_call" in intent_data:
|
||||||
# 直接从意图识别获取了function_call
|
# 直接从意图识别获取了function_call
|
||||||
logger.bind(tag=TAG).debug(
|
conn.logger.bind(tag=TAG).debug(
|
||||||
f"检测到function_call格式的意图结果: {intent_data['function_call']['name']}"
|
f"检测到function_call格式的意图结果: {intent_data['function_call']['name']}"
|
||||||
)
|
)
|
||||||
function_name = intent_data["function_call"]["name"]
|
function_name = intent_data["function_call"]["name"]
|
||||||
@@ -118,7 +116,7 @@ async def process_intent_result(conn, intent_result, original_text):
|
|||||||
conn.speak_and_play, text, text_index
|
conn.speak_and_play, text, text_index
|
||||||
)
|
)
|
||||||
conn.llm_finish_task = True
|
conn.llm_finish_task = True
|
||||||
conn.tts_queue.put(future)
|
conn.tts_queue.put((future, text_index))
|
||||||
conn.dialogue.put(Message(role="assistant", content=text))
|
conn.dialogue.put(Message(role="assistant", content=text))
|
||||||
|
|
||||||
# 将函数执行放在线程池中
|
# 将函数执行放在线程池中
|
||||||
@@ -126,7 +124,7 @@ async def process_intent_result(conn, intent_result, original_text):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
logger.bind(tag=TAG).error(f"处理意图结果时出错: {e}")
|
conn.logger.bind(tag=TAG).error(f"处理意图结果时出错: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ from plugins_func.register import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
def wrap_async_function(async_func):
|
def wrap_async_function(async_func):
|
||||||
@@ -21,7 +20,7 @@ def wrap_async_function(async_func):
|
|||||||
# 获取连接对象(第一个参数)
|
# 获取连接对象(第一个参数)
|
||||||
conn = args[0]
|
conn = args[0]
|
||||||
if not hasattr(conn, "loop"):
|
if not hasattr(conn, "loop"):
|
||||||
logger.bind(tag=TAG).error("Connection对象没有loop属性")
|
conn.logger.bind(tag=TAG).error("Connection对象没有loop属性")
|
||||||
return ActionResponse(
|
return ActionResponse(
|
||||||
Action.ERROR,
|
Action.ERROR,
|
||||||
"Connection对象没有loop属性",
|
"Connection对象没有loop属性",
|
||||||
@@ -35,7 +34,7 @@ def wrap_async_function(async_func):
|
|||||||
# 等待结果返回
|
# 等待结果返回
|
||||||
return future.result()
|
return future.result()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"运行异步函数时出错: {e}")
|
conn.logger.bind(tag=TAG).error(f"运行异步函数时出错: {e}")
|
||||||
return ActionResponse(Action.ERROR, str(e), f"执行操作时出错: {e}")
|
return ActionResponse(Action.ERROR, str(e), f"执行操作时出错: {e}")
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
@@ -57,7 +56,7 @@ def create_iot_function(device_name, method_name, method_info):
|
|||||||
response_failure = "操作失败"
|
response_failure = "操作失败"
|
||||||
|
|
||||||
# 打印响应参数
|
# 打印响应参数
|
||||||
logger.bind(tag=TAG).debug(
|
conn.logger.bind(tag=TAG).debug(
|
||||||
f"控制函数接收到的响应参数: success='{response_success}', failure='{response_failure}'"
|
f"控制函数接收到的响应参数: success='{response_success}', failure='{response_failure}'"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -86,7 +85,9 @@ def create_iot_function(device_name, method_name, method_info):
|
|||||||
|
|
||||||
return ActionResponse(Action.RESPONSE, result, response)
|
return ActionResponse(Action.RESPONSE, result, response)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"执行{device_name}的{method_name}操作失败: {e}")
|
conn.logger.bind(tag=TAG).error(
|
||||||
|
f"执行{device_name}的{method_name}操作失败: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
# 操作失败时使用大模型提供的失败响应
|
# 操作失败时使用大模型提供的失败响应
|
||||||
response = response_failure
|
response = response_failure
|
||||||
@@ -104,7 +105,7 @@ def create_iot_query_function(device_name, prop_name, prop_info):
|
|||||||
async def iot_query_function(conn, response_success=None, response_failure=None):
|
async def iot_query_function(conn, response_success=None, response_failure=None):
|
||||||
try:
|
try:
|
||||||
# 打印响应参数
|
# 打印响应参数
|
||||||
logger.bind(tag=TAG).info(
|
conn.logger.bind(tag=TAG).info(
|
||||||
f"查询函数接收到的响应参数: success='{response_success}', failure='{response_failure}'"
|
f"查询函数接收到的响应参数: success='{response_success}', failure='{response_failure}'"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -122,7 +123,9 @@ def create_iot_query_function(device_name, prop_name, prop_info):
|
|||||||
|
|
||||||
return ActionResponse(Action.ERROR, f"属性{prop_name}不存在", response)
|
return ActionResponse(Action.ERROR, f"属性{prop_name}不存在", response)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"查询{device_name}的{prop_name}时出错: {e}")
|
conn.logger.bind(tag=TAG).error(
|
||||||
|
f"查询{device_name}的{prop_name}时出错: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
# 查询出错时使用大模型提供的失败响应
|
# 查询出错时使用大模型提供的失败响应
|
||||||
response = response_failure
|
response = response_failure
|
||||||
@@ -280,7 +283,7 @@ async def handleIotDescriptors(conn, descriptors):
|
|||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
wait_max_time -= 1
|
wait_max_time -= 1
|
||||||
if wait_max_time <= 0:
|
if wait_max_time <= 0:
|
||||||
logger.bind(tag=TAG).debug("连接对象没有func_handler")
|
conn.logger.bind(tag=TAG).debug("连接对象没有func_handler")
|
||||||
return
|
return
|
||||||
"""处理物联网描述"""
|
"""处理物联网描述"""
|
||||||
functions_changed = False
|
functions_changed = False
|
||||||
@@ -323,7 +326,7 @@ async def handleIotDescriptors(conn, descriptors):
|
|||||||
if hasattr(conn, "func_handler"):
|
if hasattr(conn, "func_handler"):
|
||||||
for func_name in device_functions:
|
for func_name in device_functions:
|
||||||
conn.func_handler.function_registry.register_function(func_name)
|
conn.func_handler.function_registry.register_function(func_name)
|
||||||
logger.bind(tag=TAG).info(
|
conn.logger.bind(tag=TAG).info(
|
||||||
f"注册IOT函数到function handler: {func_name}"
|
f"注册IOT函数到function handler: {func_name}"
|
||||||
)
|
)
|
||||||
functions_changed = True
|
functions_changed = True
|
||||||
@@ -332,8 +335,8 @@ async def handleIotDescriptors(conn, descriptors):
|
|||||||
if functions_changed and hasattr(conn, "func_handler"):
|
if functions_changed and hasattr(conn, "func_handler"):
|
||||||
conn.func_handler.upload_functions_desc()
|
conn.func_handler.upload_functions_desc()
|
||||||
func_names = conn.func_handler.current_support_functions()
|
func_names = conn.func_handler.current_support_functions()
|
||||||
logger.bind(tag=TAG).info(f"设备类型: {type_id}")
|
conn.logger.bind(tag=TAG).info(f"设备类型: {type_id}")
|
||||||
logger.bind(tag=TAG).info(
|
conn.logger.bind(tag=TAG).info(
|
||||||
f"更新function描述列表完成,当前支持的函数: {func_names}"
|
f"更新function描述列表完成,当前支持的函数: {func_names}"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -347,13 +350,13 @@ async def handleIotStatus(conn, states):
|
|||||||
for k, v in state["state"].items():
|
for k, v in state["state"].items():
|
||||||
if property_item["name"] == k:
|
if property_item["name"] == k:
|
||||||
if type(v) != type(property_item["value"]):
|
if type(v) != type(property_item["value"]):
|
||||||
logger.bind(tag=TAG).error(
|
conn.logger.bind(tag=TAG).error(
|
||||||
f"属性{property_item['name']}的值类型不匹配"
|
f"属性{property_item['name']}的值类型不匹配"
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
property_item["value"] = v
|
property_item["value"] = v
|
||||||
logger.bind(tag=TAG).info(
|
conn.logger.bind(tag=TAG).info(
|
||||||
f"物联网状态更新: {key} , {property_item['name']} = {v}"
|
f"物联网状态更新: {key} , {property_item['name']} = {v}"
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
@@ -367,7 +370,7 @@ async def get_iot_status(conn, name, property_name):
|
|||||||
for property_item in value.properties:
|
for property_item in value.properties:
|
||||||
if property_item["name"] == property_name:
|
if property_item["name"] == property_name:
|
||||||
return property_item["value"]
|
return property_item["value"]
|
||||||
logger.bind(tag=TAG).warning(f"未找到设备 {name} 的属性 {property_name}")
|
conn.logger.bind(tag=TAG).warning(f"未找到设备 {name} 的属性 {property_name}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -378,16 +381,16 @@ async def set_iot_status(conn, name, property_name, value):
|
|||||||
for property_item in iot_descriptor.properties:
|
for property_item in iot_descriptor.properties:
|
||||||
if property_item["name"] == property_name:
|
if property_item["name"] == property_name:
|
||||||
if type(value) != type(property_item["value"]):
|
if type(value) != type(property_item["value"]):
|
||||||
logger.bind(tag=TAG).error(
|
conn.logger.bind(tag=TAG).error(
|
||||||
f"属性{property_item['name']}的值类型不匹配"
|
f"属性{property_item['name']}的值类型不匹配"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
property_item["value"] = value
|
property_item["value"] = value
|
||||||
logger.bind(tag=TAG).info(
|
conn.logger.bind(tag=TAG).info(
|
||||||
f"物联网状态更新: {name} , {property_name} = {value}"
|
f"物联网状态更新: {name} , {property_name} = {value}"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
logger.bind(tag=TAG).warning(f"未找到设备 {name} 的属性 {property_name}")
|
conn.logger.bind(tag=TAG).warning(f"未找到设备 {name} 的属性 {property_name}")
|
||||||
|
|
||||||
|
|
||||||
async def send_iot_conn(conn, name, method_name, parameters):
|
async def send_iot_conn(conn, name, method_name, parameters):
|
||||||
@@ -409,6 +412,6 @@ async def send_iot_conn(conn, name, method_name, parameters):
|
|||||||
command["parameters"] = parameters
|
command["parameters"] = parameters
|
||||||
send_message = json.dumps({"type": "iot", "commands": [command]})
|
send_message = json.dumps({"type": "iot", "commands": [command]})
|
||||||
await conn.websocket.send(send_message)
|
await conn.websocket.send(send_message)
|
||||||
logger.bind(tag=TAG).info(f"发送物联网指令: {send_message}")
|
conn.logger.bind(tag=TAG).info(f"发送物联网指令: {send_message}")
|
||||||
return
|
return
|
||||||
logger.bind(tag=TAG).error(f"未找到方法{method_name}")
|
conn.logger.bind(tag=TAG).error(f"未找到方法{method_name}")
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
from config.logger import setup_logging
|
|
||||||
import time
|
import time
|
||||||
import copy
|
import copy
|
||||||
from core.utils.util import remove_punctuation_and_length
|
from core.utils.util import remove_punctuation_and_length
|
||||||
@@ -9,12 +8,13 @@ from core.handle.ttsReportHandle import enqueue_tts_report
|
|||||||
from core.providers.tts.base import audio_to_opus_data
|
from core.providers.tts.base import audio_to_opus_data
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
async def handleAudioMessage(conn, audio):
|
async def handleAudioMessage(conn, audio):
|
||||||
|
if conn.vad is None:
|
||||||
|
return
|
||||||
if not conn.asr_server_receive:
|
if not conn.asr_server_receive:
|
||||||
logger.bind(tag=TAG).debug(f"前期数据处理中,暂停接收")
|
conn.logger.bind(tag=TAG).debug(f"前期数据处理中,暂停接收")
|
||||||
return
|
return
|
||||||
if conn.client_listen_mode == "auto":
|
if conn.client_listen_mode == "auto":
|
||||||
have_voice = conn.vad.is_vad(conn, audio)
|
have_voice = conn.vad.is_vad(conn, audio)
|
||||||
@@ -40,7 +40,7 @@ async def handleAudioMessage(conn, audio):
|
|||||||
conn.asr_server_receive = True
|
conn.asr_server_receive = True
|
||||||
else:
|
else:
|
||||||
text, _ = await conn.asr.speech_to_text(conn.asr_audio, conn.session_id)
|
text, _ = await conn.asr.speech_to_text(conn.asr_audio, conn.session_id)
|
||||||
logger.bind(tag=TAG).info(f"识别文本: {text}")
|
conn.logger.bind(tag=TAG).info(f"识别文本: {text}")
|
||||||
text_len, _ = remove_punctuation_and_length(text)
|
text_len, _ = remove_punctuation_and_length(text)
|
||||||
if text_len > 0:
|
if text_len > 0:
|
||||||
# 使用自定义模块进行上报
|
# 使用自定义模块进行上报
|
||||||
@@ -120,7 +120,7 @@ async def check_bind_device(conn):
|
|||||||
if conn.bind_code:
|
if conn.bind_code:
|
||||||
# 确保bind_code是6位数字
|
# 确保bind_code是6位数字
|
||||||
if len(conn.bind_code) != 6:
|
if len(conn.bind_code) != 6:
|
||||||
logger.bind(tag=TAG).error(f"无效的绑定码格式: {conn.bind_code}")
|
conn.logger.bind(tag=TAG).error(f"无效的绑定码格式: {conn.bind_code}")
|
||||||
text = "绑定码格式错误,请检查配置。"
|
text = "绑定码格式错误,请检查配置。"
|
||||||
await send_stt_message(conn, text)
|
await send_stt_message(conn, text)
|
||||||
return
|
return
|
||||||
@@ -144,7 +144,7 @@ async def check_bind_device(conn):
|
|||||||
num_packets, _ = audio_to_opus_data(num_path)
|
num_packets, _ = audio_to_opus_data(num_path)
|
||||||
conn.audio_play_queue.put((num_packets, None, i + 1))
|
conn.audio_play_queue.put((num_packets, None, i + 1))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"播放数字音频失败: {e}")
|
conn.logger.bind(tag=TAG).error(f"播放数字音频失败: {e}")
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
text = f"没有找到该设备的版本信息,请正确配置 OTA地址,然后重新编译固件。"
|
text = f"没有找到该设备的版本信息,请正确配置 OTA地址,然后重新编译固件。"
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
from config.logger import setup_logging
|
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
import time
|
||||||
from core.utils.util import get_string_no_punctuation_or_emoji, analyze_emotion
|
from core.utils.util import get_string_no_punctuation_or_emoji, analyze_emotion
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
emoji_map = {
|
emoji_map = {
|
||||||
"neutral": "😶",
|
"neutral": "😶",
|
||||||
@@ -49,10 +47,10 @@ async def sendAudioMessage(conn, audios, text, text_index=0):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if text_index == conn.tts_first_text_index:
|
if text_index == conn.tts_first_text_index:
|
||||||
logger.bind(tag=TAG).info(f"发送第一段语音: {text}")
|
conn.logger.bind(tag=TAG).info(f"发送第一段语音: {text}")
|
||||||
await send_tts_message(conn, "sentence_start", text)
|
await send_tts_message(conn, "sentence_start", text)
|
||||||
|
|
||||||
is_first_audio = (text_index == conn.tts_first_text_index)
|
is_first_audio = text_index == conn.tts_first_text_index
|
||||||
await sendAudio(conn, audios, pre_buffer=is_first_audio)
|
await sendAudio(conn, audios, pre_buffer=is_first_audio)
|
||||||
|
|
||||||
await send_tts_message(conn, "sentence_end", text)
|
await send_tts_message(conn, "sentence_end", text)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
from config.logger import setup_logging
|
|
||||||
import json
|
import json
|
||||||
from core.handle.abortHandle import handleAbortMessage
|
from core.handle.abortHandle import handleAbortMessage
|
||||||
from core.handle.helloHandle import handleHelloMessage
|
from core.handle.helloHandle import handleHelloMessage
|
||||||
@@ -10,12 +9,11 @@ from core.handle.ttsReportHandle import enqueue_tts_report
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
async def handleTextMessage(conn, message):
|
async def handleTextMessage(conn, message):
|
||||||
"""处理文本消息"""
|
"""处理文本消息"""
|
||||||
logger.bind(tag=TAG).info(f"收到文本消息:{message}")
|
conn.logger.bind(tag=TAG).info(f"收到文本消息:{message}")
|
||||||
try:
|
try:
|
||||||
msg_json = json.loads(message)
|
msg_json = json.loads(message)
|
||||||
if isinstance(msg_json, int):
|
if isinstance(msg_json, int):
|
||||||
@@ -28,7 +26,9 @@ async def handleTextMessage(conn, message):
|
|||||||
elif msg_json["type"] == "listen":
|
elif msg_json["type"] == "listen":
|
||||||
if "mode" in msg_json:
|
if "mode" in msg_json:
|
||||||
conn.client_listen_mode = msg_json["mode"]
|
conn.client_listen_mode = msg_json["mode"]
|
||||||
logger.bind(tag=TAG).debug(f"客户端拾音模式:{conn.client_listen_mode}")
|
conn.logger.bind(tag=TAG).debug(
|
||||||
|
f"客户端拾音模式:{conn.client_listen_mode}"
|
||||||
|
)
|
||||||
if msg_json["state"] == "start":
|
if msg_json["state"] == "start":
|
||||||
conn.client_have_voice = True
|
conn.client_have_voice = True
|
||||||
conn.client_voice_stop = False
|
conn.client_voice_stop = False
|
||||||
|
|||||||
@@ -9,16 +9,11 @@ TTS上报功能已集成到ConnectionHandler类中。
|
|||||||
具体实现请参考core/connection.py中的相关代码。
|
具体实现请参考core/connection.py中的相关代码。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import uuid
|
|
||||||
import wave
|
|
||||||
import opuslib_next
|
import opuslib_next
|
||||||
|
|
||||||
from config.logger import setup_logging
|
|
||||||
from config.manage_api_client import report
|
from config.manage_api_client import report
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
|
|
||||||
def report_tts(conn, type, text, opus_data):
|
def report_tts(conn, type, text, opus_data):
|
||||||
@@ -32,7 +27,7 @@ def report_tts(conn, type, text, opus_data):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if opus_data:
|
if opus_data:
|
||||||
audio_data = opus_to_wav(opus_data)
|
audio_data = opus_to_wav(conn, opus_data)
|
||||||
else:
|
else:
|
||||||
audio_data = None
|
audio_data = None
|
||||||
# 执行上报
|
# 执行上报
|
||||||
@@ -44,10 +39,10 @@ def report_tts(conn, type, text, opus_data):
|
|||||||
audio=audio_data,
|
audio=audio_data,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"TTS上报失败: {e}")
|
conn.logger.bind(tag=TAG).error(f"TTS上报失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
def opus_to_wav(opus_data):
|
def opus_to_wav(conn, opus_data):
|
||||||
"""将Opus数据转换为WAV格式的字节流
|
"""将Opus数据转换为WAV格式的字节流
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -65,7 +60,7 @@ def opus_to_wav(opus_data):
|
|||||||
pcm_frame = decoder.decode(opus_packet, 960) # 960 samples = 60ms
|
pcm_frame = decoder.decode(opus_packet, 960) # 960 samples = 60ms
|
||||||
pcm_data.append(pcm_frame)
|
pcm_data.append(pcm_frame)
|
||||||
except opuslib_next.OpusError as e:
|
except opuslib_next.OpusError as e:
|
||||||
logger.bind(tag=TAG).error(f"Opus解码错误: {e}", exc_info=True)
|
conn.logger.bind(tag=TAG).error(f"Opus解码错误: {e}", exc_info=True)
|
||||||
|
|
||||||
if not pcm_data:
|
if not pcm_data:
|
||||||
raise ValueError("没有有效的PCM数据")
|
raise ValueError("没有有效的PCM数据")
|
||||||
@@ -108,8 +103,8 @@ def enqueue_tts_report(conn, type, text, opus_data):
|
|||||||
# 使用连接对象的队列,传入文本和二进制数据而非文件路径
|
# 使用连接对象的队列,传入文本和二进制数据而非文件路径
|
||||||
conn.tts_report_queue.put((type, text, opus_data))
|
conn.tts_report_queue.put((type, text, opus_data))
|
||||||
|
|
||||||
logger.bind(tag=TAG).debug(
|
conn.logger.bind(tag=TAG).debug(
|
||||||
f"TTS数据已加入上报队列: {conn.device_id}, 音频大小: {len(opus_data)} "
|
f"TTS数据已加入上报队列: {conn.device_id}, 音频大小: {len(opus_data)} "
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"加入TTS上报队列失败: {text}, {e}")
|
conn.logger.bind(tag=TAG).error(f"加入TTS上报队列失败: {text}, {e}")
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"""MCP服务管理器"""
|
"""MCP服务管理器"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import os, json
|
import os, json
|
||||||
from typing import Dict, Any, List
|
from typing import Dict, Any, List
|
||||||
from .MCPClient import MCPClient
|
from .MCPClient import MCPClient
|
||||||
from config.logger import setup_logging
|
|
||||||
from plugins_func.register import register_function, ToolType
|
from plugins_func.register import register_function, ToolType
|
||||||
from config.config_loader import get_project_dir
|
from config.config_loader import get_project_dir
|
||||||
|
|
||||||
@@ -18,11 +18,10 @@ class MCPManager:
|
|||||||
初始化MCP管理器
|
初始化MCP管理器
|
||||||
"""
|
"""
|
||||||
self.conn = conn
|
self.conn = conn
|
||||||
self.logger = setup_logging()
|
|
||||||
self.config_path = get_project_dir() + "data/.mcp_server_settings.json"
|
self.config_path = get_project_dir() + "data/.mcp_server_settings.json"
|
||||||
if os.path.exists(self.config_path) == False:
|
if os.path.exists(self.config_path) == False:
|
||||||
self.config_path = ""
|
self.config_path = ""
|
||||||
self.logger.bind(tag=TAG).warning(
|
self.conn.logger.bind(tag=TAG).warning(
|
||||||
f"请检查mcp服务配置文件:data/.mcp_server_settings.json"
|
f"请检查mcp服务配置文件:data/.mcp_server_settings.json"
|
||||||
)
|
)
|
||||||
self.client: Dict[str, MCPClient] = {}
|
self.client: Dict[str, MCPClient] = {}
|
||||||
@@ -41,7 +40,7 @@ class MCPManager:
|
|||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
return config.get("mcpServers", {})
|
return config.get("mcpServers", {})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.bind(tag=TAG).error(
|
self.conn.logger.bind(tag=TAG).error(
|
||||||
f"Error loading MCP config from {self.config_path}: {e}"
|
f"Error loading MCP config from {self.config_path}: {e}"
|
||||||
)
|
)
|
||||||
return {}
|
return {}
|
||||||
@@ -51,7 +50,7 @@ class MCPManager:
|
|||||||
config = self.load_config()
|
config = self.load_config()
|
||||||
for name, srv_config in config.items():
|
for name, srv_config in config.items():
|
||||||
if not srv_config.get("command") and not srv_config.get("url"):
|
if not srv_config.get("command") and not srv_config.get("url"):
|
||||||
self.logger.bind(tag=TAG).warning(
|
self.conn.logger.bind(tag=TAG).warning(
|
||||||
f"Skipping server {name}: neither command nor url specified"
|
f"Skipping server {name}: neither command nor url specified"
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
@@ -60,7 +59,7 @@ class MCPManager:
|
|||||||
client = MCPClient(srv_config)
|
client = MCPClient(srv_config)
|
||||||
await client.initialize()
|
await client.initialize()
|
||||||
self.client[name] = client
|
self.client[name] = client
|
||||||
self.logger.bind(tag=TAG).info(f"Initialized MCP client: {name}")
|
self.conn.logger.bind(tag=TAG).info(f"Initialized MCP client: {name}")
|
||||||
client_tools = client.get_available_tools()
|
client_tools = client.get_available_tools()
|
||||||
self.tools.extend(client_tools)
|
self.tools.extend(client_tools)
|
||||||
for tool in client_tools:
|
for tool in client_tools:
|
||||||
@@ -73,7 +72,7 @@ class MCPManager:
|
|||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.bind(tag=TAG).error(
|
self.conn.logger.bind(tag=TAG).error(
|
||||||
f"Failed to initialize MCP server {name}: {e}"
|
f"Failed to initialize MCP server {name}: {e}"
|
||||||
)
|
)
|
||||||
self.conn.func_handler.upload_functions_desc()
|
self.conn.func_handler.upload_functions_desc()
|
||||||
@@ -94,8 +93,8 @@ class MCPManager:
|
|||||||
"""
|
"""
|
||||||
for tool in self.tools:
|
for tool in self.tools:
|
||||||
if (
|
if (
|
||||||
tool.get("function") != None
|
tool.get("function") != None
|
||||||
and tool["function"].get("name") == tool_name
|
and tool["function"].get("name") == tool_name
|
||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@@ -110,7 +109,7 @@ class MCPManager:
|
|||||||
Raises:
|
Raises:
|
||||||
ValueError: 工具未找到时抛出
|
ValueError: 工具未找到时抛出
|
||||||
"""
|
"""
|
||||||
self.logger.bind(tag=TAG).info(
|
self.conn.logger.bind(tag=TAG).info(
|
||||||
f"Executing tool {tool_name} with arguments: {arguments}"
|
f"Executing tool {tool_name} with arguments: {arguments}"
|
||||||
)
|
)
|
||||||
for client in self.client.values():
|
for client in self.client.values():
|
||||||
@@ -124,9 +123,9 @@ class MCPManager:
|
|||||||
for name, client in list(self.client.items()):
|
for name, client in list(self.client.items()):
|
||||||
try:
|
try:
|
||||||
await asyncio.wait_for(client.cleanup(), timeout=20)
|
await asyncio.wait_for(client.cleanup(), timeout=20)
|
||||||
self.logger.bind(tag=TAG).info(f"MCP client closed: {name}")
|
self.conn.logger.bind(tag=TAG).info(f"MCP client closed: {name}")
|
||||||
except (asyncio.TimeoutError, Exception) as e:
|
except (asyncio.TimeoutError, Exception) as e:
|
||||||
self.logger.bind(tag=TAG).error(
|
self.conn.logger.bind(tag=TAG).error(
|
||||||
f"Error closing MCP client {name}: {e}"
|
f"Error closing MCP client {name}: {e}"
|
||||||
)
|
)
|
||||||
self.client.clear()
|
self.client.clear()
|
||||||
|
|||||||
@@ -4,7 +4,14 @@ from datetime import datetime
|
|||||||
|
|
||||||
|
|
||||||
class Message:
|
class Message:
|
||||||
def __init__(self, role: str, content: str = None, uniq_id: str = None, tool_calls = None, tool_call_id=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
role: str,
|
||||||
|
content: str = None,
|
||||||
|
uniq_id: str = None,
|
||||||
|
tool_calls=None,
|
||||||
|
tool_call_id=None,
|
||||||
|
):
|
||||||
self.uniq_id = uniq_id if uniq_id is not None else str(uuid.uuid4())
|
self.uniq_id = uniq_id if uniq_id is not None else str(uuid.uuid4())
|
||||||
self.role = role
|
self.role = role
|
||||||
self.content = content
|
self.content = content
|
||||||
@@ -16,7 +23,7 @@ class Dialogue:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.dialogue: List[Message] = []
|
self.dialogue: List[Message] = []
|
||||||
# 获取当前时间
|
# 获取当前时间
|
||||||
self.current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
self.current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
def put(self, message: Message):
|
def put(self, message: Message):
|
||||||
self.dialogue.append(message)
|
self.dialogue.append(message)
|
||||||
@@ -25,7 +32,9 @@ class Dialogue:
|
|||||||
if m.tool_calls is not None:
|
if m.tool_calls is not None:
|
||||||
dialogue.append({"role": m.role, "tool_calls": m.tool_calls})
|
dialogue.append({"role": m.role, "tool_calls": m.tool_calls})
|
||||||
elif m.role == "tool":
|
elif m.role == "tool":
|
||||||
dialogue.append({"role": m.role, "tool_call_id": m.tool_call_id, "content": m.content})
|
dialogue.append(
|
||||||
|
{"role": m.role, "tool_call_id": m.tool_call_id, "content": m.content}
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
dialogue.append({"role": m.role, "content": m.content})
|
dialogue.append({"role": m.role, "content": m.content})
|
||||||
|
|
||||||
@@ -44,23 +53,23 @@ class Dialogue:
|
|||||||
else:
|
else:
|
||||||
self.put(Message(role="system", content=new_content))
|
self.put(Message(role="system", content=new_content))
|
||||||
|
|
||||||
def get_llm_dialogue_with_memory(self, memory_str: str = None) -> List[Dict[str, str]]:
|
def get_llm_dialogue_with_memory(
|
||||||
|
self, memory_str: str = None
|
||||||
|
) -> List[Dict[str, str]]:
|
||||||
if memory_str is None or len(memory_str) == 0:
|
if memory_str is None or len(memory_str) == 0:
|
||||||
return self.get_llm_dialogue()
|
return self.get_llm_dialogue()
|
||||||
|
|
||||||
# 构建带记忆的对话
|
# 构建带记忆的对话
|
||||||
dialogue = []
|
dialogue = []
|
||||||
|
|
||||||
# 添加系统提示和记忆
|
# 添加系统提示和记忆
|
||||||
system_message = next(
|
system_message = next(
|
||||||
(msg for msg in self.dialogue if msg.role == "system"), None
|
(msg for msg in self.dialogue if msg.role == "system"), None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if system_message:
|
if system_message:
|
||||||
enhanced_system_prompt = (
|
enhanced_system_prompt = (
|
||||||
f"{system_message.content}\n\n"
|
f"{system_message.content}\n\n" f"相关记忆:\n{memory_str}"
|
||||||
f"相关记忆:\n{memory_str}"
|
|
||||||
)
|
)
|
||||||
dialogue.append({"role": "system", "content": enhanced_system_prompt})
|
dialogue.append({"role": "system", "content": enhanced_system_prompt})
|
||||||
|
|
||||||
|
|||||||
@@ -350,12 +350,6 @@ def initialize_modules(
|
|||||||
str(config.get("delete_audio", True)).lower() in ("true", "1", "yes"),
|
str(config.get("delete_audio", True)).lower() in ("true", "1", "yes"),
|
||||||
)
|
)
|
||||||
logger.bind(tag=TAG).info(f"初始化组件: asr成功 {select_asr_module}")
|
logger.bind(tag=TAG).info(f"初始化组件: asr成功 {select_asr_module}")
|
||||||
|
|
||||||
# 初始化自定义prompt
|
|
||||||
if config.get("prompt", None) is not None:
|
|
||||||
modules["prompt"] = config["prompt"]
|
|
||||||
logger.bind(tag=TAG).info(f"初始化组件: prompt成功 {modules['prompt'][:50]}...")
|
|
||||||
|
|
||||||
return modules
|
return modules
|
||||||
|
|
||||||
|
|
||||||
@@ -913,3 +907,45 @@ def audio_to_opus_data(audio_file_path):
|
|||||||
opus_datas.append(opus_data)
|
opus_datas.append(opus_data)
|
||||||
|
|
||||||
return opus_datas, duration
|
return opus_datas, duration
|
||||||
|
|
||||||
|
|
||||||
|
def check_vad_update(before_config, new_config):
|
||||||
|
if new_config["selected_module"].get("VAD") is None:
|
||||||
|
return False
|
||||||
|
update_vad = False
|
||||||
|
current_vad_module = before_config["selected_module"]["VAD"]
|
||||||
|
new_vad_module = new_config["selected_module"]["VAD"]
|
||||||
|
current_vad_type = (
|
||||||
|
current_vad_module
|
||||||
|
if "type" not in before_config["VAD"][current_vad_module]
|
||||||
|
else before_config["VAD"][current_vad_module]["type"]
|
||||||
|
)
|
||||||
|
new_vad_type = (
|
||||||
|
new_vad_module
|
||||||
|
if "type" not in new_config["VAD"][new_vad_module]
|
||||||
|
else new_config["VAD"][new_vad_module]["type"]
|
||||||
|
)
|
||||||
|
print(f"前vad:{current_vad_type},后vad:{new_vad_type}")
|
||||||
|
update_vad = current_vad_type != new_vad_type
|
||||||
|
return update_vad
|
||||||
|
|
||||||
|
|
||||||
|
def check_asr_update(before_config, new_config):
|
||||||
|
if new_config["selected_module"].get("ASR") is None:
|
||||||
|
return False
|
||||||
|
update_asr = False
|
||||||
|
current_asr_module = before_config["selected_module"]["ASR"]
|
||||||
|
new_asr_module = new_config["selected_module"]["ASR"]
|
||||||
|
current_asr_type = (
|
||||||
|
current_asr_module
|
||||||
|
if "type" not in before_config["ASR"][current_asr_module]
|
||||||
|
else before_config["ASR"][current_asr_module]["type"]
|
||||||
|
)
|
||||||
|
new_asr_type = (
|
||||||
|
new_asr_module
|
||||||
|
if "type" not in new_config["ASR"][new_asr_module]
|
||||||
|
else new_config["ASR"][new_asr_module]["type"]
|
||||||
|
)
|
||||||
|
print(f"前asr:{current_asr_type},后asr:{new_asr_type}")
|
||||||
|
update_asr = current_asr_type != new_asr_type
|
||||||
|
return update_asr
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import asyncio
|
|||||||
import websockets
|
import websockets
|
||||||
from config.logger import setup_logging
|
from config.logger import setup_logging
|
||||||
from core.connection import ConnectionHandler
|
from core.connection import ConnectionHandler
|
||||||
from core.utils.util import initialize_modules
|
from core.utils.util import initialize_modules, check_vad_update, check_asr_update
|
||||||
from config.config_loader import get_config_from_api
|
from config.config_loader import get_config_from_api
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
@@ -84,38 +84,8 @@ class WebSocketServer:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# 检查 VAD 和 ASR 类型是否需要更新
|
# 检查 VAD 和 ASR 类型是否需要更新
|
||||||
update_vad = False
|
update_vad = check_vad_update(self.config, new_config)
|
||||||
update_asr = False
|
update_asr = check_asr_update(self.config, new_config)
|
||||||
|
|
||||||
# 获取当前和新的 VAD 类型
|
|
||||||
current_vad_module = self.config["selected_module"]["VAD"]
|
|
||||||
new_vad_module = new_config["selected_module"]["VAD"]
|
|
||||||
current_vad_type = (
|
|
||||||
current_vad_module
|
|
||||||
if "type" not in self.config["VAD"][current_vad_module]
|
|
||||||
else self.config["VAD"][current_vad_module]["type"]
|
|
||||||
)
|
|
||||||
new_vad_type = (
|
|
||||||
new_vad_module
|
|
||||||
if "type" not in new_config["VAD"][new_vad_module]
|
|
||||||
else new_config["VAD"][new_vad_module]["type"]
|
|
||||||
)
|
|
||||||
update_vad = current_vad_type != new_vad_type
|
|
||||||
|
|
||||||
# 获取当前和新的 ASR 类型
|
|
||||||
current_asr_module = self.config["selected_module"]["ASR"]
|
|
||||||
new_asr_module = new_config["selected_module"]["ASR"]
|
|
||||||
current_asr_type = (
|
|
||||||
current_asr_module
|
|
||||||
if "type" not in self.config["ASR"][current_asr_module]
|
|
||||||
else self.config["ASR"][current_asr_module]["type"]
|
|
||||||
)
|
|
||||||
new_asr_type = (
|
|
||||||
new_asr_module
|
|
||||||
if "type" not in new_config["ASR"][new_asr_module]
|
|
||||||
else new_config["ASR"][new_asr_module]["type"]
|
|
||||||
)
|
|
||||||
update_asr = current_asr_type != new_asr_type
|
|
||||||
|
|
||||||
# 更新配置
|
# 更新配置
|
||||||
self.config = new_config
|
self.config = new_config
|
||||||
@@ -132,12 +102,18 @@ class WebSocketServer:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 更新组件实例
|
# 更新组件实例
|
||||||
self._vad = modules["vad"] if "vad" in modules else None
|
if "vad" in modules:
|
||||||
self._asr = modules["asr"] if "asr" in modules else None
|
self._vad = modules["vad"]
|
||||||
self._tts = modules["tts"] if "tts" in modules else None
|
if "asr" in modules:
|
||||||
self._llm = modules["llm"] if "llm" in modules else None
|
self._asr = modules["asr"]
|
||||||
self._intent = modules["intent"] if "intent" in modules else None
|
if "tts" in modules:
|
||||||
self._memory = modules["memory"] if "memory" in modules else None
|
self._tts = modules["tts"]
|
||||||
|
if "llm" in modules:
|
||||||
|
self._llm = modules["llm"]
|
||||||
|
if "intent" in modules:
|
||||||
|
self._intent = modules["intent"]
|
||||||
|
if "memory" in modules:
|
||||||
|
self._memory = modules["memory"]
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ from core.utils import p3
|
|||||||
from core.handle.sendAudioHandle import send_stt_message
|
from core.handle.sendAudioHandle import send_stt_message
|
||||||
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
||||||
|
|
||||||
|
|
||||||
TAG = __name__
|
TAG = __name__
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
MUSIC_CACHE = {}
|
MUSIC_CACHE = {}
|
||||||
|
|
||||||
@@ -45,7 +43,7 @@ def play_music(conn, song_name: str):
|
|||||||
|
|
||||||
# 检查事件循环状态
|
# 检查事件循环状态
|
||||||
if not conn.loop.is_running():
|
if not conn.loop.is_running():
|
||||||
logger.bind(tag=TAG).error("事件循环未运行,无法提交任务")
|
conn.logger.bind(tag=TAG).error("事件循环未运行,无法提交任务")
|
||||||
return ActionResponse(
|
return ActionResponse(
|
||||||
action=Action.RESPONSE, result="系统繁忙", response="请稍后再试"
|
action=Action.RESPONSE, result="系统繁忙", response="请稍后再试"
|
||||||
)
|
)
|
||||||
@@ -59,9 +57,9 @@ def play_music(conn, song_name: str):
|
|||||||
def handle_done(f):
|
def handle_done(f):
|
||||||
try:
|
try:
|
||||||
f.result() # 可在此处理成功逻辑
|
f.result() # 可在此处理成功逻辑
|
||||||
logger.bind(tag=TAG).info("播放完成")
|
conn.logger.bind(tag=TAG).info("播放完成")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"播放失败: {e}")
|
conn.logger.bind(tag=TAG).error(f"播放失败: {e}")
|
||||||
|
|
||||||
future.add_done_callback(handle_done)
|
future.add_done_callback(handle_done)
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ def play_music(conn, song_name: str):
|
|||||||
action=Action.NONE, result="指令已接收", response="正在为您播放音乐"
|
action=Action.NONE, result="指令已接收", response="正在为您播放音乐"
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"处理音乐意图错误: {e}")
|
conn.logger.bind(tag=TAG).error(f"处理音乐意图错误: {e}")
|
||||||
return ActionResponse(
|
return ActionResponse(
|
||||||
action=Action.RESPONSE, result=str(e), response="播放音乐时出错了"
|
action=Action.RESPONSE, result=str(e), response="播放音乐时出错了"
|
||||||
)
|
)
|
||||||
@@ -150,7 +148,7 @@ async def handle_music_command(conn, text):
|
|||||||
|
|
||||||
"""处理音乐播放指令"""
|
"""处理音乐播放指令"""
|
||||||
clean_text = re.sub(r"[^\w\s]", "", text).strip()
|
clean_text = re.sub(r"[^\w\s]", "", text).strip()
|
||||||
logger.bind(tag=TAG).debug(f"检查是否是音乐命令: {clean_text}")
|
conn.logger.bind(tag=TAG).debug(f"检查是否是音乐命令: {clean_text}")
|
||||||
|
|
||||||
# 尝试匹配具体歌名
|
# 尝试匹配具体歌名
|
||||||
if os.path.exists(MUSIC_CACHE["music_dir"]):
|
if os.path.exists(MUSIC_CACHE["music_dir"]):
|
||||||
@@ -165,7 +163,7 @@ async def handle_music_command(conn, text):
|
|||||||
if potential_song:
|
if potential_song:
|
||||||
best_match = _find_best_match(potential_song, MUSIC_CACHE["music_files"])
|
best_match = _find_best_match(potential_song, MUSIC_CACHE["music_files"])
|
||||||
if best_match:
|
if best_match:
|
||||||
logger.bind(tag=TAG).info(f"找到最匹配的歌曲: {best_match}")
|
conn.logger.bind(tag=TAG).info(f"找到最匹配的歌曲: {best_match}")
|
||||||
await play_local_music(conn, specific_file=best_match)
|
await play_local_music(conn, specific_file=best_match)
|
||||||
return True
|
return True
|
||||||
# 检查是否是通用播放音乐命令
|
# 检查是否是通用播放音乐命令
|
||||||
@@ -195,7 +193,9 @@ async def play_local_music(conn, specific_file=None):
|
|||||||
"""播放本地音乐文件"""
|
"""播放本地音乐文件"""
|
||||||
try:
|
try:
|
||||||
if not os.path.exists(MUSIC_CACHE["music_dir"]):
|
if not os.path.exists(MUSIC_CACHE["music_dir"]):
|
||||||
logger.bind(tag=TAG).error(f"音乐目录不存在: " + MUSIC_CACHE["music_dir"])
|
conn.logger.bind(tag=TAG).error(
|
||||||
|
f"音乐目录不存在: " + MUSIC_CACHE["music_dir"]
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# 确保路径正确性
|
# 确保路径正确性
|
||||||
@@ -204,13 +204,13 @@ async def play_local_music(conn, specific_file=None):
|
|||||||
music_path = os.path.join(MUSIC_CACHE["music_dir"], specific_file)
|
music_path = os.path.join(MUSIC_CACHE["music_dir"], specific_file)
|
||||||
else:
|
else:
|
||||||
if not MUSIC_CACHE["music_files"]:
|
if not MUSIC_CACHE["music_files"]:
|
||||||
logger.bind(tag=TAG).error("未找到MP3音乐文件")
|
conn.logger.bind(tag=TAG).error("未找到MP3音乐文件")
|
||||||
return
|
return
|
||||||
selected_music = random.choice(MUSIC_CACHE["music_files"])
|
selected_music = random.choice(MUSIC_CACHE["music_files"])
|
||||||
music_path = os.path.join(MUSIC_CACHE["music_dir"], selected_music)
|
music_path = os.path.join(MUSIC_CACHE["music_dir"], selected_music)
|
||||||
|
|
||||||
if not os.path.exists(music_path):
|
if not os.path.exists(music_path):
|
||||||
logger.bind(tag=TAG).error(f"选定的音乐文件不存在: {music_path}")
|
conn.logger.bind(tag=TAG).error(f"选定的音乐文件不存在: {music_path}")
|
||||||
return
|
return
|
||||||
text = _get_random_play_prompt(selected_music)
|
text = _get_random_play_prompt(selected_music)
|
||||||
await send_stt_message(conn, text)
|
await send_stt_message(conn, text)
|
||||||
@@ -233,5 +233,5 @@ async def play_local_music(conn, specific_file=None):
|
|||||||
conn.audio_play_queue.put((opus_packets, None, conn.tts_last_text_index))
|
conn.audio_play_queue.put((opus_packets, None, conn.tts_last_text_index))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.bind(tag=TAG).error(f"播放音乐失败: {str(e)}")
|
conn.logger.bind(tag=TAG).error(f"播放音乐失败: {str(e)}")
|
||||||
logger.bind(tag=TAG).error(f"详细错误: {traceback.format_exc()}")
|
conn.logger.bind(tag=TAG).error(f"详细错误: {traceback.format_exc()}")
|
||||||
|
|||||||
@@ -1,51 +1,56 @@
|
|||||||
from plugins_func.register import register_function,ToolType, ActionResponse, Action
|
from plugins_func.register import register_function, ToolType, ActionResponse, Action
|
||||||
from config.logger import setup_logging
|
|
||||||
|
|
||||||
TAG = __name__
|
|
||||||
logger = setup_logging()
|
|
||||||
|
|
||||||
plugin_loader_function_desc = {
|
plugin_loader_function_desc = {
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "plugin_loader",
|
"name": "plugin_loader",
|
||||||
"description": "当用户想加载或卸载插件/function时,调用此函数:支持的插件列表为[plugins]",
|
"description": "当用户想加载或卸载插件/function时,调用此函数:支持的插件列表为[plugins]",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"oper": {
|
"oper": {"type": "string", "description": "load or unload"},
|
||||||
"type": "string",
|
"name": {"type": "string", "description": "要加载或卸载的插件名字"},
|
||||||
"description": "load or unload"
|
},
|
||||||
},
|
"required": ["oper", "name"],
|
||||||
"name":{
|
},
|
||||||
"type": "string",
|
},
|
||||||
"description": "要加载或卸载的插件名字"
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["oper","name"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@register_function('plugin_loader', plugin_loader_function_desc, ToolType.SYSTEM_CTL)
|
|
||||||
|
@register_function("plugin_loader", plugin_loader_function_desc, ToolType.SYSTEM_CTL)
|
||||||
def plugin_loader(conn, oper: str, name: str):
|
def plugin_loader(conn, oper: str, name: str):
|
||||||
"""插件加载"""
|
"""插件加载"""
|
||||||
if oper not in ["load", "unload"]:
|
if oper not in ["load", "unload"]:
|
||||||
return ActionResponse(action=Action.RESPONSE, result="插件操作失败", response="不支持的操作")
|
return ActionResponse(
|
||||||
|
action=Action.RESPONSE, result="插件操作失败", response="不支持的操作"
|
||||||
|
)
|
||||||
|
|
||||||
cur_support = conn.func_handler.current_support_functions()
|
cur_support = conn.func_handler.current_support_functions()
|
||||||
if oper == "load":
|
if oper == "load":
|
||||||
if name in cur_support:
|
if name in cur_support:
|
||||||
return ActionResponse(action=Action.RESPONSE, result="插件加载失败", response=f"{name}插件已加载,无需重复加载")
|
return ActionResponse(
|
||||||
|
action=Action.RESPONSE,
|
||||||
|
result="插件加载失败",
|
||||||
|
response=f"{name}插件已加载,无需重复加载",
|
||||||
|
)
|
||||||
func = conn.func_handler.function_registry.register_function(name)
|
func = conn.func_handler.function_registry.register_function(name)
|
||||||
if not func:
|
if not func:
|
||||||
return ActionResponse(action=Action.RESPONSE, result="插件加载失败", response="插件未找到")
|
return ActionResponse(
|
||||||
|
action=Action.RESPONSE, result="插件加载失败", response="插件未找到"
|
||||||
|
)
|
||||||
res = f"{name}插件加载成功"
|
res = f"{name}插件加载成功"
|
||||||
else:
|
else:
|
||||||
if name not in cur_support:
|
if name not in cur_support:
|
||||||
return ActionResponse(action=Action.RESPONSE, result="插件卸载失败", response=f"{name}插件未加载")
|
return ActionResponse(
|
||||||
|
action=Action.RESPONSE,
|
||||||
|
result="插件卸载失败",
|
||||||
|
response=f"{name}插件未加载",
|
||||||
|
)
|
||||||
bOK = conn.func_handler.function_registry.unregister_function(name)
|
bOK = conn.func_handler.function_registry.unregister_function(name)
|
||||||
if not bOK:
|
if not bOK:
|
||||||
return ActionResponse(action=Action.RESPONSE, result="插件卸载失败", response="插件未找到")
|
return ActionResponse(
|
||||||
|
action=Action.RESPONSE, result="插件卸载失败", response="插件未找到"
|
||||||
|
)
|
||||||
res = f"{name}插件卸载成功"
|
res = f"{name}插件卸载成功"
|
||||||
conn.func_handler.upload_functions_desc()
|
conn.func_handler.upload_functions_desc()
|
||||||
return ActionResponse(action=Action.RESPONSE, result="插件操作成功", response=res)
|
return ActionResponse(action=Action.RESPONSE, result="插件操作成功", response=res)
|
||||||
|
|||||||
Reference in New Issue
Block a user