diff --git a/agents/matmaster_agent/flow_agents/agent.py b/agents/matmaster_agent/flow_agents/agent.py index a6d88f8f..249fa73d 100644 --- a/agents/matmaster_agent/flow_agents/agent.py +++ b/agents/matmaster_agent/flow_agents/agent.py @@ -75,6 +75,7 @@ get_report_instruction, ) from agents.matmaster_agent.flow_agents.scene_agent.constant import SCENE_AGENT +from agents.matmaster_agent.flow_agents.scene_agent.model import SceneEnum from agents.matmaster_agent.flow_agents.scene_agent.prompt import SCENE_INSTRUCTION from agents.matmaster_agent.flow_agents.scene_agent.schema import SceneSchema from agents.matmaster_agent.flow_agents.schema import FlowStatusEnum @@ -406,8 +407,21 @@ async def _run_scene_agent( logger.info(f'{ctx.session.id} scenes = {scenes}') yield update_state_event(ctx, state_delta={'scenes': copy.deepcopy(scenes)}) + def _is_query_job_status_only(self, ctx: InvocationContext) -> bool: + """True when user intent is only to query task/job status (no thinking needed).""" + scenes = ctx.session.state.get('scenes') or [] + query_status_value = SceneEnum.QUERY_JOB_STATUS.value + return any( + getattr(s, 'value', s) == query_status_value for s in scenes + ) + async def _run_plan_make_agent( - self, ctx: InvocationContext, UPDATE_USER_CONTENT, TOOLCHAIN_EXAMPLES_PROMPT + self, + ctx: InvocationContext, + UPDATE_USER_CONTENT, + TOOLCHAIN_EXAMPLES_PROMPT, + *, + skip_thinking: bool = False, ) -> AsyncGenerator[Event, None]: # 制定计划 if check_plan(ctx) == FlowStatusEnum.FAILED: @@ -471,41 +485,46 @@ async def _run_plan_make_agent( ) expanded_query = expand_state.get('update_user_content', '') - # Thinking: loop (and optional revision) is handled inside ThinkingAgent + # Thinking: skip for "query job status only" (e.g. 查看任务状态); run otherwise thinking_text = '' - try: - self._thinking_agent.set_thinking_params( - available_tools_with_info_str, - session_file_summary, - original_query, - expanded_query, - short_term_memory=short_term_memory_block, - ) - last_full_text = '' - async for thinking_event in self._thinking_agent.run_async(ctx): - yield thinking_event - if ( - not getattr(thinking_event, 'partial', True) - and getattr(thinking_event, 'content', None) - and getattr(thinking_event.content, 'parts', None) - ): - parts_text = ''.join( - p.text or '' - for p in thinking_event.content.parts - if getattr(p, 'text', None) - ) - if parts_text.strip(): - last_full_text = parts_text.strip() - thinking_text = (last_full_text or '').strip() - if getattr(self._thinking_agent, '_last_thinking_text', None) is not None: - thinking_text = self._thinking_agent._last_thinking_text + if not skip_thinking: + try: + self._thinking_agent.set_thinking_params( + available_tools_with_info_str, + session_file_summary, + original_query, + expanded_query, + short_term_memory=short_term_memory_block, + ) + last_full_text = '' + async for thinking_event in self._thinking_agent.run_async(ctx): + yield thinking_event + if ( + not getattr(thinking_event, 'partial', True) + and getattr(thinking_event, 'content', None) + and getattr(thinking_event.content, 'parts', None) + ): + parts_text = ''.join( + p.text or '' + for p in thinking_event.content.parts + if getattr(p, 'text', None) + ) + if parts_text.strip(): + last_full_text = parts_text.strip() + thinking_text = (last_full_text or '').strip() + if getattr(self._thinking_agent, '_last_thinking_text', None) is not None: + thinking_text = self._thinking_agent._last_thinking_text + logger.info( + f'{ctx.session.id} reasoning_agent result length={len(thinking_text)}, ' + f'preview={repr(thinking_text[:300]) if thinking_text else "empty"}' + ) + except Exception as e: + logger.warning( + f'{ctx.session.id} reasoning_agent failed: {e}, proceed without thinking' + ) + else: logger.info( - f'{ctx.session.id} reasoning_agent result length={len(thinking_text)}, ' - f'preview={repr(thinking_text[:300]) if thinking_text else "empty"}' - ) - except Exception as e: - logger.warning( - f'{ctx.session.id} reasoning_agent failed: {e}, proceed without thinking' + f'{ctx.session.id} skip reasoning_agent (query_job_status_only)' ) self.plan_make_agent.instruction = get_plan_make_instruction( @@ -873,13 +892,18 @@ async def _run_research_flow( yield update_state_event(ctx, state_delta={PLAN: {}, MULTI_PLANS: {}}) # 制定计划(1. 无计划;2. 计划已完成;3. 计划失败;4. 用户未确认计划) + # 仅查询任务状态时跳过 thinking(查任务状态不 thinking) + skip_thinking = self._is_query_job_status_only(ctx) if check_plan(ctx) in [ FlowStatusEnum.NO_PLAN, FlowStatusEnum.COMPLETE, FlowStatusEnum.FAILED, ] or not is_plan_confirmed(ctx): async for _plan_make_event in self._run_plan_make_agent( - ctx, UPDATE_USER_CONTENT, TOOLCHAIN_EXAMPLES_PROMPT + ctx, + UPDATE_USER_CONTENT, + TOOLCHAIN_EXAMPLES_PROMPT, + skip_thinking=skip_thinking, ): yield _plan_make_event diff --git a/agents/matmaster_agent/flow_agents/scene_agent/model.py b/agents/matmaster_agent/flow_agents/scene_agent/model.py index 649c59b7..3556a568 100644 --- a/agents/matmaster_agent/flow_agents/scene_agent/model.py +++ b/agents/matmaster_agent/flow_agents/scene_agent/model.py @@ -126,3 +126,9 @@ class SceneEnum(DescriptiveEnum): 'perovskite_research', 'Research, literature/database search, and semantic mining focused on perovskite solar cells (efficiency, stability, additives, architectures, new molecules).', ) + + # job/task status only (no planning/thinking needed) + QUERY_JOB_STATUS = ( + 'query_job_status', + 'User only asks to check task/job status or get task results. e.g. 查看任务状态, 查看任务结果, check task status, check task results. Use this when the sole intent is to query status or retrieve results of submitted jobs, not to create a new plan.', + )