camel-ai 0.2.25__py3-none-any.whl → 0.2.27__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 +4 -4
- camel/agents/knowledge_graph_agent.py +15 -3
- camel/configs/anthropic_config.py +0 -1
- camel/datasets/base.py +219 -17
- camel/environments/base.py +16 -8
- camel/extractors/__init__.py +2 -2
- camel/extractors/base.py +86 -64
- camel/extractors/python_strategies.py +226 -0
- camel/models/__init__.py +4 -0
- camel/models/anthropic_model.py +19 -55
- camel/models/azure_openai_model.py +88 -8
- camel/models/model_factory.py +3 -0
- camel/models/openai_compatible_model.py +88 -8
- camel/models/volcano_model.py +100 -0
- camel/py.typed +0 -0
- camel/storages/graph_storages/graph_element.py +3 -1
- camel/storages/graph_storages/neo4j_graph.py +78 -4
- camel/toolkits/__init__.py +4 -2
- camel/toolkits/{web_toolkit.py → browser_toolkit.py} +143 -76
- camel/toolkits/pubmed_toolkit.py +346 -0
- camel/toolkits/search_toolkit.py +63 -0
- camel/toolkits/terminal_toolkit.py +2 -2
- camel/types/enums.py +7 -0
- {camel_ai-0.2.25.dist-info → camel_ai-0.2.27.dist-info}/METADATA +2 -1
- {camel_ai-0.2.25.dist-info → camel_ai-0.2.27.dist-info}/RECORD +28 -24
- {camel_ai-0.2.25.dist-info → camel_ai-0.2.27.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.25.dist-info → camel_ai-0.2.27.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
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 os
|
|
16
|
+
from typing import Any, Dict, Optional, Union
|
|
17
|
+
|
|
18
|
+
from camel.configs import OPENAI_API_PARAMS
|
|
19
|
+
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
20
|
+
from camel.types import ModelType
|
|
21
|
+
from camel.utils import (
|
|
22
|
+
BaseTokenCounter,
|
|
23
|
+
OpenAITokenCounter,
|
|
24
|
+
api_keys_required,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class VolcanoModel(OpenAICompatibleModel):
|
|
29
|
+
r"""Volcano Engine API in a unified BaseModelBackend interface.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
model_type (Union[ModelType, str]): Model for which a backend is
|
|
33
|
+
created.
|
|
34
|
+
model_config_dict (Optional[Dict[str, Any]], optional): A dictionary
|
|
35
|
+
that will be fed into the API call. If
|
|
36
|
+
:obj:`None`, :obj:`{}` will be used. (default: :obj:`None`)
|
|
37
|
+
api_key (Optional[str], optional): The API key for authenticating with
|
|
38
|
+
the Volcano Engine service. (default: :obj:`None`)
|
|
39
|
+
url (Optional[str], optional): The url to the Volcano Engine service.
|
|
40
|
+
(default: :obj:`https://ark.cn-beijing.volces.com/api/v3`)
|
|
41
|
+
token_counter (Optional[BaseTokenCounter], optional): Token counter to
|
|
42
|
+
use for the model. If not provided, :obj:`OpenAITokenCounter`
|
|
43
|
+
will be used. (default: :obj:`None`)
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
@api_keys_required(
|
|
47
|
+
[
|
|
48
|
+
("api_key", "VOLCANO_API_KEY"),
|
|
49
|
+
]
|
|
50
|
+
)
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
model_type: Union[ModelType, str],
|
|
54
|
+
model_config_dict: Optional[Dict[str, Any]] = None,
|
|
55
|
+
api_key: Optional[str] = None,
|
|
56
|
+
url: Optional[str] = None,
|
|
57
|
+
token_counter: Optional[BaseTokenCounter] = None,
|
|
58
|
+
) -> None:
|
|
59
|
+
if model_config_dict is None:
|
|
60
|
+
model_config_dict = {}
|
|
61
|
+
|
|
62
|
+
api_key = api_key or os.environ.get("VOLCANO_API_KEY")
|
|
63
|
+
url = (
|
|
64
|
+
url
|
|
65
|
+
or os.environ.get("VOLCANO_API_BASE_URL")
|
|
66
|
+
or "https://ark.cn-beijing.volces.com/api/v3"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
super().__init__(
|
|
70
|
+
model_type, model_config_dict, api_key, url, token_counter
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def token_counter(self) -> BaseTokenCounter:
|
|
75
|
+
r"""Initialize the token counter for the model backend.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
BaseTokenCounter: The token counter following the model's
|
|
79
|
+
tokenization style.
|
|
80
|
+
"""
|
|
81
|
+
if not self._token_counter:
|
|
82
|
+
# Use OpenAI token counter as an approximation
|
|
83
|
+
self._token_counter = OpenAITokenCounter(ModelType.GPT_4O_MINI)
|
|
84
|
+
return self._token_counter
|
|
85
|
+
|
|
86
|
+
def check_model_config(self):
|
|
87
|
+
r"""Check whether the model configuration is valid for Volcano
|
|
88
|
+
model backends.
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
ValueError: If the model configuration dictionary contains any
|
|
92
|
+
unexpected arguments to Volcano API.
|
|
93
|
+
"""
|
|
94
|
+
# Using OpenAI API params as Volcano Engine API is OpenAI-compatible
|
|
95
|
+
for param in self.model_config_dict:
|
|
96
|
+
if param not in OPENAI_API_PARAMS:
|
|
97
|
+
raise ValueError(
|
|
98
|
+
f"Unexpected argument `{param}` is "
|
|
99
|
+
"input into Volcano model backend."
|
|
100
|
+
)
|
camel/py.typed
ADDED
|
File without changes
|
|
@@ -13,7 +13,7 @@
|
|
|
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 List, Optional, Union
|
|
17
17
|
|
|
18
18
|
from pydantic import BaseModel, ConfigDict, Field
|
|
19
19
|
|
|
@@ -45,6 +45,7 @@ class Relationship(BaseModel):
|
|
|
45
45
|
subj (Node): The subject/source node of the relationship.
|
|
46
46
|
obj (Node): The object/target node of the relationship.
|
|
47
47
|
type (str): The type of the relationship.
|
|
48
|
+
timestamp (str, optional): The timestamp of the relationship.
|
|
48
49
|
properties (dict): Additional properties associated with the
|
|
49
50
|
relationship.
|
|
50
51
|
"""
|
|
@@ -52,6 +53,7 @@ class Relationship(BaseModel):
|
|
|
52
53
|
subj: Node
|
|
53
54
|
obj: Node
|
|
54
55
|
type: str = "Relationship"
|
|
56
|
+
timestamp: Optional[str] = None
|
|
55
57
|
properties: dict = Field(default_factory=dict)
|
|
56
58
|
|
|
57
59
|
|
|
@@ -339,18 +339,24 @@ class Neo4jGraph(BaseGraphStorage):
|
|
|
339
339
|
]
|
|
340
340
|
)
|
|
341
341
|
|
|
342
|
-
def add_triplet(
|
|
343
|
-
|
|
342
|
+
def add_triplet(
|
|
343
|
+
self, subj: str, obj: str, rel: str, timestamp: Optional[str] = None
|
|
344
|
+
) -> None:
|
|
345
|
+
r"""Adds a relationship (triplet) between two entities
|
|
346
|
+
in the database with a timestamp.
|
|
344
347
|
|
|
345
348
|
Args:
|
|
346
349
|
subj (str): The identifier for the subject entity.
|
|
347
350
|
obj (str): The identifier for the object entity.
|
|
348
351
|
rel (str): The relationship between the subject and object.
|
|
352
|
+
timestamp (Optional[str]): The timestamp of the relationship.
|
|
353
|
+
Defaults to None.
|
|
349
354
|
"""
|
|
350
355
|
query = """
|
|
351
356
|
MERGE (n1:`%s` {id:$subj})
|
|
352
357
|
MERGE (n2:`%s` {id:$obj})
|
|
353
|
-
MERGE (n1)-[:`%s`]->(n2)
|
|
358
|
+
MERGE (n1)-[r:`%s`]->(n2)
|
|
359
|
+
SET r.timestamp = $timestamp
|
|
354
360
|
"""
|
|
355
361
|
|
|
356
362
|
prepared_statement = query % (
|
|
@@ -361,7 +367,10 @@ class Neo4jGraph(BaseGraphStorage):
|
|
|
361
367
|
|
|
362
368
|
# Execute the query within a database session
|
|
363
369
|
with self.driver.session(database=self.database) as session:
|
|
364
|
-
session.run(
|
|
370
|
+
session.run(
|
|
371
|
+
prepared_statement,
|
|
372
|
+
{"subj": subj, "obj": obj, "timestamp": timestamp},
|
|
373
|
+
)
|
|
365
374
|
|
|
366
375
|
def _delete_rel(self, subj: str, obj: str, rel: str) -> None:
|
|
367
376
|
r"""Deletes a specific relationship between two nodes in the Neo4j
|
|
@@ -721,3 +730,68 @@ class Neo4jGraph(BaseGraphStorage):
|
|
|
721
730
|
return result[0] if result else {}
|
|
722
731
|
except CypherSyntaxError as e:
|
|
723
732
|
raise ValueError(f"Generated Cypher Statement is not valid\n{e}")
|
|
733
|
+
|
|
734
|
+
def get_triplet(
|
|
735
|
+
self,
|
|
736
|
+
subj: Optional[str] = None,
|
|
737
|
+
obj: Optional[str] = None,
|
|
738
|
+
rel: Optional[str] = None,
|
|
739
|
+
) -> List[Dict[str, Any]]:
|
|
740
|
+
r"""
|
|
741
|
+
Query triplet information. If subj, obj, or rel is
|
|
742
|
+
not specified, returns all matching triplets.
|
|
743
|
+
|
|
744
|
+
Args:
|
|
745
|
+
subj (Optional[str]): The ID of the subject node.
|
|
746
|
+
If None, matches any subject node.
|
|
747
|
+
obj (Optional[str]): The ID of the object node.
|
|
748
|
+
If None, matches any object node.
|
|
749
|
+
rel (Optional[str]): The type of relationship.
|
|
750
|
+
If None, matches any relationship type.
|
|
751
|
+
|
|
752
|
+
Returns:
|
|
753
|
+
List[Dict[str, Any]]: A list of matching triplets,
|
|
754
|
+
each containing subj, obj, rel, and timestamp.
|
|
755
|
+
"""
|
|
756
|
+
import logging
|
|
757
|
+
|
|
758
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
759
|
+
logger = logging.getLogger(__name__)
|
|
760
|
+
|
|
761
|
+
# Construct the query
|
|
762
|
+
query = """
|
|
763
|
+
MATCH (n1:Entity)-[r]->(n2:Entity)
|
|
764
|
+
WHERE ($subj IS NULL OR n1.id = $subj)
|
|
765
|
+
AND ($obj IS NULL OR n2.id = $obj)
|
|
766
|
+
AND ($rel IS NULL OR type(r) = $rel)
|
|
767
|
+
RETURN n1.id AS subj, n2.id AS obj,
|
|
768
|
+
type(r) AS rel, r.timestamp AS timestamp
|
|
769
|
+
"""
|
|
770
|
+
|
|
771
|
+
# Construct the query parameters
|
|
772
|
+
params = {
|
|
773
|
+
"subj": subj
|
|
774
|
+
if subj is not None
|
|
775
|
+
else None, # If subj is None, match any subject node
|
|
776
|
+
"obj": obj
|
|
777
|
+
if obj is not None
|
|
778
|
+
else None, # If obj is None, match any object node
|
|
779
|
+
"rel": rel
|
|
780
|
+
if rel is not None
|
|
781
|
+
else None, # If rel is None, match any relationship type
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
logger.debug(f"Executing query: {query}")
|
|
785
|
+
logger.debug(f"Query parameters: {params}")
|
|
786
|
+
|
|
787
|
+
with self.driver.session(database=self.database) as session:
|
|
788
|
+
try:
|
|
789
|
+
result = session.run(query, params)
|
|
790
|
+
records = [record.data() for record in result]
|
|
791
|
+
logger.debug(
|
|
792
|
+
f"Query returned {len(records)} records: {records}"
|
|
793
|
+
)
|
|
794
|
+
return records
|
|
795
|
+
except Exception as e:
|
|
796
|
+
logger.error(f"Error executing query: {e}")
|
|
797
|
+
return []
|
camel/toolkits/__init__.py
CHANGED
|
@@ -55,9 +55,10 @@ from .excel_toolkit import ExcelToolkit
|
|
|
55
55
|
from .video_analysis_toolkit import VideoAnalysisToolkit
|
|
56
56
|
from .image_analysis_toolkit import ImageAnalysisToolkit
|
|
57
57
|
from .mcp_toolkit import MCPToolkit
|
|
58
|
-
from .
|
|
58
|
+
from .browser_toolkit import BrowserToolkit
|
|
59
59
|
from .file_write_toolkit import FileWriteToolkit
|
|
60
60
|
from .terminal_toolkit import TerminalToolkit
|
|
61
|
+
from .pubmed_toolkit import PubMedToolkit
|
|
61
62
|
|
|
62
63
|
|
|
63
64
|
__all__ = [
|
|
@@ -101,7 +102,8 @@ __all__ = [
|
|
|
101
102
|
'ExcelToolkit',
|
|
102
103
|
'VideoAnalysisToolkit',
|
|
103
104
|
'ImageAnalysisToolkit',
|
|
104
|
-
'
|
|
105
|
+
'BrowserToolkit',
|
|
105
106
|
'FileWriteToolkit',
|
|
106
107
|
'TerminalToolkit',
|
|
108
|
+
'PubMedToolkit',
|
|
107
109
|
]
|