camel-ai 0.1.1__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 (75) hide show
  1. camel/__init__.py +30 -0
  2. camel/agents/__init__.py +40 -0
  3. camel/agents/base.py +29 -0
  4. camel/agents/chat_agent.py +539 -0
  5. camel/agents/critic_agent.py +179 -0
  6. camel/agents/embodied_agent.py +138 -0
  7. camel/agents/role_assignment_agent.py +117 -0
  8. camel/agents/task_agent.py +382 -0
  9. camel/agents/tool_agents/__init__.py +20 -0
  10. camel/agents/tool_agents/base.py +40 -0
  11. camel/agents/tool_agents/hugging_face_tool_agent.py +203 -0
  12. camel/configs.py +159 -0
  13. camel/embeddings/__init__.py +20 -0
  14. camel/embeddings/base.py +65 -0
  15. camel/embeddings/openai_embedding.py +74 -0
  16. camel/functions/__init__.py +27 -0
  17. camel/functions/base_io_functions.py +261 -0
  18. camel/functions/math_functions.py +61 -0
  19. camel/functions/openai_function.py +88 -0
  20. camel/functions/search_functions.py +309 -0
  21. camel/functions/unstructured_io_fuctions.py +616 -0
  22. camel/functions/weather_functions.py +136 -0
  23. camel/generators.py +263 -0
  24. camel/human.py +130 -0
  25. camel/memories/__init__.py +28 -0
  26. camel/memories/base.py +75 -0
  27. camel/memories/chat_history_memory.py +111 -0
  28. camel/memories/context_creators/__init__.py +18 -0
  29. camel/memories/context_creators/base.py +72 -0
  30. camel/memories/context_creators/score_based.py +130 -0
  31. camel/memories/records.py +92 -0
  32. camel/messages/__init__.py +38 -0
  33. camel/messages/base.py +223 -0
  34. camel/messages/func_message.py +106 -0
  35. camel/models/__init__.py +26 -0
  36. camel/models/base_model.py +110 -0
  37. camel/models/model_factory.py +59 -0
  38. camel/models/open_source_model.py +144 -0
  39. camel/models/openai_model.py +103 -0
  40. camel/models/stub_model.py +106 -0
  41. camel/prompts/__init__.py +38 -0
  42. camel/prompts/ai_society.py +121 -0
  43. camel/prompts/base.py +227 -0
  44. camel/prompts/code.py +111 -0
  45. camel/prompts/evaluation.py +40 -0
  46. camel/prompts/misalignment.py +84 -0
  47. camel/prompts/prompt_templates.py +117 -0
  48. camel/prompts/role_description_prompt_template.py +53 -0
  49. camel/prompts/solution_extraction.py +44 -0
  50. camel/prompts/task_prompt_template.py +56 -0
  51. camel/prompts/translation.py +42 -0
  52. camel/responses/__init__.py +18 -0
  53. camel/responses/agent_responses.py +42 -0
  54. camel/societies/__init__.py +20 -0
  55. camel/societies/babyagi_playing.py +254 -0
  56. camel/societies/role_playing.py +456 -0
  57. camel/storages/__init__.py +23 -0
  58. camel/storages/key_value_storages/__init__.py +23 -0
  59. camel/storages/key_value_storages/base.py +57 -0
  60. camel/storages/key_value_storages/in_memory.py +51 -0
  61. camel/storages/key_value_storages/json.py +97 -0
  62. camel/terminators/__init__.py +23 -0
  63. camel/terminators/base.py +44 -0
  64. camel/terminators/response_terminator.py +118 -0
  65. camel/terminators/token_limit_terminator.py +55 -0
  66. camel/types/__init__.py +54 -0
  67. camel/types/enums.py +176 -0
  68. camel/types/openai_types.py +39 -0
  69. camel/utils/__init__.py +47 -0
  70. camel/utils/commons.py +243 -0
  71. camel/utils/python_interpreter.py +435 -0
  72. camel/utils/token_counting.py +220 -0
  73. camel_ai-0.1.1.dist-info/METADATA +311 -0
  74. camel_ai-0.1.1.dist-info/RECORD +75 -0
  75. camel_ai-0.1.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,88 @@
