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"
    )