From 77193539848912cb80810c6563c801172d987c7a Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Fri, 24 Apr 2026 21:27:45 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E7=B2=BE=E7=AE=80=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E9=80=89=E6=8B=A9=EF=BC=8C=E4=BC=98=E5=8C=96replyer?= =?UTF-8?q?=E8=A1=A8=E7=8E=B0=EF=BC=8C=E4=BC=98=E5=8C=96=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E5=91=BD=E4=B8=AD=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prompts/zh-CN/maisaka_replyer.prompt | 5 +- pytests/test_context_message_fallback.py | 20 ++- pytests/test_maisaka_monitor_protocol.py | 5 + .../replyer/maisaka_expression_selector.py | 47 +----- src/chat/replyer/maisaka_generator_base.py | 144 +++++++++++++++--- src/config/official_configs.py | 9 -- src/maisaka/context_messages.py | 4 +- src/maisaka/history_post_processor.py | 47 +----- src/maisaka/message_adapter.py | 25 ++- src/maisaka/monitor_events.py | 12 +- src/maisaka/reasoning_engine.py | 12 +- 11 files changed, 188 insertions(+), 142 deletions(-) diff --git a/prompts/zh-CN/maisaka_replyer.prompt b/prompts/zh-CN/maisaka_replyer.prompt index 8605bfc5..0647d43a 100644 --- a/prompts/zh-CN/maisaka_replyer.prompt +++ b/prompts/zh-CN/maisaka_replyer.prompt @@ -1,10 +1,7 @@ -在下面的内容中,标注 {bot_name}(你) 的发言是你自己的发言,请注意区分: {identity} -{time_block} - 现在请你读读之前的聊天记录,把握当前的话题,然后给出日常且口语化的回复, {reply_style} 你可以参考【回复信息参考】中的信息,但是视情况而定,不用完全遵守。 {group_chat_attention_block} {replyer_at_block} -请注意不要输出多余内容(包括不必要的前后缀,冒号,括号,表情包,普通 at 或 @等 ),只输出发言内容就好。 +请注意不要输出多余内容(包括不必要的前后缀,冒号,括号,表情包,@等 ),只输出发言内容就好。 diff --git a/pytests/test_context_message_fallback.py b/pytests/test_context_message_fallback.py index 47c958aa..2c344dc5 100644 --- a/pytests/test_context_message_fallback.py +++ b/pytests/test_context_message_fallback.py @@ -1,4 +1,9 @@ -from src.common.data_models.message_component_data_model import ImageComponent, MessageSequence, TextComponent +from src.common.data_models.message_component_data_model import ( + ImageComponent, + MessageSequence, + ReplyComponent, + TextComponent, +) from src.llm_models.payload_content.message import RoleType from src.maisaka.context_messages import _build_message_from_sequence from src.maisaka.message_adapter import build_visible_text_from_sequence @@ -53,3 +58,16 @@ def test_visible_text_uses_image_placeholder_for_whitespace_content() -> None: ) assert visible_text == "看这个[图片]" + + +def test_visible_text_adds_body_marker_after_reply_component() -> None: + visible_text = build_visible_text_from_sequence( + MessageSequence( + [ + ReplyComponent(target_message_id="75625487"), + TextComponent("你说是那就是"), + ] + ) + ) + + assert visible_text == "[引用]quote_id=75625487\n[发言内容]你说是那就是" diff --git a/pytests/test_maisaka_monitor_protocol.py b/pytests/test_maisaka_monitor_protocol.py index 31cc4f09..d6502821 100644 --- a/pytests/test_maisaka_monitor_protocol.py +++ b/pytests/test_maisaka_monitor_protocol.py @@ -118,11 +118,16 @@ def test_legacy_replyer_builds_message_sequence_like_multimodal() -> None: assert len(request_messages) == 4 assert request_messages[0].role.value == "system" + assert request_messages[0].get_text_content() == "legacy prompt" assert request_messages[1].role.value == "user" assert request_messages[1].get_text_content() == "[Alice]你好" assert request_messages[2].role.value == "user" assert request_messages[2].get_text_content() == "[Bob]在吗" assert request_messages[3].role.value == "user" + assert "当前时间:" in request_messages[3].get_text_content() + assert "【回复信息参考】" in request_messages[3].get_text_content() + assert "【最新推理】\n测试原因" in request_messages[3].get_text_content() + assert "请自然地回复。" in request_messages[3].get_text_content() @pytest.mark.asyncio diff --git a/src/chat/replyer/maisaka_expression_selector.py b/src/chat/replyer/maisaka_expression_selector.py index eccd617f..d46ea9c9 100644 --- a/src/chat/replyer/maisaka_expression_selector.py +++ b/src/chat/replyer/maisaka_expression_selector.py @@ -268,6 +268,11 @@ class MaisakaExpressionSelector: reply_reason: str, sub_agent_runner: Optional[SubAgentRunner], ) -> MaisakaExpressionSelectionResult: + del chat_history + del reply_message + del reply_reason + del sub_agent_runner + if not session_id: logger.info("表达方式选择已跳过:缺少 session_id") return MaisakaExpressionSelectionResult() @@ -280,48 +285,10 @@ class MaisakaExpressionSelector: logger.info(f"表达方式选择已跳过:本地候选不足,session_id={session_id}") return MaisakaExpressionSelectionResult() - if not global_config.expression.advanced_chosen: - return self._build_direct_selection_result( - session_id=session_id, - candidates=candidates, - ) - - if sub_agent_runner is None: - logger.info(f"表达方式选择已跳过:缺少 sub_agent_runner,session_id={session_id}") - return MaisakaExpressionSelectionResult() - - logger.info( - f"表达方式选择开始:session_id={session_id} 候选数={len(candidates)} " - f"候选预览={self._format_candidate_preview(candidates)}" - ) - - selector_prompt = self._build_selector_prompt( - chat_history=chat_history, - reply_message=reply_message, - reply_reason=reply_reason, + return self._build_direct_selection_result( + session_id=session_id, candidates=candidates, ) - try: - raw_response = await sub_agent_runner(selector_prompt) - except Exception: - logger.exception("表达方式选择子代理执行失败") - return MaisakaExpressionSelectionResult() - - selected_ids = self._parse_selected_ids(raw_response, candidates) - if not selected_ids: - logger.info(f"表达方式选择完成但未命中,session_id={session_id}") - return MaisakaExpressionSelectionResult() - - selected_expressions = [candidate for candidate in candidates if candidate.get("id") in selected_ids] - self._update_last_active_time(selected_ids) - logger.info( - f"表达方式选择完成:session_id={session_id} 已选数={len(selected_ids)} " - f"selected_ids={selected_ids!r} 已选预览={self._format_candidate_preview(selected_expressions)}" - ) - return MaisakaExpressionSelectionResult( - expression_habits=self._build_expression_habits_block(selected_expressions), - selected_expression_ids=selected_ids, - ) maisaka_expression_selector = MaisakaExpressionSelector() diff --git a/src/chat/replyer/maisaka_generator_base.py b/src/chat/replyer/maisaka_generator_base.py index 2f541370..d9aa6cfd 100644 --- a/src/chat/replyer/maisaka_generator_base.py +++ b/src/chat/replyer/maisaka_generator_base.py @@ -18,6 +18,14 @@ from src.common.data_models.reply_generation_data_models import ( ReplyGenerationResult, build_reply_monitor_detail, ) +from src.common.data_models.message_component_data_model import ( + AtComponent, + EmojiComponent, + ImageComponent, + ReplyComponent, + TextComponent, + VoiceComponent, +) from src.common.logger import get_logger from src.common.utils.utils_session import SessionUtils from src.config.config import global_config @@ -100,6 +108,30 @@ class BaseMaisakaReplyGenerator: del message return "" + @staticmethod + def _strip_guided_reply_formatting(content: str) -> str: + """移除 guided_reply 可见文本中的引用包装,仅保留真正回复正文。""" + + normalized_content = content.strip() + if not normalized_content: + return "" + + reply_body_marker = "[发言内容]" + if normalized_content.startswith("[引用]quote_id=") or normalized_content.startswith("[引用消息]"): + marker_index = normalized_content.find(reply_body_marker) + if marker_index >= 0: + return normalized_content[marker_index + len(reply_body_marker) :].strip() + + newline_index = normalized_content.find("\n") + if newline_index < 0: + return "" + normalized_content = normalized_content[newline_index + 1 :].lstrip() + + if normalized_content.startswith(reply_body_marker): + normalized_content = normalized_content[len(reply_body_marker) :].lstrip() + + return normalized_content.strip() + def _extract_guided_bot_reply(self, message: SessionBackedMessage) -> str: # 只能根据结构化来源字段判断是否为 bot 自身写回的历史消息, # 不能依赖昵称/群名片等可控文本,避免误判和提示注入。 @@ -108,7 +140,9 @@ class BaseMaisakaReplyGenerator: plain_text = message.processed_plain_text.strip() _, body = parse_speaker_content(plain_text) - normalized_body = body.strip() or plain_text + normalized_body = self._strip_guided_reply_formatting(body) or self._strip_guided_reply_formatting( + plain_text + ) return self._normalize_content(normalized_body) if normalized_body else "" def _build_target_message_block(self, reply_message: Optional[SessionMessage]) -> str: @@ -118,18 +152,62 @@ class BaseMaisakaReplyGenerator: user_info = reply_message.message_info.user_info sender_name = user_info.user_cardname or user_info.user_nickname or user_info.user_id target_message_id = reply_message.message_id.strip() if reply_message.message_id else "未知" - target_content = self._normalize_content((reply_message.processed_plain_text or "").strip(), limit=300) + target_time = reply_message.timestamp.strftime("%Y-%m-%d %H:%M:%S") + target_content = self._normalize_content(self._build_target_message_content(reply_message), limit=300) if not target_content: target_content = "[无可见文本内容]" return ( "【本次回复目标】\n" - f"- 目标消息ID:{target_message_id}\n" - f"- 发送者:{sender_name}\n" - f"- 消息内容:{target_content}\n" - "- 你这次要回复的就是这条目标消息,请结合整段上下文理解,但不要把其他历史消息当成当前回复对象。" + f"- msg_id:{target_message_id}\n" + f"- 时间:{target_time}\n" + f"- 用户名:{sender_name}\n" + f"- 发言内容:{target_content}\n\n" + "你这次要回复的就是这条目标消息,请结合整段上下文理解,但不要把其他历史消息当成当前回复对象。" ) + @staticmethod + def _render_target_at_component(component: AtComponent) -> str: + target_name = component.target_user_cardname or component.target_user_nickname or component.target_user_id + return f"@{target_name}".strip() + + def _build_target_message_content(self, reply_message: SessionMessage) -> str: + rendered_parts: List[str] = [] + + for component in reply_message.raw_message.components: + if isinstance(component, TextComponent): + if component.text: + rendered_parts.append(component.text) + continue + + if isinstance(component, ReplyComponent): + target_message_id = component.target_message_id.strip() + if target_message_id: + rendered_parts.append(f"[引用:quote_id={target_message_id}]") + continue + + if isinstance(component, AtComponent): + rendered_at = self._render_target_at_component(component) + if rendered_at: + rendered_parts.append(rendered_at) + continue + + if isinstance(component, ImageComponent): + rendered_parts.append(component.content.strip() or "[图片]") + continue + + if isinstance(component, EmojiComponent): + rendered_parts.append(component.content.strip() or "[表情包]") + continue + + if isinstance(component, VoiceComponent): + rendered_parts.append(component.content.strip() or "[语音消息]") + + normalized_content = " ".join(part.strip() for part in rendered_parts if part and part.strip()).strip() + if normalized_content: + return normalized_content + return (reply_message.processed_plain_text or "").strip() + @staticmethod def _get_chat_prompt_for_chat(chat_id: str, is_group_chat: Optional[bool]) -> str: """根据聊天流 ID 获取匹配的额外 prompt。""" @@ -221,8 +299,10 @@ class BaseMaisakaReplyGenerator: expression_habits: str = "", stream_id: Optional[str] = None, ) -> str: - current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - target_message_block = self._build_target_message_block(reply_message) + del reply_message + del reply_reason + del reference_info + del expression_habits session_id = self._resolve_session_id(stream_id) try: @@ -231,16 +311,29 @@ class BaseMaisakaReplyGenerator: bot_name=global_config.bot.nickname, group_chat_attention_block=self._build_group_chat_attention_block(session_id), replyer_at_block=self._build_replyer_at_block(), - time_block=f"当前时间:{current_time}", identity=self._personality_prompt, reply_style=global_config.personality.reply_style, ) except Exception: system_prompt = "你是一个友好的 AI 助手,请根据聊天记录自然回复。" - sections: List[str] = [] + return system_prompt + + def _build_reply_instruction(self) -> str: + return "请自然地回复。不要输出多余说明、括号、@ 或额外标记,只输出实际要发送的内容。" + + def _build_final_user_message( + self, + reply_message: Optional[SessionMessage], + reply_reason: str, + reference_info: str = "", + expression_habits: str = "", + ) -> str: + current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + sections: List[str] = [f"当前时间:{current_time}"] if expression_habits.strip(): sections.append(expression_habits.strip()) + target_message_block = self._build_target_message_block(reply_message) if target_message_block: sections.append(target_message_block) reply_reference_lines: List[str] = [] @@ -250,12 +343,8 @@ class BaseMaisakaReplyGenerator: reply_reference_lines.append(f"【参考信息】\n{reference_info.strip()}") if reply_reference_lines: sections.append("【回复信息参考】\n" + "\n\n".join(reply_reference_lines)) - if not sections: - return system_prompt - return f"{system_prompt}\n\n" + "\n\n".join(sections) - - def _build_reply_instruction(self) -> str: - return "请自然地回复。不要输出多余说明、括号、@ 或额外标记,只输出实际要发送的内容。" + sections.append(self._build_reply_instruction()) + return "\n\n".join(sections) def _build_history_messages( self, @@ -311,11 +400,16 @@ class BaseMaisakaReplyGenerator: expression_habits=expression_habits, stream_id=stream_id, ) - instruction = self._build_reply_instruction() + final_user_message = self._build_final_user_message( + reply_message=reply_message, + reply_reason=reply_reason, + reference_info=reference_info, + expression_habits=expression_habits, + ) messages.append(MessageBuilder().set_role(RoleType.System).add_text_content(system_prompt).build()) messages.extend(self._build_history_messages(chat_history, enable_visual_message)) - messages.append(MessageBuilder().set_role(RoleType.User).add_text_content(instruction).build()) + messages.append(MessageBuilder().set_role(RoleType.User).add_text_content(final_user_message).build()) return messages def _resolve_enable_visual_message(self, model_info: Optional[ModelInfo] = None) -> bool: @@ -403,10 +497,10 @@ class BaseMaisakaReplyGenerator: result.error_message = "聊天历史为空" return finalize(False) - logger.info( - f"Maisaka 回复器开始生成: 流={stream_id} 原因={reply_reason!r} " - f"历史条数={len(chat_history)} 目标ID={reply_message.message_id if reply_message else None}" - ) + # logger.info( + # f"Maisaka 回复器开始生成: 流={stream_id} 原因={reply_reason!r} " + # f"历史条数={len(chat_history)} 目标ID={reply_message.message_id if reply_message else None}" + # ) filtered_history = [ message @@ -444,9 +538,9 @@ class BaseMaisakaReplyGenerator: else list(reply_context.selected_expression_ids) ) - logger.info( - f"回复上下文完成 流={stream_id} 已选表达={result.selected_expression_ids!r}" - ) + # logger.info( + # f"回复上下文完成 流={stream_id} 已选表达={result.selected_expression_ids!r}" + # ) prompt_started_at = time.perf_counter() try: diff --git a/src/config/official_configs.py b/src/config/official_configs.py index 74169ce9..15feba67 100644 --- a/src/config/official_configs.py +++ b/src/config/official_configs.py @@ -720,15 +720,6 @@ class ExpressionConfig(ConfigBase): ) """_wrap_表达学习配置列表,支持按聊天流配置""" - advanced_chosen: bool = Field( - default=False, - json_schema_extra={ - "x-widget": "switch", - "x-icon": "sparkles", - }, - ) - """是否启用基于子代理的二次表达方式选择""" - expression_groups: list[ExpressionGroup] = Field( default_factory=list, json_schema_extra={ diff --git a/src/maisaka/context_messages.py b/src/maisaka/context_messages.py index ac6b3dea..590ac5e6 100644 --- a/src/maisaka/context_messages.py +++ b/src/maisaka/context_messages.py @@ -90,7 +90,7 @@ def _append_reply_component(builder: MessageBuilder, component: ReplyComponent) if not target_message_id: return False - builder.add_text_content(f"[引用]quote_id={target_message_id}") + builder.add_text_content(f"[引用消息]{target_message_id}") return True @@ -167,7 +167,7 @@ def _render_component_for_prompt(component: StandardMessageComponents) -> str: if target_content: return f"[回复消息: {target_content}]" target_message_id = component.target_message_id.strip() - return f"[引用]quote_id={target_message_id}" if target_message_id else "[回复消息]" + return f"[引用消息]{target_message_id}" if target_message_id else "[回复消息]" if isinstance(component, ForwardNodeComponent): return _build_forward_preview_block(component) diff --git a/src/maisaka/history_post_processor.py b/src/maisaka/history_post_processor.py index 39df5a31..7c9f6c0d 100644 --- a/src/maisaka/history_post_processor.py +++ b/src/maisaka/history_post_processor.py @@ -2,10 +2,9 @@ from dataclasses import dataclass -from .context_messages import AssistantMessage, LLMContextMessage, ToolResultMessage +from .context_messages import AssistantMessage, LLMContextMessage from .history_utils import drop_leading_orphan_tool_results, drop_orphan_tool_results, normalize_tool_result_order -TIMING_HISTORY_TOOL_NAMES = {"continue", "finish", "no_reply", "wait"} EARLY_TRIM_RATIO = 0.2 @@ -27,7 +26,6 @@ def process_chat_history_after_cycle( """在每轮结束后统一执行历史裁切与清理。""" processed_history = list(chat_history) - removed_timing_tool_count = _remove_early_timing_tool_records(processed_history) removed_assistant_thought_count = _remove_early_assistant_thoughts(processed_history) processed_history, orphan_removed_count = drop_orphan_tool_results(processed_history) @@ -45,8 +43,7 @@ def process_chat_history_after_cycle( removed_overflow_count += leading_orphan_removed_count remaining_context_count = sum(1 for message in processed_history if message.count_in_context) removed_count = ( - removed_timing_tool_count - + removed_assistant_thought_count + removed_assistant_thought_count + orphan_removed_count + removed_overflow_count ) @@ -59,41 +56,6 @@ def process_chat_history_after_cycle( ) -def _remove_early_timing_tool_records(chat_history: list[LLMContextMessage]) -> int: - """移除最早 20% 的门控/结束类工具链记录。""" - - candidate_assistant_indexes = [ - index - for index, message in enumerate(chat_history) - if _is_timing_tool_assistant_message(message) - ] - remove_count = int(len(candidate_assistant_indexes) * EARLY_TRIM_RATIO) - if remove_count <= 0: - return 0 - - removed_indexes = set(candidate_assistant_indexes[:remove_count]) - removed_tool_call_ids = { - tool_call.call_id - for index in removed_indexes - for tool_call in chat_history[index].tool_calls - if tool_call.call_id - } - - filtered_history: list[LLMContextMessage] = [] - removed_total = 0 - for index, message in enumerate(chat_history): - if index in removed_indexes: - removed_total += 1 - continue - if isinstance(message, ToolResultMessage) and message.tool_call_id in removed_tool_call_ids: - removed_total += 1 - continue - filtered_history.append(message) - - chat_history[:] = filtered_history - return removed_total - - def _remove_early_assistant_thoughts(chat_history: list[LLMContextMessage]) -> int: """移除最早 20% 的非工具 assistant 思考内容。""" @@ -122,8 +84,3 @@ def _remove_early_assistant_thoughts(chat_history: list[LLMContextMessage]) -> i return removed_total -def _is_timing_tool_assistant_message(message: LLMContextMessage) -> bool: - if not isinstance(message, AssistantMessage) or not message.tool_calls: - return False - - return all(tool_call.func_name in TIMING_HISTORY_TOOL_NAMES for tool_call in message.tool_calls) diff --git a/src/maisaka/message_adapter.py b/src/maisaka/message_adapter.py index aa36580f..1b9e8991 100644 --- a/src/maisaka/message_adapter.py +++ b/src/maisaka/message_adapter.py @@ -60,11 +60,23 @@ def build_visible_text_from_sequence(message_sequence: MessageSequence) -> str: """从消息片段序列提取可见文本。""" parts: list[str] = [] + pending_reply_body_prefix = False + + def append_visible_part(text: str) -> None: + nonlocal pending_reply_body_prefix + if not text: + return + if pending_reply_body_prefix: + parts.append(f"\n[发言内容]{text}") + pending_reply_body_prefix = False + return + parts.append(text) + for component in message_sequence.components: if isinstance(component, TextComponent): match = SPEAKER_PREFIX_PATTERN.match(component.text or "") if not match: - parts.append(component.text) + append_visible_part(component.text) continue normalized_parts: list[str] = [] @@ -75,24 +87,25 @@ def build_visible_text_from_sequence(message_sequence: MessageSequence) -> str: normalized_parts.append(f"[msg_id:{message_id}]") normalized_parts.append(f"[{match.group('speaker')}]") normalized_parts.append(match.group("content")) - parts.append("".join(normalized_parts)) + append_visible_part("".join(normalized_parts)) continue if isinstance(component, EmojiComponent): - parts.append(component.content.strip() or "[表情包]") + append_visible_part(component.content.strip() or "[表情包]") continue if isinstance(component, ImageComponent): - parts.append(component.content.strip() or "[图片]") + append_visible_part(component.content.strip() or "[图片]") continue if isinstance(component, AtComponent): - parts.append(_render_at_component_text(component)) + append_visible_part(_render_at_component_text(component)) continue if isinstance(component, ReplyComponent): target_message_id = component.target_message_id.strip() if target_message_id: - parts.append(f"[引用]quote_id={target_message_id}") + parts.append(f"[引用消息]{target_message_id}") + pending_reply_body_prefix = True return "".join(parts) diff --git a/src/maisaka/monitor_events.py b/src/maisaka/monitor_events.py index 0f5a7b3e..ffe85e11 100644 --- a/src/maisaka/monitor_events.py +++ b/src/maisaka/monitor_events.py @@ -273,10 +273,14 @@ async def _broadcast(event: str, data: Dict[str, Any]) -> None: for connection in websocket_manager.connections.values() if subscription_key in connection.subscriptions ) - logger.info( - f"[诊断] _broadcast: manager_id={id(websocket_manager)} " - f"总连接={total_connections} 订阅者={subscriber_count} event={event}" - ) +# The above code is using the Python logging module to log a diagnostic message. It is logging +# information about the `_broadcast` function, including the `manager_id`, `total_connections`, +# `subscriber_count`, and `event` variables. The `logger.info()` function is used to log the message +# at the INFO level. + # logger.info( + # f"[诊断] _broadcast: manager_id={id(websocket_manager)} " + # f"总连接={total_connections} 订阅者={subscriber_count} event={event}" + # ) await websocket_manager.broadcast_to_topic( domain=MONITOR_DOMAIN, topic=MONITOR_TOPIC, diff --git a/src/maisaka/reasoning_engine.py b/src/maisaka/reasoning_engine.py index b9fbce77..04fc04cb 100644 --- a/src/maisaka/reasoning_engine.py +++ b/src/maisaka/reasoning_engine.py @@ -478,11 +478,11 @@ class MaisakaReasoningEngine: ) planner_duration_ms = (time.time() - planner_started_at) * 1000 cycle_detail.time_records["planner"] = planner_duration_ms / 1000 - logger.info( - f"{self._runtime.log_prefix} 规划器执行完成: " - f"回合={round_index + 1} " - f"耗时={cycle_detail.time_records['planner']:.3f} 秒" - ) + # logger.info( + # f"{self._runtime.log_prefix} 规划器执行完成: " + # f"回合={round_index + 1} " + # f"耗时={cycle_detail.time_records['planner']:.3f} 秒" + # ) reasoning_content = response.content or "" if self._should_replace_reasoning(reasoning_content): response.content = "我应该根据我上面思考的内容进行反思,重新思考我下一步的行动,我需要分析当前场景,对话,以及我可以使用的工具,然后直接输出我的想法" @@ -865,7 +865,7 @@ class MaisakaReasoningEngine: return False similarity = self._calculate_similarity(current_content, self._last_reasoning_content) - logger.info(f"{self._runtime.log_prefix} 思考内容相似度: {similarity:.2f}") + logger.debug(f"{self._runtime.log_prefix} 思考内容相似度: {similarity:.2f}") return similarity > 0.9 @staticmethod