camel-ai 0.2.3__py3-none-any.whl → 0.2.3a1__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 camel-ai might be problematic. Click here for more details.
- camel/__init__.py +1 -1
- camel/agents/chat_agent.py +69 -93
- camel/agents/knowledge_graph_agent.py +6 -4
- camel/bots/__init__.py +2 -16
- camel/bots/discord_bot.py +206 -0
- camel/configs/__init__.py +2 -1
- camel/configs/anthropic_config.py +5 -2
- camel/configs/base_config.py +6 -6
- camel/configs/groq_config.py +3 -2
- camel/configs/ollama_config.py +2 -1
- camel/configs/openai_config.py +23 -2
- camel/configs/samba_config.py +2 -2
- camel/configs/togetherai_config.py +1 -1
- camel/configs/vllm_config.py +1 -1
- camel/configs/zhipuai_config.py +3 -2
- camel/embeddings/openai_embedding.py +2 -2
- camel/loaders/__init__.py +0 -2
- camel/loaders/firecrawl_reader.py +3 -3
- camel/loaders/unstructured_io.py +33 -35
- camel/messages/__init__.py +0 -1
- camel/models/__init__.py +4 -2
- camel/models/anthropic_model.py +26 -32
- camel/models/azure_openai_model.py +36 -39
- camel/models/base_model.py +20 -31
- camel/models/gemini_model.py +29 -37
- camel/models/groq_model.py +23 -29
- camel/models/litellm_model.py +61 -44
- camel/models/mistral_model.py +29 -32
- camel/models/model_factory.py +76 -66
- camel/models/nemotron_model.py +23 -33
- camel/models/ollama_model.py +47 -42
- camel/models/open_source_model.py +170 -0
- camel/models/{openai_compatible_model.py → openai_compatibility_model.py} +49 -31
- camel/models/openai_model.py +29 -48
- camel/models/reka_model.py +28 -30
- camel/models/samba_model.py +177 -82
- camel/models/stub_model.py +2 -2
- camel/models/togetherai_model.py +43 -37
- camel/models/vllm_model.py +50 -43
- camel/models/zhipuai_model.py +27 -33
- camel/retrievers/auto_retriever.py +10 -28
- camel/retrievers/vector_retriever.py +47 -58
- camel/societies/babyagi_playing.py +3 -6
- camel/societies/role_playing.py +3 -5
- camel/storages/graph_storages/graph_element.py +5 -3
- camel/storages/key_value_storages/json.py +1 -6
- camel/toolkits/__init__.py +7 -20
- camel/toolkits/base.py +3 -2
- camel/toolkits/code_execution.py +7 -6
- camel/toolkits/dalle_toolkit.py +6 -6
- camel/toolkits/github_toolkit.py +10 -9
- camel/toolkits/google_maps_toolkit.py +7 -7
- camel/toolkits/linkedin_toolkit.py +7 -7
- camel/toolkits/math_toolkit.py +8 -8
- camel/toolkits/open_api_toolkit.py +5 -5
- camel/toolkits/{function_tool.py → openai_function.py} +11 -34
- camel/toolkits/reddit_toolkit.py +7 -7
- camel/toolkits/retrieval_toolkit.py +5 -5
- camel/toolkits/search_toolkit.py +9 -9
- camel/toolkits/slack_toolkit.py +11 -11
- camel/toolkits/twitter_toolkit.py +452 -378
- camel/toolkits/weather_toolkit.py +6 -6
- camel/types/__init__.py +1 -6
- camel/types/enums.py +85 -40
- camel/types/openai_types.py +0 -3
- camel/utils/__init__.py +2 -0
- camel/utils/async_func.py +7 -7
- camel/utils/commons.py +3 -32
- camel/utils/token_counting.py +212 -30
- camel/workforce/role_playing_worker.py +1 -1
- camel/workforce/single_agent_worker.py +1 -1
- camel/workforce/task_channel.py +3 -4
- camel/workforce/workforce.py +4 -4
- {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a1.dist-info}/METADATA +56 -27
- {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a1.dist-info}/RECORD +76 -85
- {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a1.dist-info}/WHEEL +1 -1
- camel/bots/discord_app.py +0 -138
- camel/bots/slack/__init__.py +0 -30
- camel/bots/slack/models.py +0 -158
- camel/bots/slack/slack_app.py +0 -255
- camel/loaders/chunkr_reader.py +0 -163
- camel/toolkits/arxiv_toolkit.py +0 -155
- camel/toolkits/ask_news_toolkit.py +0 -653
- camel/toolkits/google_scholar_toolkit.py +0 -146
- camel/toolkits/whatsapp_toolkit.py +0 -177
- camel/types/unified_model_type.py +0 -104
- camel_ai-0.2.3.dist-info/LICENSE +0 -201
camel/bots/slack/slack_app.py
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the “License”);
|
|
3
|
-
# you may not use this file except in compliance with the License.
|
|
4
|
-
# You may obtain a copy of the License at
|
|
5
|
-
#
|
|
6
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
#
|
|
8
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
# distributed under the License is distributed on an “AS IS” BASIS,
|
|
10
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
# See the License for the specific language governing permissions and
|
|
12
|
-
# limitations under the License.
|
|
13
|
-
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
14
|
-
import logging
|
|
15
|
-
import os
|
|
16
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional
|
|
17
|
-
|
|
18
|
-
from slack_sdk.oauth.installation_store.async_installation_store import (
|
|
19
|
-
AsyncInstallationStore,
|
|
20
|
-
)
|
|
21
|
-
from starlette import requests, responses
|
|
22
|
-
|
|
23
|
-
from camel.bots.slack.models import (
|
|
24
|
-
SlackAppMentionEventBody,
|
|
25
|
-
SlackAppMentionEventProfile,
|
|
26
|
-
SlackEventBody,
|
|
27
|
-
SlackEventProfile,
|
|
28
|
-
)
|
|
29
|
-
from camel.utils import dependencies_required
|
|
30
|
-
|
|
31
|
-
if TYPE_CHECKING:
|
|
32
|
-
from slack_bolt.context.async_context import AsyncBoltContext
|
|
33
|
-
from slack_bolt.context.say.async_say import AsyncSay
|
|
34
|
-
from slack_sdk.web.async_client import AsyncWebClient
|
|
35
|
-
|
|
36
|
-
logging.basicConfig(level=logging.INFO)
|
|
37
|
-
logger = logging.getLogger(__name__)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class SlackApp:
|
|
41
|
-
r"""Represents a Slack app that is powered by a Slack Bolt `AsyncApp`.
|
|
42
|
-
|
|
43
|
-
This class is responsible for initializing and managing the Slack
|
|
44
|
-
application by setting up event handlers, running the app server, and
|
|
45
|
-
handling events such as messages and mentions from Slack.
|
|
46
|
-
|
|
47
|
-
Args:
|
|
48
|
-
token (Optional[str]): Slack API token for authentication.
|
|
49
|
-
scopes (Optional[str]): Slack app scopes for permissions.
|
|
50
|
-
signing_secret (Optional[str]): Signing secret for verifying Slack
|
|
51
|
-
requests.
|
|
52
|
-
client_id (Optional[str]): Slack app client ID.
|
|
53
|
-
client_secret (Optional[str]): Slack app client secret.
|
|
54
|
-
redirect_uri_path (str): The URI path for OAuth redirect, defaults to
|
|
55
|
-
"/slack/oauth_redirect".
|
|
56
|
-
installation_store (Optional[AsyncInstallationStore]): The installation
|
|
57
|
-
store for handling OAuth installations.
|
|
58
|
-
"""
|
|
59
|
-
|
|
60
|
-
@dependencies_required('slack_bolt')
|
|
61
|
-
def __init__(
|
|
62
|
-
self,
|
|
63
|
-
token: Optional[str] = None,
|
|
64
|
-
scopes: Optional[str] = None,
|
|
65
|
-
signing_secret: Optional[str] = None,
|
|
66
|
-
client_id: Optional[str] = None,
|
|
67
|
-
client_secret: Optional[str] = None,
|
|
68
|
-
redirect_uri_path: str = "/slack/oauth_redirect",
|
|
69
|
-
installation_store: Optional[AsyncInstallationStore] = None,
|
|
70
|
-
) -> None:
|
|
71
|
-
r"""Initializes the SlackApp instance by setting up the Slack Bolt app
|
|
72
|
-
and configuring event handlers and OAuth settings.
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
token (Optional[str]): The Slack API token.
|
|
76
|
-
scopes (Optional[str]): The scopes for Slack app permissions.
|
|
77
|
-
signing_secret (Optional[str]): The signing secret for verifying
|
|
78
|
-
requests.
|
|
79
|
-
client_id (Optional[str]): The Slack app client ID.
|
|
80
|
-
client_secret (Optional[str]): The Slack app client secret.
|
|
81
|
-
redirect_uri_path (str): The URI path for handling OAuth redirects
|
|
82
|
-
(default is "/slack/oauth_redirect").
|
|
83
|
-
installation_store (Optional[AsyncInstallationStore]): An optional
|
|
84
|
-
installation store for OAuth installations.
|
|
85
|
-
"""
|
|
86
|
-
from slack_bolt.adapter.starlette.async_handler import (
|
|
87
|
-
AsyncSlackRequestHandler,
|
|
88
|
-
)
|
|
89
|
-
from slack_bolt.app.async_app import AsyncApp
|
|
90
|
-
from slack_bolt.oauth.async_oauth_settings import AsyncOAuthSettings
|
|
91
|
-
|
|
92
|
-
self.token: Optional[str] = token or os.getenv("SLACK_TOKEN")
|
|
93
|
-
self.scopes: Optional[str] = scopes or os.getenv("SLACK_SCOPES")
|
|
94
|
-
self.signing_secret: Optional[str] = signing_secret or os.getenv(
|
|
95
|
-
"SLACK_SIGNING_SECRET"
|
|
96
|
-
)
|
|
97
|
-
self.client_id: Optional[str] = client_id or os.getenv(
|
|
98
|
-
"SLACK_CLIENT_ID"
|
|
99
|
-
)
|
|
100
|
-
self.client_secret: Optional[str] = client_secret or os.getenv(
|
|
101
|
-
"SLACK_CLIENT_SECRET"
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
if not all([self.token, self.scopes, self.signing_secret]):
|
|
105
|
-
raise ValueError(
|
|
106
|
-
"`SLACK_TOKEN`, `SLACK_SCOPES`, and `SLACK_SIGNING_SECRET` "
|
|
107
|
-
"environment variables must be set. Get it here: "
|
|
108
|
-
"`https://api.slack.com/apps`."
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
# Setup OAuth settings if client ID and secret are provided
|
|
112
|
-
if self.client_id and self.client_secret:
|
|
113
|
-
self._app = AsyncApp(
|
|
114
|
-
oauth_settings=AsyncOAuthSettings(
|
|
115
|
-
client_id=self.client_id,
|
|
116
|
-
client_secret=self.client_secret,
|
|
117
|
-
scopes=self.scopes,
|
|
118
|
-
redirect_uri_path=redirect_uri_path,
|
|
119
|
-
),
|
|
120
|
-
logger=logger,
|
|
121
|
-
signing_secret=self.signing_secret,
|
|
122
|
-
installation_store=installation_store,
|
|
123
|
-
token=self.token,
|
|
124
|
-
)
|
|
125
|
-
else:
|
|
126
|
-
# Initialize Slack Bolt AsyncApp with settings
|
|
127
|
-
self._app = AsyncApp(
|
|
128
|
-
logger=logger,
|
|
129
|
-
signing_secret=self.signing_secret,
|
|
130
|
-
installation_store=installation_store,
|
|
131
|
-
token=self.token,
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
self._handler = AsyncSlackRequestHandler(self._app)
|
|
135
|
-
self.setup_handlers()
|
|
136
|
-
|
|
137
|
-
def setup_handlers(self) -> None:
|
|
138
|
-
r"""Sets up the event handlers for Slack events, such as `app_mention`
|
|
139
|
-
and `message`.
|
|
140
|
-
|
|
141
|
-
This method registers the `app_mention` and `on_message` event handlers
|
|
142
|
-
with the Slack Bolt app to respond to Slack events.
|
|
143
|
-
"""
|
|
144
|
-
self._app.event("app_mention")(self.app_mention)
|
|
145
|
-
self._app.event("message")(self.on_message)
|
|
146
|
-
|
|
147
|
-
def run(
|
|
148
|
-
self,
|
|
149
|
-
port: int = 3000,
|
|
150
|
-
path: str = "/slack/events",
|
|
151
|
-
host: Optional[str] = None,
|
|
152
|
-
) -> None:
|
|
153
|
-
r"""Starts the Slack Bolt app server to listen for incoming Slack
|
|
154
|
-
events.
|
|
155
|
-
|
|
156
|
-
Args:
|
|
157
|
-
port (int): The port on which the server should run (default is
|
|
158
|
-
3000).
|
|
159
|
-
path (str): The endpoint path for receiving Slack events (default
|
|
160
|
-
is "/slack/events").
|
|
161
|
-
host (Optional[str]): The hostname to bind the server (default is
|
|
162
|
-
None).
|
|
163
|
-
"""
|
|
164
|
-
self._app.start(port=port, path=path, host=host)
|
|
165
|
-
|
|
166
|
-
async def handle_request(
|
|
167
|
-
self, request: requests.Request
|
|
168
|
-
) -> responses.Response:
|
|
169
|
-
r"""Handles incoming requests from Slack through the request handler.
|
|
170
|
-
|
|
171
|
-
Args:
|
|
172
|
-
request (Request): A Starlette request object representing the
|
|
173
|
-
incoming request.
|
|
174
|
-
|
|
175
|
-
Returns:
|
|
176
|
-
The response generated by the Slack Bolt handler.
|
|
177
|
-
"""
|
|
178
|
-
return await self._handler.handle(request)
|
|
179
|
-
|
|
180
|
-
async def app_mention(
|
|
181
|
-
self,
|
|
182
|
-
context: "AsyncBoltContext",
|
|
183
|
-
client: "AsyncWebClient",
|
|
184
|
-
event: Dict[str, Any],
|
|
185
|
-
body: Dict[str, Any],
|
|
186
|
-
say: "AsyncSay",
|
|
187
|
-
) -> None:
|
|
188
|
-
r"""Event handler for `app_mention` events.
|
|
189
|
-
|
|
190
|
-
This method is triggered when someone mentions the app in Slack.
|
|
191
|
-
|
|
192
|
-
Args:
|
|
193
|
-
context (AsyncBoltContext): The Slack Bolt context for the event.
|
|
194
|
-
client (AsyncWebClient): The Slack Web API client.
|
|
195
|
-
event (Dict[str, Any]): The event data for the app mention.
|
|
196
|
-
body (Dict[str, Any]): The full request body from Slack.
|
|
197
|
-
say (AsyncSay): A function to send a response back to the channel.
|
|
198
|
-
"""
|
|
199
|
-
event_profile = SlackAppMentionEventProfile(**event)
|
|
200
|
-
event_body = SlackAppMentionEventBody(**body)
|
|
201
|
-
|
|
202
|
-
logger.info(f"app_mention, context: {context}")
|
|
203
|
-
logger.info(f"app_mention, client: {client}")
|
|
204
|
-
logger.info(f"app_mention, event_profile: {event_profile}")
|
|
205
|
-
logger.info(f"app_mention, event_body: {event_body}")
|
|
206
|
-
logger.info(f"app_mention, say: {say}")
|
|
207
|
-
|
|
208
|
-
async def on_message(
|
|
209
|
-
self,
|
|
210
|
-
context: "AsyncBoltContext",
|
|
211
|
-
client: "AsyncWebClient",
|
|
212
|
-
event: Dict[str, Any],
|
|
213
|
-
body: Dict[str, Any],
|
|
214
|
-
say: "AsyncSay",
|
|
215
|
-
) -> None:
|
|
216
|
-
r"""Event handler for `message` events.
|
|
217
|
-
|
|
218
|
-
This method is triggered when the app receives a message in Slack.
|
|
219
|
-
|
|
220
|
-
Args:
|
|
221
|
-
context (AsyncBoltContext): The Slack Bolt context for the event.
|
|
222
|
-
client (AsyncWebClient): The Slack Web API client.
|
|
223
|
-
event (Dict[str, Any]): The event data for the message.
|
|
224
|
-
body (Dict[str, Any]): The full request body from Slack.
|
|
225
|
-
say (AsyncSay): A function to send a response back to the channel.
|
|
226
|
-
"""
|
|
227
|
-
await context.ack()
|
|
228
|
-
|
|
229
|
-
event_profile = SlackEventProfile(**event)
|
|
230
|
-
event_body = SlackEventBody(**body)
|
|
231
|
-
|
|
232
|
-
logger.info(f"on_message, context: {context}")
|
|
233
|
-
logger.info(f"on_message, client: {client}")
|
|
234
|
-
logger.info(f"on_message, event_profile: {event_profile}")
|
|
235
|
-
logger.info(f"on_message, event_body: {event_body}")
|
|
236
|
-
logger.info(f"on_message, say: {say}")
|
|
237
|
-
|
|
238
|
-
logger.info(f"Received message: {event_profile.text}")
|
|
239
|
-
|
|
240
|
-
def mention_me(
|
|
241
|
-
self, context: "AsyncBoltContext", body: SlackEventBody
|
|
242
|
-
) -> bool:
|
|
243
|
-
r"""Check if the bot is mentioned in the message.
|
|
244
|
-
|
|
245
|
-
Args:
|
|
246
|
-
context (AsyncBoltContext): The Slack Bolt context for the event.
|
|
247
|
-
body (SlackEventBody): The body of the Slack event.
|
|
248
|
-
|
|
249
|
-
Returns:
|
|
250
|
-
bool: True if the bot is mentioned in the message, False otherwise.
|
|
251
|
-
"""
|
|
252
|
-
message = body.event.text
|
|
253
|
-
bot_user_id = context.bot_user_id
|
|
254
|
-
mention = f"<@{bot_user_id}>"
|
|
255
|
-
return mention in message
|
camel/loaders/chunkr_reader.py
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the “License”);
|
|
3
|
-
# you may not use this file except in compliance with the License.
|
|
4
|
-
# You may obtain a copy of the License at
|
|
5
|
-
#
|
|
6
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
#
|
|
8
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
# distributed under the License is distributed on an “AS IS” BASIS,
|
|
10
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
# See the License for the specific language governing permissions and
|
|
12
|
-
# limitations under the License.
|
|
13
|
-
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
14
|
-
|
|
15
|
-
import json
|
|
16
|
-
import logging
|
|
17
|
-
import os
|
|
18
|
-
import time
|
|
19
|
-
from typing import IO, Any, Optional, Union
|
|
20
|
-
|
|
21
|
-
import requests
|
|
22
|
-
|
|
23
|
-
from camel.utils import api_keys_required
|
|
24
|
-
|
|
25
|
-
logger = logging.getLogger(__name__)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class ChunkrReader:
|
|
29
|
-
r"""Chunkr Reader for processing documents and returning content
|
|
30
|
-
in various formats.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
api_key (Optional[str], optional): The API key for Chunkr API. If not
|
|
34
|
-
provided, it will be retrieved from the environment variable
|
|
35
|
-
`CHUNKR_API_KEY`. (default: :obj:`None`)
|
|
36
|
-
url (Optional[str], optional): The url to the Chunkr service.
|
|
37
|
-
(default: :obj:`https://api.chunkr.ai/api/v1/task`)
|
|
38
|
-
timeout (int, optional): The maximum time in seconds to wait for the
|
|
39
|
-
API responses. (default: :obj:`30`)
|
|
40
|
-
**kwargs (Any): Additional keyword arguments for request headers.
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
@api_keys_required("CHUNKR_API_KEY")
|
|
44
|
-
def __init__(
|
|
45
|
-
self,
|
|
46
|
-
api_key: Optional[str] = None,
|
|
47
|
-
url: Optional[str] = "https://api.chunkr.ai/api/v1/task",
|
|
48
|
-
timeout: int = 30,
|
|
49
|
-
**kwargs: Any,
|
|
50
|
-
) -> None:
|
|
51
|
-
self._api_key = api_key or os.getenv('CHUNKR_API_KEY')
|
|
52
|
-
self._url = os.getenv('CHUNKR_API_URL') or url
|
|
53
|
-
self._headers = {
|
|
54
|
-
"Authorization": f"{self._api_key}",
|
|
55
|
-
**kwargs,
|
|
56
|
-
}
|
|
57
|
-
self.timeout = timeout
|
|
58
|
-
|
|
59
|
-
def submit_task(
|
|
60
|
-
self,
|
|
61
|
-
file_path: str,
|
|
62
|
-
model: str = "Fast",
|
|
63
|
-
ocr_strategy: str = "Auto",
|
|
64
|
-
target_chunk_length: str = "512",
|
|
65
|
-
) -> str:
|
|
66
|
-
r"""Submits a file to the Chunkr API and returns the task ID.
|
|
67
|
-
|
|
68
|
-
Args:
|
|
69
|
-
file_path (str): The path to the file to be uploaded.
|
|
70
|
-
model (str, optional): The model to be used for the task.
|
|
71
|
-
(default: :obj:`Fast`)
|
|
72
|
-
ocr_strategy (str, optional): The OCR strategy. Defaults to 'Auto'.
|
|
73
|
-
target_chunk_length (str, optional): The target chunk length.
|
|
74
|
-
(default: :obj:`512`)
|
|
75
|
-
|
|
76
|
-
Returns:
|
|
77
|
-
str: The task ID.
|
|
78
|
-
"""
|
|
79
|
-
with open(file_path, 'rb') as file:
|
|
80
|
-
files: dict[
|
|
81
|
-
str, Union[tuple[None, IO[bytes]], tuple[None, str]]
|
|
82
|
-
] = {
|
|
83
|
-
'file': (
|
|
84
|
-
None,
|
|
85
|
-
file,
|
|
86
|
-
), # Properly pass the file as a binary stream
|
|
87
|
-
'model': (None, model),
|
|
88
|
-
'ocr_strategy': (None, ocr_strategy),
|
|
89
|
-
'target_chunk_length': (None, target_chunk_length),
|
|
90
|
-
}
|
|
91
|
-
try:
|
|
92
|
-
response = requests.post(
|
|
93
|
-
self._url, # type: ignore[arg-type]
|
|
94
|
-
headers=self._headers,
|
|
95
|
-
files=files,
|
|
96
|
-
timeout=self.timeout,
|
|
97
|
-
)
|
|
98
|
-
response.raise_for_status()
|
|
99
|
-
task_id = response.json().get('task_id')
|
|
100
|
-
if not task_id:
|
|
101
|
-
raise ValueError("Task ID not returned in the response.")
|
|
102
|
-
logger.info(f"Task submitted successfully. Task ID: {task_id}")
|
|
103
|
-
return task_id
|
|
104
|
-
except Exception as e:
|
|
105
|
-
logger.error(f"Failed to submit task: {e}")
|
|
106
|
-
raise ValueError(f"Failed to submit task: {e}") from e
|
|
107
|
-
|
|
108
|
-
def get_task_output(self, task_id: str, max_retries: int = 5) -> str:
|
|
109
|
-
r"""Polls the Chunkr API to check the task status and returns the task
|
|
110
|
-
result.
|
|
111
|
-
|
|
112
|
-
Args:
|
|
113
|
-
task_id (str): The task ID to check the status for.
|
|
114
|
-
max_retries (int, optional): Maximum number of retry attempts.
|
|
115
|
-
(default: :obj:`5`)
|
|
116
|
-
|
|
117
|
-
Returns:
|
|
118
|
-
str: The formatted task result in JSON format.
|
|
119
|
-
|
|
120
|
-
Raises:
|
|
121
|
-
ValueError: If the task status cannot be retrieved.
|
|
122
|
-
RuntimeError: If the maximum number of retries is reached without
|
|
123
|
-
a successful task completion.
|
|
124
|
-
"""
|
|
125
|
-
url_get = f"{self._url}/{task_id}"
|
|
126
|
-
attempts = 0
|
|
127
|
-
|
|
128
|
-
while attempts < max_retries:
|
|
129
|
-
try:
|
|
130
|
-
response = requests.get(
|
|
131
|
-
url_get, headers=self._headers, timeout=self.timeout
|
|
132
|
-
)
|
|
133
|
-
response.raise_for_status()
|
|
134
|
-
task_status = response.json().get('status')
|
|
135
|
-
|
|
136
|
-
if task_status == "Succeeded":
|
|
137
|
-
logger.info(f"Task {task_id} completed successfully.")
|
|
138
|
-
return self._pretty_print_response(response.json())
|
|
139
|
-
else:
|
|
140
|
-
logger.info(
|
|
141
|
-
f"Task {task_id} is still {task_status}. Retrying "
|
|
142
|
-
"in 5 seconds..."
|
|
143
|
-
)
|
|
144
|
-
except Exception as e:
|
|
145
|
-
logger.error(f"Failed to retrieve task status: {e}")
|
|
146
|
-
raise ValueError(f"Failed to retrieve task status: {e}") from e
|
|
147
|
-
|
|
148
|
-
attempts += 1
|
|
149
|
-
time.sleep(5)
|
|
150
|
-
|
|
151
|
-
logger.error(f"Max retries reached for task {task_id}.")
|
|
152
|
-
raise RuntimeError(f"Max retries reached for task {task_id}.")
|
|
153
|
-
|
|
154
|
-
def _pretty_print_response(self, response_json: dict) -> str:
|
|
155
|
-
r"""Pretty prints the JSON response.
|
|
156
|
-
|
|
157
|
-
Args:
|
|
158
|
-
response_json (dict): The response JSON to pretty print.
|
|
159
|
-
|
|
160
|
-
Returns:
|
|
161
|
-
str: Formatted JSON as a string.
|
|
162
|
-
"""
|
|
163
|
-
return json.dumps(response_json, indent=4)
|
camel/toolkits/arxiv_toolkit.py
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
2
|
-
# Licensed under the Apache License, Version 2.0 (the “License”);
|
|
3
|
-
# you may not use this file except in compliance with the License.
|
|
4
|
-
# You may obtain a copy of the License at
|
|
5
|
-
#
|
|
6
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
#
|
|
8
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
-
# distributed under the License is distributed on an “AS IS” BASIS,
|
|
10
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
-
# See the License for the specific language governing permissions and
|
|
12
|
-
# limitations under the License.
|
|
13
|
-
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
14
|
-
|
|
15
|
-
from typing import Dict, Generator, List, Optional
|
|
16
|
-
|
|
17
|
-
from camel.toolkits.base import BaseToolkit
|
|
18
|
-
from camel.toolkits.function_tool import FunctionTool
|
|
19
|
-
from camel.utils import dependencies_required
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class ArxivToolkit(BaseToolkit):
|
|
23
|
-
r"""A toolkit for interacting with the arXiv API to search and download
|
|
24
|
-
academic papers.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
@dependencies_required('arxiv')
|
|
28
|
-
def __init__(self) -> None:
|
|
29
|
-
r"""Initializes the ArxivToolkit and sets up the arXiv client."""
|
|
30
|
-
import arxiv
|
|
31
|
-
|
|
32
|
-
self.client = arxiv.Client()
|
|
33
|
-
|
|
34
|
-
def _get_search_results(
|
|
35
|
-
self,
|
|
36
|
-
query: str,
|
|
37
|
-
paper_ids: Optional[List[str]] = None,
|
|
38
|
-
max_results: Optional[int] = 5,
|
|
39
|
-
) -> Generator:
|
|
40
|
-
r"""Retrieves search results from the arXiv API based on the provided
|
|
41
|
-
query and optional paper IDs.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
query (str): The search query string used to search for papers on
|
|
45
|
-
arXiv.
|
|
46
|
-
paper_ids (List[str], optional): A list of specific arXiv paper
|
|
47
|
-
IDs to search for. (default::obj: `None`)
|
|
48
|
-
max_results (int, optional): The maximum number of search results
|
|
49
|
-
to retrieve. (default::obj: `5`)
|
|
50
|
-
|
|
51
|
-
Returns:
|
|
52
|
-
Generator: A generator that yields results from the arXiv search
|
|
53
|
-
query, which includes metadata about each paper matching the
|
|
54
|
-
query.
|
|
55
|
-
"""
|
|
56
|
-
import arxiv
|
|
57
|
-
|
|
58
|
-
paper_ids = paper_ids or []
|
|
59
|
-
search_query = arxiv.Search(
|
|
60
|
-
query=query,
|
|
61
|
-
id_list=paper_ids,
|
|
62
|
-
max_results=max_results,
|
|
63
|
-
)
|
|
64
|
-
return self.client.results(search_query)
|
|
65
|
-
|
|
66
|
-
def search_papers(
|
|
67
|
-
self,
|
|
68
|
-
query: str,
|
|
69
|
-
paper_ids: Optional[List[str]] = None,
|
|
70
|
-
max_results: Optional[int] = 5,
|
|
71
|
-
) -> List[Dict[str, str]]:
|
|
72
|
-
r"""Searches for academic papers on arXiv using a query string and
|
|
73
|
-
optional paper IDs.
|
|
74
|
-
|
|
75
|
-
Args:
|
|
76
|
-
query (str): The search query string.
|
|
77
|
-
paper_ids (List[str], optional): A list of specific arXiv paper
|
|
78
|
-
IDs to search for. (default::obj: `None`)
|
|
79
|
-
max_results (int, optional): The maximum number of search results
|
|
80
|
-
to return. (default::obj: `5`)
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
List[Dict[str, str]]: A list of dictionaries, each containing
|
|
84
|
-
information about a paper, including title, published date,
|
|
85
|
-
authors, entry ID, summary, and extracted text from the paper.
|
|
86
|
-
"""
|
|
87
|
-
from arxiv2text import arxiv_to_text
|
|
88
|
-
|
|
89
|
-
search_results = self._get_search_results(
|
|
90
|
-
query, paper_ids, max_results
|
|
91
|
-
)
|
|
92
|
-
papers_data = []
|
|
93
|
-
|
|
94
|
-
for paper in search_results:
|
|
95
|
-
paper_info = {
|
|
96
|
-
"title": paper.title,
|
|
97
|
-
"published_date": paper.updated.date().isoformat(),
|
|
98
|
-
"authors": [author.name for author in paper.authors],
|
|
99
|
-
"entry_id": paper.entry_id,
|
|
100
|
-
"summary": paper.summary,
|
|
101
|
-
# TODO: Use chunkr instead of atxiv_to_text for better
|
|
102
|
-
# performance
|
|
103
|
-
"paper_text": arxiv_to_text(paper.pdf_url),
|
|
104
|
-
}
|
|
105
|
-
papers_data.append(paper_info)
|
|
106
|
-
|
|
107
|
-
return papers_data
|
|
108
|
-
|
|
109
|
-
def download_papers(
|
|
110
|
-
self,
|
|
111
|
-
query: str,
|
|
112
|
-
paper_ids: Optional[List[str]] = None,
|
|
113
|
-
max_results: Optional[int] = 5,
|
|
114
|
-
output_dir: Optional[str] = "./",
|
|
115
|
-
) -> str:
|
|
116
|
-
r"""Downloads PDFs of academic papers from arXiv based on the provided
|
|
117
|
-
query.
|
|
118
|
-
|
|
119
|
-
Args:
|
|
120
|
-
query (str): The search query string.
|
|
121
|
-
paper_ids (List[str], optional): A list of specific arXiv paper
|
|
122
|
-
IDs to download. (default::obj: `None`)
|
|
123
|
-
max_results (int, optional): The maximum number of search results
|
|
124
|
-
to download. (default::obj: `5`)
|
|
125
|
-
output_dir (str, optional): The directory to save the downloaded
|
|
126
|
-
PDFs. Defaults to the current directory.
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
str: Status message indicating success or failure.
|
|
130
|
-
"""
|
|
131
|
-
try:
|
|
132
|
-
search_results = self._get_search_results(
|
|
133
|
-
query, paper_ids, max_results
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
for paper in search_results:
|
|
137
|
-
paper.download_pdf(
|
|
138
|
-
dirpath=output_dir, filename=f"{paper.title}" + ".pdf"
|
|
139
|
-
)
|
|
140
|
-
return "papers downloaded successfully"
|
|
141
|
-
except Exception as e:
|
|
142
|
-
return f"An error occurred: {e}"
|
|
143
|
-
|
|
144
|
-
def get_tools(self) -> List[FunctionTool]:
|
|
145
|
-
r"""Returns a list of FunctionTool objects representing the
|
|
146
|
-
functions in the toolkit.
|
|
147
|
-
|
|
148
|
-
Returns:
|
|
149
|
-
List[FunctionTool]: A list of FunctionTool objects
|
|
150
|
-
representing the functions in the toolkit.
|
|
151
|
-
"""
|
|
152
|
-
return [
|
|
153
|
-
FunctionTool(self.search_papers),
|
|
154
|
-
FunctionTool(self.download_papers),
|
|
155
|
-
]
|