camel-ai 0.2.14__py3-none-any.whl → 0.2.16__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 (69) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +362 -237
  3. camel/benchmarks/__init__.py +11 -1
  4. camel/benchmarks/apibank.py +560 -0
  5. camel/benchmarks/apibench.py +496 -0
  6. camel/benchmarks/gaia.py +2 -2
  7. camel/benchmarks/nexus.py +518 -0
  8. camel/datagen/__init__.py +21 -0
  9. camel/datagen/cotdatagen.py +448 -0
  10. camel/datagen/self_instruct/__init__.py +36 -0
  11. camel/datagen/self_instruct/filter/__init__.py +34 -0
  12. camel/datagen/self_instruct/filter/filter_function.py +216 -0
  13. camel/datagen/self_instruct/filter/filter_registry.py +56 -0
  14. camel/datagen/self_instruct/filter/instruction_filter.py +81 -0
  15. camel/datagen/self_instruct/self_instruct.py +393 -0
  16. camel/datagen/self_instruct/templates.py +384 -0
  17. camel/datahubs/huggingface.py +12 -2
  18. camel/datahubs/models.py +4 -2
  19. camel/embeddings/mistral_embedding.py +5 -1
  20. camel/embeddings/openai_compatible_embedding.py +6 -1
  21. camel/embeddings/openai_embedding.py +5 -1
  22. camel/interpreters/e2b_interpreter.py +5 -1
  23. camel/loaders/apify_reader.py +5 -1
  24. camel/loaders/chunkr_reader.py +5 -1
  25. camel/loaders/firecrawl_reader.py +0 -30
  26. camel/logger.py +11 -5
  27. camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +4 -1
  28. camel/models/anthropic_model.py +5 -1
  29. camel/models/azure_openai_model.py +1 -2
  30. camel/models/cohere_model.py +5 -1
  31. camel/models/deepseek_model.py +5 -1
  32. camel/models/gemini_model.py +5 -1
  33. camel/models/groq_model.py +5 -1
  34. camel/models/mistral_model.py +5 -1
  35. camel/models/nemotron_model.py +5 -1
  36. camel/models/nvidia_model.py +5 -1
  37. camel/models/openai_model.py +5 -1
  38. camel/models/qwen_model.py +5 -1
  39. camel/models/reka_model.py +5 -1
  40. camel/models/reward/nemotron_model.py +5 -1
  41. camel/models/samba_model.py +5 -1
  42. camel/models/togetherai_model.py +5 -1
  43. camel/models/yi_model.py +5 -1
  44. camel/models/zhipuai_model.py +5 -1
  45. camel/retrievers/auto_retriever.py +8 -0
  46. camel/retrievers/vector_retriever.py +6 -3
  47. camel/schemas/openai_converter.py +5 -1
  48. camel/societies/role_playing.py +4 -4
  49. camel/societies/workforce/workforce.py +2 -2
  50. camel/storages/graph_storages/nebula_graph.py +119 -27
  51. camel/storages/graph_storages/neo4j_graph.py +138 -0
  52. camel/toolkits/__init__.py +4 -0
  53. camel/toolkits/arxiv_toolkit.py +20 -3
  54. camel/toolkits/dappier_toolkit.py +196 -0
  55. camel/toolkits/function_tool.py +61 -61
  56. camel/toolkits/meshy_toolkit.py +5 -1
  57. camel/toolkits/notion_toolkit.py +1 -1
  58. camel/toolkits/openbb_toolkit.py +869 -0
  59. camel/toolkits/search_toolkit.py +91 -5
  60. camel/toolkits/stripe_toolkit.py +5 -1
  61. camel/toolkits/twitter_toolkit.py +24 -16
  62. camel/types/enums.py +7 -1
  63. camel/types/unified_model_type.py +5 -0
  64. camel/utils/__init__.py +4 -0
  65. camel/utils/commons.py +142 -20
  66. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/METADATA +17 -5
  67. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/RECORD +69 -55
  68. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/LICENSE +0 -0
  69. {camel_ai-0.2.14.dist-info → camel_ai-0.2.16.dist-info}/WHEEL +0 -0
