fix:已经使用了intent_llm,不应该再回到functioncall的chat中

This commit is contained in:
hrz
2025-03-28 17:17:14 +08:00
parent 05356b6652
commit 17126303fa
5 changed files with 136 additions and 358 deletions
+27 -163
View File
@@ -210,11 +210,6 @@ class ConnectionHandler:
intent_llm = llm_utils.create_instance(intent_llm_type, intent_llm_config)
self.logger.bind(tag=TAG).info(f"为意图识别创建了专用LLM: {intent_llm_name}, 类型: {intent_llm_type}")
# 记录额外的模型信息
model_name = intent_llm_config.get("model_name", "未指定")
base_url = intent_llm_config.get("base_url", "未指定")
self.logger.bind(tag=TAG).info(f"意图识别LLM详细信息 - 模型名称: {model_name}, 服务地址: {base_url}")
self.intent.set_llm(intent_llm)
else:
# 否则使用主LLM
@@ -337,7 +332,7 @@ class ConnectionHandler:
self.logger.bind(tag=TAG).debug(json.dumps(self.dialogue.get_llm_dialogue(), indent=4, ensure_ascii=False))
return True
def chat_with_function_calling(self, query, tool_call=False, is_weather_query=False, is_news_query=False):
def chat_with_function_calling(self, query, tool_call=False):
self.logger.bind(tag=TAG).debug(f"Chat with function calling start: {query}")
"""Chat with function calling for intent detection using streaming"""
if self.isNeedAuth():
@@ -355,7 +350,7 @@ class ConnectionHandler:
functions = self.func_handler.get_functions()
response_message = []
processed_chars = 0
processed_chars = 0 # 跟踪已处理的字符位置
try:
start_time = time.time()
@@ -364,58 +359,14 @@ class ConnectionHandler:
future = asyncio.run_coroutine_threadsafe(self.memory.query_memory(query), self.loop)
memory_str = future.result()
# 为天气查询添加特殊处理
if is_weather_query:
self.logger.bind(tag=TAG).info(f"检测到天气查询,添加特殊指令")
# 获取对话历史
dialogue_with_memory = self.dialogue.get_llm_dialogue_with_memory(memory_str)
# 找到最后一条tool消息(可能是天气数据)
for i in range(len(dialogue_with_memory) - 1, -1, -1):
if dialogue_with_memory[i].get("role") == "tool" and "当前天气" in dialogue_with_memory[i].get("content", ""):
# 添加特殊指令
dialogue_with_memory.append({
"role": "system",
"content": "请根据上面的天气数据,以简洁友好的方式回答用户的天气查询。直接告诉用户当前天气状况、温度以及可能需要的建议,不要提及数据来源或解释你是如何获取这些信息的。"
})
self.logger.bind(tag=TAG).info(f"已添加天气查询特殊指令")
break
# 使用支持functions的streaming接口并传入修改后的对话历史
llm_responses = self.llm.response_with_functions(
self.session_id,
dialogue_with_memory,
functions=functions
)
# 为新闻查询添加特殊处理
elif is_news_query:
self.logger.bind(tag=TAG).info(f"检测到新闻查询,添加特殊指令")
# 获取对话历史
dialogue_with_memory = self.dialogue.get_llm_dialogue_with_memory(memory_str)
# 找到最后一条tool消息(可能是新闻数据)
for i in range(len(dialogue_with_memory) - 1, -1, -1):
if dialogue_with_memory[i].get("role") == "tool" and "新闻" in dialogue_with_memory[i].get("content", ""):
# 添加特殊指令
dialogue_with_memory.append({
"role": "system",
"content": "请根据上面的新闻数据,以简洁友好的方式回答用户的新闻查询。直接告诉用户新闻内容,不要提及数据来源或解释你是如何获取这些信息的。保持新闻播报的语气和风格。"
})
self.logger.bind(tag=TAG).info(f"已添加新闻查询特殊指令")
break
# 使用支持functions的streaming接口并传入修改后的对话历史
llm_responses = self.llm.response_with_functions(
self.session_id,
dialogue_with_memory,
functions=functions
)
else:
llm_responses = self.llm.response_with_functions(
self.session_id,
self.dialogue.get_llm_dialogue_with_memory(memory_str),
functions=functions
)
# self.logger.bind(tag=TAG).info(f"对话记录: {self.dialogue.get_llm_dialogue_with_memory(memory_str)}")
# 使用支持functions的streaming接口
llm_responses = self.llm.response_with_functions(
self.session_id,
self.dialogue.get_llm_dialogue_with_memory(memory_str),
functions=functions
)
except Exception as e:
self.logger.bind(tag=TAG).error(f"LLM 处理出错 {query}: {e}")
return None
@@ -431,6 +382,9 @@ class ConnectionHandler:
content_arguments = ""
for response in llm_responses:
content, tools_call = response
if "content" in response:
content = response["content"]
tools_call = None
if content is not None and len(content) > 0:
if len(response_message) <= 0 and (content == "```" or "<tool_call>" in content):
tool_call_flag = True
@@ -533,126 +487,36 @@ class ConnectionHandler:
return True
def _handle_function_result(self, result, function_call_data, text_index):
self.logger.bind(tag=TAG).info(f"处理函数调用结果,动作类型: {result.action.name if result.action else 'None'}")
# 检查是否有备用直接回复
direct_response = getattr(result, 'response', None)
if result.action == Action.RESPONSE: # 直接回复前端
text = result.response
self.logger.bind(tag=TAG).info(f"函数返回直接回复: {text[:100] if text else 'None'}...")
self.recode_first_last_text(text, text_index)
future = self.executor.submit(self.speak_and_play, text, text_index)
self.tts_queue.put(future)
self.dialogue.put(Message(role="assistant", content=text))
elif result.action == Action.REQLLM: # 调用函数后再请求llm生成回复
self.logger.bind(tag=TAG).info(f"处理REQLLM动作,需要进一步处理结果")
text = result.result
function_id = function_call_data["id"]
function_name = function_call_data["name"]
function_arguments = function_call_data["arguments"]
if text is not None and len(text) > 0:
self.logger.bind(tag=TAG).info(f"函数返回结果长度: {len(text)}, 前100字符: {text[:100]}...")
# 特殊处理天气查询
if function_name == "get_weather":
self.logger.bind(tag=TAG).info(f"检测到天气查询结果,使用特殊处理")
# 记录工具调用到对话历史
self.dialogue.put(Message(role='assistant',
tool_calls=[{"id": function_id,
"function": {"arguments": function_arguments,
"name": function_name},
"type": 'function',
"index": 0}]))
# 记录工具返回结果到对话历史
self.dialogue.put(Message(role="tool", tool_call_id=function_id, content=text))
try:
# 使用天气数据生成回复
self.chat_with_function_calling(text, tool_call=True, is_weather_query=True)
except Exception as e:
self.logger.bind(tag=TAG).error(f"处理天气查询数据失败: {e}")
if direct_response:
self.logger.bind(tag=TAG).info(f"使用备用直接回复: {direct_response}")
self.recode_first_last_text(direct_response, text_index)
future = self.executor.submit(self.speak_and_play, direct_response, text_index)
self.tts_queue.put(future)
self.dialogue.put(Message(role="assistant", content=direct_response))
# 特殊处理新闻查询
elif function_name == "get_news":
self.logger.bind(tag=TAG).info(f"检测到新闻查询结果,使用特殊处理")
# 记录工具调用到对话历史
self.dialogue.put(Message(role='assistant',
tool_calls=[{"id": function_id,
"function": {"arguments": function_arguments,
"name": function_name},
"type": 'function',
"index": 0}]))
# 记录工具返回结果到对话历史
self.dialogue.put(Message(role="tool", tool_call_id=function_id, content=text))
try:
# 使用新闻数据生成回复,设置is_news_query=True
self.chat_with_function_calling(text, tool_call=True, is_news_query=True)
except Exception as e:
self.logger.bind(tag=TAG).error(f"处理新闻查询数据失败: {e}")
if direct_response:
self.logger.bind(tag=TAG).info(f"使用备用直接回复: {direct_response}")
self.recode_first_last_text(direct_response, text_index)
future = self.executor.submit(self.speak_and_play, direct_response, text_index)
self.tts_queue.put(future)
self.dialogue.put(Message(role="assistant", content=direct_response))
else:
# 其他类型的函数调用
self.dialogue.put(Message(role='assistant',
tool_calls=[{"id": function_id,
"function": {"arguments": function_arguments,
"name": function_name},
"type": 'function',
"index": 0}]))
self.dialogue.put(Message(role="tool", tool_call_id=function_id, content=text))
try:
self.chat_with_function_calling(text, tool_call=True)
except Exception as e:
self.logger.bind(tag=TAG).error(f"处理函数调用结果失败: {e}")
if direct_response:
self.logger.bind(tag=TAG).info(f"使用备用直接回复: {direct_response}")
self.recode_first_last_text(direct_response, text_index)
future = self.executor.submit(self.speak_and_play, direct_response, text_index)
self.tts_queue.put(future)
self.dialogue.put(Message(role="assistant", content=direct_response))
else:
self.logger.bind(tag=TAG).warning(f"函数返回结果为空")
if direct_response:
self.logger.bind(tag=TAG).info(f"使用备用直接回复: {direct_response}")
self.recode_first_last_text(direct_response, text_index)
future = self.executor.submit(self.speak_and_play, direct_response, text_index)
self.tts_queue.put(future)
self.dialogue.put(Message(role="assistant", content=direct_response))
else:
error_text = f"抱歉,我无法获取{function_name}的结果,请稍后再试。"
self.recode_first_last_text(error_text, text_index)
future = self.executor.submit(self.speak_and_play, error_text, text_index)
self.tts_queue.put(future)
self.dialogue.put(Message(role="assistant", content=error_text))
text = result.result
if text is not None and len(text) > 0:
function_id = function_call_data["id"]
function_name = function_call_data["name"]
function_arguments = function_call_data["arguments"]
self.dialogue.put(Message(role='assistant',
tool_calls=[{"id": function_id,
"function": {"arguments": function_arguments,
"name": function_name},
"type": 'function',
"index": 0}]))
self.dialogue.put(Message(role="tool", tool_call_id=function_id, content=text))
self.chat_with_function_calling(text, tool_call=True)
elif result.action == Action.NOTFOUND:
text = result.result
self.logger.bind(tag=TAG).info(f"未找到对应函数: {text}")
self.recode_first_last_text(text, text_index)
future = self.executor.submit(self.speak_and_play, text, text_index)
self.tts_queue.put(future)
self.dialogue.put(Message(role="assistant", content=text))
else:
text = result.result
self.logger.bind(tag=TAG).info(f"其他动作类型,直接返回结果: {text[:100] if text else None}...")
self.recode_first_last_text(text, text_index)
future = self.executor.submit(self.speak_and_play, text, text_index)
self.tts_queue.put(future)
@@ -91,11 +91,18 @@ async def process_intent_result(conn, intent_result, original_text):
def process_function_call():
conn.dialogue.put(Message(role="user", content=original_text))
result = conn.func_handler.handle_llm_function_call(conn, function_call_data)
if result:
if result and function_name != 'play_music':
# 获取当前最新的文本索引
text_index = conn.tts_last_text_index + 1 if hasattr(conn, 'tts_last_text_index') else 0
# 处理函数调用结果
conn._handle_function_result(result, function_call_data, text_index)
text = result.response
if text is None:
text = result.result
if text is not None:
text_index = conn.tts_last_text_index + 1 if hasattr(conn, 'tts_last_text_index') else 0
conn.recode_first_last_text(text, text_index)
future = conn.executor.submit(conn.speak_and_play, text, text_index)
conn.llm_finish_task = True
conn.tts_queue.put(future)
conn.dialogue.put(Message(role="assistant", content=text))
# 将函数执行放在线程池中
conn.executor.submit(process_function_call)
@@ -23,13 +23,8 @@ class IntentProviderBase(ABC):
self.llm = llm
# 获取模型名称和类型信息
model_name = getattr(llm, 'model_name', str(llm.__class__.__name__))
model_type = getattr(llm, 'type', 'unknown')
# 记录更详细的日志
logger.bind(tag=TAG).info(f"意图识别设置LLM: {model_name}, 类型: {model_type}")
# 尝试获取模型基础URL
base_url = getattr(llm, 'base_url', 'N/A')
if base_url != 'N/A':
logger.bind(tag=TAG).debug(f"意图识别LLM基础URL: {base_url}")
logger.bind(tag=TAG).info(f"意图识别设置LLM: {model_name}")
@abstractmethod
async def detect_intent(self, conn, dialogue_history: List[Dict], text: str) -> str: