CRag / rag_system /models.py
quantumbit's picture
Upload folder using huggingface_hub
6504f2b verified
Raw
History Blame Contribute Delete
3.33 kB
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
@field_validator("texts")
@classmethod
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
@field_validator("query")
@classmethod
def sanitize_query(cls,v):
return v.strip()
@field_validator("top_k", "top_k_retrieval")
@classmethod
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
@field_validator("mmr_lambda", "bm25_weight", "vector_weight")
@classmethod
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")