camel-ai 0.2.45__py3-none-any.whl → 0.2.47__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/configs/__init__.py +6 -0
- camel/configs/bedrock_config.py +73 -0
- camel/configs/lmstudio_config.py +94 -0
- camel/configs/qwen_config.py +3 -3
- camel/datasets/few_shot_generator.py +19 -3
- camel/datasets/models.py +1 -1
- camel/loaders/__init__.py +2 -0
- camel/loaders/scrapegraph_reader.py +96 -0
- camel/models/__init__.py +4 -0
- camel/models/aiml_model.py +11 -104
- camel/models/anthropic_model.py +11 -76
- camel/models/aws_bedrock_model.py +112 -0
- camel/models/deepseek_model.py +11 -44
- camel/models/gemini_model.py +10 -72
- camel/models/groq_model.py +11 -131
- camel/models/internlm_model.py +11 -61
- camel/models/lmstudio_model.py +82 -0
- camel/models/model_factory.py +7 -1
- camel/models/modelscope_model.py +11 -122
- camel/models/moonshot_model.py +10 -76
- camel/models/nemotron_model.py +4 -60
- camel/models/nvidia_model.py +11 -111
- camel/models/ollama_model.py +12 -205
- camel/models/openai_compatible_model.py +51 -12
- camel/models/openai_model.py +3 -1
- camel/models/openrouter_model.py +12 -131
- camel/models/ppio_model.py +10 -99
- camel/models/qwen_model.py +11 -122
- camel/models/reka_model.py +1 -1
- camel/models/sglang_model.py +5 -3
- camel/models/siliconflow_model.py +10 -58
- camel/models/togetherai_model.py +10 -177
- camel/models/vllm_model.py +11 -218
- camel/models/volcano_model.py +1 -15
- camel/models/yi_model.py +11 -98
- camel/models/zhipuai_model.py +11 -102
- camel/storages/__init__.py +2 -0
- camel/storages/vectordb_storages/__init__.py +2 -0
- camel/storages/vectordb_storages/oceanbase.py +458 -0
- camel/toolkits/__init__.py +4 -0
- camel/toolkits/browser_toolkit.py +4 -7
- camel/toolkits/jina_reranker_toolkit.py +231 -0
- camel/toolkits/pyautogui_toolkit.py +428 -0
- camel/toolkits/search_toolkit.py +167 -0
- camel/toolkits/video_analysis_toolkit.py +215 -80
- camel/toolkits/video_download_toolkit.py +10 -3
- camel/types/enums.py +70 -0
- camel/types/unified_model_type.py +10 -0
- camel/utils/token_counting.py +7 -3
- {camel_ai-0.2.45.dist-info → camel_ai-0.2.47.dist-info}/METADATA +13 -1
- {camel_ai-0.2.45.dist-info → camel_ai-0.2.47.dist-info}/RECORD +54 -46
- {camel_ai-0.2.45.dist-info → camel_ai-0.2.47.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.45.dist-info → camel_ai-0.2.47.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,458 @@
|
|
|
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
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional
|
|
18
|
+
|
|
19
|
+
from sqlalchemy import JSON, Column, Integer
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from pyobvector.client import ObVecClient
|
|
23
|
+
|
|
24
|
+
from camel.storages.vectordb_storages import (
|
|
25
|
+
BaseVectorStorage,
|
|
26
|
+
VectorDBQuery,
|
|
27
|
+
VectorDBQueryResult,
|
|
28
|
+
VectorDBStatus,
|
|
29
|
+
VectorRecord,
|
|
30
|
+
)
|
|
31
|
+
from camel.utils import dependencies_required
|
|
32
|
+
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class OceanBaseStorage(BaseVectorStorage):
|
|
37
|
+
r"""An implementation of the `BaseVectorStorage` for interacting with
|
|
38
|
+
OceanBase Vector Database.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
vector_dim (int): The dimension of storing vectors.
|
|
42
|
+
table_name (str): Name for the table in OceanBase.
|
|
43
|
+
uri (str): Connection URI for OceanBase (host:port).
|
|
44
|
+
(default: :obj:`"127.0.0.1:2881"`)
|
|
45
|
+
user (str): Username for connecting to OceanBase.
|
|
46
|
+
(default: :obj:`"root@test"`)
|
|
47
|
+
password (str): Password for the user. (default: :obj:`""`)
|
|
48
|
+
db_name (str): Database name in OceanBase.
|
|
49
|
+
(default: :obj:`"test"`)
|
|
50
|
+
distance (Literal["l2", "cosine"], optional): The distance metric for
|
|
51
|
+
vector comparison. Options: "l2", "cosine". (default: :obj:`"l2"`)
|
|
52
|
+
delete_table_on_del (bool, optional): Flag to determine if the
|
|
53
|
+
table should be deleted upon object destruction.
|
|
54
|
+
(default: :obj:`False`)
|
|
55
|
+
**kwargs (Any): Additional keyword arguments for initializing
|
|
56
|
+
`ObVecClient`.
|
|
57
|
+
|
|
58
|
+
Raises:
|
|
59
|
+
ImportError: If `pyobvector` package is not installed.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
@dependencies_required('pyobvector')
|
|
63
|
+
def __init__(
|
|
64
|
+
self,
|
|
65
|
+
vector_dim: int,
|
|
66
|
+
table_name: str,
|
|
67
|
+
uri: str = "127.0.0.1:2881",
|
|
68
|
+
user: str = "root@test",
|
|
69
|
+
password: str = "",
|
|
70
|
+
db_name: str = "test",
|
|
71
|
+
distance: Literal["l2", "cosine"] = "l2",
|
|
72
|
+
delete_table_on_del: bool = False,
|
|
73
|
+
**kwargs: Any,
|
|
74
|
+
) -> None:
|
|
75
|
+
from pyobvector.client import (
|
|
76
|
+
ObVecClient,
|
|
77
|
+
)
|
|
78
|
+
from pyobvector.client.index_param import (
|
|
79
|
+
IndexParam,
|
|
80
|
+
IndexParams,
|
|
81
|
+
)
|
|
82
|
+
from pyobvector.schema import VECTOR
|
|
83
|
+
|
|
84
|
+
self.vector_dim: int = vector_dim
|
|
85
|
+
self.table_name: str = table_name
|
|
86
|
+
self.distance: Literal["l2", "cosine"] = distance
|
|
87
|
+
self.delete_table_on_del: bool = delete_table_on_del
|
|
88
|
+
|
|
89
|
+
# Create client
|
|
90
|
+
self._client: ObVecClient = ObVecClient(
|
|
91
|
+
uri=uri, user=user, password=password, db_name=db_name, **kwargs
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Map distance to distance function in OceanBase
|
|
95
|
+
self._distance_func_map: Dict[str, str] = {
|
|
96
|
+
"cosine": "cosine_distance",
|
|
97
|
+
"l2": "l2_distance",
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Check or create table with vector index
|
|
101
|
+
if not self._client.check_table_exists(self.table_name):
|
|
102
|
+
# Define table schema
|
|
103
|
+
columns: List[Column] = [
|
|
104
|
+
Column("id", Integer, primary_key=True, autoincrement=True),
|
|
105
|
+
Column("embedding", VECTOR(vector_dim)),
|
|
106
|
+
Column("metadata", JSON),
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
# Create table
|
|
110
|
+
self._client.create_table(
|
|
111
|
+
table_name=self.table_name, columns=columns
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Create vector index
|
|
115
|
+
index_params: IndexParams = IndexParams()
|
|
116
|
+
index_params.add_index_param(
|
|
117
|
+
IndexParam(
|
|
118
|
+
index_name="embedding_idx",
|
|
119
|
+
field_name="embedding",
|
|
120
|
+
distance=self.distance,
|
|
121
|
+
type="hnsw",
|
|
122
|
+
m=16,
|
|
123
|
+
ef_construction=256,
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
self._client.create_vidx_with_vec_index_param(
|
|
128
|
+
table_name=self.table_name, vidx_param=index_params.params[0]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
logger.info(f"Created table {self.table_name} with vector index")
|
|
132
|
+
else:
|
|
133
|
+
logger.info(f"Using existing table {self.table_name}")
|
|
134
|
+
|
|
135
|
+
def __del__(self):
|
|
136
|
+
r"""Deletes the table if :obj:`delete_table_on_del` is set to
|
|
137
|
+
:obj:`True`.
|
|
138
|
+
"""
|
|
139
|
+
if hasattr(self, "delete_table_on_del") and self.delete_table_on_del:
|
|
140
|
+
try:
|
|
141
|
+
self._client.drop_table_if_exist(self.table_name)
|
|
142
|
+
logger.info(f"Deleted table {self.table_name}")
|
|
143
|
+
except Exception as e:
|
|
144
|
+
logger.error(f"Failed to delete table {self.table_name}: {e}")
|
|
145
|
+
|
|
146
|
+
def add(
|
|
147
|
+
self,
|
|
148
|
+
records: List[VectorRecord],
|
|
149
|
+
batch_size: int = 100,
|
|
150
|
+
**kwargs: Any,
|
|
151
|
+
) -> None:
|
|
152
|
+
r"""Saves a list of vector records to the storage.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
records (List[VectorRecord]): List of vector records to be saved.
|
|
156
|
+
batch_size (int): Number of records to insert each batch.
|
|
157
|
+
Larger batches are more efficient but use more memory.
|
|
158
|
+
(default: :obj:`100`)
|
|
159
|
+
**kwargs (Any): Additional keyword arguments.
|
|
160
|
+
|
|
161
|
+
Raises:
|
|
162
|
+
RuntimeError: If there is an error during the saving process.
|
|
163
|
+
ValueError: If any vector dimension doesn't match vector_dim.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
if not records:
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
# Convert records to OceanBase format
|
|
171
|
+
data: List[Dict[str, Any]] = []
|
|
172
|
+
for i, record in enumerate(records):
|
|
173
|
+
# Validate vector dimensions
|
|
174
|
+
if len(record.vector) != self.vector_dim:
|
|
175
|
+
raise ValueError(
|
|
176
|
+
f"Vector at index {i} has dimension "
|
|
177
|
+
f"{len(record.vector)}, expected {self.vector_dim}"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
item: Dict[str, Any] = {
|
|
181
|
+
"embedding": record.vector,
|
|
182
|
+
"metadata": record.payload or {},
|
|
183
|
+
}
|
|
184
|
+
# If id is specified, use it
|
|
185
|
+
if record.id:
|
|
186
|
+
try:
|
|
187
|
+
# If id is numeric, use it directly
|
|
188
|
+
item["id"] = int(record.id)
|
|
189
|
+
except ValueError:
|
|
190
|
+
# If id is not numeric, store it in payload
|
|
191
|
+
item["metadata"]["_id"] = record.id
|
|
192
|
+
|
|
193
|
+
data.append(item)
|
|
194
|
+
|
|
195
|
+
# Batch insert when reaching batch_size
|
|
196
|
+
if len(data) >= batch_size:
|
|
197
|
+
self._client.insert(self.table_name, data=data)
|
|
198
|
+
data = []
|
|
199
|
+
|
|
200
|
+
# Insert any remaining records
|
|
201
|
+
if data:
|
|
202
|
+
self._client.insert(self.table_name, data=data)
|
|
203
|
+
|
|
204
|
+
except ValueError as e:
|
|
205
|
+
# Re-raise ValueError for dimension mismatch
|
|
206
|
+
raise e
|
|
207
|
+
except Exception as e:
|
|
208
|
+
error_msg = f"Failed to add records to OceanBase: {e}"
|
|
209
|
+
logger.error(error_msg)
|
|
210
|
+
raise RuntimeError(error_msg)
|
|
211
|
+
|
|
212
|
+
def delete(
|
|
213
|
+
self,
|
|
214
|
+
ids: List[str],
|
|
215
|
+
**kwargs: Any,
|
|
216
|
+
) -> None:
|
|
217
|
+
r"""Deletes a list of vectors identified by their IDs from the storage.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
ids (List[str]): List of unique identifiers for the vectors to
|
|
221
|
+
be deleted.
|
|
222
|
+
**kwargs (Any): Additional keyword arguments.
|
|
223
|
+
|
|
224
|
+
Raises:
|
|
225
|
+
RuntimeError: If there is an error during the deletion process.
|
|
226
|
+
"""
|
|
227
|
+
if not ids:
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
try:
|
|
231
|
+
numeric_ids: List[int] = []
|
|
232
|
+
non_numeric_ids: List[str] = []
|
|
233
|
+
|
|
234
|
+
# Separate numeric and non-numeric IDs
|
|
235
|
+
for id_val in ids:
|
|
236
|
+
try:
|
|
237
|
+
numeric_ids.append(int(id_val))
|
|
238
|
+
except ValueError:
|
|
239
|
+
non_numeric_ids.append(id_val)
|
|
240
|
+
|
|
241
|
+
# Delete records with numeric IDs
|
|
242
|
+
if numeric_ids:
|
|
243
|
+
self._client.delete(self.table_name, ids=numeric_ids)
|
|
244
|
+
|
|
245
|
+
# Delete records with non-numeric IDs stored in metadata
|
|
246
|
+
if non_numeric_ids:
|
|
247
|
+
from sqlalchemy import text
|
|
248
|
+
|
|
249
|
+
for id_val in non_numeric_ids:
|
|
250
|
+
self._client.delete(
|
|
251
|
+
self.table_name,
|
|
252
|
+
where_clause=[
|
|
253
|
+
text(f"metadata->>'$.._id' = '{id_val}'")
|
|
254
|
+
],
|
|
255
|
+
)
|
|
256
|
+
except Exception as e:
|
|
257
|
+
error_msg = f"Failed to delete records from OceanBase: {e}"
|
|
258
|
+
logger.error(error_msg)
|
|
259
|
+
raise RuntimeError(error_msg)
|
|
260
|
+
|
|
261
|
+
def status(self) -> VectorDBStatus:
|
|
262
|
+
r"""Returns status of the vector database.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
VectorDBStatus: The vector database status.
|
|
266
|
+
"""
|
|
267
|
+
try:
|
|
268
|
+
# Get count of records
|
|
269
|
+
result = self._client.perform_raw_text_sql(
|
|
270
|
+
f"SELECT COUNT(*) FROM {self.table_name}"
|
|
271
|
+
)
|
|
272
|
+
count: int = result.fetchone()[0]
|
|
273
|
+
|
|
274
|
+
return VectorDBStatus(
|
|
275
|
+
vector_dim=self.vector_dim, vector_count=count
|
|
276
|
+
)
|
|
277
|
+
except Exception as e:
|
|
278
|
+
error_msg = f"Failed to get status from OceanBase: {e}"
|
|
279
|
+
logger.error(error_msg)
|
|
280
|
+
raise RuntimeError(error_msg)
|
|
281
|
+
|
|
282
|
+
def query(
|
|
283
|
+
self,
|
|
284
|
+
query: VectorDBQuery,
|
|
285
|
+
**kwargs: Any,
|
|
286
|
+
) -> List[VectorDBQueryResult]:
|
|
287
|
+
r"""Searches for similar vectors in the storage based on the
|
|
288
|
+
provided query.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
query (VectorDBQuery): The query object containing the search
|
|
292
|
+
vector and the number of top similar vectors to retrieve.
|
|
293
|
+
**kwargs (Any): Additional keyword arguments.
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
List[VectorDBQueryResult]: A list of vectors retrieved from the
|
|
297
|
+
storage based on similarity to the query vector.
|
|
298
|
+
|
|
299
|
+
Raises:
|
|
300
|
+
RuntimeError: If there is an error during the query process.
|
|
301
|
+
ValueError: If the query vector dimension does not match the
|
|
302
|
+
storage dimension.
|
|
303
|
+
"""
|
|
304
|
+
from sqlalchemy import func
|
|
305
|
+
|
|
306
|
+
try:
|
|
307
|
+
# Get distance function name
|
|
308
|
+
distance_func_name: str = self._distance_func_map.get(
|
|
309
|
+
self.distance, "l2_distance"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
distance_func = getattr(func, distance_func_name)
|
|
313
|
+
|
|
314
|
+
# Validate query vector dimensions
|
|
315
|
+
if len(query.query_vector) != self.vector_dim:
|
|
316
|
+
raise ValueError(
|
|
317
|
+
f"Query vector dimension {len(query.query_vector)} "
|
|
318
|
+
f"does not match storage dimension {self.vector_dim}"
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
results = self._client.ann_search(
|
|
322
|
+
table_name=self.table_name,
|
|
323
|
+
vec_data=query.query_vector,
|
|
324
|
+
vec_column_name="embedding",
|
|
325
|
+
distance_func=distance_func,
|
|
326
|
+
with_dist=True,
|
|
327
|
+
topk=query.top_k,
|
|
328
|
+
output_column_names=["id", "embedding", "metadata"],
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
# Convert results to VectorDBQueryResult format
|
|
332
|
+
query_results: List[VectorDBQueryResult] = []
|
|
333
|
+
for row in results:
|
|
334
|
+
try:
|
|
335
|
+
result_dict: Dict[str, Any] = dict(row._mapping)
|
|
336
|
+
|
|
337
|
+
# Extract data
|
|
338
|
+
id_val: str = str(result_dict["id"])
|
|
339
|
+
|
|
340
|
+
# Handle vector - ensure it's a proper list of floats
|
|
341
|
+
vector: Any = result_dict.get("embedding")
|
|
342
|
+
if isinstance(vector, str):
|
|
343
|
+
# If vector is a string, try to parse it
|
|
344
|
+
try:
|
|
345
|
+
if vector.startswith('[') and vector.endswith(']'):
|
|
346
|
+
# Remove brackets and split by commas
|
|
347
|
+
vector = [
|
|
348
|
+
float(x.strip())
|
|
349
|
+
for x in vector[1:-1].split(',')
|
|
350
|
+
]
|
|
351
|
+
except (ValueError, TypeError) as e:
|
|
352
|
+
logger.warning(
|
|
353
|
+
f"Failed to parse vector string: {e}"
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
# Ensure we have a proper vector
|
|
357
|
+
if (
|
|
358
|
+
not isinstance(vector, list)
|
|
359
|
+
or len(vector) != self.vector_dim
|
|
360
|
+
):
|
|
361
|
+
logger.warning(
|
|
362
|
+
f"Invalid vector format, using zeros: {vector}"
|
|
363
|
+
)
|
|
364
|
+
vector = [0.0] * self.vector_dim
|
|
365
|
+
|
|
366
|
+
# Ensure metadata is a dictionary
|
|
367
|
+
metadata: Dict[str, Any] = result_dict.get("metadata", {})
|
|
368
|
+
if not isinstance(metadata, dict):
|
|
369
|
+
# Convert to dict if it's not already
|
|
370
|
+
try:
|
|
371
|
+
if isinstance(metadata, str):
|
|
372
|
+
metadata = json.loads(metadata)
|
|
373
|
+
else:
|
|
374
|
+
metadata = {"value": metadata}
|
|
375
|
+
except Exception:
|
|
376
|
+
metadata = {"value": str(metadata)}
|
|
377
|
+
|
|
378
|
+
distance_value: Optional[float] = None
|
|
379
|
+
for key in result_dict:
|
|
380
|
+
if (
|
|
381
|
+
key.endswith(distance_func_name)
|
|
382
|
+
or distance_func_name in key
|
|
383
|
+
):
|
|
384
|
+
distance_value = float(result_dict[key])
|
|
385
|
+
break
|
|
386
|
+
|
|
387
|
+
if distance_value is None:
|
|
388
|
+
# If we can't find the distance, use a default value
|
|
389
|
+
logger.warning(
|
|
390
|
+
"Could not find distance value in query results, "
|
|
391
|
+
"using default"
|
|
392
|
+
)
|
|
393
|
+
distance_value = 0.0
|
|
394
|
+
|
|
395
|
+
similarity: float = self._convert_distance_to_similarity(
|
|
396
|
+
distance_value
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
# Check if the id is stored in metadata
|
|
400
|
+
if isinstance(metadata, dict) and "_id" in metadata:
|
|
401
|
+
id_val = metadata.pop("_id")
|
|
402
|
+
|
|
403
|
+
# Create query result
|
|
404
|
+
query_results.append(
|
|
405
|
+
VectorDBQueryResult.create(
|
|
406
|
+
similarity=similarity,
|
|
407
|
+
vector=vector,
|
|
408
|
+
id=id_val,
|
|
409
|
+
payload=metadata,
|
|
410
|
+
)
|
|
411
|
+
)
|
|
412
|
+
except Exception as e:
|
|
413
|
+
logger.warning(f"Failed to process result row: {e}")
|
|
414
|
+
continue
|
|
415
|
+
|
|
416
|
+
return query_results
|
|
417
|
+
except Exception as e:
|
|
418
|
+
error_msg = f"Failed to query OceanBase: {e}"
|
|
419
|
+
logger.error(error_msg)
|
|
420
|
+
raise RuntimeError(error_msg)
|
|
421
|
+
|
|
422
|
+
def _convert_distance_to_similarity(self, distance: float) -> float:
|
|
423
|
+
r"""Converts distance to similarity score based on distance metric."""
|
|
424
|
+
# Ensure distance is non-negative
|
|
425
|
+
distance = max(0.0, distance)
|
|
426
|
+
|
|
427
|
+
if self.distance == "cosine":
|
|
428
|
+
# Cosine distance = 1 - cosine similarity
|
|
429
|
+
# Ensure similarity is between 0 and 1
|
|
430
|
+
return max(0.0, min(1.0, 1.0 - distance))
|
|
431
|
+
elif self.distance == "l2":
|
|
432
|
+
import math
|
|
433
|
+
|
|
434
|
+
# Exponential decay function for L2 distance
|
|
435
|
+
return math.exp(-distance)
|
|
436
|
+
else:
|
|
437
|
+
# Default normalization, ensure result is between 0 and 1
|
|
438
|
+
return max(0.0, min(1.0, 1.0 - min(1.0, distance)))
|
|
439
|
+
|
|
440
|
+
def clear(self) -> None:
|
|
441
|
+
r"""Remove all vectors from the storage."""
|
|
442
|
+
try:
|
|
443
|
+
self._client.delete(self.table_name)
|
|
444
|
+
logger.info(f"Cleared all records from table {self.table_name}")
|
|
445
|
+
except Exception as e:
|
|
446
|
+
error_msg = f"Failed to clear records from OceanBase: {e}"
|
|
447
|
+
logger.error(error_msg)
|
|
448
|
+
raise RuntimeError(error_msg)
|
|
449
|
+
|
|
450
|
+
def load(self) -> None:
|
|
451
|
+
r"""Load the collection hosted on cloud service."""
|
|
452
|
+
# OceanBase doesn't require explicit loading
|
|
453
|
+
pass
|
|
454
|
+
|
|
455
|
+
@property
|
|
456
|
+
def client(self) -> "ObVecClient":
|
|
457
|
+
r"""Provides access to underlying OceanBase vector database client."""
|
|
458
|
+
return self._client
|
camel/toolkits/__init__.py
CHANGED
|
@@ -64,8 +64,10 @@ from .terminal_toolkit import TerminalToolkit
|
|
|
64
64
|
from .pubmed_toolkit import PubMedToolkit
|
|
65
65
|
from .data_commons_toolkit import DataCommonsToolkit
|
|
66
66
|
from .thinking_toolkit import ThinkingToolkit
|
|
67
|
+
from .pyautogui_toolkit import PyAutoGUIToolkit
|
|
67
68
|
from .openai_agent_toolkit import OpenAIAgentToolkit
|
|
68
69
|
from .searxng_toolkit import SearxNGToolkit
|
|
70
|
+
from .jina_reranker_toolkit import JinaRerankerToolkit
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
__all__ = [
|
|
@@ -118,6 +120,8 @@ __all__ = [
|
|
|
118
120
|
'PubMedToolkit',
|
|
119
121
|
'DataCommonsToolkit',
|
|
120
122
|
'ThinkingToolkit',
|
|
123
|
+
'PyAutoGUIToolkit',
|
|
121
124
|
'OpenAIAgentToolkit',
|
|
122
125
|
'SearxNGToolkit',
|
|
126
|
+
'JinaRerankerToolkit',
|
|
123
127
|
]
|
|
@@ -301,9 +301,9 @@ def _add_set_of_mark(
|
|
|
301
301
|
|
|
302
302
|
Returns:
|
|
303
303
|
Tuple[Image.Image, List[str], List[str], List[str]]: A tuple
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
304
|
+
containing the screenshot with marked ROIs, ROIs fully within the
|
|
305
|
+
images, ROIs located above the visible area, and ROIs located below
|
|
306
|
+
the visible area.
|
|
307
307
|
"""
|
|
308
308
|
visible_rects: List[str] = list()
|
|
309
309
|
rects_above: List[str] = list() # Scroll up to see
|
|
@@ -1013,8 +1013,6 @@ class BrowserToolkit(BaseToolkit):
|
|
|
1013
1013
|
self.browser = BaseBrowser(
|
|
1014
1014
|
headless=headless, cache_dir=cache_dir, channel=channel
|
|
1015
1015
|
)
|
|
1016
|
-
# This needs to be called explicitly
|
|
1017
|
-
self.browser.init()
|
|
1018
1016
|
|
|
1019
1017
|
self.history_window = history_window
|
|
1020
1018
|
self.web_agent_model = web_agent_model
|
|
@@ -1037,7 +1035,7 @@ class BrowserToolkit(BaseToolkit):
|
|
|
1037
1035
|
if self.web_agent_model is None:
|
|
1038
1036
|
web_agent_model = ModelFactory.create(
|
|
1039
1037
|
model_platform=ModelPlatformType.OPENAI,
|
|
1040
|
-
model_type=ModelType.
|
|
1038
|
+
model_type=ModelType.GPT_4_1,
|
|
1041
1039
|
model_config_dict={"temperature": 0, "top_p": 1},
|
|
1042
1040
|
)
|
|
1043
1041
|
else:
|
|
@@ -1499,7 +1497,6 @@ Your output should be in json format, including the following fields:
|
|
|
1499
1497
|
else:
|
|
1500
1498
|
simulation_result = self._get_final_answer(task_prompt)
|
|
1501
1499
|
|
|
1502
|
-
self.browser.close()
|
|
1503
1500
|
return simulation_result
|
|
1504
1501
|
|
|
1505
1502
|
def get_tools(self) -> List[FunctionTool]:
|