mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-30 03:43:55 +08:00
Merge branch 'main' into tts-response
# Conflicts: # main/xiaozhi-server/core/handle/intentHandler.py
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
from config.logger import setup_logging
|
||||
import json
|
||||
from plugins_func.register import FunctionRegistry, ActionResponse, Action, ToolType
|
||||
from plugins_func.register import (
|
||||
FunctionRegistry,
|
||||
ActionResponse,
|
||||
Action,
|
||||
ToolType,
|
||||
DeviceTypeRegistry,
|
||||
)
|
||||
from plugins_func.functions.hass_init import append_devices_to_prompt
|
||||
|
||||
TAG = __name__
|
||||
@@ -10,6 +16,7 @@ class FunctionHandler:
|
||||
def __init__(self, conn):
|
||||
self.conn = conn
|
||||
self.config = conn.config
|
||||
self.device_type_registry = DeviceTypeRegistry()
|
||||
self.function_registry = FunctionRegistry()
|
||||
self.register_nessary_functions()
|
||||
self.register_config_functions()
|
||||
@@ -54,7 +61,7 @@ class FunctionHandler:
|
||||
self.function_registry.register_function("plugin_loader")
|
||||
self.function_registry.register_function("get_time")
|
||||
self.function_registry.register_function("get_lunar")
|
||||
self.function_registry.register_function("handle_device")
|
||||
self.function_registry.register_function("handle_speaker_volume_or_screen_brightness")
|
||||
|
||||
def register_config_functions(self):
|
||||
"""注册配置中的函数,可以不同客户端使用不同的配置"""
|
||||
|
||||
@@ -40,8 +40,8 @@ async def checkWakeupWords(conn, text):
|
||||
if not enable_wakeup_words_response_cache:
|
||||
return False
|
||||
"""检查是否是唤醒词"""
|
||||
_, text = remove_punctuation_and_length(text)
|
||||
if text in conn.config.get("wakeup_words"):
|
||||
_, filtered_text = remove_punctuation_and_length(text)
|
||||
if filtered_text in conn.config.get("wakeup_words"):
|
||||
await send_stt_message(conn, text)
|
||||
conn.tts_first_text_index = 0
|
||||
conn.tts_last_text_index = 0
|
||||
|
||||
@@ -12,11 +12,12 @@ TAG = __name__
|
||||
|
||||
async def handle_user_intent(conn, text):
|
||||
# 检查是否有明确的退出命令
|
||||
if await check_direct_exit(conn, text):
|
||||
filtered_text = remove_punctuation_and_length(text)[1]
|
||||
if await check_direct_exit(conn, filtered_text):
|
||||
return True
|
||||
# 4月4日因流式改造暂时关闭唤醒词加速功能
|
||||
# # 检查是否是唤醒词
|
||||
# if await checkWakeupWords(conn, text):
|
||||
# 检查是否是唤醒词
|
||||
# if await checkWakeupWords(conn, filtered_text):
|
||||
# return True
|
||||
|
||||
if conn.intent_type == "function_call":
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import json
|
||||
import asyncio
|
||||
from config.logger import setup_logging
|
||||
from plugins_func.register import (
|
||||
device_type_registry,
|
||||
register_function,
|
||||
FunctionItem,
|
||||
register_device_function,
|
||||
ActionResponse,
|
||||
Action,
|
||||
ToolType,
|
||||
@@ -177,7 +176,7 @@ class IotDescriptor:
|
||||
self.methods.append(method)
|
||||
|
||||
|
||||
def register_device_type(descriptor):
|
||||
def register_device_type(descriptor, device_type_registry):
|
||||
"""注册设备类型及其功能"""
|
||||
device_name = descriptor["name"]
|
||||
type_id = device_type_registry.generate_device_type_id(descriptor)
|
||||
@@ -213,10 +212,12 @@ def register_device_type(descriptor):
|
||||
},
|
||||
}
|
||||
query_func = create_iot_query_function(device_name, prop_name, prop_info)
|
||||
decorated_func = register_function(func_name, func_desc, ToolType.IOT_CTL)(
|
||||
query_func
|
||||
decorated_func = register_device_function(
|
||||
func_name, func_desc, ToolType.IOT_CTL
|
||||
)(query_func)
|
||||
functions[func_name] = FunctionItem(
|
||||
func_name, func_desc, decorated_func, ToolType.IOT_CTL
|
||||
)
|
||||
functions[func_name] = decorated_func
|
||||
|
||||
# 为每个方法创建控制函数
|
||||
for method_name, method_info in descriptor["methods"].items():
|
||||
@@ -267,10 +268,12 @@ def register_device_type(descriptor):
|
||||
},
|
||||
}
|
||||
control_func = create_iot_function(device_name, method_name, method_info)
|
||||
decorated_func = register_function(func_name, func_desc, ToolType.IOT_CTL)(
|
||||
control_func
|
||||
decorated_func = register_device_function(
|
||||
func_name, func_desc, ToolType.IOT_CTL
|
||||
)(control_func)
|
||||
functions[func_name] = FunctionItem(
|
||||
func_name, func_desc, decorated_func, ToolType.IOT_CTL
|
||||
)
|
||||
functions[func_name] = decorated_func
|
||||
|
||||
device_type_registry.register_device_type(type_id, functions)
|
||||
return type_id
|
||||
@@ -289,7 +292,6 @@ async def handleIotDescriptors(conn, descriptors):
|
||||
functions_changed = False
|
||||
|
||||
for descriptor in descriptors:
|
||||
|
||||
# 如果descriptor没有properties和methods,则直接跳过
|
||||
if "properties" not in descriptor and "methods" not in descriptor:
|
||||
continue
|
||||
@@ -319,13 +321,16 @@ async def handleIotDescriptors(conn, descriptors):
|
||||
|
||||
if conn.load_function_plugin:
|
||||
# 注册或获取设备类型
|
||||
type_id = register_device_type(descriptor)
|
||||
device_type_registry = conn.func_handler.device_type_registry
|
||||
type_id = register_device_type(descriptor, device_type_registry)
|
||||
device_functions = device_type_registry.get_device_functions(type_id)
|
||||
|
||||
# 在连接级注册设备函数
|
||||
if hasattr(conn, "func_handler"):
|
||||
for func_name in device_functions:
|
||||
conn.func_handler.function_registry.register_function(func_name)
|
||||
for func_name, func_item in device_functions.items():
|
||||
conn.func_handler.function_registry.register_function(
|
||||
func_name, func_item
|
||||
)
|
||||
conn.logger.bind(tag=TAG).info(
|
||||
f"注册IOT函数到function handler: {func_name}"
|
||||
)
|
||||
|
||||
@@ -39,14 +39,14 @@ async def handleAudioMessage(conn, audio):
|
||||
if len(conn.asr_audio) < 15:
|
||||
conn.asr_server_receive = True
|
||||
else:
|
||||
text, _ = await conn.asr.speech_to_text(conn.asr_audio, conn.session_id)
|
||||
conn.logger.bind(tag=TAG).info(f"识别文本: {text}")
|
||||
text_len, _ = remove_punctuation_and_length(text)
|
||||
raw_text, _ = await conn.asr.speech_to_text(conn.asr_audio, conn.session_id) # 确保ASR模块返回原始文本
|
||||
conn.logger.bind(tag=TAG).info(f"识别文本: {raw_text}")
|
||||
text_len, _ = remove_punctuation_and_length(raw_text)
|
||||
if text_len > 0:
|
||||
# 使用自定义模块进行上报
|
||||
enqueue_asr_report(conn, text, copy.deepcopy(conn.asr_audio))
|
||||
enqueue_asr_report(conn, raw_text, copy.deepcopy(conn.asr_audio))
|
||||
|
||||
await startToChat(conn, text)
|
||||
await startToChat(conn, raw_text)
|
||||
else:
|
||||
conn.asr_server_receive = True
|
||||
conn.asr_audio.clear()
|
||||
|
||||
@@ -45,17 +45,17 @@ async def handleTextMessage(conn, message):
|
||||
conn.client_have_voice = False
|
||||
conn.asr_audio.clear()
|
||||
if "text" in msg_json:
|
||||
text = msg_json["text"]
|
||||
_, text = remove_punctuation_and_length(text)
|
||||
original_text = msg_json["text"] # 保留原始文本
|
||||
filtered_len, filtered_text = remove_punctuation_and_length(original_text)
|
||||
|
||||
# 识别是否是唤醒词
|
||||
is_wakeup_words = text in conn.config.get("wakeup_words")
|
||||
is_wakeup_words = filtered_text in conn.config.get("wakeup_words")
|
||||
# 是否开启唤醒词回复
|
||||
enable_greeting = conn.config.get("enable_greeting", True)
|
||||
|
||||
if is_wakeup_words and not enable_greeting:
|
||||
# 如果是唤醒词,且关闭了唤醒词回复,就不用回答
|
||||
await send_stt_message(conn, text)
|
||||
await send_stt_message(conn, original_text)
|
||||
await send_tts_message(conn, "stop", None)
|
||||
elif is_wakeup_words:
|
||||
# 上报纯文字数据(复用ASR上报功能,但不提供音频数据)
|
||||
@@ -63,9 +63,9 @@ async def handleTextMessage(conn, message):
|
||||
await startToChat(conn, "嘿,你好呀")
|
||||
else:
|
||||
# 上报纯文字数据(复用ASR上报功能,但不提供音频数据)
|
||||
enqueue_asr_report(conn, text, [])
|
||||
enqueue_asr_report(conn, original_text, [])
|
||||
# 否则需要LLM对文字内容进行答复
|
||||
await startToChat(conn, text)
|
||||
await startToChat(conn, original_text)
|
||||
elif msg_json["type"] == "iot":
|
||||
conn.logger.bind(tag=TAG).info(f"收到iot消息:{message}")
|
||||
if "descriptors" in msg_json:
|
||||
|
||||
Reference in New Issue
Block a user