PMFlow/backend/app/api/rag_ask_contract.py

98 lines
3.6 KiB
Python

from __future__ import annotations
from typing import Any
from ..models import User
from ..schemas.rag import RAGAskRequest
def resolve_effective_tenant_id(current_user: User, fallback_tenant_id: int) -> int:
try:
return int(getattr(current_user, "tenant_id") or fallback_tenant_id or 1)
except Exception:
return int(fallback_tenant_id or 1)
def build_answer_question_kwargs(request: RAGAskRequest, current_user: User) -> dict[str, Any]:
asked_by = int(getattr(current_user, "id"))
return {
"question": request.question,
"asked_by": asked_by,
"asked_via": request.asked_via,
"project_id": request.project_id,
"source_chat_id": request.source_chat_id,
"session_id": request.session_id,
"force_new_session": bool(request.new_session),
"thinking_mode": request.thinking_mode,
"action_mode": request.action_mode,
"sync_requirement": bool(request.sync_requirement),
"message_intent": request.message_intent,
"mixed_signal_part": request.mixed_signal_part,
}
def _safe_int(value: Any) -> int | None:
try:
if value is None:
return None
return int(value)
except Exception:
return None
def _resolve_sender_name(current_user: User) -> str:
sender = str(
getattr(current_user, "name", None)
or getattr(current_user, "username", None)
or "PMFlow用户"
).strip()
return sender or "PMFlow用户"
def build_kernel_ingress_kwargs(request: RAGAskRequest, current_user: User) -> dict[str, Any]:
rag_request_context = build_answer_question_kwargs(request=request, current_user=current_user)
return {
"source_system": str(request.asked_via or "pmflow").strip() or "pmflow",
"source_message_id": None,
"message_text": request.question,
"sender": _resolve_sender_name(current_user),
"channel_ref": request.source_chat_id,
"source_sender_open_id": None,
"captured_at": None,
"chat_type": "manual",
"project_hint_id": request.project_id,
"ingress_options": {
"rag_request_context": rag_request_context,
},
}
def build_rag_response_payload(*, ingress_result: dict[str, Any]) -> dict[str, Any]:
result = ingress_result if isinstance(ingress_result, dict) else {}
rag_result = result.get("rag_result") if isinstance(result.get("rag_result"), dict) else {}
payload = dict(rag_result)
consultant_dispatch = (
payload.get("consultant_dispatch")
if isinstance(payload.get("consultant_dispatch"), dict)
else (result.get("consultant_dispatch") if isinstance(result.get("consultant_dispatch"), dict) else None)
)
if isinstance(consultant_dispatch, dict):
payload["consultant_dispatch"] = consultant_dispatch
answer = str(payload.get("answer") or result.get("direct_reply_text") or "").strip()
payload["answer"] = answer or "当前暂无可用回答。"
if "reply_required" not in payload:
payload["reply_required"] = bool(result.get("direct_reply_required"))
if "reply_text" not in payload:
payload["reply_text"] = str(result.get("direct_reply_text") or "").strip() or None
if "trace_id" not in payload:
payload["trace_id"] = str(result.get("ai_trace_id") or "").strip() or None
if "processing_stage" not in payload:
payload["processing_stage"] = "qa"
payload["work_item_id"] = _safe_int(result.get("work_item_id"))
payload["ingress_status"] = str(result.get("status") or "").strip() or None
payload["intent"] = str(result.get("intent") or "").strip() or None
return payload