diff --git a/astrbot/core/conversation_mgr.py b/astrbot/core/conversation_mgr.py index c506fa8f1..b0f5c136d 100644 --- a/astrbot/core/conversation_mgr.py +++ b/astrbot/core/conversation_mgr.py @@ -175,7 +175,15 @@ class ConversationManager: if record["role"] == "user": temp_contexts.append(f"User: {record['content']}") elif record["role"] == "assistant": - temp_contexts.append(f"Assistant: {record['content']}") + if "content" in record and record["content"]: + temp_contexts.append(f"Assistant: {record['content']}") + elif "tool_calls" in record: + tool_calls_str = json.dumps( + record["tool_calls"], ensure_ascii=False + ) + temp_contexts.append(f"Assistant: [函数调用] {tool_calls_str}") + else: + temp_contexts.append("Assistant: [未知的内容]") contexts.insert(0, temp_contexts) temp_contexts = [] diff --git a/astrbot/core/pipeline/process_stage/method/llm_request.py b/astrbot/core/pipeline/process_stage/method/llm_request.py index a7ddd9607..617e458c8 100644 --- a/astrbot/core/pipeline/process_stage/method/llm_request.py +++ b/astrbot/core/pipeline/process_stage/method/llm_request.py @@ -66,12 +66,16 @@ class LLMRequestSubStage(Stage): if event.get_extra("provider_request"): req = event.get_extra("provider_request") - assert isinstance(req, ProviderRequest), ( - "provider_request 必须是 ProviderRequest 类型。" - ) + assert isinstance( + req, ProviderRequest + ), "provider_request 必须是 ProviderRequest 类型。" if req.conversation: - req.contexts = json.loads(req.conversation.history) + all_contexts = json.loads(req.conversation.history) + req.contexts = self._process_tool_message_pairs( + all_contexts, remove_tags=True + ) + else: req = ProviderRequest(prompt="", image_urls=[]) if self.provider_wake_prefix: @@ -447,12 +451,22 @@ class LLMRequestSubStage(Stage): if llm_response.role == "assistant": # 文本回复 - contexts = req.contexts + contexts = req.contexts.copy() contexts.append(await req.assemble_context()) - # tool calls result + # 记录并标记函数调用结果 if req.tool_calls_result: - contexts.extend(req.tool_calls_result.to_openai_messages()) + tool_calls_messages = req.tool_calls_result.to_openai_messages() + + # 添加标记 + for message in tool_calls_messages: + message["_tool_call_history"] = True + + processed_tool_messages = self._process_tool_message_pairs( + tool_calls_messages, remove_tags=False + ) + + contexts.extend(processed_tool_messages) contexts.append( {"role": "assistant", "content": llm_response.completion_text} @@ -463,3 +477,59 @@ class LLMRequestSubStage(Stage): await self.conv_manager.update_conversation( event.unified_msg_origin, req.conversation.cid, history=contexts_to_save ) + + def _process_tool_message_pairs(self, messages, remove_tags=True): + """处理工具调用消息,确保assistant和tool消息成对出现 + + Args: + messages (list): 消息列表 + remove_tags (bool): 是否移除_tool_call_history标记 + + Returns: + list: 处理后的消息列表,保证了assistant和对应tool消息的成对出现 + """ + result = [] + i = 0 + + while i < len(messages): + current_msg = messages[i] + + # 普通消息直接添加 + if "_tool_call_history" not in current_msg: + result.append(current_msg.copy() if remove_tags else current_msg) + i += 1 + continue + + # 工具调用消息成对处理 + if current_msg.get("role") == "assistant" and "tool_calls" in current_msg: + assistant_msg = current_msg.copy() + + if remove_tags and "_tool_call_history" in assistant_msg: + del assistant_msg["_tool_call_history"] + + related_tools = [] + j = i + 1 + while ( + j < len(messages) + and messages[j].get("role") == "tool" + and "_tool_call_history" in messages[j] + ): + tool_msg = messages[j].copy() + + if remove_tags: + del tool_msg["_tool_call_history"] + + related_tools.append(tool_msg) + j += 1 + + # 成对的时候添加到结果 + if related_tools: + result.append(assistant_msg) + result.extend(related_tools) + + i = j # 跳过已处理 + else: + # 单独的tool消息 + i += 1 + + return result diff --git a/astrbot/core/provider/sources/gemini_source.py b/astrbot/core/provider/sources/gemini_source.py index 7def203db..a3ca8c8f2 100644 --- a/astrbot/core/provider/sources/gemini_source.py +++ b/astrbot/core/provider/sources/gemini_source.py @@ -180,7 +180,7 @@ class ProviderGoogleGenAI(Provider): if message["role"] == "user": if isinstance(message["content"], str): if not message["content"]: - message["content"] = "" + message["content"] = " " google_genai_conversation.append( {"role": "user", "parts": [{"text": message["content"]}]} @@ -209,7 +209,7 @@ class ProviderGoogleGenAI(Provider): elif message["role"] == "assistant": if "content" in message: if not message["content"]: - message["content"] = "" + message["content"] = " " google_genai_conversation.append( {"role": "model", "parts": [{"text": message["content"]}]} )