"""RAG / 知识库 / QA 记录请求模型。""" from __future__ import annotations from datetime import datetime from typing import Optional from pydantic import BaseModel, Field class RAGAskRequest(BaseModel): question: str = Field(..., min_length=1, max_length=4000) project_id: Optional[int] = Field(default=None) asked_via: str = Field(default="pmflow", pattern="^(pmflow|feishu)$") source_chat_id: Optional[str] = Field(default=None, max_length=128) session_id: Optional[int] = Field(default=None, ge=1) new_session: bool = Field(default=False) thinking_mode: str = Field(default="normal", pattern="^(normal|deep)$") action_mode: str = Field(default="auto", pattern="^(auto|read|write|read_write)$") sync_requirement: bool = Field(default=True) class KnowledgeDocCreateRequest(BaseModel): title: str = Field(..., min_length=1, max_length=255) file_type: str = Field(default="txt", max_length=32) content: str = Field(..., min_length=1, max_length=200000) source_type: str = Field(default="file", max_length=32) file_url: Optional[str] = Field(default=None, max_length=1024) project_id: Optional[int] = Field(default=None) class KnowledgeURLCreateRequest(BaseModel): url: str = Field(..., min_length=5, max_length=1024) title: Optional[str] = Field(default=None, max_length=255) project_id: Optional[int] = Field(default=None) class QAFeedbackCreateRequest(BaseModel): rating: str = Field(..., pattern="^(positive|negative)$") helpfulness: Optional[str] = Field(default=None, pattern="^(fully|partially|could_be_better)$") error_types: list[str] = Field(default_factory=list) correct_answer: Optional[str] = Field(default=None, max_length=4000) class QAListQuery(BaseModel): project_id: Optional[int] = None date_from: Optional[datetime] = None date_to: Optional[datetime] = None rating: Optional[str] = Field(default=None, pattern="^(positive|negative)$") page: int = Field(default=1, ge=1) page_size: int = Field(default=20, ge=1, le=100) class QAExportQuery(BaseModel): include_unrated: bool = False project_id: Optional[int] = None rating: Optional[str] = Field(default=None, pattern="^(positive|negative|unrated)$") domain: Optional[str] = None date_from: Optional[datetime] = None date_to: Optional[datetime] = None class QASessionListQuery(BaseModel): date_from: Optional[datetime] = None date_to: Optional[datetime] = None page: int = Field(default=1, ge=1) page_size: int = Field(default=20, ge=1, le=100) class QASessionRenameRequest(BaseModel): title: str = Field(..., min_length=1, max_length=120) class EntityResolutionRequest(BaseModel): question: str = Field(..., min_length=1, max_length=4000) project_id: Optional[int] = Field(default=None) limit: int = Field(default=10, ge=1, le=50) class MultiStepSearchRequest(BaseModel): question: str = Field(..., min_length=1, max_length=4000) project_id: Optional[int] = Field(default=None) source_chat_id: Optional[str] = Field(default=None, max_length=128) class SymbolSyncRequest(BaseModel): base_dir: Optional[str] = Field(default=None, max_length=500) max_files: int = Field(default=500, ge=1, le=3000) force_reindex: bool = Field(default=False) class SymbolSearchRequest(BaseModel): query: str = Field(..., min_length=1, max_length=255) language: Optional[str] = Field(default=None, max_length=20) symbol_type: Optional[str] = Field(default=None, max_length=32) limit: int = Field(default=30, ge=1, le=200)