| """ |
| API models and schemas for requests/responses |
| Extended with: confidence judgment, eval, temporal, GoT, community endpoints |
| """ |
|
|
| from pydantic import BaseModel, Field |
| from typing import Optional, List, Dict, Any, Literal |
| from datetime import datetime |
|
|
|
|
| |
| class LoginRequest(BaseModel): |
| username: str |
| password: str |
|
|
| class RegisterRequest(BaseModel): |
| username: str |
| password: str |
| email: Optional[str] = None |
| full_name: Optional[str] = None |
| scopes: List[str] = ["read", "write"] |
| tenant_id: Optional[str] = None |
|
|
| class TokenResponse(BaseModel): |
| access_token: str |
| token_type: str = "bearer" |
|
|
|
|
| |
| class DocumentUploadResponse(BaseModel): |
| document_id: str |
| filename: str |
| size_bytes: int |
| task_id: Optional[str] = None |
| message: str |
|
|
|
|
| class ScrapeRequest(BaseModel): |
| url: str |
|
|
| class CrawlRequest(BaseModel): |
| url: str |
| max_depth: Optional[int] = 1 |
| max_pages: Optional[int] = 10 |
|
|
|
|
| |
| class IngestionStatusResponse(BaseModel): |
| task_id: str |
| status: str |
| progress: Optional[Dict[str, Any]] = None |
| result: Optional[Dict[str, Any]] = None |
|
|
|
|
| |
| class DocumentInfo(BaseModel): |
| id: str |
| filename: str |
| file_type: str |
| size_bytes: int |
| upload_date: str |
|
|
|
|
| class DocumentListResponse(BaseModel): |
| documents: List[DocumentInfo] |
| total: int |
|
|
|
|
| |
|
|
| class QueryRequest(BaseModel): |
| query: str = Field(..., min_length=1, max_length=10000, description="User query") |
| top_k: Optional[int] = Field(5, description="Number of results to retrieve") |
| streaming: Optional[bool] = Field(False, description="Enable streaming responses") |
| document_id: Optional[str] = Field(None, description="Filter query to a specific document") |
| conversation_id: Optional[str] = Field(None, description="Persist memory in a conversation thread") |
| mode: Optional[str] = Field("auto", description="Retrieval mode: auto, naive, hybrid, local_graph, global_community, hippo, cypher") |
| use_got: Optional[bool] = Field(False, description="Enable Graph-of-Thought parallel exploration (deprecated: use mode='got')") |
| at_time: Optional[datetime] = Field(None, description="Query knowledge graph state at this time") |
|
|
|
|
| class ConfidenceJudgmentResponse(BaseModel): |
| """Gap #4 β LLM-as-a-Judge response shape""" |
| score: float |
| reasoning: str |
| grounded_claims: int |
| ungrounded_claims: int |
| hallucination_risk: Literal["low", "medium", "high"] |
|
|
|
|
| class QueryResponse(BaseModel): |
| answer: str |
| sources: List[Dict[str, Any]] |
| reasoning_chain: List[str] |
| confidence: float |
| |
| confidence_judgment: Optional[ConfidenceJudgmentResponse] = None |
| retrieval_method: str |
| processing_time_seconds: float |
| conversation_id: Optional[str] = None |
| |
| drift_expanded: Optional[bool] = False |
| total_sub_queries: Optional[int] = 1 |
|
|
|
|
| |
| class Message(BaseModel): |
| id: str |
| role: str |
| content: str |
| reasoning: Optional[List[str]] = None |
| sources: Optional[List[Dict[str, Any]]] = None |
| confidence: Optional[float] = None |
| hallucination_risk: Optional[str] = None |
| created_at: str |
|
|
| class Conversation(BaseModel): |
| id: str |
| title: str |
| created_at: str |
| updated_at: str |
| messages: Optional[List[Message]] = [] |
|
|
| class ConversationListResponse(BaseModel): |
| conversations: List[Conversation] |
|
|
|
|
| |
| class OntologyResponse(BaseModel): |
| version: str |
| entity_types: List[str] |
| relationship_types: List[str] |
| properties: Dict[str, List[str]] |
| created_at: datetime |
| approved: bool |
|
|
|
|
| class OntologyUpdateRequest(BaseModel): |
| entity_types: Optional[List[str]] = None |
| relationship_types: Optional[List[str]] = None |
| properties: Optional[Dict[str, List[str]]] = None |
| approved: Optional[bool] = None |
|
|
|
|
| |
| class GraphNode(BaseModel): |
| id: str |
| label: str |
| type: str |
| description: Optional[str] = None |
| properties: Dict[str, Any] = {} |
| community_id: Optional[int] = None |
| valid_from: Optional[str] = None |
| valid_until: Optional[str] = None |
|
|
|
|
| class GraphEdge(BaseModel): |
| source: str |
| target: str |
| type: str |
| properties: Dict[str, Any] = {} |
| valid_from: Optional[str] = None |
| confidence: Optional[float] = None |
|
|
|
|
| class EntityUpdateRequest(BaseModel): |
| name: str |
|
|
|
|
| class GraphVisualizationResponse(BaseModel): |
| nodes: List[GraphNode] |
| edges: List[GraphEdge] |
|
|
|
|
| |
| class SystemHealthResponse(BaseModel): |
| status: str |
| version: str |
| neo4j_connected: bool |
| redis_connected: bool |
| workers_active: int |
| gds_version: Optional[str] = None |
| timestamp: datetime |
|
|
|
|
| class SystemStatsResponse(BaseModel): |
| documents_count: int |
| entities_count: int |
| relationships_count: int |
| chunks_count: int |
| ontology_version: str |
|
|
|
|
| |
| class OntologyRefineRequest(BaseModel): |
| feedback: Optional[str] = Field(None, description="Human feedback to guide LLM refinement") |
| document_id: Optional[str] = Field(None, description="Specific document ID to source chunks from") |
|
|
|
|
| class OntologyRefineResponse(BaseModel): |
| version: str |
| entity_types: List[str] |
| relationship_types: List[str] |
| properties: Dict[str, List[str]] |
| created_at: datetime |
| approved: bool |
| changes: Optional[str] = None |
|
|
|
|
| |
| class DeduplicateResponse(BaseModel): |
| merged_count: int |
| groups: List[List[str]] |
|
|
|
|
| |
|
|
| class EvalRequest(BaseModel): |
| """Request to run quality evaluation on a Q&A pair""" |
| question: str = Field(..., description="The question that was asked") |
| answer: str = Field(..., description="The answer that was generated") |
| contexts: List[str] = Field(..., description="Retrieved chunk texts used to answer") |
| ground_truth: Optional[str] = Field(None, description="Known correct answer (optional)") |
| document_id: Optional[str] = None |
|
|
|
|
| class EvalResponse(BaseModel): |
| """Evaluation metrics for a Q&A pair""" |
| question: str |
| faithfulness: float = Field(..., description="0-1: Is answer grounded in contexts?") |
| answer_relevancy: float = Field(..., description="0-1: Does answer address the question?") |
| context_precision: float = Field(..., description="0-1: Are retrieved chunks relevant?") |
| context_recall: float = Field(default=0.0, description="0-1: Did we retrieve enough info?") |
| overall_score: float = Field(..., description="0-1: Weighted overall quality score") |
| hallucination_detected: bool |
| eval_id: Optional[str] = None |
|
|
|
|
| class EvalTrendPoint(BaseModel): |
| """Single data point for eval trending chart""" |
| timestamp: str |
| overall_score: float |
| faithfulness: float |
| answer_relevancy: float |
| hallucination_detected: bool |
| document_id: Optional[str] = None |
|
|
|
|
| class EvalDashboardResponse(BaseModel): |
| """Full eval dashboard data""" |
| total_evaluations: int |
| avg_overall_score: float |
| avg_faithfulness: float |
| avg_relevancy: float |
| hallucination_rate: float |
| trend_data: List[EvalTrendPoint] |
|
|
|
|
| |
|
|
| class CommunityAssignResponse(BaseModel): |
| """Response from community assignment task""" |
| communities_found: int |
| message: str |
|
|
|
|
| class CommunitySummaryResponse(BaseModel): |
| """Summary of a graph community""" |
| community_id: int |
| entity_count: int |
| entities: List[str] |
| summary: str |
| themes: List[str] = [] |
|
|
|
|
| |
|
|
| class SupportedFormatsResponse(BaseModel): |
| """List of supported ingestion file formats""" |
| formats: List[str] |
| descriptions: Dict[str, str] |
|
|
|
|
| |
|
|
| class GraphUpdateRequest(BaseModel): |
| """Request to merge text directly into the live knowledge graph""" |
| text: str = Field(..., description="Raw text to extract entities/relationships from") |
| source_label: Optional[str] = Field( |
| "api_push", |
| description="Traceability tag e.g. 'api_push', 'chat:conv_123'" |
| ) |
| valid_from: Optional[datetime] = Field( |
| None, |
| description="Timestamp for temporal graph edges (default: now)" |
| ) |
|
|
|
|
| class GraphUpdateResponse(BaseModel): |
| """Response from a graph memory update operation""" |
| entities_added: int |
| relationships_added: int |
| entities_merged: int |
| source_label: str |
| timestamp: datetime |
| message: str |
|
|
|
|
| |
|
|
| class EnrichmentStatusResponse(BaseModel): |
| """Response from entity enrichment task""" |
| entities_enriched: int |
| entities_skipped: int |
| errors: int |
| duration_seconds: float |
| message: str |
|
|
|
|
| class EntitySummaryResponse(BaseModel): |
| """Entity profile summary returned from the graph""" |
| entity_name: str |
| entity_type: Optional[str] = None |
| summary: Optional[str] = None |
| summary_updated_at: Optional[str] = None |
| has_summary: bool = False |
|
|
|
|
| |
|
|
| class ReportRequest(BaseModel): |
| """Request to generate an analytical report""" |
| topic: str = Field(..., description="High-level topic or question for analysis") |
| report_type: Optional[Literal["executive", "detailed", "entity_focus"]] = Field( |
| "detailed", |
| description="'executive' (short), 'detailed' (full), 'entity_focus' (scoped to one entity)" |
| ) |
| target_entity: Optional[str] = Field( |
| None, |
| description="For entity_focus β name of the entity to focus the report on" |
| ) |
|
|
|
|
| class ReportResponse(BaseModel): |
| """Analytical report generated by the ReACT ReportAgent""" |
| topic: str |
| executive_summary: str |
| sections: Dict[str, str] |
| key_entities: List[str] |
| confidence: float |
| tool_calls_made: int |
| generated_at: datetime |
| markdown: str |
|
|
|
|
| |
|
|
| class EntityChatRequest(BaseModel): |
| """Request to chat with a single entity's knowledge neighborhood""" |
| message: str = Field(..., description="Question to ask about the entity") |
| conversation_id: Optional[str] = Field( |
| None, description="Optional conversation ID for multi-turn context" |
| ) |
|
|
|
|
| class EntityChatResponse(BaseModel): |
| """Response from entity-scoped chat""" |
| response: str |
| entity_name: str |
| neighborhood_size: int |
| conversation_id: str |
|
|
|
|
| |
|
|
| class DriftReportResponse(BaseModel): |
| """Schema drift report from OntologyDriftDetector""" |
| id: str |
| detected_at: datetime |
| new_entity_types: List[str] |
| new_relationship_types: List[str] |
| removed_entity_types: List[str] |
| removed_relationship_types: List[str] |
| sample_size: int |
| drift_score: float |
| status: str |
| approved_by: Optional[str] = None |
| approved_at: Optional[datetime] = None |
|
|
|
|
| class DriftListResponse(BaseModel): |
| """List of drift reports""" |
| reports: List[DriftReportResponse] |
| total: int |
|
|