intentkit 0.6.7.dev7__py3-none-any.whl → 0.6.7.dev9__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.
Potentially problematic release.
This version of intentkit might be problematic. Click here for more details.
- intentkit/__init__.py +1 -1
- intentkit/config/config.py +1 -0
- intentkit/models/db.py +8 -4
- intentkit/skills/elfa/README.md +91 -39
- intentkit/skills/elfa/__init__.py +1 -10
- intentkit/skills/elfa/base.py +1 -1
- intentkit/skills/elfa/mention.py +143 -424
- intentkit/skills/elfa/schema.json +1 -17
- intentkit/skills/elfa/stats.py +53 -86
- intentkit/skills/elfa/tokens.py +76 -80
- intentkit/skills/elfa/utils.py +129 -0
- intentkit/skills/twitter/get_mentions.py +1 -1
- intentkit/skills/twitter/get_timeline.py +1 -1
- intentkit/skills/twitter/get_user_by_username.py +1 -1
- intentkit/skills/twitter/get_user_tweets.py +1 -1
- intentkit/skills/twitter/search_tweets.py +1 -1
- {intentkit-0.6.7.dev7.dist-info → intentkit-0.6.7.dev9.dist-info}/METADATA +1 -1
- {intentkit-0.6.7.dev7.dist-info → intentkit-0.6.7.dev9.dist-info}/RECORD +20 -19
- {intentkit-0.6.7.dev7.dist-info → intentkit-0.6.7.dev9.dist-info}/WHEEL +0 -0
- {intentkit-0.6.7.dev7.dist-info → intentkit-0.6.7.dev9.dist-info}/licenses/LICENSE +0 -0
intentkit/skills/elfa/mention.py
CHANGED
|
@@ -1,504 +1,223 @@
|
|
|
1
|
-
|
|
2
|
-
import time
|
|
3
|
-
from typing import Type
|
|
1
|
+
"""Mention-related skills for Elfa AI API."""
|
|
4
2
|
|
|
5
|
-
import
|
|
6
|
-
from langchain.tools.base import ToolException
|
|
7
|
-
from langchain_core.runnables import RunnableConfig
|
|
8
|
-
from pydantic import BaseModel, Field, HttpUrl
|
|
9
|
-
|
|
10
|
-
from .base import ElfaBaseTool, base_url
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def get_current_epoch_timestamp() -> int:
|
|
14
|
-
"""Returns the current epoch timestamp (seconds since 1970-01-01 UTC)."""
|
|
15
|
-
return int(time.time())
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def get_yesterday_epoch_timestamp() -> int:
|
|
19
|
-
"""Returns the epoch timestamp for yesterday (beginning of yesterday in UTC)."""
|
|
20
|
-
yesterday = datetime.date.today() - datetime.timedelta(days=1)
|
|
21
|
-
# Combine with midnight time to get beginning of yesterday
|
|
22
|
-
yesterday_midnight = datetime.datetime.combine(yesterday, datetime.time.min)
|
|
23
|
-
# Convert to UTC
|
|
24
|
-
yesterday_midnight_utc = yesterday_midnight.replace(tzinfo=datetime.timezone.utc)
|
|
25
|
-
return int(yesterday_midnight_utc.timestamp())
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class ElfaGetMentionsInput(BaseModel):
|
|
29
|
-
pass
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class MediaUrl(BaseModel):
|
|
33
|
-
url: str | None = Field(None, description="Media URL")
|
|
34
|
-
type: str | None = Field(None, description="Media type")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class AccountData(BaseModel):
|
|
38
|
-
name: str | None = Field(None, description="the name of the account")
|
|
39
|
-
location: str | None = Field(
|
|
40
|
-
None, description="the geographical location of the user account"
|
|
41
|
-
)
|
|
42
|
-
userSince: str | None = Field(None, description="account registration date")
|
|
43
|
-
description: str | None = Field(None, description="description of the account")
|
|
44
|
-
profileImageUrl: str | None = Field(None, description="url of the profile image")
|
|
45
|
-
profileBannerUrl: str | None = Field(
|
|
46
|
-
None, description="the url of the user profile banner"
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
class Account(BaseModel):
|
|
51
|
-
id: int | None = Field(None, description="id of the account")
|
|
52
|
-
username: str | None = Field(None, description="username of the account")
|
|
53
|
-
data: AccountData | None = Field(
|
|
54
|
-
None, description="detailed information of the account"
|
|
55
|
-
)
|
|
56
|
-
followerCount: int | None = Field(
|
|
57
|
-
None, description="the total number of the followers"
|
|
58
|
-
)
|
|
59
|
-
followingCount: int | None = Field(
|
|
60
|
-
None, description="the total number of the followings"
|
|
61
|
-
)
|
|
62
|
-
isVerified: bool | None = Field(
|
|
63
|
-
None, description="whether is a verified account of Twitter or not"
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class TweetData(BaseModel):
|
|
68
|
-
mediaUrls: list[MediaUrl] | None = Field(
|
|
69
|
-
None, description="the URLs of the media files"
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class Tweet(BaseModel):
|
|
74
|
-
id: str | None = Field(None, description="Tweet ID")
|
|
75
|
-
type: str | None = Field(None, description="Tweet type")
|
|
76
|
-
content: str | None = Field(None, description="content of the Tweet")
|
|
77
|
-
originalUrl: str | None = Field(None, description="the original URL of the tweet")
|
|
78
|
-
data: TweetData | None = Field(None, description="the data of the Tweet")
|
|
79
|
-
likeCount: int | None = Field(None, description="number of times liked")
|
|
80
|
-
quoteCount: int | None = Field(None, description="content of the quoted")
|
|
81
|
-
replyCount: int | None = Field(None, description="number of times replied")
|
|
82
|
-
repostCount: int | None = Field(None, description="number of the reposts")
|
|
83
|
-
viewCount: int | None = Field(None, description="number of views")
|
|
84
|
-
mentionedAt: str | None = Field(
|
|
85
|
-
None, description="the time of getting mentioned by other accounts"
|
|
86
|
-
)
|
|
87
|
-
bookmarkCount: int | None = Field(None, description="number of times bookmarked")
|
|
88
|
-
account: Account | None = Field(None, description="the account information")
|
|
89
|
-
repliedToUser: str | None = Field(None, description="replied to user")
|
|
90
|
-
repliedToTweet: str | None = Field(None, description="replied to tweet")
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
class ElfaGetMentionsOutput(BaseModel):
|
|
94
|
-
success: bool
|
|
95
|
-
data: list[Tweet] | None = Field(None, description="the list of tweets.")
|
|
3
|
+
from typing import Any, Dict, List, Optional, Type
|
|
96
4
|
|
|
5
|
+
from langchain_core.runnables import RunnableConfig
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
97
7
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
This tool uses the Elfa AI API to query hourly-updated tweets from "smart accounts" – accounts identified as influential or relevant – that have received at least 10 interactions (comments, retweets, quote tweets).
|
|
101
|
-
|
|
102
|
-
This tool is useful for:
|
|
103
|
-
|
|
104
|
-
* **Real-time Trend Analysis:** Identify emerging trends and discussions as they happen.
|
|
105
|
-
* **Competitor Monitoring:** Track the social media activity of your competitors.
|
|
106
|
-
* **Influencer Tracking:** Monitor the conversations and content shared by key influencers.
|
|
107
|
-
* **Reputation Management:** Identify and address potential PR issues.
|
|
108
|
-
|
|
109
|
-
The data returned includes the tweet content, timestamp, and potentially other relevant metadata.
|
|
110
|
-
|
|
111
|
-
Attributes:
|
|
112
|
-
name (str): Name of the tool, specifically "elfa_get_mentions".
|
|
113
|
-
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
114
|
-
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
115
|
-
"""
|
|
116
|
-
|
|
117
|
-
name: str = "elfa_get_mentions"
|
|
118
|
-
description: str = """This tool uses the Elfa AI API to query hourly-updated tweets from "smart accounts" – accounts identified as influential or relevant – that have received at least 10 interactions (comments, retweets, quote tweets).
|
|
119
|
-
|
|
120
|
-
This tool is useful for:
|
|
121
|
-
|
|
122
|
-
* **Real-time Trend Analysis:** Identify emerging trends and discussions as they happen.
|
|
123
|
-
* **Competitor Monitoring:** Track the social media activity of your competitors.
|
|
124
|
-
* **Influencer Tracking:** Monitor the conversations and content shared by key influencers.
|
|
125
|
-
* **Reputation Management:** Identify and address potential PR issues.
|
|
126
|
-
|
|
127
|
-
The data returned includes the tweet content, timestamp, and potentially other relevant metadata."""
|
|
128
|
-
args_schema: Type[BaseModel] = ElfaGetMentionsInput
|
|
129
|
-
|
|
130
|
-
async def _arun(
|
|
131
|
-
self, config: RunnableConfig = None, **kwargs
|
|
132
|
-
) -> ElfaGetMentionsOutput:
|
|
133
|
-
"""Run the tool to get the the ELFA AI API to query hourly-updated tweets from smart accounts with at least 10 interactions (comments, retweets, quote tweets).
|
|
134
|
-
|
|
135
|
-
Args:
|
|
136
|
-
config: The configuration for the runnable, containing agent context.
|
|
137
|
-
**kwargs: Additional parameters.
|
|
138
|
-
|
|
139
|
-
Returns:
|
|
140
|
-
ElfaGetMentionsOutput: A structured output containing output of Elfa get mentions API.
|
|
141
|
-
|
|
142
|
-
Raises:
|
|
143
|
-
Exception: If there's an error accessing the Elfa API.
|
|
144
|
-
"""
|
|
145
|
-
context = self.context_from_config(config)
|
|
146
|
-
api_key = self.get_api_key(context)
|
|
147
|
-
if not api_key:
|
|
148
|
-
raise ValueError("Elfa API key not found")
|
|
149
|
-
|
|
150
|
-
url = f"{base_url}/v1/mentions"
|
|
151
|
-
headers = {
|
|
152
|
-
"accept": "application/json",
|
|
153
|
-
"x-elfa-api-key": api_key,
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
params = ElfaGetMentionsInput(limit=100, offset=0).model_dump(exclude_none=True)
|
|
157
|
-
|
|
158
|
-
async with httpx.AsyncClient() as client:
|
|
159
|
-
try:
|
|
160
|
-
response = await client.get(
|
|
161
|
-
url, headers=headers, timeout=30, params=params
|
|
162
|
-
)
|
|
163
|
-
response.raise_for_status()
|
|
164
|
-
json_dict = response.json()
|
|
165
|
-
|
|
166
|
-
res = ElfaGetMentionsOutput(**json_dict)
|
|
167
|
-
|
|
168
|
-
return res
|
|
169
|
-
except httpx.RequestError as req_err:
|
|
170
|
-
raise ToolException(
|
|
171
|
-
f"request error from Elfa API: {req_err}"
|
|
172
|
-
) from req_err
|
|
173
|
-
except httpx.HTTPStatusError as http_err:
|
|
174
|
-
raise ToolException(
|
|
175
|
-
f"http error from Elfa API: {http_err}"
|
|
176
|
-
) from http_err
|
|
177
|
-
except Exception as e:
|
|
178
|
-
raise ToolException(f"error from Elfa API: {e}") from e
|
|
8
|
+
from .base import ElfaBaseTool
|
|
9
|
+
from .utils import MentionData, make_elfa_request
|
|
179
10
|
|
|
180
11
|
|
|
181
12
|
class ElfaGetTopMentionsInput(BaseModel):
|
|
182
|
-
|
|
183
|
-
timeWindow: str | None = Field("24h", description="Time window (e.g., 24h, 7d)")
|
|
184
|
-
includeAccountDetails: bool | None = Field(
|
|
185
|
-
False, description="Include account details"
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
class TopMentionsPostMetrics(BaseModel):
|
|
190
|
-
like_count: int | None = Field(None, description="Number of likes for the post")
|
|
191
|
-
reply_count: int | None = Field(None, description="Number of replies for the post")
|
|
192
|
-
repost_count: int | None = Field(None, description="Number of reposts for the post")
|
|
193
|
-
view_count: int | None = Field(None, description="Number of views for the post")
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
class TwitterAccountInfo(BaseModel):
|
|
197
|
-
username: str | None = Field(None, description="Twitter username")
|
|
198
|
-
twitter_user_id: str | None = Field(None, description="Twitter user ID")
|
|
199
|
-
description: str | None = Field(None, description="Twitter account description")
|
|
200
|
-
profileImageUrl: HttpUrl | None = Field(
|
|
201
|
-
None, description="URL of the profile image"
|
|
202
|
-
)
|
|
203
|
-
|
|
13
|
+
"""Input parameters for top mentions."""
|
|
204
14
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
twitter_user_id: str | None = Field(
|
|
209
|
-
None, description="Twitter user ID of the poster"
|
|
210
|
-
)
|
|
211
|
-
content: str | None = Field(None, description="Content of the post")
|
|
212
|
-
mentioned_at: str | None = Field(
|
|
213
|
-
None, description="Timestamp when the post was mentioned"
|
|
214
|
-
) # Consider using datetime if needed
|
|
215
|
-
type: str | None = Field(None, description="Type of the post (e.g., post, quote)")
|
|
216
|
-
metrics: TopMentionsPostMetrics | None = Field(
|
|
217
|
-
None, description="Metrics related to the post"
|
|
218
|
-
)
|
|
219
|
-
twitter_account_info: TwitterAccountInfo | None = Field(
|
|
220
|
-
None, description="Information about the Twitter account"
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
class TopMentionsData(BaseModel):
|
|
225
|
-
data: list[TopMentionsPostData] | None = Field(
|
|
226
|
-
None, description="List of post data"
|
|
15
|
+
ticker: str = Field(description="Stock ticker symbol (e.g., ETH, $ETH, BTC, $BTC)")
|
|
16
|
+
timeWindow: Optional[str] = Field(
|
|
17
|
+
"1h", description="Time window (e.g., '1h', '24h', '7d')"
|
|
227
18
|
)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
pageSize: int | None = Field(None, description="Number of posts per page")
|
|
19
|
+
page: Optional[int] = Field(1, description="Page number for pagination")
|
|
20
|
+
pageSize: Optional[int] = Field(10, description="Number of items per page")
|
|
231
21
|
|
|
232
22
|
|
|
233
23
|
class ElfaGetTopMentionsOutput(BaseModel):
|
|
234
|
-
|
|
235
|
-
|
|
24
|
+
"""Output structure for top mentions response."""
|
|
25
|
+
|
|
26
|
+
success: bool
|
|
27
|
+
data: Optional[List[MentionData]] = Field(None, description="List of top mentions")
|
|
28
|
+
metadata: Optional[Dict[str, Any]] = Field(None, description="Response metadata")
|
|
236
29
|
|
|
237
30
|
|
|
238
31
|
class ElfaGetTopMentions(ElfaBaseTool):
|
|
239
32
|
"""
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
This tool is useful for:
|
|
33
|
+
Get top mentions for a specific ticker.
|
|
243
34
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
35
|
+
This tool uses the Elfa API to query tweets mentioning a specific stock ticker.
|
|
36
|
+
The tweets are ranked by view count, providing insight into the most visible and
|
|
37
|
+
potentially influential discussions surrounding the stock. Results are updated hourly.
|
|
247
38
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
description (str): Comprehensive description of the tool's purpose and functionality.
|
|
253
|
-
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
39
|
+
Use Cases:
|
|
40
|
+
- Real-time sentiment analysis: Track changes in public opinion about a stock
|
|
41
|
+
- News monitoring: Identify trending news and discussions related to a specific ticker
|
|
42
|
+
- Investor insights: Monitor conversations and opinions of investors and traders
|
|
254
43
|
"""
|
|
255
44
|
|
|
256
45
|
name: str = "elfa_get_top_mentions"
|
|
257
|
-
description: str = """
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
* **Real-time Sentiment Analysis:** Track changes in public opinion about a stock.
|
|
262
|
-
* **News Monitoring:** Identify trending news and discussions related to a specific ticker.
|
|
263
|
-
* **Investor Insights:** Monitor the conversations and opinions of investors and traders.
|
|
264
|
-
|
|
265
|
-
To use this tool, simply provide the stock ticker symbol (e.g., "AAPL", "TSLA"). The tool will return a list of tweets, ranked by view count."""
|
|
46
|
+
description: str = """Get top mentions for a specific ticker symbol ranked by view count.
|
|
47
|
+
Updated hourly. Returns engagement metrics and account information for market sentiment analysis.
|
|
48
|
+
|
|
49
|
+
Use this to track public opinion, identify trending news, and monitor investor discussions."""
|
|
266
50
|
args_schema: Type[BaseModel] = ElfaGetTopMentionsInput
|
|
267
51
|
|
|
268
|
-
def _run(
|
|
269
|
-
self,
|
|
270
|
-
ticker: str,
|
|
271
|
-
timeWindow: str = "24h",
|
|
272
|
-
includeAccountDetails: bool = False,
|
|
273
|
-
) -> ElfaGetTopMentionsOutput:
|
|
274
|
-
"""Run the tool to get the Elfa API to query tweets mentioning a specific stock ticker. The tweets are ranked by view count and the results are updated hourly.
|
|
275
|
-
|
|
276
|
-
Returns:
|
|
277
|
-
ElfaAskOutput: A structured output containing output of Elfa top mentions API.
|
|
278
|
-
|
|
279
|
-
Raises:
|
|
280
|
-
Exception: If there's an error accessing the Elfa API.
|
|
281
|
-
"""
|
|
282
|
-
raise NotImplementedError("Use _arun instead")
|
|
283
|
-
|
|
284
52
|
async def _arun(
|
|
285
53
|
self,
|
|
286
54
|
ticker: str,
|
|
287
|
-
timeWindow: str = "
|
|
288
|
-
|
|
55
|
+
timeWindow: str = "1h",
|
|
56
|
+
page: int = 1,
|
|
57
|
+
pageSize: int = 10,
|
|
289
58
|
config: RunnableConfig = None,
|
|
290
59
|
**kwargs,
|
|
291
60
|
) -> ElfaGetTopMentionsOutput:
|
|
292
|
-
"""
|
|
61
|
+
"""
|
|
62
|
+
Execute the top mentions request.
|
|
293
63
|
|
|
294
64
|
Args:
|
|
295
|
-
ticker: Stock ticker symbol
|
|
296
|
-
timeWindow: Time window (
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
65
|
+
ticker: Stock ticker symbol
|
|
66
|
+
timeWindow: Time window for mentions (default: 1h)
|
|
67
|
+
page: Page number for pagination (default: 1)
|
|
68
|
+
pageSize: Items per page (default: 10)
|
|
69
|
+
config: LangChain runnable configuration
|
|
70
|
+
**kwargs: Additional parameters
|
|
300
71
|
|
|
301
72
|
Returns:
|
|
302
|
-
ElfaGetTopMentionsOutput:
|
|
73
|
+
ElfaGetTopMentionsOutput: Structured response with top mentions
|
|
303
74
|
|
|
304
75
|
Raises:
|
|
305
|
-
|
|
76
|
+
ValueError: If API key is not found
|
|
77
|
+
ToolException: If there's an error with the API request
|
|
306
78
|
"""
|
|
307
79
|
context = self.context_from_config(config)
|
|
308
80
|
api_key = self.get_api_key(context)
|
|
309
|
-
if not api_key:
|
|
310
|
-
raise ValueError("Elfa API key not found")
|
|
311
81
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
"
|
|
315
|
-
"
|
|
82
|
+
# Prepare parameters according to API spec
|
|
83
|
+
params = {
|
|
84
|
+
"ticker": ticker,
|
|
85
|
+
"timeWindow": timeWindow,
|
|
86
|
+
"page": page,
|
|
87
|
+
"pageSize": pageSize,
|
|
316
88
|
}
|
|
317
89
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
pageSize=20,
|
|
323
|
-
includeAccountDetails=includeAccountDetails,
|
|
324
|
-
).model_dump(exclude_none=True)
|
|
325
|
-
|
|
326
|
-
async with httpx.AsyncClient() as client:
|
|
327
|
-
try:
|
|
328
|
-
response = await client.get(
|
|
329
|
-
url, headers=headers, timeout=30, params=params
|
|
330
|
-
)
|
|
331
|
-
response.raise_for_status()
|
|
332
|
-
json_dict = response.json()
|
|
333
|
-
|
|
334
|
-
res = ElfaGetTopMentionsOutput(**json_dict)
|
|
335
|
-
|
|
336
|
-
return res
|
|
337
|
-
except httpx.RequestError as req_err:
|
|
338
|
-
raise ToolException(
|
|
339
|
-
f"request error from Elfa API: {req_err}"
|
|
340
|
-
) from req_err
|
|
341
|
-
except httpx.HTTPStatusError as http_err:
|
|
342
|
-
raise ToolException(
|
|
343
|
-
f"http error from Elfa API: {http_err}"
|
|
344
|
-
) from http_err
|
|
345
|
-
except Exception as e:
|
|
346
|
-
raise ToolException(f"error from Elfa API: {e}") from e
|
|
90
|
+
# Make API request using shared utility
|
|
91
|
+
response = await make_elfa_request(
|
|
92
|
+
endpoint="data/top-mentions", api_key=api_key, params=params
|
|
93
|
+
)
|
|
347
94
|
|
|
95
|
+
# Parse response data into MentionData objects
|
|
96
|
+
mentions = []
|
|
97
|
+
if response.data and isinstance(response.data, list):
|
|
98
|
+
mentions = [MentionData(**item) for item in response.data]
|
|
348
99
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
)
|
|
353
|
-
from_: int | None = Field(
|
|
354
|
-
None, description="Start date (unix timestamp), set default as 24 hours ago"
|
|
355
|
-
)
|
|
356
|
-
to: int | None = Field(
|
|
357
|
-
None, description="End date (unix timestamp), set default as now"
|
|
358
|
-
)
|
|
359
|
-
|
|
100
|
+
return ElfaGetTopMentionsOutput(
|
|
101
|
+
success=response.success, data=mentions, metadata=response.metadata
|
|
102
|
+
)
|
|
360
103
|
|
|
361
|
-
class SearchMentionsPostMetrics(BaseModel):
|
|
362
|
-
like_count: int | None = Field(None, description="Number of likes for the post")
|
|
363
|
-
reply_count: int | None = Field(None, description="Number of replies for the post")
|
|
364
|
-
repost_count: int | None = Field(None, description="Number of reposts for the post")
|
|
365
|
-
view_count: int | None = Field(None, description="Number of views for the post")
|
|
366
104
|
|
|
105
|
+
class ElfaSearchMentionsInput(BaseModel):
|
|
106
|
+
"""Input parameters for search mentions."""
|
|
367
107
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
twitter_user_id: str | None = Field(
|
|
372
|
-
None, description="Twitter user ID of the poster"
|
|
373
|
-
)
|
|
374
|
-
content: str | None = Field(None, description="Content of the post")
|
|
375
|
-
mentioned_at: str | None = Field(
|
|
376
|
-
None, description="Timestamp when the post was mentioned"
|
|
108
|
+
keywords: Optional[str] = Field(
|
|
109
|
+
None,
|
|
110
|
+
description="Up to 5 keywords to search for, separated by commas. Phrases accepted",
|
|
377
111
|
)
|
|
378
|
-
|
|
379
|
-
None,
|
|
112
|
+
accountName: Optional[str] = Field(
|
|
113
|
+
None,
|
|
114
|
+
description="Account username to filter by (optional if keywords provided)",
|
|
380
115
|
)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
None, description="Sentiment of the post (e.g., positive, negative, neutral)"
|
|
116
|
+
timeWindow: Optional[str] = Field("7d", description="Time window for search")
|
|
117
|
+
limit: Optional[int] = Field(20, description="Number of results to return (max 30)")
|
|
118
|
+
searchType: Optional[str] = Field(
|
|
119
|
+
"or", description="Type of search ('and' or 'or')"
|
|
386
120
|
)
|
|
121
|
+
cursor: Optional[str] = Field(None, description="Cursor for pagination")
|
|
387
122
|
|
|
388
123
|
|
|
389
124
|
class ElfaSearchMentionsOutput(BaseModel):
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
125
|
+
"""Output structure for search mentions response."""
|
|
126
|
+
|
|
127
|
+
success: bool
|
|
128
|
+
data: Optional[List[MentionData]] = Field(
|
|
129
|
+
None, description="List of matching mentions"
|
|
130
|
+
)
|
|
131
|
+
metadata: Optional[Dict[str, Any]] = Field(
|
|
132
|
+
None, description="Response metadata with cursor"
|
|
393
133
|
)
|
|
394
134
|
|
|
395
135
|
|
|
396
136
|
class ElfaSearchMentions(ElfaBaseTool):
|
|
397
137
|
"""
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
This tool is useful for:
|
|
138
|
+
Search mentions by keywords or account name.
|
|
401
139
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
* **Competitive Analysis:** See what people are saying about your competitors.
|
|
140
|
+
This tool uses the Elfa API to search tweets mentioning up to five keywords or from specific accounts.
|
|
141
|
+
It can search within the past 30 days of data (updated every 5 minutes) or access historical data.
|
|
142
|
+
Returns sanitized engagement metrics and sentiment data.
|
|
406
143
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
args_schema (Type[BaseModel]): Schema for input arguments, specifying expected parameters.
|
|
144
|
+
Use Cases:
|
|
145
|
+
- Market research: Track conversations and sentiment around specific products or industries
|
|
146
|
+
- Brand monitoring: Monitor mentions of your brand and identify potential PR issues
|
|
147
|
+
- Public opinion tracking: Analyze public opinion on various topics
|
|
148
|
+
- Competitive analysis: See what people are saying about your competitors
|
|
413
149
|
"""
|
|
414
150
|
|
|
415
151
|
name: str = "elfa_search_mentions"
|
|
416
|
-
description: str = """
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
* **Market Research:** Track conversations and sentiment around specific products or industries.
|
|
421
|
-
* **Brand Monitoring:** Monitor mentions of your brand and identify potential PR issues.
|
|
422
|
-
* **Public Opinion Tracking:** Analyze public opinion on various topics.
|
|
423
|
-
* **Competitive Analysis:** See what people are saying about your competitors.
|
|
424
|
-
|
|
425
|
-
To use this tool, provide up to five keywords. You can also specify whether you want to search recent or historical tweets."""
|
|
152
|
+
description: str = """Search tweets by keywords or account name with engagement data and sentiment analysis.
|
|
153
|
+
Updated every 5 minutes. Access 30 days of recent data or historical archives.
|
|
154
|
+
|
|
155
|
+
Use this for market research, brand monitoring, opinion tracking, and competitive analysis."""
|
|
426
156
|
args_schema: Type[BaseModel] = ElfaSearchMentionsInput
|
|
427
157
|
|
|
428
|
-
def _run(
|
|
429
|
-
self,
|
|
430
|
-
keywords: str,
|
|
431
|
-
from_: int = get_current_epoch_timestamp(),
|
|
432
|
-
to: int = get_yesterday_epoch_timestamp(),
|
|
433
|
-
) -> ElfaSearchMentionsOutput:
|
|
434
|
-
"""Run the tool to for tweets mentioning up to five keywords within the past 30 days. It can access up to six months of historical tweet data, updated every five minutes via the Elfa API.
|
|
435
|
-
|
|
436
|
-
Returns:
|
|
437
|
-
ElfaAskOutput: A structured output containing output of Elfa top mentions API.
|
|
438
|
-
|
|
439
|
-
Raises:
|
|
440
|
-
Exception: If there's an error accessing the Elfa API.
|
|
441
|
-
"""
|
|
442
|
-
raise NotImplementedError("Use _arun instead")
|
|
443
|
-
|
|
444
158
|
async def _arun(
|
|
445
159
|
self,
|
|
446
|
-
keywords: str,
|
|
447
|
-
|
|
448
|
-
|
|
160
|
+
keywords: Optional[str] = None,
|
|
161
|
+
accountName: Optional[str] = None,
|
|
162
|
+
timeWindow: str = "7d",
|
|
163
|
+
limit: int = 20,
|
|
164
|
+
searchType: str = "or",
|
|
165
|
+
cursor: Optional[str] = None,
|
|
449
166
|
config: RunnableConfig = None,
|
|
450
167
|
**kwargs,
|
|
451
168
|
) -> ElfaSearchMentionsOutput:
|
|
452
|
-
"""
|
|
169
|
+
"""
|
|
170
|
+
Execute the search mentions request.
|
|
453
171
|
|
|
454
172
|
Args:
|
|
455
|
-
keywords: Keywords to search
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
173
|
+
keywords: Keywords to search for (optional if accountName provided)
|
|
174
|
+
accountName: Account username to filter by (optional if keywords provided)
|
|
175
|
+
timeWindow: Time window for search (default: 7d)
|
|
176
|
+
limit: Number of results to return (default: 20, max 30)
|
|
177
|
+
searchType: Type of search - 'and' or 'or' (default: 'or')
|
|
178
|
+
cursor: Pagination cursor (optional)
|
|
179
|
+
config: LangChain runnable configuration
|
|
180
|
+
**kwargs: Additional parameters
|
|
460
181
|
|
|
461
182
|
Returns:
|
|
462
|
-
ElfaSearchMentionsOutput:
|
|
183
|
+
ElfaSearchMentionsOutput: Structured response with matching mentions
|
|
463
184
|
|
|
464
185
|
Raises:
|
|
465
|
-
|
|
186
|
+
ValueError: If API key is not found or neither keywords nor accountName provided
|
|
187
|
+
ToolException: If there's an error with the API request
|
|
466
188
|
"""
|
|
467
189
|
context = self.context_from_config(config)
|
|
468
190
|
api_key = self.get_api_key(context)
|
|
469
|
-
if not api_key:
|
|
470
|
-
raise ValueError("Elfa API key not found")
|
|
471
191
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
"
|
|
475
|
-
|
|
192
|
+
# Validate that at least one search criteria is provided
|
|
193
|
+
if not keywords and not accountName:
|
|
194
|
+
raise ValueError("Either keywords or accountName must be provided")
|
|
195
|
+
|
|
196
|
+
# Prepare parameters according to API spec
|
|
197
|
+
params = {
|
|
198
|
+
"timeWindow": timeWindow,
|
|
199
|
+
"limit": min(limit, 30), # API max is 30
|
|
200
|
+
"searchType": searchType,
|
|
476
201
|
}
|
|
477
202
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
except httpx.HTTPStatusError as http_err:
|
|
500
|
-
raise ToolException(
|
|
501
|
-
f"http error from Elfa API: {http_err}"
|
|
502
|
-
) from http_err
|
|
503
|
-
except Exception as e:
|
|
504
|
-
raise ToolException(f"error from Elfa API: {e}") from e
|
|
203
|
+
# Add optional parameters
|
|
204
|
+
if keywords:
|
|
205
|
+
params["keywords"] = keywords
|
|
206
|
+
if accountName:
|
|
207
|
+
params["accountName"] = accountName
|
|
208
|
+
if cursor:
|
|
209
|
+
params["cursor"] = cursor
|
|
210
|
+
|
|
211
|
+
# Make API request using shared utility
|
|
212
|
+
response = await make_elfa_request(
|
|
213
|
+
endpoint="data/keyword-mentions", api_key=api_key, params=params
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Parse response data into MentionData objects
|
|
217
|
+
mentions = []
|
|
218
|
+
if response.data and isinstance(response.data, list):
|
|
219
|
+
mentions = [MentionData(**item) for item in response.data]
|
|
220
|
+
|
|
221
|
+
return ElfaSearchMentionsOutput(
|
|
222
|
+
success=response.success, data=mentions, metadata=response.metadata
|
|
223
|
+
)
|