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.

@@ -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(self, subj: str, obj: str, rel: str) -> None:
343
- r"""Adds a relationship (triplet) between two entities in the database.
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(prepared_statement, {"subj": subj, "obj": obj})
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 []
@@ -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 .web_toolkit import WebToolkit
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
- 'WebToolkit',
105
+ 'BrowserToolkit',
105
106
  'FileWriteToolkit',
106
107
  'TerminalToolkit',
108
+ 'PubMedToolkit',
107
109
  ]