noesium 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- noesium/agents/askura_agent/__init__.py +22 -0
- noesium/agents/askura_agent/askura_agent.py +480 -0
- noesium/agents/askura_agent/conversation.py +164 -0
- noesium/agents/askura_agent/extractor.py +175 -0
- noesium/agents/askura_agent/memory.py +14 -0
- noesium/agents/askura_agent/models.py +239 -0
- noesium/agents/askura_agent/prompts.py +202 -0
- noesium/agents/askura_agent/reflection.py +234 -0
- noesium/agents/askura_agent/summarizer.py +30 -0
- noesium/agents/askura_agent/utils.py +6 -0
- noesium/agents/deep_research/__init__.py +13 -0
- noesium/agents/deep_research/agent.py +398 -0
- noesium/agents/deep_research/prompts.py +84 -0
- noesium/agents/deep_research/schemas.py +42 -0
- noesium/agents/deep_research/state.py +54 -0
- noesium/agents/search/__init__.py +5 -0
- noesium/agents/search/agent.py +474 -0
- noesium/agents/search/state.py +28 -0
- noesium/core/__init__.py +1 -1
- noesium/core/agent/base.py +10 -2
- noesium/core/goalith/decomposer/llm_decomposer.py +1 -1
- noesium/core/llm/__init__.py +1 -1
- noesium/core/llm/base.py +2 -2
- noesium/core/llm/litellm.py +42 -21
- noesium/core/llm/llamacpp.py +25 -4
- noesium/core/llm/ollama.py +43 -22
- noesium/core/llm/openai.py +25 -5
- noesium/core/llm/openrouter.py +1 -1
- noesium/core/toolify/base.py +9 -2
- noesium/core/toolify/config.py +2 -2
- noesium/core/toolify/registry.py +21 -5
- noesium/core/tracing/opik_tracing.py +7 -7
- noesium/core/vector_store/__init__.py +2 -2
- noesium/core/vector_store/base.py +1 -1
- noesium/core/vector_store/pgvector.py +10 -13
- noesium/core/vector_store/weaviate.py +2 -1
- noesium/toolkits/__init__.py +1 -0
- noesium/toolkits/arxiv_toolkit.py +310 -0
- noesium/toolkits/audio_aliyun_toolkit.py +441 -0
- noesium/toolkits/audio_toolkit.py +370 -0
- noesium/toolkits/bash_toolkit.py +332 -0
- noesium/toolkits/document_toolkit.py +454 -0
- noesium/toolkits/file_edit_toolkit.py +552 -0
- noesium/toolkits/github_toolkit.py +395 -0
- noesium/toolkits/gmail_toolkit.py +575 -0
- noesium/toolkits/image_toolkit.py +425 -0
- noesium/toolkits/memory_toolkit.py +398 -0
- noesium/toolkits/python_executor_toolkit.py +334 -0
- noesium/toolkits/search_toolkit.py +451 -0
- noesium/toolkits/serper_toolkit.py +623 -0
- noesium/toolkits/tabular_data_toolkit.py +537 -0
- noesium/toolkits/user_interaction_toolkit.py +365 -0
- noesium/toolkits/video_toolkit.py +168 -0
- noesium/toolkits/wikipedia_toolkit.py +420 -0
- {noesium-0.1.0.dist-info → noesium-0.2.0.dist-info}/METADATA +56 -48
- {noesium-0.1.0.dist-info → noesium-0.2.0.dist-info}/RECORD +59 -23
- {noesium-0.1.0.dist-info → noesium-0.2.0.dist-info}/licenses/LICENSE +1 -1
- {noesium-0.1.0.dist-info → noesium-0.2.0.dist-info}/WHEEL +0 -0
- {noesium-0.1.0.dist-info → noesium-0.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Serper toolkit for comprehensive Google search capabilities.
|
|
3
|
+
|
|
4
|
+
Provides tools for various Google search services including web search,
|
|
5
|
+
images, news, maps, scholar, and more through the Serper API.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import os
|
|
10
|
+
from typing import Any, Callable, Dict, Optional
|
|
11
|
+
|
|
12
|
+
import aiohttp
|
|
13
|
+
|
|
14
|
+
from noesium.core.toolify.base import AsyncBaseToolkit
|
|
15
|
+
from noesium.core.toolify.config import ToolkitConfig
|
|
16
|
+
from noesium.core.toolify.registry import register_toolkit
|
|
17
|
+
from noesium.core.utils.logging import get_logger
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@register_toolkit("serper")
|
|
23
|
+
class SerperToolkit(AsyncBaseToolkit):
|
|
24
|
+
"""
|
|
25
|
+
Toolkit for comprehensive Google search using Serper API.
|
|
26
|
+
|
|
27
|
+
This toolkit provides access to various Google search services through
|
|
28
|
+
the Serper API (google.serper.dev), offering comprehensive search
|
|
29
|
+
capabilities across different Google services.
|
|
30
|
+
|
|
31
|
+
Features:
|
|
32
|
+
- Web search with customizable parameters
|
|
33
|
+
- Image search and visual content discovery
|
|
34
|
+
- News search with date filtering
|
|
35
|
+
- Google Maps and Places search
|
|
36
|
+
- Academic search via Google Scholar
|
|
37
|
+
- Video search capabilities
|
|
38
|
+
- Autocomplete suggestions
|
|
39
|
+
- Google Lens visual search
|
|
40
|
+
- Configurable location and language settings
|
|
41
|
+
|
|
42
|
+
Search Services:
|
|
43
|
+
- **Web Search**: General Google search results
|
|
44
|
+
- **Image Search**: Visual content and image discovery
|
|
45
|
+
- **News Search**: Current news and articles
|
|
46
|
+
- **Maps Search**: Location-based search and places
|
|
47
|
+
- **Scholar Search**: Academic papers and research
|
|
48
|
+
- **Video Search**: Video content discovery
|
|
49
|
+
- **Places Search**: Business and location information
|
|
50
|
+
- **Autocomplete**: Search suggestions and completions
|
|
51
|
+
- **Google Lens**: Visual search and image analysis
|
|
52
|
+
|
|
53
|
+
Required configuration:
|
|
54
|
+
- SERPER_API_KEY: API key from google.serper.dev
|
|
55
|
+
|
|
56
|
+
Optional configuration:
|
|
57
|
+
- default_location: Default search location
|
|
58
|
+
- default_language: Default interface language
|
|
59
|
+
- default_country: Default country code
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(self, config: ToolkitConfig = None):
|
|
63
|
+
"""
|
|
64
|
+
Initialize the Serper toolkit.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
config: Toolkit configuration containing API key and settings
|
|
68
|
+
|
|
69
|
+
Raises:
|
|
70
|
+
ValueError: If SERPER_API_KEY is not provided
|
|
71
|
+
"""
|
|
72
|
+
super().__init__(config)
|
|
73
|
+
|
|
74
|
+
# Get API key from config or environment
|
|
75
|
+
self.api_key = self.config.config.get("SERPER_API_KEY") or os.getenv("SERPER_API_KEY")
|
|
76
|
+
|
|
77
|
+
if not self.api_key:
|
|
78
|
+
raise ValueError(
|
|
79
|
+
"SERPER_API_KEY is required for SerperToolkit. " "Set it in config or environment variables."
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Configuration
|
|
83
|
+
self.base_url = "https://google.serper.dev"
|
|
84
|
+
self.default_location = self.config.config.get("default_location", "United States")
|
|
85
|
+
self.default_gl = self.config.config.get("default_gl", "us")
|
|
86
|
+
self.default_hl = self.config.config.get("default_hl", "en")
|
|
87
|
+
self.timeout = self.config.config.get("timeout", 30)
|
|
88
|
+
|
|
89
|
+
# Request headers
|
|
90
|
+
self.headers = {"X-API-KEY": self.api_key, "Content-Type": "application/json"}
|
|
91
|
+
|
|
92
|
+
self.logger.info("Serper toolkit initialized with Google search capabilities")
|
|
93
|
+
|
|
94
|
+
async def _make_search_request(self, endpoint: str, payload: Dict) -> Dict[str, Any]:
|
|
95
|
+
"""
|
|
96
|
+
Make a request to the Serper API.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
endpoint: API endpoint (search, images, news, etc.)
|
|
100
|
+
payload: Request payload
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
API response as dictionary
|
|
104
|
+
"""
|
|
105
|
+
url = f"{self.base_url}/{endpoint}"
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
async with aiohttp.ClientSession() as session:
|
|
109
|
+
async with session.post(
|
|
110
|
+
url, headers=self.headers, json=payload, timeout=aiohttp.ClientTimeout(total=self.timeout)
|
|
111
|
+
) as response:
|
|
112
|
+
if response.status == 200:
|
|
113
|
+
return await response.json()
|
|
114
|
+
elif response.status == 429:
|
|
115
|
+
return {"error": "Rate limit exceeded. Please try again later."}
|
|
116
|
+
elif response.status == 401:
|
|
117
|
+
return {"error": "Invalid API key or authentication failed."}
|
|
118
|
+
elif response.status == 400:
|
|
119
|
+
error_text = await response.text()
|
|
120
|
+
return {"error": f"Bad request: {error_text}"}
|
|
121
|
+
else:
|
|
122
|
+
error_text = await response.text()
|
|
123
|
+
return {"error": f"HTTP {response.status}: {error_text}"}
|
|
124
|
+
|
|
125
|
+
except asyncio.TimeoutError:
|
|
126
|
+
return {"error": f"Request timeout after {self.timeout} seconds"}
|
|
127
|
+
except aiohttp.ClientError as e:
|
|
128
|
+
return {"error": f"Connection error: {str(e)}"}
|
|
129
|
+
except Exception as e:
|
|
130
|
+
return {"error": f"Unexpected error: {str(e)}"}
|
|
131
|
+
|
|
132
|
+
async def google_search(
|
|
133
|
+
self,
|
|
134
|
+
query: str,
|
|
135
|
+
location: Optional[str] = None,
|
|
136
|
+
gl: Optional[str] = None,
|
|
137
|
+
hl: Optional[str] = None,
|
|
138
|
+
num: int = 10,
|
|
139
|
+
date_range: Optional[str] = None,
|
|
140
|
+
) -> Dict[str, Any]:
|
|
141
|
+
"""
|
|
142
|
+
Search the web using Google Search.
|
|
143
|
+
|
|
144
|
+
This tool performs comprehensive web searches using Google's search engine
|
|
145
|
+
through the Serper API. It provides access to organic search results with
|
|
146
|
+
customizable parameters for location, language, and filtering.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
query: Search query string
|
|
150
|
+
location: Geographic location for search (default: "United States")
|
|
151
|
+
gl: Country code for search results (default: "us")
|
|
152
|
+
hl: Language code for search interface (default: "en")
|
|
153
|
+
num: Number of results to return (1-100, default: 10)
|
|
154
|
+
date_range: Time filter for search results
|
|
155
|
+
Options: "h" (past hour), "d" (past day), "w" (past week),
|
|
156
|
+
"m" (past month), "y" (past year)
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
Dictionary containing:
|
|
160
|
+
- query: Original search query
|
|
161
|
+
- results: List of search results with title, link, snippet
|
|
162
|
+
- searchParameters: Search configuration used
|
|
163
|
+
- total_results: Number of results returned
|
|
164
|
+
- status: "success" or "error"
|
|
165
|
+
|
|
166
|
+
Examples:
|
|
167
|
+
- google_search("artificial intelligence trends 2024")
|
|
168
|
+
- google_search("python tutorials", num=20, date_range="m")
|
|
169
|
+
- google_search("restaurants", location="New York", gl="us")
|
|
170
|
+
"""
|
|
171
|
+
self.logger.info(f"Performing Google search for: {query}")
|
|
172
|
+
|
|
173
|
+
# Use defaults if not specified
|
|
174
|
+
location = location or self.default_location
|
|
175
|
+
gl = gl or self.default_gl
|
|
176
|
+
hl = hl or self.default_hl
|
|
177
|
+
|
|
178
|
+
# Validate parameters
|
|
179
|
+
num = max(1, min(100, num)) # Clamp between 1 and 100
|
|
180
|
+
|
|
181
|
+
payload = {"q": query, "location": location, "gl": gl, "hl": hl, "num": num}
|
|
182
|
+
|
|
183
|
+
if date_range:
|
|
184
|
+
payload["tbs"] = f"qdr:{date_range}"
|
|
185
|
+
|
|
186
|
+
result = await self._make_search_request("search", payload)
|
|
187
|
+
|
|
188
|
+
if "error" in result:
|
|
189
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
"query": query,
|
|
193
|
+
"location": location,
|
|
194
|
+
"gl": gl,
|
|
195
|
+
"hl": hl,
|
|
196
|
+
"date_range": date_range,
|
|
197
|
+
"results": result.get("organic", []),
|
|
198
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
199
|
+
"total_results": len(result.get("organic", [])),
|
|
200
|
+
"status": "success",
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async def image_search(
|
|
204
|
+
self,
|
|
205
|
+
query: str,
|
|
206
|
+
location: Optional[str] = None,
|
|
207
|
+
gl: Optional[str] = None,
|
|
208
|
+
hl: Optional[str] = None,
|
|
209
|
+
num: int = 10,
|
|
210
|
+
date_range: Optional[str] = None,
|
|
211
|
+
) -> Dict[str, Any]:
|
|
212
|
+
"""
|
|
213
|
+
Search for images using Google Images.
|
|
214
|
+
|
|
215
|
+
This tool searches for visual content using Google Images, providing
|
|
216
|
+
access to a vast collection of images with metadata and source information.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
query: Image search query
|
|
220
|
+
location: Geographic location for search
|
|
221
|
+
gl: Country code for search results
|
|
222
|
+
hl: Language code for search interface
|
|
223
|
+
num: Number of results to return (1-100)
|
|
224
|
+
date_range: Time filter for images
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
Dictionary with image search results including URLs, titles, and sources
|
|
228
|
+
"""
|
|
229
|
+
self.logger.info(f"Performing image search for: {query}")
|
|
230
|
+
|
|
231
|
+
location = location or self.default_location
|
|
232
|
+
gl = gl or self.default_gl
|
|
233
|
+
hl = hl or self.default_hl
|
|
234
|
+
num = max(1, min(100, num))
|
|
235
|
+
|
|
236
|
+
payload = {"q": query, "location": location, "gl": gl, "hl": hl, "num": num}
|
|
237
|
+
|
|
238
|
+
if date_range:
|
|
239
|
+
payload["tbs"] = f"qdr:{date_range}"
|
|
240
|
+
|
|
241
|
+
result = await self._make_search_request("images", payload)
|
|
242
|
+
|
|
243
|
+
if "error" in result:
|
|
244
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
"query": query,
|
|
248
|
+
"location": location,
|
|
249
|
+
"results": result.get("images", []),
|
|
250
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
251
|
+
"total_results": len(result.get("images", [])),
|
|
252
|
+
"status": "success",
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async def news_search(
|
|
256
|
+
self,
|
|
257
|
+
query: str,
|
|
258
|
+
location: Optional[str] = None,
|
|
259
|
+
gl: Optional[str] = None,
|
|
260
|
+
hl: Optional[str] = None,
|
|
261
|
+
num: int = 10,
|
|
262
|
+
date_range: Optional[str] = None,
|
|
263
|
+
) -> Dict[str, Any]:
|
|
264
|
+
"""
|
|
265
|
+
Search for news articles using Google News.
|
|
266
|
+
|
|
267
|
+
This tool searches current news and articles from various sources
|
|
268
|
+
worldwide, with options for location-based and time-filtered results.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
query: News search query
|
|
272
|
+
location: Geographic location for news
|
|
273
|
+
gl: Country code for news sources
|
|
274
|
+
hl: Language code for news interface
|
|
275
|
+
num: Number of results to return
|
|
276
|
+
date_range: Time filter for news articles
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
Dictionary with news search results including headlines, sources, and dates
|
|
280
|
+
"""
|
|
281
|
+
self.logger.info(f"Performing news search for: {query}")
|
|
282
|
+
|
|
283
|
+
location = location or self.default_location
|
|
284
|
+
gl = gl or self.default_gl
|
|
285
|
+
hl = hl or self.default_hl
|
|
286
|
+
num = max(1, min(100, num))
|
|
287
|
+
|
|
288
|
+
payload = {"q": query, "location": location, "gl": gl, "hl": hl, "num": num}
|
|
289
|
+
|
|
290
|
+
if date_range:
|
|
291
|
+
payload["tbs"] = f"qdr:{date_range}"
|
|
292
|
+
|
|
293
|
+
result = await self._make_search_request("news", payload)
|
|
294
|
+
|
|
295
|
+
if "error" in result:
|
|
296
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
"query": query,
|
|
300
|
+
"location": location,
|
|
301
|
+
"gl": gl,
|
|
302
|
+
"hl": hl,
|
|
303
|
+
"date_range": date_range,
|
|
304
|
+
"results": result.get("news", []),
|
|
305
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
306
|
+
"total_results": len(result.get("news", [])),
|
|
307
|
+
"status": "success",
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async def scholar_search(
|
|
311
|
+
self,
|
|
312
|
+
query: str,
|
|
313
|
+
location: Optional[str] = None,
|
|
314
|
+
gl: Optional[str] = None,
|
|
315
|
+
hl: Optional[str] = None,
|
|
316
|
+
num: int = 10,
|
|
317
|
+
) -> Dict[str, Any]:
|
|
318
|
+
"""
|
|
319
|
+
Search for academic papers using Google Scholar.
|
|
320
|
+
|
|
321
|
+
This tool searches academic literature, including papers, theses,
|
|
322
|
+
books, conference papers, and other scholarly literature.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
query: Academic search query
|
|
326
|
+
location: Geographic location
|
|
327
|
+
gl: Country code
|
|
328
|
+
hl: Language code
|
|
329
|
+
num: Number of results to return
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
Dictionary with academic search results including citations and sources
|
|
333
|
+
"""
|
|
334
|
+
self.logger.info(f"Performing scholar search for: {query}")
|
|
335
|
+
|
|
336
|
+
location = location or self.default_location
|
|
337
|
+
gl = gl or self.default_gl
|
|
338
|
+
hl = hl or self.default_hl
|
|
339
|
+
num = max(1, min(100, num))
|
|
340
|
+
|
|
341
|
+
payload = {
|
|
342
|
+
"q": query,
|
|
343
|
+
"location": location,
|
|
344
|
+
"gl": gl,
|
|
345
|
+
"hl": hl,
|
|
346
|
+
"num": num,
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
result = await self._make_search_request("scholar", payload)
|
|
350
|
+
|
|
351
|
+
if "error" in result:
|
|
352
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
"query": query,
|
|
356
|
+
"location": location,
|
|
357
|
+
"gl": gl,
|
|
358
|
+
"hl": hl,
|
|
359
|
+
"results": result.get("organic", []),
|
|
360
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
361
|
+
"total_results": len(result.get("organic", [])),
|
|
362
|
+
"status": "success",
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async def maps_search(
|
|
366
|
+
self,
|
|
367
|
+
query: str,
|
|
368
|
+
hl: Optional[str] = None,
|
|
369
|
+
latitude: Optional[float] = None,
|
|
370
|
+
longitude: Optional[float] = None,
|
|
371
|
+
zoom: Optional[int] = 18,
|
|
372
|
+
place_id: Optional[str] = None,
|
|
373
|
+
cid: Optional[str] = None,
|
|
374
|
+
num: int = 10,
|
|
375
|
+
) -> Dict[str, Any]:
|
|
376
|
+
"""
|
|
377
|
+
Search for locations using Google Maps.
|
|
378
|
+
|
|
379
|
+
This tool searches for places, businesses, and locations using Google Maps,
|
|
380
|
+
with support for GPS coordinates and place identifiers.
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
query: Location search query
|
|
384
|
+
hl: Language code
|
|
385
|
+
latitude: GPS latitude coordinate
|
|
386
|
+
longitude: GPS longitude coordinate
|
|
387
|
+
zoom: Map zoom level (1-21)
|
|
388
|
+
place_id: Google Place ID
|
|
389
|
+
cid: Google CID (Customer ID)
|
|
390
|
+
num: Number of results to return
|
|
391
|
+
|
|
392
|
+
Returns:
|
|
393
|
+
Dictionary with location search results including addresses and details
|
|
394
|
+
"""
|
|
395
|
+
self.logger.info(f"Performing maps search for: {query}")
|
|
396
|
+
|
|
397
|
+
hl = hl or self.default_hl
|
|
398
|
+
num = max(1, min(100, num))
|
|
399
|
+
|
|
400
|
+
payload = {"q": query, "hl": hl, "num": num}
|
|
401
|
+
|
|
402
|
+
if latitude is not None and longitude is not None:
|
|
403
|
+
if zoom is not None:
|
|
404
|
+
payload["ll"] = f"@{latitude},{longitude},{zoom}z"
|
|
405
|
+
else:
|
|
406
|
+
payload["ll"] = f"@{latitude},{longitude}"
|
|
407
|
+
if place_id:
|
|
408
|
+
payload["placeId"] = place_id
|
|
409
|
+
if cid:
|
|
410
|
+
payload["cid"] = cid
|
|
411
|
+
|
|
412
|
+
result = await self._make_search_request("maps", payload)
|
|
413
|
+
|
|
414
|
+
if "error" in result:
|
|
415
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
416
|
+
|
|
417
|
+
return {
|
|
418
|
+
"query": query,
|
|
419
|
+
"hl": hl,
|
|
420
|
+
"latitude": latitude,
|
|
421
|
+
"longitude": longitude,
|
|
422
|
+
"zoom": zoom,
|
|
423
|
+
"place_id": place_id,
|
|
424
|
+
"cid": cid,
|
|
425
|
+
"results": result.get("places", []),
|
|
426
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
427
|
+
"total_results": len(result.get("places", [])),
|
|
428
|
+
"status": "success",
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
async def video_search(
|
|
432
|
+
self,
|
|
433
|
+
query: str,
|
|
434
|
+
location: Optional[str] = None,
|
|
435
|
+
gl: Optional[str] = None,
|
|
436
|
+
hl: Optional[str] = None,
|
|
437
|
+
num: int = 10,
|
|
438
|
+
date_range: Optional[str] = None,
|
|
439
|
+
) -> Dict[str, Any]:
|
|
440
|
+
"""
|
|
441
|
+
Search for videos using Google Videos.
|
|
442
|
+
|
|
443
|
+
Args:
|
|
444
|
+
query: Video search query
|
|
445
|
+
location: Geographic location
|
|
446
|
+
gl: Country code
|
|
447
|
+
hl: Language code
|
|
448
|
+
num: Number of results to return
|
|
449
|
+
date_range: Time filter for videos
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
Dictionary with video search results
|
|
453
|
+
"""
|
|
454
|
+
self.logger.info(f"Performing video search for: {query}")
|
|
455
|
+
|
|
456
|
+
location = location or self.default_location
|
|
457
|
+
gl = gl or self.default_gl
|
|
458
|
+
hl = hl or self.default_hl
|
|
459
|
+
num = max(1, min(100, num))
|
|
460
|
+
|
|
461
|
+
payload = {"q": query, "location": location, "gl": gl, "hl": hl, "num": num}
|
|
462
|
+
|
|
463
|
+
if date_range:
|
|
464
|
+
payload["tbs"] = f"qdr:{date_range}"
|
|
465
|
+
|
|
466
|
+
result = await self._make_search_request("videos", payload)
|
|
467
|
+
|
|
468
|
+
if "error" in result:
|
|
469
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
"query": query,
|
|
473
|
+
"location": location,
|
|
474
|
+
"results": result.get("videos", []),
|
|
475
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
476
|
+
"total_results": len(result.get("videos", [])),
|
|
477
|
+
"status": "success",
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
async def autocomplete(
|
|
481
|
+
self, query: str, location: Optional[str] = None, gl: Optional[str] = None, hl: Optional[str] = None
|
|
482
|
+
) -> Dict[str, Any]:
|
|
483
|
+
"""
|
|
484
|
+
Get autocomplete suggestions for a search query.
|
|
485
|
+
|
|
486
|
+
Args:
|
|
487
|
+
query: Partial search query
|
|
488
|
+
location: Geographic location
|
|
489
|
+
gl: Country code
|
|
490
|
+
hl: Language code
|
|
491
|
+
|
|
492
|
+
Returns:
|
|
493
|
+
Dictionary with autocomplete suggestions
|
|
494
|
+
"""
|
|
495
|
+
self.logger.info(f"Getting autocomplete for: {query}")
|
|
496
|
+
|
|
497
|
+
location = location or self.default_location
|
|
498
|
+
gl = gl or self.default_gl
|
|
499
|
+
hl = hl or self.default_hl
|
|
500
|
+
|
|
501
|
+
payload = {"q": query, "location": location, "gl": gl, "hl": hl}
|
|
502
|
+
|
|
503
|
+
result = await self._make_search_request("autocomplete", payload)
|
|
504
|
+
|
|
505
|
+
if "error" in result:
|
|
506
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
507
|
+
|
|
508
|
+
return {
|
|
509
|
+
"query": query,
|
|
510
|
+
"location": location,
|
|
511
|
+
"gl": gl,
|
|
512
|
+
"hl": hl,
|
|
513
|
+
"suggestions": result.get("suggestions", []),
|
|
514
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
515
|
+
"total_suggestions": len(result.get("suggestions", [])),
|
|
516
|
+
"status": "success",
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
async def google_lens(
|
|
520
|
+
self, url: str, gl: Optional[str] = None, hl: Optional[str] = None, num: int = 10
|
|
521
|
+
) -> Dict[str, Any]:
|
|
522
|
+
"""
|
|
523
|
+
Analyze an image using Google Lens.
|
|
524
|
+
|
|
525
|
+
Args:
|
|
526
|
+
url: URL of the image to analyze
|
|
527
|
+
gl: Country code
|
|
528
|
+
hl: Language code
|
|
529
|
+
num: Number of results to return
|
|
530
|
+
|
|
531
|
+
Returns:
|
|
532
|
+
Dictionary with visual search results
|
|
533
|
+
"""
|
|
534
|
+
self.logger.info(f"Performing Google Lens analysis for: {url}")
|
|
535
|
+
|
|
536
|
+
gl = gl or self.default_gl
|
|
537
|
+
hl = hl or self.default_hl
|
|
538
|
+
num = max(1, min(100, num))
|
|
539
|
+
|
|
540
|
+
payload = {"url": url, "gl": gl, "hl": hl}
|
|
541
|
+
|
|
542
|
+
result = await self._make_search_request("lens", payload)
|
|
543
|
+
|
|
544
|
+
if "error" in result:
|
|
545
|
+
return {"url": url, "error": result["error"], "status": "error"}
|
|
546
|
+
|
|
547
|
+
return {
|
|
548
|
+
"url": url,
|
|
549
|
+
"gl": gl,
|
|
550
|
+
"hl": hl,
|
|
551
|
+
"results": result.get("organic", [])[:num],
|
|
552
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
553
|
+
"total_results": min(len(result.get("organic", [])), num),
|
|
554
|
+
"status": "success",
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
async def places_search(
|
|
558
|
+
self,
|
|
559
|
+
query: str,
|
|
560
|
+
location: Optional[str] = None,
|
|
561
|
+
gl: Optional[str] = None,
|
|
562
|
+
hl: Optional[str] = None,
|
|
563
|
+
num: int = 10,
|
|
564
|
+
date_range: Optional[str] = None,
|
|
565
|
+
) -> Dict[str, Any]:
|
|
566
|
+
"""
|
|
567
|
+
Search for places using Google Places.
|
|
568
|
+
|
|
569
|
+
Args:
|
|
570
|
+
query: Places search query
|
|
571
|
+
location: Geographic location
|
|
572
|
+
gl: Country code
|
|
573
|
+
hl: Language code
|
|
574
|
+
num: Number of results to return
|
|
575
|
+
date_range: Time filter
|
|
576
|
+
|
|
577
|
+
Returns:
|
|
578
|
+
Dictionary with places search results
|
|
579
|
+
"""
|
|
580
|
+
self.logger.info(f"Performing places search for: {query}")
|
|
581
|
+
|
|
582
|
+
location = location or self.default_location
|
|
583
|
+
gl = gl or self.default_gl
|
|
584
|
+
hl = hl or self.default_hl
|
|
585
|
+
num = max(1, min(100, num))
|
|
586
|
+
|
|
587
|
+
payload = {"q": query, "location": location, "gl": gl, "hl": hl, "num": num}
|
|
588
|
+
|
|
589
|
+
if date_range:
|
|
590
|
+
payload["tbs"] = f"qdr:{date_range}"
|
|
591
|
+
|
|
592
|
+
result = await self._make_search_request("places", payload)
|
|
593
|
+
|
|
594
|
+
if "error" in result:
|
|
595
|
+
return {"query": query, "error": result["error"], "status": "error"}
|
|
596
|
+
|
|
597
|
+
return {
|
|
598
|
+
"query": query,
|
|
599
|
+
"location": location,
|
|
600
|
+
"results": result.get("places", []),
|
|
601
|
+
"searchParameters": result.get("searchParameters", {}),
|
|
602
|
+
"total_results": len(result.get("places", [])),
|
|
603
|
+
"status": "success",
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
async def get_tools_map(self) -> Dict[str, Callable]:
|
|
607
|
+
"""
|
|
608
|
+
Get the mapping of tool names to their implementation functions.
|
|
609
|
+
|
|
610
|
+
Returns:
|
|
611
|
+
Dictionary mapping tool names to callable functions
|
|
612
|
+
"""
|
|
613
|
+
return {
|
|
614
|
+
"google_search": self.google_search,
|
|
615
|
+
"image_search": self.image_search,
|
|
616
|
+
"news_search": self.news_search,
|
|
617
|
+
"scholar_search": self.scholar_search,
|
|
618
|
+
"maps_search": self.maps_search,
|
|
619
|
+
"video_search": self.video_search,
|
|
620
|
+
"autocomplete": self.autocomplete,
|
|
621
|
+
"google_lens": self.google_lens,
|
|
622
|
+
"places_search": self.places_search,
|
|
623
|
+
}
|