249 lines
9.4 KiB
Python
249 lines
9.4 KiB
Python
"""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,
|
|
) -> 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,
|
|
)
|
|
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),
|
|
)
|
|
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_row = await self._ensure_session_state(session_id=session_id)
|
|
effective_q, rewrite_meta = self._rewrite_question_with_state(
|
|
question=clean_q,
|
|
conversation=conversation,
|
|
session_state=state_row,
|
|
)
|
|
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=clean_q,
|
|
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,
|
|
"effective_q": effective_q,
|
|
"rewrite_meta": rewrite_meta,
|
|
"query_type": query_type,
|
|
"effective_action_mode": effective_action_mode,
|
|
}
|
|
|
|
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],
|
|
) -> 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_answer = self._build_clarification_question(
|
|
original_question=clean_q,
|
|
effective_question=effective_q,
|
|
session_state=state_row,
|
|
)
|
|
clarification_result = await self._maybe_return_clarification_response(
|
|
clarification_answer=clarification_answer,
|
|
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,
|
|
)
|