camel-ai 0.2.16__py3-none-any.whl → 0.2.17__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.

Files changed (49) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +18 -4
  3. camel/agents/multi_hop_generator_agent.py +85 -0
  4. camel/agents/programmed_agent_instruction.py +148 -0
  5. camel/benchmarks/__init__.py +2 -0
  6. camel/benchmarks/apibank.py +5 -0
  7. camel/benchmarks/apibench.py +8 -4
  8. camel/benchmarks/gaia.py +2 -2
  9. camel/benchmarks/ragbench.py +333 -0
  10. camel/bots/__init__.py +1 -1
  11. camel/bots/discord/__init__.py +26 -0
  12. camel/bots/discord/discord_app.py +384 -0
  13. camel/bots/discord/discord_installation.py +64 -0
  14. camel/bots/discord/discord_store.py +160 -0
  15. camel/configs/__init__.py +3 -0
  16. camel/configs/anthropic_config.py +17 -15
  17. camel/configs/internlm_config.py +60 -0
  18. camel/data_collector/base.py +5 -5
  19. camel/data_collector/sharegpt_collector.py +2 -2
  20. camel/datagen/self_instruct/self_instruct.py +1 -1
  21. camel/datagen/self_instruct/templates.py +12 -14
  22. camel/loaders/__init__.py +2 -0
  23. camel/loaders/panda_reader.py +337 -0
  24. camel/messages/__init__.py +10 -4
  25. camel/messages/conversion/conversation_models.py +5 -0
  26. camel/messages/func_message.py +30 -22
  27. camel/models/__init__.py +2 -0
  28. camel/models/anthropic_model.py +1 -22
  29. camel/models/cohere_model.py +8 -0
  30. camel/models/gemini_model.py +10 -1
  31. camel/models/internlm_model.py +143 -0
  32. camel/models/mistral_model.py +14 -7
  33. camel/models/model_factory.py +3 -0
  34. camel/models/reward/__init__.py +2 -0
  35. camel/models/reward/skywork_model.py +88 -0
  36. camel/synthetic_datagen/source2synth/data_processor.py +373 -0
  37. camel/synthetic_datagen/source2synth/models.py +68 -0
  38. camel/synthetic_datagen/source2synth/user_data_processor_config.py +73 -0
  39. camel/toolkits/google_scholar_toolkit.py +9 -0
  40. camel/types/__init__.py +4 -2
  41. camel/types/enums.py +34 -1
  42. camel/types/openai_types.py +6 -4
  43. camel/types/unified_model_type.py +5 -0
  44. camel/utils/token_counting.py +3 -3
  45. {camel_ai-0.2.16.dist-info → camel_ai-0.2.17.dist-info}/METADATA +158 -187
  46. {camel_ai-0.2.16.dist-info → camel_ai-0.2.17.dist-info}/RECORD +48 -35
  47. {camel_ai-0.2.16.dist-info → camel_ai-0.2.17.dist-info}/WHEEL +1 -1
  48. camel/bots/discord_app.py +0 -138
  49. {camel_ai-0.2.16.dist-info → camel_ai-0.2.17.dist-info}/LICENSE +0 -0
