rusticai-serpapi 0.0.1__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.
File without changes
@@ -0,0 +1,148 @@
1
+ import os
2
+ from enum import Enum
3
+ from typing import List, Optional
4
+ from urllib.parse import urlparse
5
+
6
+ import shortuuid
7
+ from pydantic import BaseModel, Field
8
+
9
+ import serpapi
10
+ from rustic_ai.core.agents.commons.media import MediaLink
11
+ from rustic_ai.core.guild import Agent, AgentMode, AgentSpec, AgentType, agent
12
+ from rustic_ai.core.messaging.core import JsonDict
13
+
14
+
15
+ class SearchEngines(Enum):
16
+ google = {"key": "q"}
17
+ bing = {"key": "q"}
18
+ baidu = {"key": "q"}
19
+ yahoo = {"key": "p"}
20
+ duckduckgo = {"key": "q"}
21
+ ebay = {"key": "_nkw"}
22
+ yandex = {"key": "text"}
23
+ home_depot = {"key": "keyword"}
24
+ google_scholar = {"key": "q"}
25
+ youtube = {"key": "search_query"}
26
+ walmart = {"key": "query"}
27
+ google_maps = {"key": "query"}
28
+ google_patents = {"key": "q"}
29
+
30
+ def get_query(self, query):
31
+ return {self.value["key"]: query}
32
+
33
+
34
+ class SERPQuery(BaseModel):
35
+ """
36
+ A class representing a search query.
37
+ """
38
+
39
+ engine: str
40
+ query: str
41
+ id: str = Field(default="")
42
+ num: Optional[int] = Field(default=12)
43
+ start: Optional[int] = Field(default=0)
44
+
45
+
46
+ class SERPResults(BaseModel):
47
+ """
48
+ A class representing a search result.
49
+ """
50
+
51
+ engine: str
52
+ query: str
53
+ count: int
54
+ id: str = Field(default="")
55
+ results: List[MediaLink]
56
+ total_results: Optional[int] = Field(default=None)
57
+
58
+
59
+ class SearchError(BaseModel):
60
+
61
+ id: str = Field(default="")
62
+ response: JsonDict
63
+
64
+
65
+ class SERPAgent(Agent):
66
+ def __init__(self, agent_spec: AgentSpec):
67
+ super().__init__(agent_spec=agent_spec, agent_type=AgentType.BOT, agent_mode=AgentMode.LOCAL)
68
+
69
+ self.serp_api_key = os.getenv("SERP_API_KEY", "")
70
+ assert self.serp_api_key, "SERP_API_KEY environment variable not set"
71
+ self.client = serpapi.Client(api_key=self.serp_api_key)
72
+
73
+ @agent.processor(SERPQuery)
74
+ def search(self, ctx: agent.ProcessContext[SERPQuery]) -> None:
75
+ """
76
+ Handles the received message.
77
+
78
+ Args:
79
+ message (Message): The received message.
80
+ """
81
+ search_query = ctx.payload
82
+
83
+ # Use the message.payload as search parameters
84
+ search_params = SearchEngines[search_query.engine].get_query(search_query.query)
85
+
86
+ # Execute asynchronous search and add it to the queue
87
+ results = self.client.search(
88
+ params=search_params,
89
+ engine=search_query.engine,
90
+ num=search_query.num,
91
+ start=search_query.start,
92
+ )
93
+
94
+ metadata = results["search_metadata"]
95
+
96
+ if metadata["status"] == "Success":
97
+ # Get the search results
98
+ search_results = results["organic_results"]
99
+
100
+ result_links = []
101
+
102
+ # Publish the message
103
+ for result in search_results:
104
+ result.update({"search_parameters": search_params})
105
+
106
+ filepath = urlparse(result["link"]).path
107
+ filename = os.path.basename(filepath)
108
+
109
+ if not filename:
110
+ filename = f"{shortuuid.uuid()}.html"
111
+
112
+ metadata = {
113
+ "title": result["title"],
114
+ "favicon": result.get("favicon", ""),
115
+ "search_position": result["position"],
116
+ "snippet": result["snippet"],
117
+ "date": result.get("date", ""),
118
+ "query_id": search_query.id,
119
+ }
120
+
121
+ link = MediaLink(
122
+ url=result["link"],
123
+ name=filename,
124
+ metadata=metadata,
125
+ mimetype="text/html",
126
+ encoding="utf-8",
127
+ )
128
+
129
+ result_links.append(link)
130
+
131
+ total_results = None
132
+ if "search_information" in results and "total_results" in results["search_information"]:
133
+ total_results = results["search_information"]["total_results"]
134
+
135
+ ctx.send(
136
+ SERPResults(
137
+ count=len(result_links),
138
+ results=result_links,
139
+ total_results=total_results,
140
+ id=search_query.id,
141
+ query=result["search_parameters"]["q"],
142
+ engine=result["search_parameters"]["engine"],
143
+ ),
144
+ new_thread=True,
145
+ )
146
+ else:
147
+ # Publish the error message
148
+ ctx.send(SearchError(response=results["search_metadata"], id=search_query.id))
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.1
2
+ Name: rusticai-serpapi
3
+ Version: 0.0.1
4
+ Summary: Rustic AI module supporting Search through SerpApi
5
+ Home-page: https://www.rustic.ai/
6
+ License: Apache-2.0
7
+ Author: Dragonscale Industries Inc.
8
+ Author-email: dev@dragonscale.ai
9
+ Requires-Python: >=3.12,<4.0
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Provides-Extra: test
15
+ Requires-Dist: rusticai-core (>=0.0.5,<0.1.0)
16
+ Requires-Dist: serpapi (>=0.1.5,<0.2.0)
17
+ Project-URL: Repository, https://github.com/rustic-ai/python-framework
18
+ Project-URL: Rustic AI Core, https://pypi.org/project/rusticai-core/
19
+ Description-Content-Type: text/markdown
20
+
21
+ # Rustic AI SerpApi
22
+
23
+ This module provides an agent that can be used to Search the web using [SerpApi](https://serpapi.com/)
24
+
25
+
26
+ ## Installing
27
+
28
+ ```shell
29
+ pip install rusticai-serpapi
30
+ ```
31
+ **Note:** It depends on [rusticai-core](https://pypi.org/project/rusticai-core/)
32
+
33
+ ## Building from Source
34
+
35
+ ```shell
36
+ poetry install --with dev
37
+ poetry build
38
+ ```
@@ -0,0 +1,5 @@
1
+ rustic_ai/serpapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ rustic_ai/serpapi/agent.py,sha256=YGlh49h5g3XC4nYZ6G4w-p5yqvAiBWHl6H3h9NwXNZk,4477
3
+ rusticai_serpapi-0.0.1.dist-info/METADATA,sha256=_J8diRF6hZMn9EuTYNrHB8VSoQ2DHmvpqLAKZ97ypxc,1115
4
+ rusticai_serpapi-0.0.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
5
+ rusticai_serpapi-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any