Spaces:
Sleeping
Sleeping
File size: 7,080 Bytes
6c9b8f1 c78c2c1 6c9b8f1 c78c2c1 6c9b8f1 c78c2c1 6c9b8f1 c78c2c1 6c9b8f1 8af997f affe2db 6c9b8f1 7e55328 c78c2c1 8af997f affe2db 6c9b8f1 b1c84b5 6c9b8f1 b1c84b5 6c9b8f1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | """
PhilVerify β Pydantic Request / Response Schemas
Matches the structured JSON output format from the system spec.
"""
from __future__ import annotations
from enum import Enum
from typing import Optional
from pydantic import BaseModel, HttpUrl, Field
# ββ Enums βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
class Verdict(str, Enum):
CREDIBLE = "Credible"
UNVERIFIED = "Unverified"
LIKELY_FAKE = "Likely Fake"
class Stance(str, Enum):
SUPPORTS = "Supports"
REFUTES = "Refutes"
NOT_ENOUGH_INFO = "Not Enough Info"
class Language(str, Enum):
TAGALOG = "Tagalog"
ENGLISH = "English"
TAGLISH = "Taglish"
UNKNOWN = "Unknown"
class Sentiment(str, Enum):
POSITIVE = "positive"
NEGATIVE = "negative"
NEUTRAL = "neutral"
HIGH_POSITIVE = "high positive"
HIGH_NEGATIVE = "high negative"
class DomainTier(int, Enum):
CREDIBLE = 1
SATIRE_OPINION = 2
SUSPICIOUS = 3
KNOWN_FAKE = 4
# ββ Request Models βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
class TextVerifyRequest(BaseModel):
text: str = Field(..., min_length=10, max_length=10_000, description="Raw text to verify")
image_url: Optional[str] = Field(None, description="Optional image URL to run OCR on alongside the text")
class URLVerifyRequest(BaseModel):
url: HttpUrl = Field(..., description="URL of the news article or social media post")
# ββ Nested Response Models ββββββββββββββββββββββββββββββββββββββββββββββββββββ
class EntitiesResult(BaseModel):
persons: list[str] = []
organizations: list[str] = []
locations: list[str] = []
dates: list[str] = []
class Layer1Result(BaseModel):
verdict: Verdict
confidence: float = Field(..., ge=0.0, le=100.0, description="Confidence % from ML classifier")
triggered_features: list[str] = Field(
default_factory=list,
description="Human-readable list of suspicious features detected",
)
model_tier: Optional[str] = Field(None, description="Classifier used: ensemble | xlmr | tfidf")
class EvidenceSource(BaseModel):
title: str
url: str
similarity: float = Field(..., ge=0.0, le=1.0, description="Cosine similarity to input claim")
stance: Stance
stance_reason: Optional[str] = Field(None, description="NLI entailment or keyword reason for stance")
domain_tier: DomainTier
published_at: Optional[str] = None
source_name: Optional[str] = None
class Layer2Result(BaseModel):
verdict: Verdict
evidence_score: float = Field(..., ge=0.0, le=100.0)
sources: list[EvidenceSource] = []
claim_used: Optional[str] = Field(None, description="Extracted claim sent to evidence search")
claim_method: Optional[str] = Field(None, description="How the claim was extracted: sentence_scoring | sentence_heuristic | passthrough")
# ββ Classifier Comparison βββββββββββββββββββββββββββββββββββββββββββββββββββββ
class ClassifierComparisonEntry(BaseModel):
name: str # "BoW", "TF-IDF", "Naive Bayes", "LDA"
verdict: Verdict
confidence: float = Field(..., ge=0.0, le=100.0)
top_features: list[str] = [] # up to 3 top features / lda_topic_N label
# ββ LDA Topic Result ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
class LDATopicResult(BaseModel):
label: str # Human-assigned topic name
top_words: list[str] # Top 6 words defining this topic
confidence: float = Field(..., ge=0.0, le=100.0) # Dominant topic probability (%)
# ββ Main Response βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
class VerificationResponse(BaseModel):
verdict: Verdict
confidence: float = Field(..., ge=0.0, le=100.0)
final_score: float = Field(..., ge=0.0, le=100.0)
layer1: Layer1Result
layer2: Layer2Result
entities: EntitiesResult
sentiment: str
emotion: str
language: Language
domain_credibility: Optional[DomainTier] = None
input_type: str = "text"
processing_time_ms: Optional[float] = None
extracted_text: Optional[str] = Field(None, description="Raw text extracted from the URL / image / video for transparency")
ocr_text: Optional[str] = Field(None, description="Text extracted from an image via OCR (when image_url was provided alongside text)")
classifier_comparison: list[ClassifierComparisonEntry] = Field(
default_factory=list,
description="Per-classifier results from all classical ML models (BoW, TF-IDF, NB, LDA)",
)
lda_topic: Optional[LDATopicResult] = Field(
None,
description="Dominant LDA topic inferred for this text",
)
# ββ History / Trends ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
class HistoryEntry(BaseModel):
id: str
timestamp: str
input_type: str
text_preview: str
verdict: Verdict
confidence: float
final_score: float
class HistoryResponse(BaseModel):
total: int
entries: list[HistoryEntry]
class TrendingEntity(BaseModel):
entity: str
entity_type: str # person | org | location
count: int
fake_count: int
fake_ratio: float
class TrendingTopic(BaseModel):
topic: str
count: int
dominant_verdict: Verdict
class VerdictDayPoint(BaseModel):
date: str # YYYY-MM-DD
credible: int = 0
unverified: int = 0
fake: int = 0
class TrendsResponse(BaseModel):
top_entities: list[TrendingEntity]
top_topics: list[TrendingTopic]
verdict_distribution: dict[str, int] = Field(
default_factory=dict,
description="Counts per verdict: Credible, Unverified, Likely Fake",
)
verdict_by_day: list[VerdictDayPoint] = Field(
default_factory=list,
description="Day-by-day verdict counts for the area chart (last N days)",
)
# ββ Error βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
class ErrorResponse(BaseModel):
error: str
detail: Optional[str] = None
code: Optional[str] = None
|