Spaces:
Running
Running
| """ | |
| models.py — Pydantic request/response schemas for Space 2. | |
| Changes vs previous version: | |
| - ChunkSchema: added `outline_path` and `source_block_id` fields so the | |
| enriched payload produced by the new serialiser.py round-trips cleanly. | |
| Both are Optional with defaults so older payloads (fields absent) still | |
| validate without error. | |
| - IngestPayload: added all enriched fields that serialiser.py now emits: | |
| block_to_chunks { block_id: [chunk_id, ...] } | |
| outline nested section tree | |
| chunk_outline_path { chunk_id: [h1_title, h2_title, ...] } | |
| content_type_index { "paragraph": [...], "table": [...], "figure": [...] } | |
| page_index { "1": [block_id, ...], "2": [...] } | |
| All are Optional[...] = None so old single-field payloads keep working. | |
| `graph` is also Optional — serialiser.py supports include_graph=False for | |
| lightweight payloads. | |
| """ | |
| from __future__ import annotations | |
| from typing import Any, Dict, List, Optional | |
| from pydantic import BaseModel, Field | |
| # ── Ingest (Space 1 → Space 2) ──────────────────────────────────────────────── | |
| class ChunkSchema(BaseModel): | |
| chunk_id: str | |
| doc_name: str | |
| page_num: int | |
| region_type: str | |
| text: str | |
| section_title: str | |
| bbox: List[float] | |
| confidence: float | |
| char_count: int | |
| table_html: Optional[str] = None | |
| figure_path: Optional[str] = None | |
| source_block_id: Optional[str] = None | |
| outline_path: Optional[List[str]] = None # [h1_title, h2_title, ...] | |
| # Space 1 FIX #1: carry-forward context is now a separate field, NOT in text. | |
| # chunk.text is always clean; context is the previous sentence for | |
| # display / re-ranking only. Never embed this field. | |
| context: Optional[str] = None | |
| class IngestPayload(BaseModel): | |
| doc_name: str | |
| total_pages: int | |
| reading_order: List[str] | |
| chunks: List[ChunkSchema] | |
| # Node-link graph — Optional because serialiser supports include_graph=False | |
| graph: Optional[Dict[str, Any]] = None | |
| # Enriched indexes added by the new serialiser.py (Optional for back-compat) | |
| block_to_chunks: Optional[Dict[str, List[str]]] = None | |
| outline: Optional[List[Dict[str, Any]]] = None | |
| chunk_outline_path: Optional[Dict[str, List[str]]] = None | |
| content_type_index: Optional[Dict[str, List[str]]] = None | |
| page_index: Optional[Dict[str, List[str]]] = None | |
| class IngestResponse(BaseModel): | |
| doc_name: str | |
| chunks_indexed: int | |
| message: str | |
| # ── Query (caller → Space 2) ────────────────────────────────────────────────── | |
| class QueryRequest(BaseModel): | |
| question: str = Field(..., min_length=3) | |
| doc_name: Optional[str] = Field( | |
| None, | |
| description="Restrict retrieval to a single ingested document. " | |
| "If omitted, all documents are searched.", | |
| ) | |
| top_k: Optional[int] = Field( | |
| None, | |
| description="Override the default RETRIEVAL_TOP_K for this request.", | |
| ge=1, le=20, | |
| ) | |
| class RetrievedChunk(BaseModel): | |
| chunk_id: str | |
| doc_name: str | |
| page_num: int | |
| region_type: str | |
| section_title: str | |
| text: str | |
| score: float # final score after graph re-ranking | |
| table_html: Optional[str] = None | |
| outline_path: Optional[List[str]] = None # full breadcrumb for generator context headers | |
| class RAGResponse(BaseModel): | |
| question: str | |
| answer: str | |
| retrieved_chunks: List[RetrievedChunk] | |
| doc_names_searched: List[str] | |
| # ── Health ──────────────────────────────────────────────────────────────────── | |
| class HealthResponse(BaseModel): | |
| status: str | |
| docs_ingested: int | |
| embedder_ready: bool | |
| llm_ready: bool |