camel-ai 0.1.3__py3-none-any.whl → 0.1.4__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/__init__.py +2 -0
- camel/agents/chat_agent.py +40 -53
- camel/agents/knowledge_graph_agent.py +221 -0
- camel/configs/__init__.py +29 -0
- camel/configs/anthropic_config.py +73 -0
- camel/configs/base_config.py +22 -0
- camel/configs/openai_config.py +132 -0
- camel/embeddings/openai_embedding.py +7 -2
- camel/functions/__init__.py +13 -8
- camel/functions/open_api_function.py +380 -0
- camel/functions/open_api_specs/coursera/__init__.py +13 -0
- camel/functions/open_api_specs/coursera/openapi.yaml +82 -0
- camel/functions/open_api_specs/klarna/__init__.py +13 -0
- camel/functions/open_api_specs/klarna/openapi.yaml +87 -0
- camel/functions/open_api_specs/speak/__init__.py +13 -0
- camel/functions/open_api_specs/speak/openapi.yaml +151 -0
- camel/functions/openai_function.py +3 -1
- camel/functions/retrieval_functions.py +61 -0
- camel/functions/slack_functions.py +275 -0
- camel/models/__init__.py +2 -0
- camel/models/anthropic_model.py +16 -2
- camel/models/base_model.py +8 -2
- camel/models/model_factory.py +7 -3
- camel/models/openai_audio_models.py +251 -0
- camel/models/openai_model.py +12 -4
- camel/models/stub_model.py +5 -1
- camel/retrievers/__init__.py +2 -0
- camel/retrievers/auto_retriever.py +47 -36
- camel/retrievers/base.py +42 -37
- camel/retrievers/bm25_retriever.py +10 -19
- camel/retrievers/cohere_rerank_retriever.py +108 -0
- camel/retrievers/vector_retriever.py +43 -26
- camel/storages/vectordb_storages/qdrant.py +3 -1
- camel/toolkits/__init__.py +21 -0
- camel/toolkits/base.py +22 -0
- camel/toolkits/github_toolkit.py +245 -0
- camel/types/__init__.py +6 -0
- camel/types/enums.py +44 -3
- camel/utils/__init__.py +4 -2
- camel/utils/commons.py +97 -173
- {camel_ai-0.1.3.dist-info → camel_ai-0.1.4.dist-info}/METADATA +9 -3
- {camel_ai-0.1.3.dist-info → camel_ai-0.1.4.dist-info}/RECORD +44 -26
- camel/configs.py +0 -271
- {camel_ai-0.1.3.dist-info → camel_ai-0.1.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
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. ===========
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
openapi: 3.0.1
|
|
3
|
+
info:
|
|
4
|
+
version: v0
|
|
5
|
+
title: Open AI Klarna product Api
|
|
6
|
+
description: Search and compare prices from thousands of online shops. Only available in the US.
|
|
7
|
+
servers:
|
|
8
|
+
- url: https://www.klarna.com/us/shopping
|
|
9
|
+
tags:
|
|
10
|
+
- name: open-ai-product-endpoint
|
|
11
|
+
description: Open AI Product Endpoint. Query for products.
|
|
12
|
+
paths:
|
|
13
|
+
"/public/openai/v0/products":
|
|
14
|
+
get:
|
|
15
|
+
tags:
|
|
16
|
+
- open-ai-product-endpoint
|
|
17
|
+
summary: API for fetching Klarna product information
|
|
18
|
+
operationId: productsUsingGET
|
|
19
|
+
parameters:
|
|
20
|
+
- name: q
|
|
21
|
+
in: query
|
|
22
|
+
description: A precise query that matches one very small category or product
|
|
23
|
+
that needs to be searched for to find the products the user is looking for.
|
|
24
|
+
If the user explicitly stated what they want, use that as a query. The query
|
|
25
|
+
is as specific as possible to the product name or category mentioned by
|
|
26
|
+
the user in its singular form, and don't contain any clarifiers like latest,
|
|
27
|
+
newest, cheapest, budget, premium, expensive or similar. The query is always
|
|
28
|
+
taken from the latest topic, if there is a new topic a new query is started.
|
|
29
|
+
required: true
|
|
30
|
+
schema:
|
|
31
|
+
type: string
|
|
32
|
+
- name: size
|
|
33
|
+
in: query
|
|
34
|
+
description: number of products returned
|
|
35
|
+
required: false
|
|
36
|
+
schema:
|
|
37
|
+
type: integer
|
|
38
|
+
- name: min_price
|
|
39
|
+
in: query
|
|
40
|
+
description: "(Optional) Minimum price in local currency for the product searched
|
|
41
|
+
for. Either explicitly stated by the user or implicitly inferred from a
|
|
42
|
+
combination of the user's request and the kind of product searched for."
|
|
43
|
+
required: false
|
|
44
|
+
schema:
|
|
45
|
+
type: integer
|
|
46
|
+
- name: max_price
|
|
47
|
+
in: query
|
|
48
|
+
description: "(Optional) Maximum price in local currency for the product searched
|
|
49
|
+
for. Either explicitly stated by the user or implicitly inferred from a
|
|
50
|
+
combination of the user's request and the kind of product searched for."
|
|
51
|
+
required: false
|
|
52
|
+
schema:
|
|
53
|
+
type: integer
|
|
54
|
+
responses:
|
|
55
|
+
'200':
|
|
56
|
+
description: Products found
|
|
57
|
+
content:
|
|
58
|
+
application/json:
|
|
59
|
+
schema:
|
|
60
|
+
"$ref": "#/components/schemas/ProductResponse"
|
|
61
|
+
'503':
|
|
62
|
+
description: one or more services are unavailable
|
|
63
|
+
deprecated: false
|
|
64
|
+
components:
|
|
65
|
+
schemas:
|
|
66
|
+
Product:
|
|
67
|
+
type: object
|
|
68
|
+
properties:
|
|
69
|
+
attributes:
|
|
70
|
+
type: array
|
|
71
|
+
items:
|
|
72
|
+
type: string
|
|
73
|
+
name:
|
|
74
|
+
type: string
|
|
75
|
+
price:
|
|
76
|
+
type: string
|
|
77
|
+
url:
|
|
78
|
+
type: string
|
|
79
|
+
title: Product
|
|
80
|
+
ProductResponse:
|
|
81
|
+
type: object
|
|
82
|
+
properties:
|
|
83
|
+
products:
|
|
84
|
+
type: array
|
|
85
|
+
items:
|
|
86
|
+
"$ref": "#/components/schemas/Product"
|
|
87
|
+
title: ProductResponse
|
|
@@ -0,0 +1,13 @@
|
|
|
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. ===========
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
openapi: 3.0.1
|
|
2
|
+
info:
|
|
3
|
+
title: Speak
|
|
4
|
+
description: Learn how to say anything in another language with Speak, your AI-powered language tutor.
|
|
5
|
+
version: 'v1'
|
|
6
|
+
servers:
|
|
7
|
+
- url: https://api.speak.com
|
|
8
|
+
paths:
|
|
9
|
+
/v1/public/openai/translate:
|
|
10
|
+
post:
|
|
11
|
+
operationId: translate
|
|
12
|
+
summary: Translate and explain how to say a specific phrase or word in another language.
|
|
13
|
+
requestBody:
|
|
14
|
+
required: true
|
|
15
|
+
content:
|
|
16
|
+
application/json:
|
|
17
|
+
schema:
|
|
18
|
+
$ref: '#/components/schemas/translateRequest'
|
|
19
|
+
responses:
|
|
20
|
+
"200":
|
|
21
|
+
description: OK
|
|
22
|
+
content:
|
|
23
|
+
application/json:
|
|
24
|
+
schema:
|
|
25
|
+
$ref: '#/components/schemas/translateResponse'
|
|
26
|
+
/v1/public/openai/explain-phrase:
|
|
27
|
+
post:
|
|
28
|
+
operationId: explainPhrase
|
|
29
|
+
summary: Explain the meaning and usage of a specific foreign language phrase that the user is asking about.
|
|
30
|
+
requestBody:
|
|
31
|
+
required: true
|
|
32
|
+
content:
|
|
33
|
+
application/json:
|
|
34
|
+
schema:
|
|
35
|
+
$ref: '#/components/schemas/explainPhraseRequest'
|
|
36
|
+
responses:
|
|
37
|
+
"200":
|
|
38
|
+
description: OK
|
|
39
|
+
content:
|
|
40
|
+
application/json:
|
|
41
|
+
schema:
|
|
42
|
+
$ref: '#/components/schemas/explainPhraseResponse'
|
|
43
|
+
/v1/public/openai/explain-task:
|
|
44
|
+
post:
|
|
45
|
+
operationId: explainTask
|
|
46
|
+
summary: Explain the best way to say or do something in a specific situation or context with a foreign language. Use this endpoint when the user asks more general or high-level questions.
|
|
47
|
+
requestBody:
|
|
48
|
+
required: true
|
|
49
|
+
content:
|
|
50
|
+
application/json:
|
|
51
|
+
schema:
|
|
52
|
+
$ref: '#/components/schemas/explainTaskRequest'
|
|
53
|
+
responses:
|
|
54
|
+
"200":
|
|
55
|
+
description: OK
|
|
56
|
+
content:
|
|
57
|
+
application/json:
|
|
58
|
+
schema:
|
|
59
|
+
$ref: '#/components/schemas/explainTaskResponse'
|
|
60
|
+
components:
|
|
61
|
+
schemas:
|
|
62
|
+
translateRequest:
|
|
63
|
+
type: object
|
|
64
|
+
required:
|
|
65
|
+
- phrase_to_translate
|
|
66
|
+
- learning_language
|
|
67
|
+
- native_language
|
|
68
|
+
- additional_context
|
|
69
|
+
- full_query
|
|
70
|
+
properties:
|
|
71
|
+
phrase_to_translate:
|
|
72
|
+
type: string
|
|
73
|
+
description: Phrase or concept to translate into the foreign language and explain further.
|
|
74
|
+
learning_language:
|
|
75
|
+
type: string
|
|
76
|
+
description: The foreign language that the user is learning and asking about. Always use the full name of the language (e.g. Spanish, French).
|
|
77
|
+
native_language:
|
|
78
|
+
type: string
|
|
79
|
+
description: The user's native language. Infer this value from the language the user asked their question in. Always use the full name of the language (e.g. Spanish, French).
|
|
80
|
+
additional_context:
|
|
81
|
+
type: string
|
|
82
|
+
description: A description of any additional context in the user's question that could affect the explanation - e.g. setting, scenario, situation, tone, speaking style and formality, usage notes, or any other qualifiers.
|
|
83
|
+
full_query:
|
|
84
|
+
type: string
|
|
85
|
+
description: Full text of the user's question.
|
|
86
|
+
translateResponse:
|
|
87
|
+
type: object
|
|
88
|
+
properties:
|
|
89
|
+
explanation:
|
|
90
|
+
type: string
|
|
91
|
+
description: An explanation of how to say the input phrase in the foreign language.
|
|
92
|
+
explainPhraseRequest:
|
|
93
|
+
type: object
|
|
94
|
+
required:
|
|
95
|
+
- foreign_phrase
|
|
96
|
+
- learning_language
|
|
97
|
+
- native_language
|
|
98
|
+
- additional_context
|
|
99
|
+
- full_query
|
|
100
|
+
properties:
|
|
101
|
+
foreign_phrase:
|
|
102
|
+
type: string
|
|
103
|
+
description: Foreign language phrase or word that the user wants an explanation for.
|
|
104
|
+
learning_language:
|
|
105
|
+
type: string
|
|
106
|
+
description: The language that the user is asking their language question about. The value can be inferred from question - e.g. for "Somebody said no mames to me, what does that mean", the value should be "Spanish" because "no mames" is a Spanish phrase. Always use the full name of the language (e.g. Spanish, French).
|
|
107
|
+
native_language:
|
|
108
|
+
type: string
|
|
109
|
+
description: The user's native language. Infer this value from the language the user asked their question in. Always use the full name of the language (e.g. Spanish, French).
|
|
110
|
+
additional_context:
|
|
111
|
+
type: string
|
|
112
|
+
description: A description of any additional context in the user's question that could affect the explanation - e.g. setting, scenario, situation, tone, speaking style and formality, usage notes, or any other qualifiers.
|
|
113
|
+
full_query:
|
|
114
|
+
type: string
|
|
115
|
+
description: Full text of the user's question.
|
|
116
|
+
explainPhraseResponse:
|
|
117
|
+
type: object
|
|
118
|
+
properties:
|
|
119
|
+
explanation:
|
|
120
|
+
type: string
|
|
121
|
+
description: An explanation of what the foreign language phrase means, and when you might use it.
|
|
122
|
+
explainTaskRequest:
|
|
123
|
+
type: object
|
|
124
|
+
required:
|
|
125
|
+
- task_description
|
|
126
|
+
- learning_language
|
|
127
|
+
- native_language
|
|
128
|
+
- additional_context
|
|
129
|
+
- full_query
|
|
130
|
+
properties:
|
|
131
|
+
task_description:
|
|
132
|
+
type: string
|
|
133
|
+
description: Description of the task that the user wants to accomplish or do. For example, "tell the waiter they messed up my order" or "compliment someone on their shirt"
|
|
134
|
+
learning_language:
|
|
135
|
+
type: string
|
|
136
|
+
description: The foreign language that the user is learning and asking about. The value can be inferred from question - for example, if the user asks "how do i ask a girl out in mexico city", the value should be "Spanish" because of Mexico City. Always use the full name of the language (e.g. Spanish, French).
|
|
137
|
+
native_language:
|
|
138
|
+
type: string
|
|
139
|
+
description: The user's native language. Infer this value from the language the user asked their question in. Always use the full name of the language (e.g. Spanish, French).
|
|
140
|
+
additional_context:
|
|
141
|
+
type: string
|
|
142
|
+
description: A description of any additional context in the user's question that could affect the explanation - e.g. setting, scenario, situation, tone, speaking style and formality, usage notes, or any other qualifiers.
|
|
143
|
+
full_query:
|
|
144
|
+
type: string
|
|
145
|
+
description: Full text of the user's question.
|
|
146
|
+
explainTaskResponse:
|
|
147
|
+
type: object
|
|
148
|
+
properties:
|
|
149
|
+
explanation:
|
|
150
|
+
type: string
|
|
151
|
+
description: An explanation of the best thing to say in the foreign language to accomplish the task described in the user's question.
|
|
@@ -171,7 +171,6 @@ class OpenAIFunction:
|
|
|
171
171
|
self.openai_tool_schema = openai_tool_schema or get_openai_tool_schema(
|
|
172
172
|
func
|
|
173
173
|
)
|
|
174
|
-
self.properties = self.openai_tool_schema
|
|
175
174
|
|
|
176
175
|
@staticmethod
|
|
177
176
|
def validate_openai_tool_schema(openai_tool_schema: Dict[str, Any]) -> None:
|
|
@@ -193,6 +192,9 @@ class OpenAIFunction:
|
|
|
193
192
|
SchemaError: If the parameters do not meet JSON Schema reference
|
|
194
193
|
specifications.
|
|
195
194
|
"""
|
|
195
|
+
# Check the type
|
|
196
|
+
if not openai_tool_schema["type"]:
|
|
197
|
+
raise ValueError("miss type")
|
|
196
198
|
# Check the function description
|
|
197
199
|
if not openai_tool_schema["function"]["description"]:
|
|
198
200
|
raise ValueError("miss function description")
|
|
@@ -0,0 +1,61 @@
|
|
|
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 List, Union
|
|
15
|
+
|
|
16
|
+
from camel.functions import OpenAIFunction
|
|
17
|
+
from camel.retrievers import AutoRetriever
|
|
18
|
+
from camel.types import StorageType
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def information_retrieval(
|
|
22
|
+
query: str, content_input_paths: Union[str, List[str]]
|
|
23
|
+
) -> str:
|
|
24
|
+
r"""Retrieves information from a local vector storage based on the
|
|
25
|
+
specified query. This function connects to a local vector storage system
|
|
26
|
+
and retrieves relevant information by processing the input query. It is
|
|
27
|
+
essential to use this function when the answer to a question requires
|
|
28
|
+
external knowledge sources.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
query (str): The question or query for which an answer is required.
|
|
32
|
+
content_input_paths (Union[str, List[str]]): Paths to local
|
|
33
|
+
files or remote URLs.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
str: The information retrieved in response to the query, aggregated
|
|
37
|
+
and formatted as a string.
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
# Retrieve information about CAMEL AI.
|
|
41
|
+
information_retrieval(query = "what is CAMEL AI?",
|
|
42
|
+
content_input_paths="https://www.camel-ai.org/")
|
|
43
|
+
"""
|
|
44
|
+
auto_retriever = AutoRetriever(
|
|
45
|
+
vector_storage_local_path="camel/temp_storage",
|
|
46
|
+
storage_type=StorageType.QDRANT,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
retrieved_info = auto_retriever.run_vector_retriever(
|
|
50
|
+
query=query, content_input_paths=content_input_paths, top_k=3
|
|
51
|
+
)
|
|
52
|
+
return retrieved_info
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# add the function to OpenAIFunction list
|
|
56
|
+
RETRIEVAL_FUNCS: List[OpenAIFunction] = [
|
|
57
|
+
OpenAIFunction(func)
|
|
58
|
+
for func in [
|
|
59
|
+
information_retrieval,
|
|
60
|
+
]
|
|
61
|
+
]
|
|
@@ -0,0 +1,275 @@
|
|
|
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
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import logging
|
|
19
|
+
import os
|
|
20
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from ssl import SSLContext
|
|
24
|
+
|
|
25
|
+
from slack_sdk import WebClient
|
|
26
|
+
|
|
27
|
+
from slack_sdk.errors import SlackApiError
|
|
28
|
+
|
|
29
|
+
from camel.functions import OpenAIFunction
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _login_slack(
|
|
35
|
+
slack_token: Optional[str] = None,
|
|
36
|
+
ssl: Optional[SSLContext] = None,
|
|
37
|
+
) -> WebClient:
|
|
38
|
+
r"""Authenticate using the Slack API.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
slack_token (str, optional): The Slack API token. If not provided, it
|
|
42
|
+
attempts to retrieve the token from the environment variable
|
|
43
|
+
SLACK_BOT_TOKEN or SLACK_USER_TOKEN.
|
|
44
|
+
ssl (SSLContext, optional): SSL context for secure connections.
|
|
45
|
+
Defaults to `None`.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
WebClient: A WebClient object for interacting with Slack API.
|
|
49
|
+
|
|
50
|
+
Raises:
|
|
51
|
+
ImportError: If slack_sdk package is not installed.
|
|
52
|
+
KeyError: If SLACK_BOT_TOKEN or SLACK_USER_TOKEN environment variables
|
|
53
|
+
are not set.
|
|
54
|
+
"""
|
|
55
|
+
try:
|
|
56
|
+
from slack_sdk import WebClient
|
|
57
|
+
except ImportError as e:
|
|
58
|
+
raise ImportError(
|
|
59
|
+
"Cannot import slack_sdk. Please install the package with \
|
|
60
|
+
`pip install slack_sdk`."
|
|
61
|
+
) from e
|
|
62
|
+
if not slack_token:
|
|
63
|
+
slack_token = os.environ.get("SLACK_BOT_TOKEN") or os.environ.get(
|
|
64
|
+
"SLACK_USER_TOKEN"
|
|
65
|
+
)
|
|
66
|
+
if not slack_token:
|
|
67
|
+
raise KeyError(
|
|
68
|
+
"SLACK_BOT_TOKEN or SLACK_USER_TOKEN environment variable not set."
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
client = WebClient(token=slack_token, ssl=ssl)
|
|
72
|
+
logger.info("Slack login successful.")
|
|
73
|
+
return client
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def create_slack_channel(name: str, is_private: Optional[bool] = True) -> str:
|
|
77
|
+
r"""Creates a new slack channel, either public or private.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
name (str): Name of the public or private channel to create.
|
|
81
|
+
is_private (bool, optional): Whether to create a private channel
|
|
82
|
+
instead of a public one. Defaults to `True`.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
str: JSON string containing information about Slack channel created.
|
|
86
|
+
|
|
87
|
+
Raises:
|
|
88
|
+
SlackApiError: If there is an error during get slack channel
|
|
89
|
+
information.
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
slack_client = _login_slack()
|
|
93
|
+
response = slack_client.conversations_create(
|
|
94
|
+
name=name, is_private=is_private
|
|
95
|
+
)
|
|
96
|
+
channel_id = response["channel"]["id"]
|
|
97
|
+
response = slack_client.conversations_archive(channel=channel_id)
|
|
98
|
+
return str(response)
|
|
99
|
+
except SlackApiError as e:
|
|
100
|
+
return f"Error creating conversation: {e.response['error']}"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def join_slack_channel(channel_id: str) -> str:
|
|
104
|
+
r"""Joins an existing Slack channel.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
channel_id (str): The ID of the Slack channel to join.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
str: A confirmation message indicating whether join successfully or an
|
|
111
|
+
error message.
|
|
112
|
+
|
|
113
|
+
Raises:
|
|
114
|
+
SlackApiError: If there is an error during get slack channel
|
|
115
|
+
information.
|
|
116
|
+
"""
|
|
117
|
+
try:
|
|
118
|
+
slack_client = _login_slack()
|
|
119
|
+
response = slack_client.conversations_join(channel=channel_id)
|
|
120
|
+
return str(response)
|
|
121
|
+
except SlackApiError as e:
|
|
122
|
+
return f"Error creating conversation: {e.response['error']}"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def leave_slack_channel(channel_id: str) -> str:
|
|
126
|
+
r"""Leaves an existing Slack channel.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
channel_id (str): The ID of the Slack channel to leave.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
str: A confirmation message indicating whether leave successfully or an
|
|
133
|
+
error message.
|
|
134
|
+
|
|
135
|
+
Raises:
|
|
136
|
+
SlackApiError: If there is an error during get slack channel
|
|
137
|
+
information.
|
|
138
|
+
"""
|
|
139
|
+
try:
|
|
140
|
+
slack_client = _login_slack()
|
|
141
|
+
response = slack_client.conversations_leave(channel=channel_id)
|
|
142
|
+
return str(response)
|
|
143
|
+
except SlackApiError as e:
|
|
144
|
+
return f"Error creating conversation: {e.response['error']}"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def get_slack_channel_information() -> str:
|
|
148
|
+
r"""Retrieve Slack channels and return relevant information in JSON format.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
str: JSON string containing information about Slack channels.
|
|
152
|
+
|
|
153
|
+
Raises:
|
|
154
|
+
SlackApiError: If there is an error during get slack channel
|
|
155
|
+
information.
|
|
156
|
+
"""
|
|
157
|
+
try:
|
|
158
|
+
slack_client = _login_slack()
|
|
159
|
+
response = slack_client.conversations_list()
|
|
160
|
+
conversations = response["channels"]
|
|
161
|
+
# Filtering conversations and extracting required information
|
|
162
|
+
filtered_result = [
|
|
163
|
+
{
|
|
164
|
+
key: conversation[key]
|
|
165
|
+
for key in ("id", "name", "created", "num_members")
|
|
166
|
+
}
|
|
167
|
+
for conversation in conversations
|
|
168
|
+
if all(
|
|
169
|
+
key in conversation
|
|
170
|
+
for key in ("id", "name", "created", "num_members")
|
|
171
|
+
)
|
|
172
|
+
]
|
|
173
|
+
return json.dumps(filtered_result, ensure_ascii=False)
|
|
174
|
+
except SlackApiError as e:
|
|
175
|
+
return f"Error creating conversation: {e.response['error']}"
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def get_slack_channel_message(channel_id: str) -> str:
|
|
179
|
+
r"""Retrieve messages from a Slack channel.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
channel_id (str): The ID of the Slack channel to retrieve messages
|
|
183
|
+
from.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
str: JSON string containing filtered message data.
|
|
187
|
+
|
|
188
|
+
Raises:
|
|
189
|
+
SlackApiError: If there is an error during get slack channel message.
|
|
190
|
+
"""
|
|
191
|
+
try:
|
|
192
|
+
slack_client = _login_slack()
|
|
193
|
+
result = slack_client.conversations_history(channel=channel_id)
|
|
194
|
+
messages = result["messages"]
|
|
195
|
+
filtered_messages = [
|
|
196
|
+
{key: message[key] for key in ("user", "text", "ts")}
|
|
197
|
+
for message in messages
|
|
198
|
+
if all(key in message for key in ("user", "text", "ts"))
|
|
199
|
+
]
|
|
200
|
+
return json.dumps(filtered_messages, ensure_ascii=False)
|
|
201
|
+
except SlackApiError as e:
|
|
202
|
+
return f"Error retrieving messages: {e.response['error']}"
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def send_slack_message(
|
|
206
|
+
message: str,
|
|
207
|
+
channel_id: str,
|
|
208
|
+
user: Optional[str] = None,
|
|
209
|
+
) -> str:
|
|
210
|
+
r"""Send a message to a Slack channel.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
message (str): The message to send.
|
|
214
|
+
channel_id (str): The ID of the Slack channel to send message.
|
|
215
|
+
user (Optional[str]): The user ID of the recipient. Defaults to `None`.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
str: A confirmation message indicating whether the message was sent
|
|
219
|
+
successfully or an error message.
|
|
220
|
+
|
|
221
|
+
Raises:
|
|
222
|
+
SlackApiError: If an error occurs while sending the message.
|
|
223
|
+
"""
|
|
224
|
+
try:
|
|
225
|
+
slack_client = _login_slack()
|
|
226
|
+
if user:
|
|
227
|
+
response = slack_client.chat_postEphemeral(
|
|
228
|
+
channel=channel_id, text=message, user=user
|
|
229
|
+
)
|
|
230
|
+
else:
|
|
231
|
+
response = slack_client.chat_postMessage(
|
|
232
|
+
channel=channel_id, text=message
|
|
233
|
+
)
|
|
234
|
+
return str(response)
|
|
235
|
+
except SlackApiError as e:
|
|
236
|
+
return f"Error creating conversation: {e.response['error']}"
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def delete_slack_message(
|
|
240
|
+
time_stamp: str,
|
|
241
|
+
channel_id: str,
|
|
242
|
+
) -> str:
|
|
243
|
+
r"""Delete a message to a Slack channel.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
time_stamp (str): Timestamp of the message to be deleted.
|
|
247
|
+
channel_id (str): The ID of the Slack channel to delete message.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
str: A confirmation message indicating whether the message was delete
|
|
251
|
+
successfully or an error message.
|
|
252
|
+
|
|
253
|
+
Raises:
|
|
254
|
+
SlackApiError: If an error occurs while sending the message.
|
|
255
|
+
"""
|
|
256
|
+
try:
|
|
257
|
+
slack_client = _login_slack()
|
|
258
|
+
response = slack_client.chat_delete(channel=channel_id, ts=time_stamp)
|
|
259
|
+
return str(response)
|
|
260
|
+
except SlackApiError as e:
|
|
261
|
+
return f"Error creating conversation: {e.response['error']}"
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
SLACK_FUNCS: List[OpenAIFunction] = [
|
|
265
|
+
OpenAIFunction(func) # type: ignore[arg-type]
|
|
266
|
+
for func in [
|
|
267
|
+
create_slack_channel,
|
|
268
|
+
join_slack_channel,
|
|
269
|
+
leave_slack_channel,
|
|
270
|
+
get_slack_channel_information,
|
|
271
|
+
get_slack_channel_message,
|
|
272
|
+
send_slack_message,
|
|
273
|
+
delete_slack_message,
|
|
274
|
+
]
|
|
275
|
+
]
|
camel/models/__init__.py
CHANGED
|
@@ -15,6 +15,7 @@ from .anthropic_model import AnthropicModel
|
|
|
15
15
|
from .base_model import BaseModelBackend
|
|
16
16
|
from .model_factory import ModelFactory
|
|
17
17
|
from .open_source_model import OpenSourceModel
|
|
18
|
+
from .openai_audio_models import OpenAIAudioModels
|
|
18
19
|
from .openai_model import OpenAIModel
|
|
19
20
|
from .stub_model import StubModel
|
|
20
21
|
|
|
@@ -25,4 +26,5 @@ __all__ = [
|
|
|
25
26
|
'StubModel',
|
|
26
27
|
'OpenSourceModel',
|
|
27
28
|
'ModelFactory',
|
|
29
|
+
'OpenAIAudioModels',
|
|
28
30
|
]
|
camel/models/anthropic_model.py
CHANGED
|
@@ -27,10 +27,24 @@ class AnthropicModel(BaseModelBackend):
|
|
|
27
27
|
r"""Anthropic API in a unified BaseModelBackend interface."""
|
|
28
28
|
|
|
29
29
|
def __init__(
|
|
30
|
-
self,
|
|
30
|
+
self,
|
|
31
|
+
model_type: ModelType,
|
|
32
|
+
model_config_dict: Dict[str, Any],
|
|
33
|
+
api_key: Optional[str] = None,
|
|
31
34
|
) -> None:
|
|
35
|
+
r"""Constructor for Anthropic backend.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
model_type (ModelType): Model for which a backend is created,
|
|
39
|
+
one of GPT_* series.
|
|
40
|
+
model_config_dict (Dict[str, Any]): A dictionary that will
|
|
41
|
+
be fed into openai.ChatCompletion.create().
|
|
42
|
+
api_key (Optional[str]): The API key for authenticating with the
|
|
43
|
+
Anthropic service. (default: :obj:`None`)
|
|
44
|
+
"""
|
|
32
45
|
super().__init__(model_type, model_config_dict)
|
|
33
|
-
self.
|
|
46
|
+
self._api_key = api_key or os.environ.get("ANTHROPIC_API_KEY")
|
|
47
|
+
self.client = Anthropic(api_key=self._api_key)
|
|
34
48
|
self._token_counter: Optional[BaseTokenCounter] = None
|
|
35
49
|
|
|
36
50
|
def _convert_response_from_anthropic_to_openai(self, response):
|