@@ -583,3 +583,141 @@ class Neo4jGraph(BaseGraphStorage):
583
583
  ]
584
584
  },
585
585
  )
586
+
587
+ def random_walk_with_restarts(
588
+ self,
589
+ graph_name: str,
590
+ sampling_ratio: float,
591
+ start_node_ids: List[int],
592
+ restart_probability: float = 0.1,
593
+ node_label_stratification: bool = False,
594
+ relationship_weight_property: Optional[str] = None,
595
+ ) -> Dict[str, Any]:
596
+ r"""Runs the Random Walk with Restarts (RWR) sampling algorithm.
597
+
598
+ Args:
599
+ graph_name (str): The name of the original graph in the graph
600
+ catalog.
601
+ sampling_ratio (float): The fraction of nodes in the original
602
+ graph to be sampled.
603
+ start_node_ids (List[int]): IDs of the initial set of nodes of the
604
+ original graph from which the sampling random walks will start.
605
+ restart_probability (float, optional): The probability that a
606
+ sampling random walk restarts from one of the start nodes.
607
+ Defaults to `0.1`.
608
+ node_label_stratification (bool, optional): If true, preserves the
609
+ node label distribution of the original graph. Defaults to
610
+ `False`.
611
+ relationship_weight_property (Optional[str], optional): Name of
612
+ the relationship property to use as weights. If unspecified,
613
+ the algorithm runs unweighted. Defaults to `None`.
614
+
615
+ Returns:
616
+ Dict[str, Any]: A dictionary with the results of the RWR sampling.
617
+ """
618
+ from neo4j.exceptions import ClientError, CypherSyntaxError
619
+
620
+ try:
621
+ self.query(query="CALL gds.version() YIELD version RETURN version")
622
+ except ClientError:
623
+ raise ValueError(
624
+ "Graph Data Science (GDS) library is not installed or not"
625
+ " available. Reference: https://neo4j.com/docs/graph-data-science/current/installation/"
626
+ )
627
+
628
+ query = """
629
+ CALL gds.graph.sample.rwr($graphName, $fromGraphName, {
630
+ samplingRatio: $samplingRatio,
631
+ startNodes: $startNodes,
632
+ restartProbability: $restartProbability,
633
+ nodeLabelStratification: $nodeLabelStratification,
634
+ relationshipWeightProperty: $relationshipWeightProperty
635
+ })
636
+ YIELD graphName, fromGraphName, nodeCount,
637
+ relationshipCount, startNodeCount, projectMillis
638
+ RETURN graphName, fromGraphName, nodeCount,
639
+ relationshipCount, startNodeCount, projectMillis
640
+ """
641
+
642
+ params = {
643
+ "graphName": f"{graph_name}_sampled",
644
+ "fromGraphName": graph_name,
645
+ "samplingRatio": sampling_ratio,
646
+ "startNodes": start_node_ids,
647
+ "restartProbability": restart_probability,
648
+ "nodeLabelStratification": node_label_stratification,
649
+ "relationshipWeightProperty": relationship_weight_property,
650
+ }
651
+
652
+ try:
653
+ result = self.query(query, params)
654
+ return result[0] if result else {}
655
+ except CypherSyntaxError as e:
656
+ raise ValueError(f"Generated Cypher Statement is not valid\n{e}")
657
+
658
+ def common_neighbour_aware_random_walk(
659
+ self,
660
+ graph_name: str,
661
+ sampling_ratio: float,
662
+ start_node_ids: List[int],
663
+ node_label_stratification: bool = False,
664
+ relationship_weight_property: Optional[str] = None,
665
+ ) -> Dict[str, Any]:
666
+ r"""Runs the Common Neighbour Aware Random Walk (CNARW) sampling
667
+ algorithm.
668
+
669
+ Args:
670
+ graph_name (str): The name of the original graph in the graph
671
+ catalog.
672
+ sampling_ratio (float): The fraction of nodes in the original
673
+ graph to be sampled.
674
+ start_node_ids (List[int]): IDs of the initial set of nodes of the
675
+ original graph from which the sampling random walks will start.
676
+ node_label_stratification (bool, optional): If true, preserves the
677
+ node label distribution of the original graph. Defaults to
678
+ `False`.
679
+ relationship_weight_property (Optional[str], optional): Name of
680
+ the relationship property to use as weights. If unspecified,
681
+ the algorithm runs unweighted. Defaults to `None`.
682
+
683
+ Returns:
684
+ Dict[str, Any]: A dictionary with the results of the CNARW
685
+ sampling.
686
+ """
687
+ from neo4j.exceptions import ClientError, CypherSyntaxError
688
+
689
+ try:
690
+ self.query(query="CALL gds.version() YIELD version RETURN version")
691
+ except ClientError:
692
+ raise ValueError(
693
+ "Graph Data Science (GDS) library is not installed or not"
694
+ " available. Reference: https://neo4j.com/docs/graph-data-science/current/installation/"
695
+ )
696
+
697
+ query = """
698
+ CALL gds.graph.sample.cnarw($graphName, $fromGraphName, {
699
+ samplingRatio: $samplingRatio,
700
+ startNodes: $startNodes,
701
+ nodeLabelStratification: $nodeLabelStratification,
702
+ relationshipWeightProperty: $relationshipWeightProperty
703
+ })
704
+ YIELD graphName, fromGraphName, nodeCount,
705
+ relationshipCount, startNodeCount, projectMillis
706
+ RETURN graphName, fromGraphName, nodeCount,
707
+ relationshipCount, startNodeCount, projectMillis
708
+ """
709
+
710
+ params = {
711
+ "graphName": f"{graph_name}_sampled_cnarw",
712
+ "fromGraphName": graph_name,
713
+ "samplingRatio": sampling_ratio,
714
+ "startNodes": start_node_ids,
715
+ "nodeLabelStratification": node_label_stratification,
716
+ "relationshipWeightProperty": relationship_weight_property,
717
+ }
718
+
719
+ try:
720
+ result = self.query(query, params)
721
+ return result[0] if result else {}
722
+ except CypherSyntaxError as e:
723
+ raise ValueError(f"Generated Cypher Statement is not valid\n{e}")
@@ -28,6 +28,7 @@ from .ask_news_toolkit import AskNewsToolkit, AsyncAskNewsToolkit
28
28
  from .linkedin_toolkit import LinkedInToolkit
