models.py
1 """Data models for web search results.""" 2 3 from typing import List, Optional, Dict, Any 4 from pydantic import BaseModel, Field, HttpUrl 5 6 7 class SearchSource(BaseModel): 8 """Individual search result source.""" 9 10 link: str = Field(..., description="URL of the source") 11 title: str = Field(..., description="Title of the source") 12 snippet: str = Field(..., description="Text snippet from the source") 13 attribution: Optional[str] = Field(None, description="Attribution/domain name") 14 imageUrl: Optional[str] = Field(None, description="Optional image URL") 15 processed: bool = Field(default=False, description="Whether source has been cited") 16 17 class Config: 18 json_schema_extra = { 19 "example": { 20 "link": "https://example.com/article", 21 "title": "Example Article", 22 "snippet": "This is an example snippet from the article...", 23 "attribution": "example.com", 24 "processed": False 25 } 26 } 27 28 29 class ImageResult(BaseModel): 30 """Image search result.""" 31 32 imageUrl: str = Field(..., description="URL of the image") 33 title: Optional[str] = Field(None, description="Title or description of the image") 34 link: str = Field(..., description="Source page URL") 35 36 class Config: 37 json_schema_extra = { 38 "example": { 39 "imageUrl": "https://example.com/image.jpg", 40 "title": "Example Image", 41 "link": "https://example.com/page" 42 } 43 } 44 45 46 class SearchResult(BaseModel): 47 """Complete search result from a search provider.""" 48 49 success: bool = Field(..., description="Whether the search was successful") 50 query: str = Field(..., description="The search query") 51 organic: List[SearchSource] = Field(default_factory=list, description="Organic search results") 52 topStories: List[SearchSource] = Field(default_factory=list, description="Top news stories") 53 images: List[ImageResult] = Field(default_factory=list, description="Image results") 54 answerBox: Optional[str] = Field(None, description="Direct answer if available") 55 error: Optional[str] = Field(None, description="Error message if search failed") 56 metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata") 57 58 class Config: 59 json_schema_extra = { 60 "example": { 61 "success": True, 62 "query": "latest AI developments", 63 "organic": [ 64 { 65 "link": "https://example.com/ai-news", 66 "title": "Latest AI Developments", 67 "snippet": "Recent advances in artificial intelligence...", 68 "attribution": "example.com" 69 } 70 ], 71 "topStories": [], 72 "images": [], 73 "answerBox": None, 74 "error": None 75 } 76 } 77 78 79 class SearchResultData(BaseModel): 80 """Search result data with turn information for citations.""" 81 82 turn: int = Field(..., description="Search turn number (0-based)") 83 organic: List[SearchSource] = Field(default_factory=list) 84 topStories: List[SearchSource] = Field(default_factory=list) 85 images: List[ImageResult] = Field(default_factory=list) 86 references: List[Dict[str, Any]] = Field(default_factory=list, description="Additional references") 87 answerBox: Optional[str] = None 88 89 class Config: 90 json_schema_extra = { 91 "example": { 92 "turn": 0, 93 "organic": [], 94 "topStories": [], 95 "images": [], 96 "references": [], 97 "answerBox": None 98 } 99 }