1
+ # =========== Copyright 2023 @ 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 @ CAMEL-AI.org. All Rights Reserved. ===========
14
+ from typing import Any, Callable, Dict, Optional
15
+
16
+ from jsonschema.validators import Draft202012Validator as JSONValidator
17
+
18
+ from camel.utils import parse_doc
19
+
20
+
21
+ class OpenAIFunction:
22
+ r"""An abstraction of a function that OpenAI chat models can call. See
23
+ https://platform.openai.com/docs/guides/gpt/function-calling. If
24
+ :obj:`description` and :obj:`parameters` are both :obj:`None`, try to use
25
+ document parser to generate them.
26
+
27
+ # flake8: noqa :E501
28
+ Args:
29
+ func (Callable): The function to call.
30
+ name (str, optional): The name of the function to be called. Must be
31
+ a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum
32
+ length of 64. If :obj:`None`, use the name of :obj:`func`.
33
+ (default: :obj:`None`)
34
+ description (str, optional): The description of what the
35
+ function does. (default: :obj:`None`)
36
+ parameters (dict, optional): The parameters the
37
+ functions accepts, described as a JSON Schema object. See the
38
+ `Function calling guide <https://platform.openai.com/docs/guides/gpt/function-calling>`_
39
+ for examples, and the `JSON Schema reference <https://json-schema.org/understanding-json-schema/>`_
40
+ for documentation about the format.
41
+ """
42
+
43
+ def __init__(self, func: Callable, name: Optional[str] = None,
44
+ description: Optional[str] = None,
45
+ parameters: Optional[Dict[str, Any]] = None):
46
+ self.func = func
47
+ self.name = name or func.__name__
48
+
49
+ info = parse_doc(self.func)
50
+ self.description = description or info["description"]
51
+ self.parameters = parameters or info["parameters"]
52
+
53
+ @property
54
+ def parameters(self) -> Dict[str, Any]:
55
+ r"""Getter method for the property :obj:`parameters`.
56
+
57
+ Returns:
58
+ Dict[str, Any]: the dictionary containing information of
59
+ parameters of this function.
60
+ """
61
+ return self._parameters
62
+
63
+ @parameters.setter
64
+ def parameters(self, value: Dict[str, Any]):
65
+ r"""Setter method for the property :obj:`parameters`. It will
66
+ firstly check if the input parameters schema is valid. If invalid,
67
+ the method will raise :obj:`jsonschema.exceptions.SchemaError`.
68
+
69
+ Args:
70
+ value (Dict[str, Any]): the new dictionary value for the
71
+ function's parameters.
72
+ """
73
+ JSONValidator.check_schema(value)
74
+ self._parameters = value
75
+
76
+ def as_dict(self) -> Dict[str, Any]:
77
+ r"""Method to represent the information of this function into
78
+ a dictionary object.
79
+
80
+ Returns:
81
+ Dict[str, Any]: The dictionary object containing information
82
+ of this function's name, description and parameters.
83
+ """
84
+ return {
85
+ attr: getattr(self, attr)
86
+ for attr in ["name", "description", "parameters"]
87
+ if getattr(self, attr) is not None
88
+ }
@@ -0,0 +1,309 @@
1
+ # =========== Copyright 2023 @ 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 @ CAMEL-AI.org. All Rights Reserved. ===========
14
+ import os
15
+ from typing import Any, Dict, List
16
+
17
+ import camel.agents
18
+ from camel.functions import OpenAIFunction
19
+ from camel.messages import BaseMessage
20
+ from camel.prompts import TextPrompt
21
+
22
+
23
+ def search_wiki(entity: str) -> str:
24
+ r"""Search the entity in WikiPedia and return the summary of the
25
+ required page, containing factual information about the given entity.
26
+
27
+ Args:
28
+ entity (string): The entity to be searched.
29
+
30
+ Returns:
31
+ string: The search result. If the page corresponding to the entity
32
+ exists, return the summary of this entity in a string.
33
+ """
34
+ try:
35
+ import wikipedia
36
+ except ImportError:
37
+ raise ImportError(
38
+ "Please install `wikipedia` first. You can install it by running "
39
+ "`pip install wikipedia`.")
40
+
41
+ result: str
42
+
43
+ try:
44
+ result = wikipedia.summary(entity, sentences=5, auto_suggest=False)
45
+ except wikipedia.exceptions.DisambiguationError as e:
46
+ result = wikipedia.summary(e.options[0], sentences=5,
47
+ auto_suggest=False)
48
+ except wikipedia.exceptions.PageError:
49
+ result = ("There is no page in Wikipedia corresponding to entity "
50
+ f"{entity}, please specify another word to describe the"
51
+ " entity to be searched.")
52
+ except wikipedia.exceptions.WikipediaException as e:
53
+ result = f"An exception occurred during the search: {e}"
54
+
55
+ return result
56
+
57
+
58
+ def search_google(query: str) -> List[Dict[str, Any]]:
59
+ r"""Use Google search engine to search information for the given query.
60
+
61
+ Args:
62
+ query (string): The query to be searched.
63
+
64
+ Returns:
65
+ List[Dict[str, Any]]: A list of dictionaries where each dictionary
66
+ represents a website.
67
+ Each dictionary contains the following keys:
68
+ - 'result_id': A number in order.
69
+ - 'title': The title of the website.
70
+ - 'description': A brief description of the website.
71
+ - 'long_description': More detail of the website.
72
+ - 'url': The URL of the website.
73
+
74
+ Example:
75
+ {
76
+ 'result_id': 1,
77
+ 'title': 'OpenAI',
78
+ 'description': 'An organization focused on ensuring that
79
+ artificial general intelligence benefits all of humanity.',
80
+ 'long_description': 'OpenAI is a non-profit artificial
81
+ intelligence research company. Our goal is to advance digital
82
+ intelligence in the way that is most likely to benefit humanity
83
+ as a whole',
84
+ 'url': 'https://www.openai.com'
85
+ }
86
+ title, descrption, url of a website.
87
+ """
88
+ import requests
89
+
90
+ # https://developers.google.com/custom-search/v1/overview
91
+ GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
92
+ # https://cse.google.com/cse/all
93
+ SEARCH_ENGINE_ID = os.getenv("SEARCH_ENGINE_ID")
94
+
95
+ # Using the first page
96
+ start_page_idx = 1
97
+ # Different language may get different result
98
+ search_language = "en"
99
+ # How many pages to return
100
+ num_result_pages = 10
101
+ # Constructing the URL
102
+ # Doc: https://developers.google.com/custom-search/v1/using_rest
103
+ url = f"https://www.googleapis.com/customsearch/v1?" \
104
+ f"key={GOOGLE_API_KEY}&cx={SEARCH_ENGINE_ID}&q={query}&start=" \
105
+ f"{start_page_idx}&lr={search_language}&num={num_result_pages}"
106
+
107
+ responses = []
108
+ # Fetch the results given the URL
109
+ try:
110
+ # Make the get
111
+ result = requests.get(url)
112
+ data = result.json()
113
+
114
+ # Get the result items
115
+ if "items" in data:
116
+ search_items = data.get("items")
117
+
118
+ # Iterate over 10 results found
119
+ for i, search_item in enumerate(search_items, start=1):
120
+ if "og:description" in search_item["pagemap"]["metatags"][0]:
121
+ long_description = \
122
+ search_item["pagemap"]["metatags"][0]["og:description"]
123
+ else:
124
+ long_description = "N/A"
125
+ # Get the page title
126
+ title = search_item.get("title")
127
+ # Page snippet
128
+ snippet = search_item.get("snippet")
129
+
130
+ # Extract the page url
131
+ link = search_item.get("link")
132
+ response = {
133
+ "result_id": i,
134
+ "title": title,
135
+ "description": snippet,
136
+ "long_description": long_description,
137
+ "url": link
138
+ }
139
+ responses.append(response)
140
+ else:
141
+ responses.append({"error": "google search failed."})
142
+
143
+ except requests.RequestException:
144
+ responses.append({"error": "google search failed."})
145
+
146
+ return responses
147
+
148
+
149
+ def text_extract_from_web(url: str) -> str:
150
+ r"""Get the text information from given url.
151
+
152
+ Args:
153
+ url (string): The web site you want to search.
154
+
155
+ Returns:
156
+ string: All texts extract from the web.
157
+ """
158
+ import requests
159
+ from bs4 import BeautifulSoup
160
+
161
+ try:
162
+ # Request the target page
163
+ response_text = requests.get(url).text
164
+
165
+ # Parse the obtained page
166
+ soup = BeautifulSoup(response_text, features="html.parser")
167
+
168
+ for script in soup(["script", "style"]):
169
+ script.extract()
170
+
171
+ text = soup.get_text()
172
+ # Strip text
173
+ lines = (line.strip() for line in text.splitlines())
174
+ chunks = (phrase.strip() for line in lines
175
+ for phrase in line.split(" "))
176
+ text = ".".join(chunk for chunk in chunks if chunk)
177
+
178
+ except requests.RequestException:
179
+ text = f"can't access {url}"
180
+
181
+ return text
182
+
183
+
184
+ # Split a text into smaller chunks of size n
185
+ def create_chunks(text: str, n: int) -> List[str]:
186
+ r"""Returns successive n-sized chunks from provided text."
187
+
188
+ Args:
189
+ text (string): The text to be split.
190
+ n (int): The max length of a single chunk.
191
+
192
+ Returns:
193
+ List[str]: A list of splited texts.
194
+ """
195
+
196
+ chunks = []
197
+ i = 0
198
+ while i < len(text):
199
+ # Find the nearest end of sentence within a range of 0.5 * n
200
+ # and 1.5 * n tokens
201
+ j = min(i + int(1.2 * n), len(text))
202
+ while j > i + int(0.8 * n):
203
+ # Decode the tokens and check for full stop or newline
204
+ chunk = text[i:j]
205
+ if chunk.endswith(".") or chunk.endswith("\n"):
206
+ break
207
+ j -= 1
208
+ # If no end of sentence found, use n tokens as the chunk size
209
+ if j == i + int(0.8 * n):
210
+ j = min(i + n, len(text))
211
+ chunks.append(text[i:j])
212
+ i = j
213
+ return chunks
214
+
215
+
216
+ def prompt_single_step_agent(prompt: str) -> str:
217
+ """Prompt a single-step agent to summarize texts or answer a question."""
218
+
219
+ assistant_sys_msg = BaseMessage.make_assistant_message(
220
+ role_name="Assistant",
221
+ content="You are a helpful assistant.",
222
+ )
223
+ agent = camel.agents.ChatAgent(assistant_sys_msg)
224
+ agent.reset()
225
+
226
+ user_msg = BaseMessage.make_user_message(
227
+ role_name="User",
228
+ content=prompt,
229
+ )
230
+ assistant_response = agent.step(user_msg)
231
+ if assistant_response.msgs is not None:
232
+ return assistant_response.msg.content
233
+ return ""
234
+
235
+
236
+ def summarize_text(text: str, query: str) -> str:
237
+ r"""Summarize the information from the text, base on the query if query is
238
+ given.
239
+
240
+ Args:
241
+ text (string): Text to summarise.
242
+ query (string): What information you want.
243
+
244
+ Returns:
245
+ string: Strings with information.
246
+ """
247
+ summary_prompt = TextPrompt(
248
+ '''Gather information from this text that relative to the question, but
249
+ do not directly answer the question.\nquestion: {query}\ntext ''')
250
+ summary_prompt = summary_prompt.format(query=query)
251
+ # Max length of each chunk
252
+ max_len = 3000
253
+ results = ""
254
+ chunks = create_chunks(text, max_len)
255
+ # Summarize
256
+ for i, chunk in enumerate(chunks, start=1):
257
+ prompt = summary_prompt + str(i) + ": " + chunk
258
+ result = prompt_single_step_agent(prompt)
259
+ results += result + "\n"
260
+
261
+ # Final summarise
262
+ final_prompt = TextPrompt(
263
+ '''Here are some summarized texts which split from one text, Using the
264
+ information to answer the question: {query}.\n\nText: ''')
265
+ final_prompt = final_prompt.format(query=query)
266
+ prompt = final_prompt + results
267
+
268
+ response = prompt_single_step_agent(prompt)
269
+
270
+ return response
271
+
272
+
273
+ def search_google_and_summarize(query: str) -> str:
274
+ r"""Search webs for information. Given a query, this function will use
275
+ the Google search engine to search for related information from the
276
+ internet, and then return a summarized answer.
277
+
278
+ Args:
279
+ query (string): Question you want to be answered.
280
+
281
+ Returns:
282
+ string: Summarized information from webs.
283
+ """
284
+ # Google search will return a list of urls
285
+ responses = search_google(query)
286
+ for item in responses:
287
+ if "url" in item:
288
+ url = item.get("url")
289
+ # Extract text
290
+ text = text_extract_from_web(str(url))
291
+ # Using chatgpt summarise text
292
+ answer = summarize_text(text, query)
293
+
294
+ # Let chatgpt decide whether to continue search or not
295
+ prompt = TextPrompt(
296
+ '''Do you think the answer: {answer} can answer the query:
297
+ {query}. Use only 'yes' or 'no' to answer.''')
298
+ prompt = prompt.format(answer=answer, query=query)
299
+ reply = prompt_single_step_agent(prompt)
300
+ if "yes" in str(reply).lower():
301
+ return answer
302
+
303
+ return "Failed to find the answer from google search."
304
+
305
+
306
+ SEARCH_FUNCS: List[OpenAIFunction] = [
307
+ OpenAIFunction(func)
308
+ for func in [search_wiki, search_google_and_summarize]
309
+ ]