29
29
  from .reddit_toolkit import RedditToolkit
30
30
  from .meshy_toolkit import MeshyToolkit
31
+ from .openbb_toolkit import OpenBBToolkit
31
32
 
32
33
  from .base import BaseToolkit
33
34
  from .google_maps_toolkit import GoogleMapsToolkit
@@ -43,6 +44,7 @@ from .notion_toolkit import NotionToolkit
43
44
  from .human_toolkit import HumanToolkit
44
45
  from .stripe_toolkit import StripeToolkit
45
46
  from .video_toolkit import VideoDownloaderToolkit
47
+ from .dappier_toolkit import DappierToolkit
46
48
 
47
49
  __all__ = [
48
50
  'BaseToolkit',
@@ -73,4 +75,6 @@ __all__ = [
73
75
  'VideoDownloaderToolkit',
74
76
  'StripeToolkit',
75
77
  'MeshyToolkit',
78
+ 'OpenBBToolkit',
79
+ 'DappierToolkit',
76
80
  ]
@@ -14,10 +14,13 @@
14
14
 
15
15
  from typing import Dict, Generator, List, Optional
16
16
 
17
+ from camel.logger import get_logger
17
18
  from camel.toolkits.base import BaseToolkit
18
19
  from camel.toolkits.function_tool import FunctionTool
19
20
  from camel.utils import dependencies_required
20
21
 
22
+ logger = get_logger(__name__)
23
+
21
24
 
22
25
  class ArxivToolkit(BaseToolkit):
23
26
  r"""A toolkit for interacting with the arXiv API to search and download
@@ -98,10 +101,24 @@ class ArxivToolkit(BaseToolkit):
98
101
  "authors": [author.name for author in paper.authors],
99
102
  "entry_id": paper.entry_id,
100
103
  "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
+ "pdf_url": paper.pdf_url,
104
105
  }
106
+
107
+ # Extract text from the paper
108
+ try:
109
+ # TODO: Use chunkr instead of atxiv_to_text for better
110
+ # performance and reliability
111
+ text = arxiv_to_text(paper_info["pdf_url"])
112
+ except Exception as e:
113
+ logger.error(
114
+ "Failed to extract text content from the PDF at "
115
+ "the specified URL. "
116
+ f"URL: {paper_info.get('pdf_url', 'Unknown')} | Error: {e}"
117
+ )
118
+ text = ""
119
+
120
+ paper_info['paper_text'] = text
121
+
105
122
  papers_data.append(paper_info)
106
123
 
107
124
  return papers_data
@@ -0,0 +1,196 @@
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 typing import Dict, List, Literal, Optional, Union
16
+
17
+ from camel.toolkits.base import BaseToolkit
18
+ from camel.toolkits.function_tool import FunctionTool
19
+ from camel.utils import api_keys_required, dependencies_required
20
+
21
+
22
+ class DappierToolkit(BaseToolkit):
23
+ r"""A class representing a toolkit for interacting with the Dappier API.
24
+
25
+ This class provides methods for searching real time data and fetching
26
+ ai recommendations across key verticals like News, Finance, Stock Market,
27
+ Sports, Weather and more.
28
+ """
29
+
30
+ @dependencies_required("dappier")
31
+ @api_keys_required(
32
+ [
33
+ (None, "DAPPIER_API_KEY"),
34
+ ]
35
+ )
36
+ def __init__(self):
37
+ r"""Initialize the DappierTookit with API clients.The API keys and
38
+ credentials are retrieved from environment variables.
39
+ """
40
+ from dappier import Dappier
41
+
42
+ dappier_api_key = os.environ.get("DAPPIER_API_KEY")
43
+
44
+ self.dappier_client = Dappier(dappier_api_key)
45
+
46
+ def search_real_time_data(
47
+ self, query: str, ai_model_id: str = "am_01j06ytn18ejftedz6dyhz2b15"
48
+ ) -> str:
49
+ r"""Search real-time data using an AI model.
50
+
51
+ This function accesses real-time information using the specified
52
+ AI model based on the given query. Depending on the AI model ID,
53
+ the data retrieved can vary between general web search results or
54
+ financial news and stock prices.
55
+
56
+ Supported AI Models:
57
+ - `am_01j06ytn18ejftedz6dyhz2b15`:
58
+ Access real-time Google web search results, including the latest
59
+ news, weather updates, travel details, deals, and more.
60
+ - `am_01j749h8pbf7ns8r1bq9s2evrh`:
61
+ Access real-time financial news, stock prices, and trades from
62
+ polygon.io, with AI-powered insights and up-to-the-minute updates.
63
+
64
+ Args:
65
+ query (str): The user-provided query. Examples include:
66
+ - "How is the weather today in Austin, TX?"
67
+ - "What is the latest news for Meta?"
68
+ - "What is the stock price for AAPL?"
69
+ ai_model_id (str, optional): The AI model ID to use for the query.
70
+ The AI model ID always starts with the prefix "am_".
71
+ (default: `am_01j06ytn18ejftedz6dyhz2b15`)
72
+
73
+ Returns:
74
+ str: The search result corresponding to the provided query and
75
+ AI model ID. This may include real time search data,
76
+ depending on the selected AI model.
77
+
78
+ Note:
79
+ Multiple AI model IDs are available, which can be found at:
80
+ https://marketplace.dappier.com/marketplace
81
+ """
82
+ try:
83
+ response = self.dappier_client.search_real_time_data(
84
+ query=query, ai_model_id=ai_model_id
85
+ )
86
+
87
+ if response is None:
88
+ return "An unknown error occurred"
89
+
90
+ return response.message
91
+
92
+ except Exception as e:
93
+ return f"An unexpected error occurred: {e}"
94
+
95
+ def get_ai_recommendations(
96
+ self,
97
+ query: str,
98
+ data_model_id: str = "dm_01j0pb465keqmatq9k83dthx34",
99
+ similarity_top_k: int = 9,
100
+ ref: Optional[str] = None,
101
+ num_articles_ref: int = 0,
102
+ search_algorithm: Literal[
103
+ "most_recent", "semantic", "most_recent_semantic", "trending"
104
+ ] = "most_recent",
105
+ ) -> Union[List[Dict[str, str]], Dict[str, str]]:
106
+ r"""Retrieve AI-powered recommendations based on the provided query
107
+ and data model.
108
+
109
+ This function fetches real-time AI-generated recommendations using the
110
+ specified data model and search algorithm. The results include
111
+ personalized content based on the query and, optionally, relevance
112
+ to a specific reference domain.
113
+
114
+ Supported Data Models:
115
+ - `dm_01j0pb465keqmatq9k83dthx34`:
116
+ Real-time news, updates, and personalized content from top sports
117
+ sources such as Sportsnaut, Forever Blueshirts, Minnesota Sports
118
+ Fan, LAFB Network, Bounding Into Sports, and Ringside Intel.
119
+ - `dm_01j0q82s4bfjmsqkhs3ywm3x6y`:
120
+ Real-time updates, analysis, and personalized content from top
121
+ sources like The Mix, Snipdaily, Nerdable, and Familyproof.
122
+
123
+ Args:
124
+ query (str): The user query for retrieving recommendations.
125
+ data_model_id (str, optional): The data model ID to use for
126
+ recommendations. Data model IDs always start with the prefix
127
+ "dm_". (default: :obj: `dm_01j0pb465keqmatq9k83dthx34`)
128
+ similarity_top_k (int, optional): The number of top documents to
129
+ retrieve based on similarity. (default: :obj: `9`)
130
+ ref (Optional[str], optional): The site domain where AI
131
+ recommendations should be displayed. (default: :obj: `None`)
132
+ num_articles_ref (int, optional): The minimum number of articles
133
+ to return from the specified reference domain (`ref`). The
134
+ remaining articles will come from other sites in the RAG
135
+ model. (default: :obj: `0`)
136
+ search_algorithm (Literal[
137
+ "most_recent",
138
+ "semantic",
139
+ "most_recent_semantic",
140
+ "trending",
141
+ ], optional): The search algorithm to use for retrieving
142
+ articles. (default: :obj: `most_recent`)
143
+
144
+ Returns:
145
+ List[Dict[str, str]]: A list of recommended articles or content
146
+ based on the specified parameters, query, and data model.
147
+
148
+ Note:
149
+ Multiple data model IDs are available and can be found at:
150
+ https://marketplace.dappier.com/marketplace
151
+ """
152
+ try:
153
+ response = self.dappier_client.get_ai_recommendations(
154
+ query=query,
155
+ data_model_id=data_model_id,
156
+ similarity_top_k=similarity_top_k,
157
+ ref=ref,
158
+ num_articles_ref=num_articles_ref,
159
+ search_algorithm=search_algorithm,
160
+ )
161
+
162
+ if response is None or response.status != "success":
163
+ return {"error": "An unknown error occurred."}
164
+
165
+ # Collect only relevant information from the response.
166
+ results = [
167
+ {
168
+ "author": result.author,
169
+ "image_url": result.image_url,
170
+ "pubdate": result.pubdate,
171
+ "source_url": result.source_url,
172
+ "summary": result.summary,
173
+ "title": result.title,
174
+ }
175
+ for result in (
176
+ getattr(response.response, "results", None) or []
177
+ )
178
+ ]
179
+
180
+ return results
181
+
182
+ except Exception as e:
183
+ return {"error": f"An unexpected error occurred: {e!s}"}
184
+
185
+ def get_tools(self) -> List[FunctionTool]:
186
+ r"""Returns a list of FunctionTool objects representing the functions
187
+ in the toolkit.
188
+
189
+ Returns:
190
+ List[FunctionTool]: A list of FunctionTool objects representing
191
+ the functions in the toolkit.
192
+ """
193
+ return [
194
+ FunctionTool(self.search_real_time_data),
195
+ FunctionTool(self.get_ai_recommendations),
196
+ ]
@@ -14,6 +14,7 @@
14
14
  import ast
15
15
  import inspect
16
16
  import logging
17
+ import textwrap
17
18
  import warnings
18
19
  from inspect import Parameter, getsource, signature
19
20
  from typing import Any, Callable, Dict, Mapping, Optional, Tuple, Type
@@ -24,7 +25,6 @@ from jsonschema.validators import Draft202012Validator as JSONValidator
24
25
  from pydantic import BaseModel, create_model
25
26
  from pydantic.fields import FieldInfo
26
27
 
27
- from camel.agents import ChatAgent
28
28
  from camel.models import BaseModelBackend, ModelFactory
29
29
  from camel.types import ModelPlatformType, ModelType
30
30
  from camel.utils import get_pydantic_object_schema, to_pascal
@@ -237,41 +237,43 @@ def generate_docstring(
237
237
  Returns:
238
238
  str: The generated docstring.
239
239
  """
240
- # Create the docstring prompt
241
- docstring_prompt = '''
242
- **Role**: Generate professional Python docstrings conforming to
243
- PEP 8/PEP 257.
244
240
 
245
- **Requirements**:
246
- - Use appropriate format: reST, Google, or NumPy, as needed.
247
- - Include parameters, return values, and exceptions.
248
- - Reference any existing docstring in the function and
249
- retain useful information.
241
+ from camel.agents import ChatAgent
250
242
 
251
- **Input**: Python function.
243
+ # Create the docstring prompt
244
+ docstring_prompt = textwrap.dedent(
245
+ """\
246
+ **Role**: Generate professional Python docstrings conforming to PEP 8/PEP 257.
252
247
 
253
- **Output**: Docstring content (plain text, no code markers).
248
+ **Requirements**:
249
+ - Use appropriate format: reST, Google, or NumPy, as needed.
250
+ - Include parameters, return values, and exceptions.
251
+ - Reference any existing docstring in the function and retain useful information.
254
252
 
255
- **Example:**
253
+ **Input**: Python function.
256
254
 
257
- Input:
258
- ```python
259
- def add(a: int, b: int) -> int:
260
- return a + b
261
- ```
255
+ **Output**: Docstring content (plain text, no code markers).
262
256
 
263
- Output:
264
- Adds two numbers.
265
- Args:
266
- a (int): The first number.
267
- b (int): The second number.
257
+ **Example:**
268
258
 
269
- Returns:
270
- int: The sum of the two numbers.
259
+ Input:
260
+ ```python
261
+ def add(a: int, b: int) -> int:
262
+ return a + b
263
+ ```
271
264
 
272
- **Task**: Generate a docstring for the function below.
265
+ Output:
266
+ Adds two numbers.
267
+ Args:
268
+ a (int): The first number.
269
+ b (int): The second number.
270
+
271
+ Returns:
272
+ int: The sum of the two numbers.
273
273
 
274
- '''
274
+ **Task**: Generate a docstring for the function below.
275
+ """ # noqa: E501
276
+ )
275
277
  # Initialize assistant with system message and model
276
278
  assistant_sys_msg = "You are a helpful assistant."
277
279
  docstring_assistant = ChatAgent(assistant_sys_msg, model=model)
@@ -665,7 +667,7 @@ class FunctionTool:
665
667
  Any: Synthesized output from the function execution. If no
666
668
  synthesis model is provided, a warning is logged.
667
669
  """
668
- import textwrap
670
+ from camel.agents import ChatAgent
669
671
 
670
672
  # Retrieve the function source code
671
673
  function_string = inspect.getsource(self.func)
@@ -694,39 +696,37 @@ class FunctionTool:
694
696
  function_string += f"\nkwargs:\n{kwargs}"
695
697
 
696
698
  # Define the assistant system message
697
- assistant_sys_msg = '''
698
- **Role:** AI Assistant specialized in synthesizing tool execution outputs
699
- without actual execution.
700
-
701
- **Capabilities:**
702
- - Analyzes function to understand their
703
- purpose and expected outputs.
704
- - Generates synthetic outputs based on the function logic.
705
- - Ensures the synthesized output is contextually accurate and aligns with the
706
- function's intended behavior.
707
-
708
- **Instructions:**
709
- 1. **Input:** Provide the function code, function docstring, args, and kwargs.
710
- 2. **Output:** Synthesize the expected output of the function based on the
711
- provided args and kwargs.
712
-
713
- **Example:**
714
- - **User Input:**
715
- def sum(a, b, c=0):
716
- """Adds three numbers together."""
717
- return a + b + c
718
-
719
- - **Input Arguments:**
720
- args: (1, 2)
721
- kwargs: {"c": 3}
722
-
723
- - **Output:**
724
- 6
725
-
726
- **Note:**
727
- - Just return the synthesized output of the function without any explanation.
728
- - The output should be in plain text without any formatting.
729
- '''
699
+ assistant_sys_msg = textwrap.dedent(
700
+ '''\
701
+ **Role:** AI Assistant specialized in synthesizing tool execution outputs without actual execution.
702
+
703
+ **Capabilities:**
704
+ - Analyzes function to understand their purpose and expected outputs.
705
+ - Generates synthetic outputs based on the function logic.
706
+ - Ensures the synthesized output is contextually accurate and aligns with the function's intended behavior.
707
+
708
+ **Instructions:**
709
+ 1. **Input:** Provide the function code, function docstring, args, and kwargs.
710
+ 2. **Output:** Synthesize the expected output of the function based on the provided args and kwargs.
711
+
712
+ **Example:**
713
+ - **User Input:**
714
+ def sum(a, b, c=0):
715
+ """Adds three numbers together."""
716
+ return a + b + c
717
+
718
+ - **Input Arguments:**
719
+ args: (1, 2)
720
+ kwargs: {"c": 3}
721
+
722
+ - **Output:**
723
+ 6
724
+
725
+ **Note:**
726
+ - Just return the synthesized output of the function without any explanation.
727
+ - The output should be in plain text without any formatting.
728
+ ''' # noqa: E501
729
+ )
730
730
 
731
731
  # Initialize the synthesis agent
732
732
  synthesis_agent = ChatAgent(
@@ -33,7 +33,11 @@ class MeshyToolkit(BaseToolkit):
33
33
  https://docs.meshy.ai/api-text-to-3d-beta#create-a-text-to-3d-preview-task
34
34
  """
35
35
 
36
- @api_keys_required("MESHY_API_KEY")
36
+ @api_keys_required(
37
+ [
38
+ (None, 'MESHY_API_KEY'),
39
+ ]
40
+ )
37
41
  def __init__(self):
38
42
  r"""Initializes the MeshyToolkit with the API key from the
39
43
  environment.
@@ -71,7 +71,7 @@ class NotionToolkit(BaseToolkit):
71
71
 
72
72
  Attributes:
73
73
  notion_token (Optional[str], optional): The notion_token used to
74
- interact with notion APIs.(default: :obj:`None`)
74
+ interact with notion APIs. (default: :obj:`None`)
75
75
  notion_client (module): The notion module for interacting with
76
76
  the notion APIs.
77
77
  """