PMFlow/backend/app/services/adaptive_rag_service/shared_part_02.py

121 lines
3.4 KiB
Python

"""Adaptive RAG shared constants/types part."""
from __future__ import annotations
from .shared_imports import *
from .shared_utils import *
URL_RE = re.compile(r"https?://\S+", flags=re.IGNORECASE)
SENTENCE_SPLIT_RE = re.compile(r"(?<=[。!?!?\n])")
PAGE_MARKER_RE = re.compile(r"\[\[PAGE:(\d{1,6})\]\]")
MAX_CONTEXT_TOKENS = 8000
DEFAULT_TOP_K = 5
DB_QUERY_TIMEOUT_SECONDS = 5.0
VECTOR_SEARCH_TIMEOUT_SECONDS = 10.0
GRAPH_QUERY_TIMEOUT_SECONDS = 4.0
AGENT_MAX_RETRIEVAL_STEPS = 3
SESSION_GAP_MINUTES = 30
SESSION_DEFAULT_TITLE = "新会话"
SESSION_TITLE_MIN_LEN = 5
THINKING_MODE_NORMAL = "normal"
THINKING_MODE_DEEP = "deep"
DEEP_RETRIEVAL_STEPS = _env_int("RAG_DEEP_RETRIEVAL_STEPS", 5, minimum=2, maximum=8)
DEEP_VECTOR_TOP_K = _env_int("RAG_DEEP_VECTOR_TOP_K", 12, minimum=6, maximum=40)
DEEP_CONTEXT_BLOCKS = _env_int("RAG_DEEP_CONTEXT_BLOCKS", 16, minimum=8, maximum=32)
DEEP_ANSWER_MAX_TOKENS = _env_int("RAG_DEEP_ANSWER_MAX_TOKENS", 1400, minimum=900, maximum=3000)
QUERY_TYPE_COUNT = "count"
QUERY_TYPE_LIST = "list"
QUERY_TYPE_EXISTENCE = "existence"
QUERY_TYPE_STATUS = "status"
QUERY_TYPE_EXPLAIN = "explain"
QUERY_TYPE_DIAGNOSE = "diagnose"
QUERY_TYPE_COMPARE = "compare"
QUERY_TYPE_UNKNOWN = "unknown"
ANSWER_MODE_FAST_PATH = "fast_path"
ANSWER_MODE_RETRIEVAL_NORMAL = "retrieval_normal"
ANSWER_MODE_RETRIEVAL_DEEP = "retrieval_deep"
ANSWER_MODE_CLARIFY = "clarify"
ANSWER_MODE_BLOCKED = "blocked"
GROUNDING_STATUS_GROUNDED = "grounded"
GROUNDING_STATUS_PARTIALLY_GROUNDED = "partially_grounded"
GROUNDING_STATUS_INSUFFICIENT_EVIDENCE = "insufficient_evidence"
GROUNDING_STATUS_BLOCKED = "blocked"
RETRIEVAL_POLICY_VERSION = "retrieval-v2.1"
ACTION_MODE_AUTO = "auto"
ACTION_MODE_READ = "read"
ACTION_MODE_WRITE = "write"
ACTION_MODE_READ_WRITE = "read_write"
ENTITY_ALIAS_MAP: dict[str, str] = {
"能力": "skill",
"技能": "skill",
"ability": "skill",
"abilities": "skill",
"skill": "skill",
"skills": "skill",
"负责人": "owner",
"owner": "owner",
"assignee": "owner",
"成员": "member",
"人员": "member",
"member": "member",
"任务": "task",
"task": "task",
"tasks": "task",
"项目": "project",
"project": "project",
"projects": "project",
"信号": "signal",
"signal": "signal",
"signals": "signal",
"函数": "function",
"function": "function",
"method": "function",
"类": "class",
"class": "class",
"模块": "module",
"module": "module",
"智能配置": "ai_config",
"ai配置": "ai_config",
"配置中心": "ai_config",
"能力管理": "skills",
"技能管理": "skills",
"用户管理": "users",
"项目列表": "projects",
"团队负载": "workloads",
"ai管家": "ai_steward",
}
TS_SYMBOL_RE = re.compile(
r"(?:export\s+)?(?:async\s+)?(?:function|class|interface|type|const)\s+([A-Za-z_][A-Za-z0-9_]*)"
)
@dataclass
class RetrievedItem:
source: str
content: str
score: float
source_label: str
metadata: dict[str, Any]
@dataclass
class RetrievalBudget:
max_steps: int
vector_top_k: int
@dataclass
class QueryPlannerDecision:
answer_mode: str
thinking_mode: str
allow_fast_path: bool
retrieval_answer_mode: str
budget: RetrievalBudget
reason: Optional[str] = None
@dataclass
class GroundingVerdict:
status: str
missing_fields: list[str]
reason_code: Optional[str] = None