RAGForge / src /ragforge /schemas.py
ArchitSharma's picture
Upgrade RAGForge to v1.9 adaptive scale and release readiness
f0307a2
Raw
History Blame Contribute Delete
4.85 kB
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Literal
from pydantic import BaseModel, Field
KnowledgeScope = Literal["corpus", "external", "mixed", "structured_data"]
TaskType = Literal[
"fact_lookup",
"overview",
"cross_document_synthesis",
"comparison",
"aggregation",
"insight_synthesis",
"followup",
]
RetrievalStrategy = Literal["semantic", "global", "hierarchical", "analytical", "table", "none"]
WebRelevance = Literal["required", "useful", "irrelevant"]
@dataclass(slots=True)
class Document:
text: str
source: str
page: int | None = None
section: str | None = None
metadata: dict[str, Any] = field(default_factory=dict)
@dataclass(slots=True)
class Chunk:
id: str
text: str
source: str
page: int | None = None
section: str | None = None
metadata: dict[str, Any] = field(default_factory=dict)
@dataclass(slots=True)
class SearchHit:
chunk: Chunk
score: float
dense_score: float | None = None
sparse_score: float | None = None
rerank_score: float | None = None
origin: Literal["document", "web"] = "document"
url: str | None = None
title: str | None = None
@dataclass(slots=True)
class SourceProfile:
source: str
file_type: str
document_units: int
chunk_count: int
page_count: int
section_count: int
representative_chunk_ids: list[str]
profile_text: str
class QueryPlan(BaseModel):
"""Semantic plan produced before retrieval.
The fields deliberately separate *where knowledge lives* from *how it should
be retrieved*. That keeps phrases such as "current corpus" from being
mistaken for current-world/fresh-web intent.
"""
route: Literal["documents", "web", "hybrid", "sql"] = "documents"
knowledge_scope: KnowledgeScope = "corpus"
task_type: TaskType = "fact_lookup"
retrieval_strategy: RetrievalStrategy = "semantic"
web_relevance: WebRelevance = "irrelevant"
requires_fresh_web: bool = False
rewritten_query: str = ""
document_queries: list[str] = Field(default_factory=list)
web_queries: list[str] = Field(default_factory=list)
hyde: str = ""
rationale: str = ""
class EvidenceAssessment(BaseModel):
score: float = Field(default=0.0, ge=0.0, le=1.0)
top_relevance: float = Field(default=0.0, ge=0.0, le=1.0)
mean_relevance: float = Field(default=0.0, ge=0.0, le=1.0)
method_agreement: float = Field(default=0.0, ge=0.0, le=1.0)
source_coverage: float = Field(default=0.0, ge=0.0, le=1.0)
unique_sources: int = 0
corpus_sources: int = 0
sufficient: bool = False
reason: str = ""
class RAGEvalJudgement(BaseModel):
"""Auxiliary LLM-as-judge scores for benchmark cases.
These scores complement deterministic labels; they are never treated as
ground truth because judge models can be noisy or biased.
"""
faithfulness: float = Field(default=0.0, ge=0.0, le=1.0)
answer_relevance: float = Field(default=0.0, ge=0.0, le=1.0)
completeness: float = Field(default=0.0, ge=0.0, le=1.0)
citation_support: float = Field(default=0.0, ge=0.0, le=1.0)
overall: float = Field(default=0.0, ge=0.0, le=1.0)
pass_: bool = Field(default=False, alias="pass")
reason: str = ""
model_config = {"populate_by_name": True}
class PipelineConfig(BaseModel):
mode: Literal["Auto", "Documents", "Web", "Hybrid", "Data (SQL)"] = "Auto"
profile: Literal["Fast", "Balanced", "Agentic"] = "Balanced"
model: str = "gemini-3.5-flash-lite"
web_provider: Literal["Auto", "DuckDuckGo", "Tavily", "Gemini Search"] = "Auto"
use_hyde: bool = True
use_multi_query: bool = True
use_reranker: bool = True
use_context_pruning: bool = True
use_adaptive_top_k: bool = True
use_evidence_compression: bool = True
use_crag: bool = True
use_self_rag: bool = True
allow_web_fallback: bool = True
use_history: bool = True
top_k: int = Field(default=6, ge=2, le=12)
class QueryRequest(BaseModel):
session_id: str
query: str = Field(min_length=1, max_length=8000)
config: PipelineConfig = Field(default_factory=PipelineConfig)
class EvaluationRequest(BaseModel):
session_id: str
level: Literal["Quick", "Standard", "Deep"] = "Standard"
model: str = "gemini-3.5-flash-lite"
target_rpm: int = Field(default=12, ge=0, le=60)
reuse_saved: bool = True
include_profile_benchmark: bool = False
class QueryResponse(BaseModel):
answer: str
sources: list[dict[str, Any]]
trace: dict[str, Any]
confidence: float
class SessionResponse(BaseModel):
session_id: str
class CorpusSummary(BaseModel):
session_id: str
documents: int
chunks: int
tables: list[str]
sources: list[str]
source_profiles: int = 0