Spaces:
Sleeping
Sleeping
| from pydantic import BaseModel, Field, field_validator | |
| from typing import Optional, Any, Literal | |
| from enum import Enum | |
| import uuid | |
| class RetrievalMode(str, Enum): | |
| VECTOR = "vector" | |
| BM25 = "bm25" | |
| HYBRID = "hybrid" | |
| MMR = "mmr" | |
| EmbeddingMode = Literal["bge-large", "bge-small", "openai-small", "auto"] | |
| # Ingestion | |
| class IngestRequest(BaseModel): | |
| texts: list[str] = Field(..., min_length=1, description="Raw text chunks to ingest") | |
| metadatas: Optional[list[dict[str,Any]]] = None | |
| collection_name: str = Field(default="default",pattern=r"^[a-z0-9_-]+$") | |
| force_reindex: bool = False | |
| embedding_mode: Optional[EmbeddingMode] = None | |
| def texts_not_empty(cls,v): | |
| if any(not t.strip() for t in v): | |
| raise ValueError("All text entries must be non-empty") | |
| return v | |
| class IngestResponse(BaseModel): | |
| success: bool | |
| docs_indexed: int | |
| collection_name: str | |
| message: str | |
| job_id: Optional[str] = None | |
| # Query | |
| class ChatMessage(BaseModel): | |
| role: str = Field(...,pattern=r"^(user|assistant)$") | |
| content: str | |
| class QueryRequest(BaseModel): | |
| query: str = Field(...,min_length=1,max_length=2000) | |
| session_id: str = Field(default_factory=lambda: str(uuid.uuid4())) | |
| collection_name: str = Field(default="default") | |
| retrieval_mode: RetrievalMode = RetrievalMode.HYBRID | |
| embedding_mode: Optional[EmbeddingMode] = None | |
| top_k: Optional[int] = None | |
| top_k_retrieval: Optional[int] = None | |
| mmr_lambda: Optional[float] = None | |
| bm25_weight: Optional[float] = None | |
| vector_weight: Optional[float] = None | |
| doc_collections: Optional[list[str]] = None # per-doc sub-collections; None = legacy single-collection mode | |
| history: list[ChatMessage] = Field(default_factory=list) | |
| stream: bool = False | |
| def sanitize_query(cls,v): | |
| return v.strip() | |
| def validate_top_k(cls, v): | |
| if v is None: | |
| return v | |
| if v < 1: | |
| raise ValueError("top_k values must be >= 1") | |
| return v | |
| def validate_weights(cls, v): | |
| if v is None: | |
| return v | |
| if v < 0 or v > 1: | |
| raise ValueError("weights must be between 0 and 1") | |
| return v | |
| class SourceDocument(BaseModel): | |
| doc_id: str | |
| content: str | |
| metadata: dict[str,Any] | |
| relevance_score: float | |
| class QueryResponse(BaseModel): | |
| answer: str | |
| sources: list[SourceDocument] | |
| session_id: str | |
| rewritten_query: Optional[str] = None | |
| cached: bool = False | |
| latency_ms:float | |
| eval_scores: Optional[dict[str,float]] = None | |
| # Evaluation | |
| class EvalRequest(BaseModel): | |
| question: str | |
| answer: str | |
| contexts: list[str] | |
| ground_truth: Optional[str] = None | |
| class EvalResponse(BaseModel): | |
| faithfulness: float | |
| answer_relevance: float | |
| context_precision: Optional[float] = None | |
| context_recall: Optional[float] = None | |
| passed: bool | |
| # Health | |
| class HealthResponse(BaseModel): | |
| status: str | |
| vector_store_loaded: bool | |
| cache_connected: bool | |
| model: str | |
| print("[Models] Pydantic schemas loaded") |