@@ -0,0 +1,384 @@
1
+ # ========= Copyright 2023-2024 @ 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-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
+ import os
15
+ from datetime import datetime, timedelta
16
+ from typing import TYPE_CHECKING, List, Optional
17
+
18
+ import discord
19
+ import httpx
20
+ from fastapi import FastAPI
21
+
22
+ from camel.bots.discord.discord_installation import DiscordInstallation
23
+ from camel.logger import get_logger
24
+ from camel.utils import api_keys_required, dependencies_required
25
+
26
+ from .discord_store import DiscordBaseInstallationStore
27
+
28
+ if TYPE_CHECKING:
29
+ from discord import Message
30
+
31
+ logger = get_logger(__name__)
32
+
33
+ TOKEN_URL = "https://discord.com/api/oauth2/token"
34
+ USER_URL = "https://discord.com/api/users/@me"
35
+
36
+
37
+ class DiscordApp:
38
+ r"""A class representing a Discord app that uses the `discord.py` library
39
+ to interact with Discord servers.
40
+
41
+ This bot can respond to messages in specific channels and only reacts to
42
+ messages that mention the bot.
43
+
44
+ Attributes:
45
+ channel_ids (Optional[List[int]]): A list of allowed channel IDs. If
46
+ provided, the bot will only respond to messages in these channels.
47
+ token (Optional[str]): The Discord bot token used for authentication.
48
+ """
49
+
50
+ @dependencies_required('discord')
51
+ @api_keys_required(
52
+ [
53
+ ("token", "DISCORD_BOT_TOKEN"),
54
+ ]
55
+ )
56
+ def __init__(
57
+ self,
58
+ channel_ids: Optional[List[int]] = None,
59
+ token: Optional[str] = None,
60
+ client_id: Optional[str] = None,
61
+ client_secret: Optional[str] = None,
62
+ redirect_uri: Optional[str] = None,
63
+ installation_store: Optional[DiscordBaseInstallationStore] = None,
64
+ intents: Optional[discord.Intents] = None,
65
+ ) -> None:
66
+ r"""Initialize the DiscordApp instance by setting up the Discord client
67
+ and event handlers.
68
+
69
+ Args:
70
+ channel_ids (Optional[List[int]]): A list of allowed channel IDs.
71
+ The bot will only respond to messages in these channels if
72
+ provided. (default: :obj:`None`)
73
+ token (Optional[str]): The Discord bot token for authentication.
74
+ If not provided, the token will be retrieved from the
75
+ environment variable `DISCORD_TOKEN`. (default: :obj:`None`)
76
+ client_id (str, optional): The client ID for Discord OAuth.
77
+ (default: :obj:`None`)
78
+ client_secret (Optional[str]): The client secret for Discord OAuth.
79
+ (default: :obj:`None`)
80
+ redirect_uri (str): The redirect URI for OAuth callbacks.
81
+ (default: :obj:`None`)
82
+ installation_store (DiscordAsyncInstallationStore): The database
83
+ stores all information of all installations.
84
+ (default: :obj:`None`)
85
+ intents (discord.Intents): The Discord intents of this app.
86
+ (default: :obj:`None`)
87
+
88
+ Raises:
89
+ ValueError: If the `DISCORD_BOT_TOKEN` is not found in environment
90
+ variables.
91
+ """
92
+ self.token = token or os.getenv("DISCORD_BOT_TOKEN")
93
+ self.channel_ids = channel_ids
94
+ self.installation_store = installation_store
95
+
96
+ if not intents:
97
+ intents = discord.Intents.all()
98
+ intents.message_content = True
99
+ intents.guilds = True
100
+
101
+ self._client = discord.Client(intents=intents)
102
+
103
+ # Register event handlers
104
+ self._client.event(self.on_ready)
105
+ self._client.event(self.on_message)
106
+
107
+ # OAuth flow
108
+ self.client_id = client_id or os.getenv("DISCORD_CLIENT_ID")
109
+ self.client_secret = client_secret or os.getenv(
110
+ "DISCORD_CLIENT_SECRET"
111
+ )
112
+ self.redirect_uri = redirect_uri
113
+
114
+ self.oauth_flow = bool(
115
+ self.client_id
116
+ and self.client_secret
117
+ and self.redirect_uri
118
+ and self.installation_store
119
+ )
120
+
121
+ self.app = FastAPI()
122
+
123
+ async def start(self):
124
+ r"""Asynchronously start the Discord bot using its token.
125
+
126
+ This method starts the bot and logs into Discord asynchronously using
127
+ the provided token. It should be awaited when used in an async
128
+ environment.
129
+ """
130
+ await self._client.start(self.token)
131
+
132
+ def run(self) -> None:
133
+ r"""Start the Discord bot using its token.
134
+
135
+ This method starts the bot and logs into Discord synchronously using
136
+ the provided token. It blocks execution and keeps the bot running.
137
+ """
138
+ self._client.run(self.token) # type: ignore[arg-type]
139
+
140
+ async def exchange_code_for_token_response(
141
+ self, code: str
142
+ ) -> Optional[str]:
143
+ r"""Exchange the authorization code for an access token.
144
+
145
+ Args:
146
+ code (str): The authorization code received from Discord after
147
+ user authorization.
148
+
149
+ Returns:
150
+ Optional[str]: The access token if successful, otherwise None.
151
+
152
+ Raises:
153
+ ValueError: If OAuth configuration is incomplete or invalid.
154
+ httpx.RequestError: If there is a network issue during the request.
155
+ """
156
+ if not self.oauth_flow:
157
+ logger.warning(
158
+ "OAuth is not enabled. Missing client_id, "
159
+ "client_secret, or redirect_uri."
160
+ )
161
+ return None
162
+ data = {
163
+ "client_id": self.client_id,
164
+ "client_secret": self.client_secret,
165
+ "grant_type": "authorization_code",
166
+ "code": code,
167
+ "redirect_uri": self.redirect_uri,
168
+ }
169
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
170
+ try:
171
+ async with httpx.AsyncClient() as client:
172
+ response = await client.post(
173
+ TOKEN_URL, data=data, headers=headers
174
+ )
175
+ if response.status_code != 200:
176
+ logger.error(f"Failed to exchange code: {response.text}")
177
+ return None
178
+ response_data = response.json()
179
+
180
+ return response_data
181
+ except (httpx.RequestError, ValueError) as e:
182
+ logger.error(f"Error during token fetch: {e}")
183
+ return None
184
+
185
+ async def get_user_info(self, access_token: str) -> Optional[dict]:
186
+ r"""Retrieve user information using the access token.
187
+
188
+ Args:
189
+ access_token (str): The access token received from Discord.
190
+
191
+ Returns:
192
+ dict: The user information retrieved from Discord.
193
+ """
194
+ if not self.oauth_flow:
195
+ logger.warning(
196
+ "OAuth is not enabled. Missing client_id, "
197
+ "client_secret, or redirect_uri."
198
+ )
199
+ return None
200
+ headers = {"Authorization": f"Bearer {access_token}"}
201
+ async with httpx.AsyncClient() as client:
202
+ user_response = await client.get(USER_URL, headers=headers)
203
+ return user_response.json()
204
+
205
+ async def refresh_access_token(self, refresh_token: str) -> Optional[str]:
206
+ r"""Refresh the access token using a refresh token.
207
+
208
+ Args:
209
+ refresh_token (str): The refresh token issued by Discord that
210
+ can be used to obtain a new access token.
211
+
212
+ Returns:
213
+ Optional[str]: The new access token if successful, otherwise None.
214
+ """
215
+ if not self.oauth_flow:
216
+ logger.warning(
217
+ "OAuth is not enabled. Missing client_id, "
218
+ "client_secret, or redirect_uri."
219
+ )
220
+ return None
221
+ data = {
222
+ "client_id": self.client_id,
223
+ "client_secret": self.client_secret,
224
+ "grant_type": "refresh_token",
225
+ "refresh_token": refresh_token,
226
+ "redirect_uri": self.redirect_uri,
227
+ }
228
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
229
+ async with httpx.AsyncClient() as client:
230
+ response = await client.post(TOKEN_URL, data=data, headers=headers)
231
+ if response.status_code != 200:
232
+ logger.error(f"Failed to refresh token: {response.text}")
233
+ return None
234
+ response_data = response.json()
235
+ return response_data.get("access_token")
236
+
237
+ async def get_valid_access_token(self, guild_id: str) -> Optional[str]:
238
+ r"""Retrieve a valid access token for the specified guild.
239
+
240
+ This method attempts to retrieve an access token for a specific guild.
241
+ If the current access token is expired, it will refresh the token using
242
+ the refresh token.
243
+
244
+ Args:
245
+ guild_id (str): The ID of the guild to retrieve the access
246
+ token for.
247
+
248
+ Returns:
249
+ Optional[str]: The valid access token if successful,
250
+ otherwise None.
251
+ """
252
+ if not self.oauth_flow:
253
+ logger.warning(
254
+ "OAuth is not enabled. Missing client_id, "
255
+ "client_secret, or redirect_uri."
256
+ )
257
+ return None
258
+ assert self.installation_store is not None
259
+ installation = await self.installation_store.find_by_guild(
260
+ guild_id=guild_id
261
+ )
262
+ if not installation:
263
+ logger.error(f"No installation found for guild: {guild_id}")
264
+ return None
265
+
266
+ if (
267
+ installation.token_expires_at
268
+ and datetime.now() >= installation.token_expires_at
269
+ ):
270
+ logger.info(
271
+ f"Access token expired for guild: {guild_id}, "
272
+ f"refreshing token..."
273
+ )
274
+ new_access_token = await self.refresh_access_token(
275
+ installation.refresh_token
276
+ )
277
+ if new_access_token:
278
+ installation.access_token = new_access_token
279
+ installation.token_expires_at = datetime.now() + timedelta(
280
+ seconds=3600
281
+ )
282
+ await self.installation_store.save(installation)
283
+ return new_access_token
284
+ else:
285
+ logger.error(
286
+ f"Failed to refresh access token for guild: {guild_id}"
287
+ )
288
+ return None
289
+
290
+ return installation.access_token
291
+
292
+ async def save_installation(
293
+ self,
294
+ guild_id: str,
295
+ access_token: str,
296
+ refresh_token: str,
297
+ expires_in: int,
298
+ ):
299
+ r"""Save the installation information for a given guild.
300
+
301
+ Args:
302
+ guild_id (str): The ID of the guild where the bot is installed.
303
+ access_token (str): The access token for the guild.
304
+ refresh_token (str): The refresh token for the guild.
305
+ expires_in: (int): The expiration time of the
306
+ access token.
307
+ """
308
+ if not self.oauth_flow:
309
+ logger.warning(
310
+ "OAuth is not enabled. Missing client_id, "
311
+ "client_secret, or redirect_uri."
312
+ )
313
+ return None
314
+ assert self.installation_store is not None
315
+ expires_at = datetime.now() + timedelta(seconds=expires_in)
316
+ installation = DiscordInstallation(
317
+ guild_id=guild_id,
318
+ access_token=access_token,
319
+ refresh_token=refresh_token,
320
+ installed_at=datetime.now(),
321
+ token_expires_at=expires_at,
322
+ )
323
+ await self.installation_store.save(installation)
324
+ logger.info(f"Installation saved for guild: {guild_id}")
325
+
326
+ async def remove_installation(self, guild: discord.Guild):
327
+ r"""Remove the installation for a given guild.
328
+
329
+ Args:
330
+ guild (discord.Guild): The guild from which the bot is
331
+ being removed.
332
+ """
333
+ if not self.oauth_flow:
334
+ logger.warning(
335
+ "OAuth is not enabled. Missing client_id, "
336
+ "client_secret, or redirect_uri."
337
+ )
338
+ return None
339
+ assert self.installation_store is not None
340
+ await self.installation_store.delete(guild_id=str(guild.id))
341
+ print(f"Bot removed from guild: {guild.id}")
342
+
343
+ async def on_ready(self) -> None:
344
+ r"""Event handler that is called when the bot has successfully
345
+ connected to the Discord server.
346
+
347
+ When the bot is ready and logged into Discord, it prints a message
348
+ displaying the bot's username.
349
+ """
350
+ logger.info(f'We have logged in as {self._client.user}')
351
+
352
+ async def on_message(self, message: 'Message') -> None:
353
+ r"""Event handler for processing incoming messages.
354
+
355
+ This method is called whenever a new message is received by the bot. It
356
+ will ignore messages sent by the bot itself, only respond to messages
357
+ in allowed channels (if specified), and only to messages that mention
358
+ the bot.
359
+
360
+ Args:
361
+ message (discord.Message): The message object received from
362
+ Discord.
363
+ """
364
+ # If the message author is the bot itself,
365
+ # do not respond to this message
366
+ if message.author == self._client.user:
367
+ return
368
+
369
+ # If allowed channel IDs are provided,
370
+ # only respond to messages in those channels
371
+ if self.channel_ids and message.channel.id not in self.channel_ids:
372
+ return
373
+
374
+ # Only respond to messages that mention the bot
375
+ if not self._client.user or not self._client.user.mentioned_in(
376
+ message
377
+ ):
378
+ return
379
+
380
+ logger.info(f"Received message: {message.content}")
381
+
382
+ @property
383
+ def client(self):
384
+ return self._client
@@ -0,0 +1,64 @@
1
+ # ========= Copyright 2023-2024 @ 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-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
+ from datetime import datetime
15
+ from typing import Optional
16
+
17
+
18
+ class DiscordInstallation:
19
+ r"""Represents an installation of a Discord application in a
20
+ specific guild (server).
21
+
22
+ Attributes:
23
+ guild_id (str): The unique identifier for the Discord guild (server)
24
+ where the application is installed.
25
+ access_token (str): The access token used to authenticate API requests
26
+ for the installed application.
27
+ refresh_token (str): The token used to refresh the access token when
28
+ it expires.
29
+ installed_at (datetime): The timestamp indicating when the application
30
+ was installed in the guild.
31
+ token_expires_at (Optional[datetime]): The optional timestamp
32
+ indicating when the access token will expire. Defaults to None
33
+ if the token does not have an expiration time.
34
+ """
35
+
36
+ def __init__(
37
+ self,
38
+ guild_id: str,
39
+ access_token: str,
40
+ refresh_token: str,
41
+ installed_at: datetime,
42
+ token_expires_at: Optional[datetime] = None,
43
+ ):
44
+ r"""Initialize the DiscordInstallation.
45
+
46
+ Args:
47
+ guild_id (str): The unique identifier for the Discord guild
48
+ (server) where the application is installed.
49
+ access_token (str): The access token used to authenticate API
50
+ requests for the installed application.
51
+ refresh_token (str): The token used to refresh the access token
52
+ when it expires.
53
+ installed_at (datetime): The timestamp indicating when the
54
+ application was installed in the guild.
55
+ token_expires_at (Optional[datetime]): The optional timestamp
56
+ indicating when the access token will expire. Defaults to None
57
+ if the token does not have an expiration time.
58
+ (default: :obj:`None`)
59
+ """
60
+ self.guild_id = guild_id
61
+ self.access_token = access_token
62
+ self.refresh_token = refresh_token
63
+ self.installed_at = installed_at
64
+ self.token_expires_at = token_expires_at
@@ -0,0 +1,160 @@
1
+ # ========= Copyright 2023-2024 @ 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-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
+
15
+ from typing import Optional
16
+
17
+ from .discord_installation import DiscordInstallation
18
+
19
+
20
+ class DiscordBaseInstallationStore:
21
+ r"""Abstract base class for managing Discord installations.
22
+
23
+ This class defines the interface for database operations related to storing
24
+ and retrieving Discord installation data. Subclasses must implement these
25
+ methods to handle database-specific logic.
26
+ """
27
+
28
+ async def init(self):
29
+ r"""Initializes the database connection or structure."""
30
+ pass
31
+
32
+ async def save(self, installation: DiscordInstallation):
33
+ r"""Saves or updates a Discord installation record."""
34
+ pass
35
+
36
+ async def find_by_guild(
37
+ self, guild_id: str
38
+ ) -> Optional[DiscordInstallation]:
39
+ r"""Finds an installation record by guild ID."""
40
+ pass
41
+
42
+ async def delete(self, guild_id: str):
43
+ r"""Deletes an installation record by guild ID."""
44
+ pass
45
+
46
+
47
+ class DiscordSQLiteInstallationStore(DiscordBaseInstallationStore):
48
+ r"""SQLite-based implementation for managing Discord installations.
49
+
50
+ This class provides methods for initializing the database, saving,
51
+ retrieving, and deleting installation records using SQLite.
52
+
53
+ Attributes:
54
+ database (str): Path to the SQLite database file.
55
+ """
56
+
57
+ def __init__(self, database: str):
58
+ r"""Initializes the SQLite installation store.
59
+
60
+ Args:
61
+ database (str): Path to the SQLite database file.
62
+ """
63
+ self.database = database
64
+
65
+ async def init(self):
66
+ r"""Initializes the database by creating the required table if it
67
+ does not exist."""
68
+ import aiosqlite
69
+
70
+ async with aiosqlite.connect(self.database) as db:
71
+ await db.execute(
72
+ """
73
+ CREATE TABLE IF NOT EXISTS discord_installations (
74
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
75
+ guild_id TEXT NOT NULL UNIQUE,
76
+ access_token TEXT NOT NULL,
77
+ refresh_token TEXT NOT NULL,
78
+ installed_at DATETIME NOT NULL,
79
+ token_expires_at DATETIME
80
+ );
81
+ """
82
+ )
83
+ await db.commit()
84
+
85
+ async def save(self, installation: DiscordInstallation):
86
+ r"""Saves a new installation record or updates an existing one.
87
+
88
+ Args:
89
+ installation (DiscordInstallation): The installation data to save.
90
+ """
91
+ import aiosqlite
92
+
93
+ async with aiosqlite.connect(self.database) as db:
94
+ await db.execute(
95
+ """
96
+ INSERT INTO discord_installations (
97
+ guild_id, access_token, refresh_token,
98
+ installed_at, token_expires_at
99
+ ) VALUES (?, ?, ?, ?, ?)
100
+ ON CONFLICT(guild_id) DO UPDATE SET
101
+ access_token = excluded.access_token,
102
+ refresh_token = excluded.refresh_token,
103
+ token_expires_at = excluded.token_expires_at;
104
+ """,
105
+ [
106
+ installation.guild_id,
107
+ installation.access_token,
108
+ installation.refresh_token,
109
+ installation.installed_at,
110
+ installation.token_expires_at,
111
+ ],
112
+ )
113
+ await db.commit()
114
+
115
+ async def find_by_guild(
116
+ self, guild_id: str
117
+ ) -> Optional[DiscordInstallation]:
118
+ r"""Finds an installation record by guild ID.
119
+
120
+ Args:
121
+ guild_id (str): The guild ID to search for.
122
+
123
+ Returns:
124
+ Optional[DiscordInstallation]: The installation record if found,
125
+ otherwise None.
126
+ """
127
+ import aiosqlite
128
+
129
+ async with aiosqlite.connect(self.database) as db:
130
+ async with db.execute(
131
+ "SELECT guild_id, access_token, refresh_token, "
132
+ "installed_at, token_expires_at FROM discord_installations "
133
+ "WHERE guild_id = ?",
134
+ [guild_id],
135
+ ) as cursor:
136
+ row = await cursor.fetchone()
137
+ if row:
138
+ return DiscordInstallation(
139
+ guild_id=row[0],
140
+ access_token=row[1],
141
+ refresh_token=row[2],
142
+ installed_at=row[3],
143
+ token_expires_at=row[4],
144
+ )
145
+ return None
146
+
147
+ async def delete(self, guild_id: str):
148
+ r"""Deletes an installation record by guild ID.
149
+
150
+ Args:
151
+ guild_id (str): The guild ID of the record to delete.
152
+ """
153
+ import aiosqlite
154
+
155
+ async with aiosqlite.connect(self.database) as db:
156
+ await db.execute(
157
+ "DELETE FROM discord_installations WHERE guild_id = ?",
158
+ [guild_id],
159
+ )
160
+ await db.commit()
camel/configs/__init__.py CHANGED
@@ -17,6 +17,7 @@ from .cohere_config import COHERE_API_PARAMS, CohereConfig
17
17
  from .deepseek_config import DEEPSEEK_API_PARAMS, DeepSeekConfig
