"""Adaptive RAG answer mainline orchestration helpers.""" from __future__ import annotations from .shared import * class AdaptiveRAGAnswerMainlineMixin: async def _prepare_answer_runtime( self, *, clean_q: str, asked_by: Optional[int], asked_via: str, project_id: Optional[int], source_chat_id: Optional[str], session_id: Optional[int], conversation_key: Optional[str], force_new_session: bool, action_mode: str, source_message_id: Optional[str] = None, source_sender_open_id: Optional[str] = None, thread_context: Optional[dict[str, Any]] = None, ) -> dict[str, Any]: external_conversation_key = self._build_external_conversation_key( asked_via=asked_via, source_chat_id=source_chat_id, conversation_key=conversation_key, source_sender_open_id=source_sender_open_id, sender=None, thread_context=thread_context, ) self._set_active_external_qa_context( source_chat_id=source_chat_id, source_message_id=source_message_id, source_sender_open_id=source_sender_open_id, conversation_scope_key=external_conversation_key, thread_context=thread_context, ) session_id, turn_index = await self._touch_session_for_new_record( asked_by=asked_by, asked_via=asked_via, project_id=project_id, question=clean_q, preferred_session_id=session_id, force_new_session=bool(force_new_session), external_conversation_key=external_conversation_key, ) context_session_id: Optional[int] if session_id is not None: context_session_id = int(session_id) elif asked_by is None: context_session_id = self._external_session_id_from_key(external_conversation_key) else: context_session_id = None conversation = await self._load_recent_conversation( asked_by=asked_by, asked_via=asked_via, project_id=project_id, session_id=session_id, external_session_id=context_session_id, limit=10, ) state_session_id = int(session_id) if session_id is not None else ( int(context_session_id) if context_session_id is not None else None ) state_row = await self._ensure_session_state(session_id=state_session_id) pending_selection = self._consume_pending_clarification_selection( question=clean_q, session_state=state_row, ) resolved_question = str(pending_selection.get("effective_question") or clean_q).strip() if isinstance( pending_selection, dict ) else clean_q anchor_resolution = await self._resolve_followup_anchor( question=resolved_question, session_id=state_session_id, context_session_id=context_session_id, session_state=state_row, conversation_scope_key=external_conversation_key, source_chat_id=source_chat_id, source_sender_open_id=source_sender_open_id, source_message_id=source_message_id, thread_context=thread_context, ) effective_q, rewrite_meta = self._rewrite_question_with_state( question=resolved_question, conversation=conversation, session_state=state_row, anchor_resolution=anchor_resolution, ) query_type = self._classify_query_type(effective_q) requested_action_mode = self._normalize_action_mode(action_mode) effective_action_mode = self._resolve_action_mode( requested_mode=requested_action_mode, question=resolved_question, effective_question=effective_q, ) return { "session_id": session_id, "turn_index": turn_index, "context_session_id": context_session_id, "conversation": conversation, "state_row": state_row, "resolved_question": resolved_question, "effective_q": effective_q, "rewrite_meta": rewrite_meta, "query_type": query_type, "effective_action_mode": effective_action_mode, "anchor_resolution": anchor_resolution, } async def _execute_base_answer_mainline( self, *, clean_q: str, asked_by: Optional[int], asked_via: str, project_id: Optional[int], source_chat_id: Optional[str], session_id: Optional[int], turn_index: int, context_session_id: Optional[int], conversation: list[dict[str, str]], state_row: Optional[QASessionState], effective_q: str, rewrite_meta: dict[str, Any], query_type: str, thinking_mode: str, active_thinking_mode: str, deep_thinking: bool, enforce_scene_prompt_only: bool, deep_retrieval_steps: int, deep_vector_top_k: int, started: float, message_intent: Optional[str], mixed_signal_part: Optional[str], anchor_resolution: Optional[FollowupAnchorResolution] = None, ) -> dict[str, Any]: forced_deep_reason = "" if not deep_thinking: forced_deep_reason = self._forced_deep_reason( question=clean_q, effective_question=effective_q, conversation=conversation, ) if forced_deep_reason and self._should_force_deep_for_channel( asked_via=asked_via, question=clean_q, effective_question=effective_q, reason=forced_deep_reason, ): deep_thinking = True active_thinking_mode = THINKING_MODE_DEEP else: forced_deep_reason = "" clarification_payload = self._build_followup_clarification_payload( question=clean_q, anchor_resolution=anchor_resolution, session_state=state_row, ) meta_followup_payload = await self._build_meta_followup_payload( question=clean_q, anchor_resolution=anchor_resolution, conversation_scope_key=self._get_active_external_qa_context().get("conversation_scope_key"), ) meta_followup_result = await self._maybe_return_meta_followup_response( meta_followup_payload=meta_followup_payload, started=started, clean_q=clean_q, effective_q=effective_q, query_type=query_type, asked_by=asked_by, asked_via=asked_via, project_id=project_id, session_id=session_id, turn_index=turn_index, state_row=state_row, rewrite_meta=rewrite_meta, context_session_id=context_session_id, active_thinking_mode=active_thinking_mode, ) if meta_followup_result is not None: return meta_followup_result clarification_result = await self._maybe_return_clarification_response( clarification_payload=clarification_payload, started=started, clean_q=clean_q, effective_q=effective_q, query_type=query_type, asked_by=asked_by, asked_via=asked_via, project_id=project_id, session_id=session_id, turn_index=turn_index, state_row=state_row, rewrite_meta=rewrite_meta, context_session_id=context_session_id, active_thinking_mode=active_thinking_mode, ) if clarification_result is not None: return clarification_result system_snapshot = await self.context_cache.get_system_snapshot( db=self.db, tenant_id=self.tenant_id, ) user_snapshot = await self.context_cache.get_user_snapshot( db=self.db, tenant_id=self.tenant_id, user_id=asked_by, ) if not deep_thinking and not enforce_scene_prompt_only: deterministic_result = await self._run_deterministic_query( question=effective_q, project_id=project_id, query_type=query_type, ) if deterministic_result is not None: return await self._persist_fast_answer( question=clean_q, asked_by=asked_by, asked_via=asked_via, project_id=project_id, fast_result=deterministic_result, session_id=session_id, external_session_id=context_session_id, turn_index=turn_index, query_type=str(deterministic_result.get("query_type") or query_type), missing_fields=list(deterministic_result.get("missing_fields") or []), state_row=state_row, effective_question=effective_q, rewrite_meta=rewrite_meta, thinking_mode=active_thinking_mode, ) direct_answer = None if not deep_thinking and not enforce_scene_prompt_only: direct_answer = self._build_snapshot_direct_answer( effective_q, system_snapshot=system_snapshot, user_snapshot=user_snapshot, ) direct_result = await self._maybe_return_snapshot_direct_response( direct_answer=direct_answer, started=started, clean_q=clean_q, effective_q=effective_q, asked_by=asked_by, asked_via=asked_via, project_id=project_id, session_id=session_id, turn_index=turn_index, state_row=state_row, rewrite_meta=rewrite_meta, context_session_id=context_session_id, active_thinking_mode=active_thinking_mode, user_snapshot=user_snapshot, ) if direct_result is not None: return direct_result is_snapshot_direct_question = self._is_snapshot_direct_question(effective_q) if not deep_thinking and not enforce_scene_prompt_only and not is_snapshot_direct_question: glm_semantic_result = await self._try_glm_project_semantic_answer(clean_q=effective_q, project_id=project_id) if glm_semantic_result is not None: return await self._persist_fast_answer( question=clean_q, asked_by=asked_by, asked_via=asked_via, project_id=project_id, fast_result=glm_semantic_result, session_id=session_id, external_session_id=context_session_id, turn_index=turn_index, query_type=query_type if query_type != QUERY_TYPE_UNKNOWN else QUERY_TYPE_EXPLAIN, missing_fields=[], state_row=state_row, effective_question=effective_q, rewrite_meta=rewrite_meta, thinking_mode=active_thinking_mode, ) return await self._build_retrieval_response( clean_q=clean_q, effective_q=effective_q, asked_by=asked_by, asked_via=asked_via, project_id=project_id, source_chat_id=source_chat_id, session_id=session_id, turn_index=turn_index, context_session_id=context_session_id, conversation=conversation, state_row=state_row, rewrite_meta=rewrite_meta, query_type=query_type, thinking_mode=thinking_mode, active_thinking_mode=active_thinking_mode, deep_thinking=deep_thinking, forced_deep_reason=forced_deep_reason, deep_retrieval_steps=deep_retrieval_steps, deep_vector_top_k=deep_vector_top_k, system_snapshot=system_snapshot, user_snapshot=user_snapshot, started=started, message_intent=message_intent, mixed_signal_part=mixed_signal_part, )