Skip to content

Commit de8c762

Browse files
authored
fix:manager意图识别bug (#762)
* fix:连接manager后无法使用functioncallbug * fix:意图识别使用llm无法播放音乐bug * fix:manager第一图识别使用独立llm无法初始化llm的bug
1 parent 0566593 commit de8c762

File tree

15 files changed

+107
-45
lines changed

15 files changed

+107
-45
lines changed

main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public AgentServiceImpl(AgentDao agentDao) {
4444
@Override
4545
public PageData<AgentEntity> adminAgentList(Map<String, Object> params) {
4646
IPage<AgentEntity> page = agentDao.selectPage(
47-
getPage(params, "sort", true),
47+
getPage(params, "agent_name", true),
4848
new QueryWrapper<>());
4949
return new PageData<>(page.getRecords(), page.getTotal());
5050
}

main/manager-api/src/main/java/xiaozhi/modules/config/service/impl/ConfigServiceImpl.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,9 @@ private void buildModuleConfig(
231231
boolean isCache) {
232232
Map<String, String> selectedModule = new HashMap<>();
233233

234-
String[] modelTypes = { "VAD", "ASR", "LLM", "TTS", "Memory", "Intent" };
235-
String[] modelIds = { vadModelId, asrModelId, llmModelId, ttsModelId, memModelId, intentModelId };
234+
String[] modelTypes = { "VAD", "ASR", "TTS", "Memory", "Intent", "LLM" };
235+
String[] modelIds = { vadModelId, asrModelId, ttsModelId, memModelId, intentModelId, llmModelId };
236+
String intentLLMModelId = null;
236237

237238
for (int i = 0; i < modelIds.length; i++) {
238239
if (modelIds[i] == null) {
@@ -246,10 +247,27 @@ private void buildModuleConfig(
246247
if ("TTS".equals(modelTypes[i]) && voice != null) {
247248
((Map<String, Object>) model.getConfigJson()).put("private_voice", voice);
248249
}
250+
// 如果是Intent类型,且type=intent_llm,则给他添加附加模型
251+
if ("Intent".equals(modelTypes[i])) {
252+
Map<String, Object> map = (Map<String, Object>) model.getConfigJson();
253+
if ("intent_llm".equals(map.get("type"))) {
254+
intentLLMModelId = (String) map.get("llm");
255+
if (intentLLMModelId != null && intentLLMModelId.equals(llmModelId)) {
256+
intentLLMModelId = null;
257+
}
258+
}
259+
}
260+
// 如果是LLM类型,且intentLLMModelId不为空,则添加附加模型
261+
if ("LLM".equals(modelTypes[i]) && intentLLMModelId != null) {
262+
ModelConfigEntity intentLLM = modelConfigService.getModelById(intentLLMModelId, isCache);
263+
typeConfig.put(intentLLM.getId(), intentLLM.getConfigJson());
264+
}
249265
}
250266
result.put(modelTypes[i], typeConfig);
267+
251268
selectedModule.put(modelTypes[i], model.getId());
252269
}
270+
253271
result.put("selected_module", selectedModule);
254272
if (StringUtils.isNotBlank(prompt)) {
255273
prompt = prompt.replace("{{assistant_name}}", "小智");

main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public PageData<UserShowDeviceListVO> page(DevicePageUserDTO dto) {
221221
params.put(Constant.PAGE, dto.getPage());
222222
params.put(Constant.LIMIT, dto.getLimit());
223223
IPage<DeviceEntity> page = baseDao.selectPage(
224-
getPage(params, "sort", true),
224+
getPage(params, "mac_address", true),
225225
// 定义查询条件
226226
new QueryWrapper<DeviceEntity>()
227227
// 必须设备关键词查找

main/manager-api/src/main/java/xiaozhi/modules/sys/service/impl/SysParamsServiceImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public class SysParamsServiceImpl extends BaseServiceImpl<SysParamsDao, SysParam
3737
@Override
3838
public PageData<SysParamsDTO> page(Map<String, Object> params) {
3939
IPage<SysParamsEntity> page = baseDao.selectPage(
40-
getPage(params, Constant.CREATE_DATE, false),
40+
getPage(params, null, false),
4141
getWrapper(params));
4242

4343
return getPageData(page, SysParamsDTO.class);

main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public PageData<TimbreDetailsVO> page(TimbrePageDTO dto) {
4747
params.put(Constant.PAGE, dto.getPage());
4848
params.put(Constant.LIMIT, dto.getLimit());
4949
IPage<TimbreEntity> page = baseDao.selectPage(
50-
getPage(params, "sort", true),
50+
getPage(params, null, true),
5151
// 定义查询条件
5252
new QueryWrapper<TimbreEntity>()
5353
// 必须按照ttsID查找
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- 对0.3.0版本之前的参数进行修改
2+
update `sys_params` set param_value = '.mp3;.wav;.p3' where param_code = 'plugins.play_music.music_ext';
3+
update `ai_model_config` set config_json = '{\"type\": \"intent_llm\", \"llm\": \"LLM_ChatGLMLLM\"}' where id = 'Intent_intent_llm';

main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,11 @@ databaseChangeLog:
5050
changes:
5151
- sqlFile:
5252
encoding: utf8
53-
path: classpath:db/changelog/202504112058.sql
53+
path: classpath:db/changelog/202504112058.sql
54+
- changeSet:
55+
id: 202504131542
56+
author: John
57+
changes:
58+
- sqlFile:
59+
encoding: utf8
60+
path: classpath:db/changelog/202504131542.sql

main/xiaozhi-server/core/connection.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,6 @@ def __init__(
104104

105105
self.close_after_chat = False # 是否在聊天结束后关闭连接
106106
self.use_function_call_mode = False
107-
if self.config["selected_module"]["Intent"] == "function_call":
108-
self.use_function_call_mode = True
109107

110108
async def handle_connection(self, ws):
111109
try:
@@ -222,37 +220,37 @@ def _initialize_models(self):
222220
)
223221
if private_config.get("VAD", None) is not None:
224222
init_vad = True
225-
self.config["vad"] = private_config["VAD"]
223+
self.config["VAD"] = private_config["VAD"]
226224
self.config["selected_module"]["VAD"] = private_config["selected_module"][
227225
"VAD"
228226
]
229227
if private_config.get("ASR", None) is not None:
230228
init_asr = True
231-
self.config["asr"] = private_config["ASR"]
229+
self.config["ASR"] = private_config["ASR"]
232230
self.config["selected_module"]["ASR"] = private_config["selected_module"][
233231
"ASR"
234232
]
235233
if private_config.get("LLM", None) is not None:
236234
init_llm = True
237-
self.config["llm"] = private_config["LLM"]
235+
self.config["LLM"] = private_config["LLM"]
238236
self.config["selected_module"]["LLM"] = private_config["selected_module"][
239237
"LLM"
240238
]
241239
if private_config.get("TTS", None) is not None:
242240
init_tts = True
243-
self.config["tts"] = private_config["TTS"]
241+
self.config["TTS"] = private_config["TTS"]
244242
self.config["selected_module"]["TTS"] = private_config["selected_module"][
245243
"TTS"
246244
]
247245
if private_config.get("Memory", None) is not None:
248246
init_memory = True
249-
self.config["memory"] = private_config["Memory"]
247+
self.config["Memory"] = private_config["Memory"]
250248
self.config["selected_module"]["Memory"] = private_config[
251249
"selected_module"
252250
]["Memory"]
253251
if private_config.get("Intent", None) is not None:
254252
init_intent = True
255-
self.config["intent"] = private_config["Intent"]
253+
self.config["Intent"] = private_config["Intent"]
256254
self.config["selected_module"]["Intent"] = private_config[
257255
"selected_module"
258256
]["Intent"]
@@ -287,17 +285,26 @@ def _initialize_memory(self):
287285
self.memory.init_memory(device_id, self.llm)
288286

289287
def _initialize_intent(self):
288+
if (
289+
self.config["Intent"][self.config["selected_module"]["Intent"]]["type"]
290+
== "function_call"
291+
):
292+
self.use_function_call_mode = True
290293
"""初始化意图识别模块"""
291294
# 获取意图识别配置
292295
intent_config = self.config["Intent"]
293-
intent_type = self.config["selected_module"]["Intent"]
296+
intent_type = self.config["Intent"][self.config["selected_module"]["Intent"]][
297+
"type"
298+
]
294299

295300
# 如果使用 nointent,直接返回
296301
if intent_type == "nointent":
297302
return
298303
# 使用 intent_llm 模式
299304
elif intent_type == "intent_llm":
300-
intent_llm_name = intent_config["intent_llm"]["llm"]
305+
intent_llm_name = intent_config[self.config["selected_module"]["Intent"]][
306+
"llm"
307+
]
301308

302309
if intent_llm_name and intent_llm_name in self.config["LLM"]:
303310
# 如果配置了专用LLM,则创建独立的LLM实例

main/xiaozhi-server/core/handle/functionHandler.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ def register_nessary_functions(self):
5757

5858
def register_config_functions(self):
5959
"""注册配置中的函数,可以不同客户端使用不同的配置"""
60-
for func in self.config["Intent"]["function_call"].get("functions", []):
60+
for func in self.config["Intent"][self.config["selected_module"]["Intent"]].get(
61+
"functions", []
62+
):
6163
self.function_registry.register_function(func)
6264

6365
"""home assistant需要初始化提示词"""

main/xiaozhi-server/core/handle/intentHandler.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ async def process_intent_result(conn, intent_result, original_text):
7676
if function_name == "continue_chat":
7777
return False
7878

79+
if function_name == "play_music":
80+
funcItem = conn.func_handler.get_function(function_name)
81+
if not funcItem:
82+
conn.func_handler.function_registry.register_function("play_music")
83+
7984
function_args = None
8085
if "arguments" in intent_data["function_call"]:
8186
function_args = intent_data["function_call"]["arguments"]

main/xiaozhi-server/core/handle/iotHandle.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,12 @@ def register_device_type(descriptor):
269269

270270
# 用于接受前端设备推送的搜索iot描述
271271
async def handleIotDescriptors(conn, descriptors):
272-
if not conn.use_function_call_mode:
273-
return
274272
wait_max_time = 5
275273
while conn.func_handler is None or not conn.func_handler.finish_init:
276274
await asyncio.sleep(1)
277275
wait_max_time -= 1
278276
if wait_max_time <= 0:
279-
logger.bind(tag=TAG).error("连接对象没有func_handler")
277+
logger.bind(tag=TAG).debug("连接对象没有func_handler")
280278
return
281279
"""处理物联网描述"""
282280
functions_changed = False

main/xiaozhi-server/core/providers/llm/openai/openai.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,15 @@ def __init__(self, config):
1515
self.base_url = config.get("base_url")
1616
else:
1717
self.base_url = config.get("url")
18-
self.max_tokens = config.get("max_tokens", 500)
18+
max_tokens = config.get("max_tokens")
19+
if max_tokens is None or max_tokens == "":
20+
max_tokens = 500
21+
22+
try:
23+
max_tokens = int(max_tokens)
24+
except (ValueError, TypeError):
25+
max_tokens = 500
26+
self.max_tokens = max_tokens
1927

2028
check_model_key("LLM", self.api_key)
2129
self.client = openai.OpenAI(api_key=self.api_key, base_url=self.base_url)

main/xiaozhi-server/core/providers/vad/silero.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ def is_vad(self, conn, opus_packet):
4242
audio_tensor = torch.from_numpy(audio_float32)
4343

4444
# 检测语音活动
45-
speech_prob = self.model(audio_tensor, 16000).item()
45+
with torch.no_grad():
46+
speech_prob = self.model(audio_tensor, 16000).item()
4647
client_have_voice = speech_prob >= self.vad_threshold
4748

4849
# 如果之前有声音,但本次没有声音,且与上次有声音的时间查已经超过了静默阈值,则认为已经说完一句话
Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,43 @@
1-
from plugins_func.register import register_function,ToolType, ActionResponse, Action
1+
from plugins_func.register import register_function, ToolType, ActionResponse, Action
22
from config.logger import setup_logging
33

44
TAG = __name__
55
logger = setup_logging()
66

77
handle_exit_intent_function_desc = {
8-
"type": "function",
9-
"function": {
10-
"name": "handle_exit_intent",
11-
"description": "当用户想结束对话或需要退出系统时调用",
12-
"parameters": {
13-
"type": "object",
14-
"properties": {
15-
"say_goodbye": {
16-
"type": "string",
17-
"description": "和用户友好结束对话的告别语"
18-
}
19-
},
20-
"required": ["say_goodbye"]
21-
}
8+
"type": "function",
9+
"function": {
10+
"name": "handle_exit_intent",
11+
"description": "当用户想结束对话或需要退出系统时调用",
12+
"parameters": {
13+
"type": "object",
14+
"properties": {
15+
"say_goodbye": {
16+
"type": "string",
17+
"description": "和用户友好结束对话的告别语",
2218
}
23-
}
19+
},
20+
"required": ["say_goodbye"],
21+
},
22+
},
23+
}
2424

25-
@register_function('handle_exit_intent', handle_exit_intent_function_desc, ToolType.SYSTEM_CTL)
26-
def handle_exit_intent(conn, say_goodbye: str):
25+
26+
@register_function(
27+
"handle_exit_intent", handle_exit_intent_function_desc, ToolType.SYSTEM_CTL
28+
)
29+
def handle_exit_intent(conn, say_goodbye: str | None = None):
2730
# 处理退出意图
2831
try:
32+
if say_goodbye is None:
33+
say_goodbye = "再见,祝您生活愉快!"
2934
conn.close_after_chat = True
3035
logger.bind(tag=TAG).info(f"退出意图已处理:{say_goodbye}")
31-
return ActionResponse(action=Action.RESPONSE, result="退出意图已处理", response=say_goodbye)
36+
return ActionResponse(
37+
action=Action.RESPONSE, result="退出意图已处理", response=say_goodbye
38+
)
3239
except Exception as e:
3340
logger.bind(tag=TAG).error(f"处理退出意图错误: {e}")
34-
return ActionResponse(action=Action.NONE, result="退出意图处理失败", response="")
41+
return ActionResponse(
42+
action=Action.NONE, result="退出意图处理失败", response=""
43+
)

main/xiaozhi-server/plugins_func/functions/hass_init.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
def append_devices_to_prompt(conn):
1111
if conn.use_function_call_mode:
12-
funcs = conn.config["Intent"]["function_call"].get("functions", [])
12+
funcs = conn.config["Intent"][conn.config["selected_module"]["Intent"]].get(
13+
"functions", []
14+
)
1315
if "hass_get_state" in funcs or "hass_set_state" in funcs:
1416
prompt = "下面是我家智能设备,可以通过homeassistant控制\n"
1517
devices = conn.config["plugins"]["home_assistant"].get("devices", [])
@@ -26,7 +28,9 @@ def initialize_hass_handler(conn):
2628
global HASS_CACHE
2729
if HASS_CACHE == {}:
2830
if conn.use_function_call_mode:
29-
funcs = conn.config["Intent"]["function_call"].get("functions", [])
31+
funcs = conn.config["Intent"][conn.config["selected_module"]["Intent"]].get(
32+
"functions", []
33+
)
3034
if "hass_get_state" in funcs or "hass_set_state" in funcs:
3135
HASS_CACHE["base_url"] = conn.config["plugins"]["home_assistant"].get(
3236
"base_url"

0 commit comments

Comments
 (0)