18
18
  from .gemini_config import Gemini_API_PARAMS, GeminiConfig
19
19
  from .groq_config import GROQ_API_PARAMS, GroqConfig
20
+ from .internlm_config import INTERNLM_API_PARAMS, InternLMConfig
20
21
  from .litellm_config import LITELLM_API_PARAMS, LiteLLMConfig
21
22
  from .mistral_config import MISTRAL_API_PARAMS, MistralConfig
22
23
  from .nvidia_config import NVIDIA_API_PARAMS, NvidiaConfig
@@ -76,4 +77,6 @@ __all__ = [
76
77
  'QWEN_API_PARAMS',
77
78
  'DeepSeekConfig',
78
79
  'DEEPSEEK_API_PARAMS',
80
+ 'InternLMConfig',
81
+ 'INTERNLM_API_PARAMS',
79
82
  ]
@@ -13,10 +13,10 @@
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  from __future__ import annotations
15
15
 
16
- from typing import List, Union
16
+ from typing import Any, ClassVar, List, Union
17
17
 
18
18
  from camel.configs.base_config import BaseConfig
19
- from camel.types import NOT_GIVEN, NotGiven
19
+ from camel.types import NotGiven
20
20
 
21
21
 
22
22
  class AnthropicConfig(BaseConfig):
