File size: 4,212 Bytes
dc2d570 db9bbfd |
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 |
"""Pydantic schemas for API request/response models."""
from datetime import datetime
from typing import Literal
from pydantic import BaseModel, Field
# === Request Models ===
class SearchRequest(BaseModel):
"""Search request payload."""
query: str = Field(..., min_length=1, max_length=1000, description="Search query")
max_results: int = Field(default=10, ge=1, le=50, description="Maximum results to return")
freshness: Literal["day", "week", "month", "year", "any"] = Field(
default="any",
description="Filter results by recency"
)
include_domains: list[str] | None = Field(
default=None,
description="Only include results from these domains"
)
exclude_domains: list[str] | None = Field(
default=None,
description="Exclude results from these domains"
)
include_answer: bool = Field(
default=True,
description="Include AI-generated answer"
)
# === Response Models ===
class Citation(BaseModel):
"""Citation reference for the answer."""
index: int = Field(..., description="Citation index (1-based)")
url: str = Field(..., description="Source URL")
title: str = Field(..., description="Source title")
class TemporalContext(BaseModel):
"""Temporal metadata about the search."""
query_temporal_intent: Literal["current", "historical", "neutral"] = Field(
...,
description="Detected temporal intent of the query"
)
temporal_urgency: float = Field(
...,
ge=0.0,
le=1.0,
description="How important freshness is for this query (0-1)"
)
current_date: str = Field(..., description="Current date for context")
class SearchResult(BaseModel):
"""Individual search result."""
title: str = Field(..., description="Result title")
url: str = Field(..., description="Result URL")
content: str = Field(..., description="Result content/snippet")
score: float = Field(..., ge=0.0, le=1.0, description="Overall relevance score")
published_date: datetime | None = Field(
default=None,
description="Publication date if available"
)
freshness_score: float = Field(
default=0.5,
ge=0.0,
le=1.0,
description="How fresh/recent the content is"
)
authority_score: float = Field(
default=0.5,
ge=0.0,
le=1.0,
description="Domain authority/trust score"
)
class SearchResponse(BaseModel):
"""Complete search response."""
query: str = Field(..., description="Original query")
answer: str | None = Field(
default=None,
description="AI-generated answer synthesized from results"
)
results: list[SearchResult] = Field(
default_factory=list,
description="Ranked search results"
)
citations: list[Citation] = Field(
default_factory=list,
description="Citations referenced in the answer"
)
temporal_context: TemporalContext | None = Field(
default=None,
description="Temporal analysis metadata"
)
processing_time_ms: float = Field(..., description="Total processing time in milliseconds")
class ErrorResponse(BaseModel):
"""Error response model."""
error: str = Field(..., description="Error message")
detail: str | None = Field(default=None, description="Detailed error information")
# === Deep Research Models ===
class DeepResearchRequest(BaseModel):
"""Deep research request payload."""
query: str = Field(..., min_length=1, max_length=2000, description="Research query")
max_dimensions: int = Field(
default=5,
ge=2,
le=8,
description="Maximum research dimensions to explore"
)
max_sources_per_dim: int = Field(
default=5,
ge=1,
le=10,
description="Maximum sources per dimension"
)
max_total_searches: int = Field(
default=20,
ge=5,
le=30,
description="Maximum total API searches"
)
|