@@ -29,41 +29,43 @@ class AnthropicConfig(BaseConfig):
29
29
  generate before stopping. Note that Anthropic models may stop
30
30
  before reaching this maximum. This parameter only specifies the
31
31
  absolute maximum number of tokens to generate.
32
- (default: :obj:`256`)
32
+ (default: :obj:`8192`)
33
33
  stop_sequences (List[str], optional): Sequences that will cause the
34
34
  model to stop generating completion text. Anthropic models stop
35
35
  on "\n\nHuman:", and may include additional built-in stop sequences
36
36
  in the future. By providing the stop_sequences parameter, you may
37
37
  include additional strings that will cause the model to stop
38
- generating.
38
+ generating. (default: :obj:`[]`)
39
39
  temperature (float, optional): Amount of randomness injected into the
40
40
  response. Defaults to 1. Ranges from 0 to 1. Use temp closer to 0
41
41
  for analytical / multiple choice, and closer to 1 for creative
42
- and generative tasks.
43
- (default: :obj:`1`)
42
+ and generative tasks. (default: :obj:`1`)
44
43
  top_p (float, optional): Use nucleus sampling. In nucleus sampling, we
45
44
  compute the cumulative distribution over all the options for each
46
45
  subsequent token in decreasing probability order and cut it off
47
46
  once it reaches a particular probability specified by `top_p`.
48
47
  You should either alter `temperature` or `top_p`,
49
- but not both.
50
- (default: :obj:`0.7`)
48
+ but not both. (default: :obj:`0.7`)
51
49
  top_k (int, optional): Only sample from the top K options for each
52
50
  subsequent token. Used to remove "long tail" low probability
53
- responses.
54
- (default: :obj:`5`)
51
+ responses. (default: :obj:`5`)
55
52
  metadata: An object describing metadata about the request.
56
53
  stream (bool, optional): Whether to incrementally stream the response
57
54
  using server-sent events. (default: :obj:`False`)
58
55
  """
59
56
 
60
- max_tokens: int = 256
61
- stop_sequences: Union[List[str], NotGiven] = NOT_GIVEN
57
+ max_tokens: int = 8192
58
+ stop_sequences: ClassVar[Union[List[str], NotGiven]] = []
62
59
  temperature: float = 1
63
- top_p: Union[float, NotGiven] = NOT_GIVEN
64
- top_k: Union[int, NotGiven] = NOT_GIVEN
65
- metadata: NotGiven = NOT_GIVEN
60
+ top_p: Union[float, NotGiven] = 0.7
61
+ top_k: Union[int, NotGiven] = 5
66
62
  stream: bool = False
67
63
 
64
+ def as_dict(self) -> dict[str, Any]:
65
+ config_dict = super().as_dict()
66
+ if "tools" in config_dict:
67
+ del config_dict["tools"] # TODO: Support tool calling.
68
+ return config_dict
69
+
68
70
 
69
71
  ANTHROPIC_API_PARAMS = {param for param in AnthropicConfig.model_fields.keys()}