pygeai 0.4.0b3__py3-none-any.whl → 0.5.0__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.
- pygeai/__init__.py +1 -1
- pygeai/assistant/rag/models.py +1 -1
- pygeai/chat/ui.py +0 -1
- pygeai/cli/__init__.py +1 -1
- pygeai/cli/commands/chat.py +54 -56
- pygeai/cli/commands/lab/ai_lab.py +129 -466
- pygeai/cli/commands/lab/options.py +8 -0
- pygeai/cli/commands/lab/utils.py +13 -0
- pygeai/cli/geai.py +5 -2
- pygeai/cli/texts/help.py +12 -0
- pygeai/core/base/session.py +1 -1
- pygeai/core/common/config.py +0 -2
- pygeai/core/common/exceptions.py +6 -0
- pygeai/lab/agents/clients.py +30 -61
- pygeai/lab/clients.py +20 -0
- pygeai/lab/managers.py +6 -58
- pygeai/lab/models.py +1 -1
- pygeai/lab/processes/clients.py +81 -129
- pygeai/lab/processes/mappers.py +2 -2
- pygeai/lab/strategies/clients.py +11 -17
- pygeai/lab/tools/clients.py +59 -59
- pygeai/lab/tools/mappers.py +5 -5
- pygeai/tests/cli/docker/__init__.py +0 -0
- pygeai/tests/integration/assistants/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
- pygeai/tests/integration/chat/__init__.py +0 -0
- pygeai/tests/integration/chat/test_generate_image.py +158 -0
- pygeai/tests/integration/lab/agents/test_create_agent.py +21 -19
- pygeai/tests/integration/lab/agents/test_create_sharing_link.py +4 -1
- pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +0 -1
- pygeai/tests/integration/lab/agents/test_update_agent.py +19 -31
- pygeai/tests/integration/lab/processes/__init__.py +0 -0
- pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
- pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
- pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
- pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
- pygeai/tests/integration/lab/tools/test_create_tool.py +14 -20
- pygeai/tests/integration/lab/tools/test_delete_tool.py +3 -3
- pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
- pygeai/tests/integration/lab/tools/test_get_tool.py +3 -3
- pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
- pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
- pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
- pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
- pygeai/tests/snippets/lab/agentic_flow_example_4.py +23 -23
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +1 -2
- pygeai/tests/snippets/lab/samples/summarize_files.py +3 -3
- pygeai/tests/snippets/lab/tools/create_tool.py +1 -1
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example.py +3 -3
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +11 -11
- pygeai/tests/snippets/lab/use_cases/update_web_reader.py +1 -2
- {pygeai-0.4.0b3.dist-info → pygeai-0.5.0.dist-info}/METADATA +47 -19
- {pygeai-0.4.0b3.dist-info → pygeai-0.5.0.dist-info}/RECORD +61 -39
- {pygeai-0.4.0b3.dist-info → pygeai-0.5.0.dist-info}/WHEEL +0 -0
- {pygeai-0.4.0b3.dist-info → pygeai-0.5.0.dist-info}/entry_points.txt +0 -0
- {pygeai-0.4.0b3.dist-info → pygeai-0.5.0.dist-info}/licenses/LICENSE +0 -0
- {pygeai-0.4.0b3.dist-info → pygeai-0.5.0.dist-info}/top_level.txt +0 -0
pygeai/lab/processes/mappers.py
CHANGED
pygeai/lab/strategies/clients.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from json import JSONDecodeError
|
|
2
2
|
|
|
3
3
|
from pygeai import logger
|
|
4
|
-
from pygeai.core.base.clients import BaseClient
|
|
5
4
|
from pygeai.core.common.exceptions import InvalidAPIResponseException
|
|
5
|
+
from pygeai.lab.clients import AILabClient
|
|
6
6
|
from pygeai.lab.strategies.endpoints import LIST_REASONING_STRATEGIES_V2, CREATE_REASONING_STRATEGY_V2, \
|
|
7
7
|
UPDATE_REASONING_STRATEGY_V2, UPSERT_REASONING_STRATEGY_V2, GET_REASONING_STRATEGY_V2
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class ReasoningStrategyClient(
|
|
10
|
+
class ReasoningStrategyClient(AILabClient):
|
|
11
11
|
|
|
12
12
|
def list_reasoning_strategies(
|
|
13
13
|
self,
|
|
@@ -56,7 +56,6 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
56
56
|
|
|
57
57
|
def create_reasoning_strategy(
|
|
58
58
|
self,
|
|
59
|
-
project_id: str,
|
|
60
59
|
name: str,
|
|
61
60
|
system_prompt: str,
|
|
62
61
|
access_scope: str = "public",
|
|
@@ -67,7 +66,6 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
67
66
|
"""
|
|
68
67
|
Creates a new reasoning strategy in the specified project.
|
|
69
68
|
|
|
70
|
-
:param project_id: str - Unique identifier of the project.
|
|
71
69
|
:param name: str - Name of the reasoning strategy.
|
|
72
70
|
:param system_prompt: str - System prompt for the strategy.
|
|
73
71
|
:param access_scope: str, optional - Access scope, "public" or "private" (default: "public").
|
|
@@ -83,7 +81,7 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
83
81
|
|
|
84
82
|
headers = {
|
|
85
83
|
"Authorization": self.api_service.token,
|
|
86
|
-
"ProjectId": project_id,
|
|
84
|
+
"ProjectId": self.project_id,
|
|
87
85
|
"Content-Type": "application/json",
|
|
88
86
|
"Accept": "application/json"
|
|
89
87
|
}
|
|
@@ -103,14 +101,13 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
103
101
|
try:
|
|
104
102
|
result = response.json()
|
|
105
103
|
except JSONDecodeError as e:
|
|
106
|
-
logger.error(f"Unable to create reasoning strategy for project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
107
|
-
raise InvalidAPIResponseException(f"Unable to create reasoning strategy for project {project_id}: {response.text}")
|
|
104
|
+
logger.error(f"Unable to create reasoning strategy for project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
105
|
+
raise InvalidAPIResponseException(f"Unable to create reasoning strategy for project {self.project_id}: {response.text}")
|
|
108
106
|
|
|
109
107
|
return result
|
|
110
108
|
|
|
111
109
|
def update_reasoning_strategy(
|
|
112
110
|
self,
|
|
113
|
-
project_id: str,
|
|
114
111
|
reasoning_strategy_id: str,
|
|
115
112
|
name: str = None,
|
|
116
113
|
system_prompt: str = None,
|
|
@@ -123,7 +120,6 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
123
120
|
"""
|
|
124
121
|
Updates or upserts a reasoning strategy in the specified project.
|
|
125
122
|
|
|
126
|
-
:param project_id: str - Unique identifier of the project.
|
|
127
123
|
:param reasoning_strategy_id: str - Unique identifier of the strategy.
|
|
128
124
|
:param name: str, optional - Updated strategy name.
|
|
129
125
|
:param system_prompt: str, optional - Updated system prompt.
|
|
@@ -169,7 +165,7 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
169
165
|
|
|
170
166
|
headers = {
|
|
171
167
|
"Authorization": self.api_service.token,
|
|
172
|
-
"ProjectId": project_id,
|
|
168
|
+
"ProjectId": self.project_id,
|
|
173
169
|
"Content-Type": "application/json",
|
|
174
170
|
"Accept": "application/json"
|
|
175
171
|
}
|
|
@@ -181,21 +177,19 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
181
177
|
try:
|
|
182
178
|
result = response.json()
|
|
183
179
|
except JSONDecodeError as e:
|
|
184
|
-
logger.error(f"Unable to update reasoning strategy {reasoning_strategy_id} in project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
185
|
-
raise InvalidAPIResponseException(f"Unable to update reasoning strategy {reasoning_strategy_id} in project {project_id}: {response.text}")
|
|
180
|
+
logger.error(f"Unable to update reasoning strategy {reasoning_strategy_id} in project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
181
|
+
raise InvalidAPIResponseException(f"Unable to update reasoning strategy {reasoning_strategy_id} in project {self.project_id}: {response.text}")
|
|
186
182
|
|
|
187
183
|
return result
|
|
188
184
|
|
|
189
185
|
def get_reasoning_strategy(
|
|
190
186
|
self,
|
|
191
|
-
project_id: str,
|
|
192
187
|
reasoning_strategy_id: str = None,
|
|
193
188
|
reasoning_strategy_name: str = None
|
|
194
189
|
):
|
|
195
190
|
"""
|
|
196
191
|
Retrieves a reasoning strategy by ID or name in the specified project.
|
|
197
192
|
|
|
198
|
-
:param project_id: str - Unique identifier of the project.
|
|
199
193
|
:param reasoning_strategy_id: str, optional - Unique identifier of the strategy.
|
|
200
194
|
:param reasoning_strategy_name: str, optional - Name of the strategy.
|
|
201
195
|
:return: dict - Strategy details.
|
|
@@ -210,7 +204,7 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
210
204
|
|
|
211
205
|
headers = {
|
|
212
206
|
"Authorization": self.api_service.token,
|
|
213
|
-
"ProjectId": project_id
|
|
207
|
+
"ProjectId": self.project_id
|
|
214
208
|
}
|
|
215
209
|
|
|
216
210
|
if reasoning_strategy_id:
|
|
@@ -225,8 +219,8 @@ class ReasoningStrategyClient(BaseClient):
|
|
|
225
219
|
try:
|
|
226
220
|
result = response.json()
|
|
227
221
|
except JSONDecodeError as e:
|
|
228
|
-
logger.error(f"Unable to retrieve reasoning strategy {reasoning_strategy_id or reasoning_strategy_name} for project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
229
|
-
raise InvalidAPIResponseException(f"Unable to retrieve reasoning strategy {reasoning_strategy_id or reasoning_strategy_name} for project {project_id}: {response.text}")
|
|
222
|
+
logger.error(f"Unable to retrieve reasoning strategy {reasoning_strategy_id or reasoning_strategy_name} for project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
223
|
+
raise InvalidAPIResponseException(f"Unable to retrieve reasoning strategy {reasoning_strategy_id or reasoning_strategy_name} for project {self.project_id}: {response.text}")
|
|
230
224
|
|
|
231
225
|
return result
|
|
232
226
|
|
pygeai/lab/tools/clients.py
CHANGED
|
@@ -2,18 +2,17 @@ import json
|
|
|
2
2
|
from json import JSONDecodeError
|
|
3
3
|
|
|
4
4
|
from pygeai import logger
|
|
5
|
-
from pygeai.core.
|
|
6
|
-
from pygeai.core.common.exceptions import InvalidAPIResponseException, MissingRequirementException
|
|
5
|
+
from pygeai.core.common.exceptions import InvalidAPIResponseException, MissingRequirementException, APIResponseError
|
|
7
6
|
from pygeai.lab.constants import VALID_SCOPES, VALID_ACCESS_SCOPES, VALID_REPORT_EVENTS
|
|
8
7
|
from pygeai.lab.tools.endpoints import CREATE_TOOL_V2, LIST_TOOLS_V2, GET_TOOL_V2, UPDATE_TOOL_V2, UPSERT_TOOL_V2, \
|
|
9
8
|
PUBLISH_TOOL_REVISION_V2, GET_PARAMETER_V2, SET_PARAMETER_V2, DELETE_TOOL_V2, EXPORT_TOOL_V2
|
|
9
|
+
from pygeai.lab.clients import AILabClient
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class ToolClient(
|
|
12
|
+
class ToolClient(AILabClient):
|
|
13
13
|
|
|
14
14
|
def create_tool(
|
|
15
15
|
self,
|
|
16
|
-
project_id: str,
|
|
17
16
|
name: str,
|
|
18
17
|
description: str = None,
|
|
19
18
|
scope: str = None,
|
|
@@ -29,7 +28,6 @@ class ToolClient(BaseClient):
|
|
|
29
28
|
"""
|
|
30
29
|
Creates a new tool in the specified project.
|
|
31
30
|
|
|
32
|
-
:param project_id: str - Unique identifier of the project where the tool will be created.
|
|
33
31
|
:param name: str - Name of the tool. Must be non-empty, unique within the project, and exclude ':' or '/'.
|
|
34
32
|
:param description: str - Description of the tool's purpose, helping agents decide when to use it. Optional.
|
|
35
33
|
:param scope: str - Scope of the tool, either 'builtin', 'external', or 'api'. Optional.
|
|
@@ -108,7 +106,7 @@ class ToolClient(BaseClient):
|
|
|
108
106
|
"Accept": "application/json",
|
|
109
107
|
"Content-Type": "application/json",
|
|
110
108
|
"Authorization": self.api_service.token,
|
|
111
|
-
"ProjectId": project_id
|
|
109
|
+
"ProjectId": self.project_id
|
|
112
110
|
}
|
|
113
111
|
|
|
114
112
|
response = self.api_service.post(
|
|
@@ -116,18 +114,20 @@ class ToolClient(BaseClient):
|
|
|
116
114
|
headers=headers,
|
|
117
115
|
data=data
|
|
118
116
|
)
|
|
119
|
-
|
|
117
|
+
|
|
118
|
+
if response.status_code >= 300:
|
|
119
|
+
logger.error(f"Invalid status code returned from the API endpoint: {response.text}")
|
|
120
|
+
raise APIResponseError(f"API returned an error: {response.text}")
|
|
120
121
|
try:
|
|
121
122
|
result = response.json()
|
|
122
123
|
except JSONDecodeError as e:
|
|
123
|
-
logger.error(f"Unable to create tool for project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
124
|
-
raise InvalidAPIResponseException(f"Unable to create tool for project {project_id}: {response.text}")
|
|
124
|
+
logger.error(f"Unable to create tool for project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
125
|
+
raise InvalidAPIResponseException(f"Unable to create tool for project {self.project_id}: {response.text}")
|
|
125
126
|
|
|
126
127
|
return result
|
|
127
128
|
|
|
128
129
|
def list_tools(
|
|
129
130
|
self,
|
|
130
|
-
project_id: str,
|
|
131
131
|
id: str = "",
|
|
132
132
|
count: str = "100",
|
|
133
133
|
access_scope: str = "public",
|
|
@@ -138,7 +138,6 @@ class ToolClient(BaseClient):
|
|
|
138
138
|
"""
|
|
139
139
|
Retrieves a list of tools associated with the specified project.
|
|
140
140
|
|
|
141
|
-
:param project_id: str - Unique identifier of the project.
|
|
142
141
|
:param id: str - ID of the tool to filter by. Defaults to "" (no filtering).
|
|
143
142
|
:param count: str - Number of tools to retrieve. Defaults to "100".
|
|
144
143
|
:param access_scope: str - Access scope of the tools, either "public" or "private". Defaults to "public".
|
|
@@ -150,13 +149,13 @@ class ToolClient(BaseClient):
|
|
|
150
149
|
endpoint = LIST_TOOLS_V2
|
|
151
150
|
headers = {
|
|
152
151
|
"Authorization": self.api_service.token,
|
|
153
|
-
"ProjectId": project_id
|
|
152
|
+
"ProjectId": self.project_id
|
|
154
153
|
}
|
|
155
154
|
|
|
156
155
|
if scope and scope not in VALID_SCOPES:
|
|
157
156
|
raise ValueError(f"Scope must be one of {', '.join(VALID_SCOPES)}.")
|
|
158
157
|
|
|
159
|
-
logger.debug(f"Listing tools available for the project with ID: {project_id}")
|
|
158
|
+
logger.debug(f"Listing tools available for the project with ID: {self.project_id}")
|
|
160
159
|
|
|
161
160
|
response = self.api_service.get(
|
|
162
161
|
endpoint=endpoint,
|
|
@@ -170,17 +169,19 @@ class ToolClient(BaseClient):
|
|
|
170
169
|
"allowExternal": allow_external
|
|
171
170
|
}
|
|
172
171
|
)
|
|
172
|
+
if response.status_code >= 300:
|
|
173
|
+
logger.error(f"Invalid status code returned from the API endpoint: {response.text}")
|
|
174
|
+
raise APIResponseError(f"API returned an error: {response.text}")
|
|
173
175
|
try:
|
|
174
176
|
result = response.json()
|
|
175
177
|
except JSONDecodeError as e:
|
|
176
|
-
logger.error(f"Unable to list tools for project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
177
|
-
raise InvalidAPIResponseException(f"Unable to list tools for project {project_id}: {response.text}")
|
|
178
|
+
logger.error(f"Unable to list tools for project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
179
|
+
raise InvalidAPIResponseException(f"Unable to list tools for project {self.project_id}: {response.text}")
|
|
178
180
|
|
|
179
181
|
return result
|
|
180
182
|
|
|
181
183
|
def get_tool(
|
|
182
184
|
self,
|
|
183
|
-
project_id: str,
|
|
184
185
|
tool_id: str,
|
|
185
186
|
revision: str = 0,
|
|
186
187
|
version: int = 0,
|
|
@@ -189,7 +190,6 @@ class ToolClient(BaseClient):
|
|
|
189
190
|
"""
|
|
190
191
|
Retrieves details of a specific tool from the specified project.
|
|
191
192
|
|
|
192
|
-
:param project_id: str - Unique identifier of the project.
|
|
193
193
|
:param tool_id: str - Unique identifier of the tool to retrieve.
|
|
194
194
|
:param revision: str - Revision of the tool to retrieve. Defaults to 0 (latest revision).
|
|
195
195
|
:param version: int - Version of the tool to retrieve. Defaults to 0 (latest version).
|
|
@@ -199,7 +199,7 @@ class ToolClient(BaseClient):
|
|
|
199
199
|
endpoint = GET_TOOL_V2.format(toolId=tool_id)
|
|
200
200
|
headers = {
|
|
201
201
|
"Authorization": self.api_service.token,
|
|
202
|
-
"ProjectId": project_id
|
|
202
|
+
"ProjectId": self.project_id
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
logger.debug(f"Retrieving detail of tool with ID: {tool_id}")
|
|
@@ -213,24 +213,25 @@ class ToolClient(BaseClient):
|
|
|
213
213
|
"allowDrafts": allow_drafts,
|
|
214
214
|
}
|
|
215
215
|
)
|
|
216
|
+
if response.status_code >= 300:
|
|
217
|
+
logger.error(f"Invalid status code returned from the API endpoint: {response.text}")
|
|
218
|
+
raise APIResponseError(f"API returned an error: {response.text}")
|
|
216
219
|
try:
|
|
217
220
|
result = response.json()
|
|
218
221
|
except JSONDecodeError as e:
|
|
219
|
-
logger.error(f"Unable to retrieve tool {tool_id} for project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
220
|
-
raise InvalidAPIResponseException(f"Unable to retrieve tool {tool_id} for project {project_id}: {response.text}")
|
|
222
|
+
logger.error(f"Unable to retrieve tool {tool_id} for project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
223
|
+
raise InvalidAPIResponseException(f"Unable to retrieve tool {tool_id} for project {self.project_id}: {response.text}")
|
|
221
224
|
|
|
222
225
|
return result
|
|
223
226
|
|
|
224
227
|
def delete_tool(
|
|
225
228
|
self,
|
|
226
|
-
project_id: str,
|
|
227
229
|
tool_id: str = None,
|
|
228
230
|
tool_name: str = None
|
|
229
231
|
) -> dict | str:
|
|
230
232
|
"""
|
|
231
233
|
Deletes a specific tool from the specified project.
|
|
232
234
|
|
|
233
|
-
:param project_id: str - Unique identifier of the project.
|
|
234
235
|
:param tool_id: str, optional - Unique identifier of the tool to delete. Defaults to None.
|
|
235
236
|
:param tool_name: str, optional - Name of the tool to delete. Defaults to None.
|
|
236
237
|
:return: dict or str - JSON response containing the result of the delete operation if successful,
|
|
@@ -243,7 +244,7 @@ class ToolClient(BaseClient):
|
|
|
243
244
|
endpoint = DELETE_TOOL_V2.format(toolId=tool_id if tool_id else tool_name)
|
|
244
245
|
headers = {
|
|
245
246
|
"Authorization": self.api_service.token,
|
|
246
|
-
"ProjectId": project_id
|
|
247
|
+
"ProjectId": self.project_id
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
if tool_id:
|
|
@@ -255,17 +256,19 @@ class ToolClient(BaseClient):
|
|
|
255
256
|
endpoint=endpoint,
|
|
256
257
|
headers=headers
|
|
257
258
|
)
|
|
259
|
+
if response.status_code >= 300:
|
|
260
|
+
logger.error(f"Invalid status code returned from the API endpoint: {response.text}")
|
|
261
|
+
raise APIResponseError(f"API returned an error: {response.text}")
|
|
258
262
|
|
|
259
263
|
if response.status_code != 204:
|
|
260
|
-
logger.error(f"Unable to delete tool {tool_id or tool_name} from project {project_id}: JSON parsing error (status {response.status_code}). Response: {response.text}")
|
|
261
|
-
raise InvalidAPIResponseException(f"Unable to delete tool {tool_id or tool_name} from project {project_id}: {response.text}")
|
|
264
|
+
logger.error(f"Unable to delete tool {tool_id or tool_name} from project {self.project_id}: JSON parsing error (status {response.status_code}). Response: {response.text}")
|
|
265
|
+
raise InvalidAPIResponseException(f"Unable to delete tool {tool_id or tool_name} from project {self.project_id}: {response.text}")
|
|
262
266
|
else:
|
|
263
267
|
return {}
|
|
264
268
|
|
|
265
269
|
def update_tool(
|
|
266
270
|
self,
|
|
267
|
-
|
|
268
|
-
tool_id: str,
|
|
271
|
+
tool_id: str = None,
|
|
269
272
|
name: str = None,
|
|
270
273
|
description: str = None,
|
|
271
274
|
scope: str = None,
|
|
@@ -282,7 +285,6 @@ class ToolClient(BaseClient):
|
|
|
282
285
|
"""
|
|
283
286
|
Updates an existing tool in the specified project or upserts it if specified.
|
|
284
287
|
|
|
285
|
-
:param project_id: str - Unique identifier of the project containing the tool.
|
|
286
288
|
:param tool_id: str - Unique identifier of the tool to update. Required for update operations.
|
|
287
289
|
:param name: str - Updated name of the tool. Must be non-empty, unique within the project, and exclude ':' or '/' if provided. Optional.
|
|
288
290
|
:param description: str - Updated description of the tool's purpose, helping agents decide when to use it. Optional.
|
|
@@ -323,6 +325,8 @@ class ToolClient(BaseClient):
|
|
|
323
325
|
:raises JSONDecodeError: Caught internally if the response cannot be parsed as JSON; returns raw response text.
|
|
324
326
|
:raises Exception: May be raised by `api_service.put` for network issues, authentication errors, or server-side problems (not caught here).
|
|
325
327
|
"""
|
|
328
|
+
if not (tool_id or name):
|
|
329
|
+
raise ValueError(f"Either tool ID or tool Name must be defined in order to update tool.")
|
|
326
330
|
if scope and scope not in VALID_SCOPES:
|
|
327
331
|
raise ValueError(f"Scope must be one of {', '.join(VALID_SCOPES)}.")
|
|
328
332
|
if access_scope and access_scope not in VALID_ACCESS_SCOPES:
|
|
@@ -365,32 +369,32 @@ class ToolClient(BaseClient):
|
|
|
365
369
|
|
|
366
370
|
headers = {
|
|
367
371
|
"Authorization": self.api_service.token,
|
|
368
|
-
"ProjectId": project_id
|
|
372
|
+
"ProjectId": self.project_id
|
|
369
373
|
}
|
|
370
374
|
response = self.api_service.put(
|
|
371
375
|
endpoint=endpoint,
|
|
372
376
|
headers=headers,
|
|
373
377
|
data=data
|
|
374
378
|
)
|
|
375
|
-
|
|
379
|
+
if response.status_code >= 300:
|
|
380
|
+
logger.error(f"Invalid status code returned from the API endpoint: {response.text}")
|
|
381
|
+
raise APIResponseError(f"API returned an error: {response.text}")
|
|
376
382
|
try:
|
|
377
383
|
result = response.json()
|
|
378
384
|
except JSONDecodeError as e:
|
|
379
|
-
logger.error(f"Unable to update tool {tool_id} in project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
380
|
-
raise InvalidAPIResponseException(f"Unable to update tool {tool_id} in project {project_id}: {response.text}")
|
|
385
|
+
logger.error(f"Unable to update tool {tool_id} in project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
386
|
+
raise InvalidAPIResponseException(f"Unable to update tool {tool_id} in project {self.project_id}: {response.text}")
|
|
381
387
|
|
|
382
388
|
return result
|
|
383
389
|
|
|
384
390
|
def publish_tool_revision(
|
|
385
391
|
self,
|
|
386
|
-
project_id: str,
|
|
387
392
|
tool_id: str,
|
|
388
393
|
revision: str
|
|
389
394
|
):
|
|
390
395
|
"""
|
|
391
396
|
Publishes a specific revision of a tool in the specified project.
|
|
392
397
|
|
|
393
|
-
:param project_id: str - Unique identifier of the project.
|
|
394
398
|
:param tool_id: str - Unique identifier of the tool to publish.
|
|
395
399
|
:param revision: str - Revision of the tool to publish.
|
|
396
400
|
:return: dict or str - JSON response containing the result of the publish operation if successful, otherwise the raw response text.
|
|
@@ -398,7 +402,7 @@ class ToolClient(BaseClient):
|
|
|
398
402
|
endpoint = PUBLISH_TOOL_REVISION_V2.format(toolId=tool_id)
|
|
399
403
|
headers = {
|
|
400
404
|
"Authorization": self.api_service.token,
|
|
401
|
-
"ProjectId": project_id
|
|
405
|
+
"ProjectId": self.project_id
|
|
402
406
|
}
|
|
403
407
|
|
|
404
408
|
logger.debug(f"Publishing revision {revision} for tool with ID {tool_id}")
|
|
@@ -413,14 +417,13 @@ class ToolClient(BaseClient):
|
|
|
413
417
|
try:
|
|
414
418
|
result = response.json()
|
|
415
419
|
except JSONDecodeError as e:
|
|
416
|
-
logger.error(f"Unable to publish revision {revision} for tool {tool_id} in project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
417
|
-
raise InvalidAPIResponseException(f"Unable to publish revision {revision} for tool {tool_id} in project {project_id}: {response.text}")
|
|
420
|
+
logger.error(f"Unable to publish revision {revision} for tool {tool_id} in project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
421
|
+
raise InvalidAPIResponseException(f"Unable to publish revision {revision} for tool {tool_id} in project {self.project_id}: {response.text}")
|
|
418
422
|
|
|
419
423
|
return result
|
|
420
424
|
|
|
421
425
|
def get_parameter(
|
|
422
426
|
self,
|
|
423
|
-
project_id: str,
|
|
424
427
|
tool_id: str = None,
|
|
425
428
|
tool_public_name: str = None,
|
|
426
429
|
revision: str = 0,
|
|
@@ -430,7 +433,6 @@ class ToolClient(BaseClient):
|
|
|
430
433
|
"""
|
|
431
434
|
Retrieves details of parameters for a specific tool identified by either its ID or public name in the specified project.
|
|
432
435
|
|
|
433
|
-
:param project_id: str - Unique identifier of the project.
|
|
434
436
|
:param tool_id: str, optional - Unique identifier of the tool whose parameters are to be retrieved. Defaults to None.
|
|
435
437
|
:param tool_public_name: str, optional - Public name of the tool whose parameters are to be retrieved. Defaults to None.
|
|
436
438
|
:param revision: str - Revision of the parameters to retrieve. Defaults to "0" (latest revision).
|
|
@@ -450,7 +452,7 @@ class ToolClient(BaseClient):
|
|
|
450
452
|
endpoint = GET_PARAMETER_V2.format(toolPublicName=tool_public_name) if tool_public_name else GET_PARAMETER_V2.format(toolPublicName=tool_id)
|
|
451
453
|
headers = {
|
|
452
454
|
"Authorization": self.api_service.token,
|
|
453
|
-
"ProjectId": project_id
|
|
455
|
+
"ProjectId": self.project_id
|
|
454
456
|
}
|
|
455
457
|
|
|
456
458
|
response = self.api_service.get(
|
|
@@ -462,17 +464,19 @@ class ToolClient(BaseClient):
|
|
|
462
464
|
"allowDrafts": allow_drafts,
|
|
463
465
|
}
|
|
464
466
|
)
|
|
467
|
+
if response.status_code >= 300:
|
|
468
|
+
logger.error(f"Invalid status code returned from the API endpoint: {response.text}")
|
|
469
|
+
raise APIResponseError(f"API returned an error: {response.text}")
|
|
465
470
|
try:
|
|
466
471
|
result = response.json()
|
|
467
472
|
except JSONDecodeError as e:
|
|
468
|
-
logger.error(f"Unable to retrieve parameters for tool {tool_id or tool_public_name} in project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
469
|
-
raise InvalidAPIResponseException(f"Unable to retrieve parameters for tool {tool_id or tool_public_name} in project {project_id}: {response.text}")
|
|
473
|
+
logger.error(f"Unable to retrieve parameters for tool {tool_id or tool_public_name} in project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
474
|
+
raise InvalidAPIResponseException(f"Unable to retrieve parameters for tool {tool_id or tool_public_name} in project {self.project_id}: {response.text}")
|
|
470
475
|
|
|
471
476
|
return result
|
|
472
477
|
|
|
473
478
|
def set_parameter(
|
|
474
479
|
self,
|
|
475
|
-
project_id: str,
|
|
476
480
|
tool_id: str = None,
|
|
477
481
|
tool_public_name: str = None,
|
|
478
482
|
parameters: list = None
|
|
@@ -480,7 +484,6 @@ class ToolClient(BaseClient):
|
|
|
480
484
|
"""
|
|
481
485
|
Sets or updates parameters for a specific tool identified by either its ID or public name in the specified project.
|
|
482
486
|
|
|
483
|
-
:param project_id: str - Unique identifier of the project.
|
|
484
487
|
:param tool_id: str, optional - Unique identifier of the tool whose parameters are to be set. Defaults to None.
|
|
485
488
|
:param tool_public_name: str, optional - Public name of the tool whose parameters are to be set. Defaults to None.
|
|
486
489
|
:param parameters: list - List of parameter dictionaries defining the tool's parameters.
|
|
@@ -497,7 +500,7 @@ class ToolClient(BaseClient):
|
|
|
497
500
|
endpoint = SET_PARAMETER_V2.format(toolPublicName=tool_public_name) if tool_public_name else SET_PARAMETER_V2.format(toolPublicName=tool_id)
|
|
498
501
|
headers = {
|
|
499
502
|
"Authorization": self.api_service.token,
|
|
500
|
-
"ProjectId": project_id,
|
|
503
|
+
"ProjectId": self.project_id,
|
|
501
504
|
"Content-Type": "application/json",
|
|
502
505
|
"Accept": "application/json"
|
|
503
506
|
}
|
|
@@ -518,30 +521,24 @@ class ToolClient(BaseClient):
|
|
|
518
521
|
headers=headers,
|
|
519
522
|
data=data
|
|
520
523
|
)
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
return result
|
|
524
|
+
if response.status_code != 204:
|
|
525
|
+
logger.error(f"Unable to set parameter for tool {tool_id or tool_public_name} from project {self.project_id}: JSON parsing error (status {response.status_code}). Response: {response.text}")
|
|
526
|
+
raise InvalidAPIResponseException(f"Unable to set parameter for tool {tool_id or tool_public_name} from project {self.project_id}: {response.text}")
|
|
527
|
+
else:
|
|
528
|
+
return {}
|
|
528
529
|
|
|
529
530
|
def export_tool(
|
|
530
531
|
self,
|
|
531
|
-
project_id: str,
|
|
532
532
|
tool_id: str,
|
|
533
533
|
) -> dict:
|
|
534
534
|
"""
|
|
535
535
|
Retrieves details of a specific tool from the specified project.
|
|
536
536
|
|
|
537
|
-
:param project_id: str - Unique identifier of the project containing the tool.
|
|
538
537
|
:param tool_id: str - Unique identifier of the tool to retrieve.
|
|
539
538
|
:return: dict - JSON response containing the tool details.
|
|
540
539
|
:raises InvalidAPIResponseException: If the response cannot be parsed as JSON or an error occurs.
|
|
541
540
|
:raises MissingRequirementException: If project_id or tool_id is not provided.
|
|
542
541
|
"""
|
|
543
|
-
if not project_id:
|
|
544
|
-
raise MissingRequirementException("Cannot retrieve tool without specifying project_id")
|
|
545
542
|
|
|
546
543
|
if not tool_id:
|
|
547
544
|
raise MissingRequirementException("tool_id must be specified in order to retrieve the tool")
|
|
@@ -549,7 +546,7 @@ class ToolClient(BaseClient):
|
|
|
549
546
|
endpoint = EXPORT_TOOL_V2.format(toolId=tool_id)
|
|
550
547
|
headers = {
|
|
551
548
|
"Authorization": self.api_service.token,
|
|
552
|
-
"ProjectId": project_id
|
|
549
|
+
"ProjectId": self.project_id
|
|
553
550
|
}
|
|
554
551
|
|
|
555
552
|
logger.debug(f"Exporting tool with ID {tool_id}")
|
|
@@ -558,10 +555,13 @@ class ToolClient(BaseClient):
|
|
|
558
555
|
endpoint=endpoint,
|
|
559
556
|
headers=headers,
|
|
560
557
|
)
|
|
558
|
+
if response.status_code >= 300:
|
|
559
|
+
logger.error(f"Invalid status code returned from the API endpoint: {response.text}")
|
|
560
|
+
raise APIResponseError(f"API returned an error: {response.text}")
|
|
561
561
|
try:
|
|
562
562
|
result = response.json()
|
|
563
563
|
except JSONDecodeError as e:
|
|
564
|
-
logger.error(f"Unable to export tool {tool_id} for project {project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
565
|
-
raise InvalidAPIResponseException(f"Unable to export tool {tool_id} for project {project_id}: {response.text}")
|
|
564
|
+
logger.error(f"Unable to export tool {tool_id} for project {self.project_id}: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
565
|
+
raise InvalidAPIResponseException(f"Unable to export tool {tool_id} for project {self.project_id}: {response.text}")
|
|
566
566
|
|
|
567
567
|
return result
|
pygeai/lab/tools/mappers.py
CHANGED
|
@@ -37,8 +37,8 @@ class ToolMapper:
|
|
|
37
37
|
"""
|
|
38
38
|
return [
|
|
39
39
|
ToolMessage(
|
|
40
|
-
description=msg
|
|
41
|
-
type=msg
|
|
40
|
+
description=msg.get("description"),
|
|
41
|
+
type=msg.get("type")
|
|
42
42
|
)
|
|
43
43
|
for msg in messages_data
|
|
44
44
|
]
|
|
@@ -55,9 +55,9 @@ class ToolMapper:
|
|
|
55
55
|
"""
|
|
56
56
|
tool_data = data.get("tool", data)
|
|
57
57
|
|
|
58
|
-
name = tool_data
|
|
59
|
-
description = tool_data
|
|
60
|
-
scope = tool_data
|
|
58
|
+
name = tool_data.get("name")
|
|
59
|
+
description = tool_data.get("description")
|
|
60
|
+
scope = tool_data.get("scope")
|
|
61
61
|
parameter_data = tool_data.get("parameters")
|
|
62
62
|
parameters = cls._map_parameters(parameter_data) if parameter_data else None
|
|
63
63
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from unittest import TestCase
|
|
2
|
+
import uuid
|
|
3
|
+
from pygeai.assistant.managers import AssistantManager
|
|
4
|
+
from pygeai.core.models import WelcomeData, LlmSettings
|
|
5
|
+
from pygeai.assistant.rag.models import (
|
|
6
|
+
Search,
|
|
7
|
+
RetrieverOptions,
|
|
8
|
+
SearchOptions,
|
|
9
|
+
ChunkOptions,
|
|
10
|
+
IndexOptions,
|
|
11
|
+
RAGAssistant,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestAssistantCreateRagIntegration(TestCase):
|
|
16
|
+
|
|
17
|
+
def setUp(self):
|
|
18
|
+
"""
|
|
19
|
+
Set up the test environment.
|
|
20
|
+
"""
|
|
21
|
+
self.assistant_manager = AssistantManager(alias="beta")
|
|
22
|
+
|
|
23
|
+
self.new_rag = self.__load_rag()
|
|
24
|
+
self.created_rag: RAGAssistant = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def tearDown(self):
|
|
28
|
+
"""
|
|
29
|
+
Clean up after each test if necessary.
|
|
30
|
+
This can be used to delete the created tool
|
|
31
|
+
"""
|
|
32
|
+
if isinstance(self.created_rag, RAGAssistant):
|
|
33
|
+
self.assistant_manager.delete_assistant(assistant_name=self.created_rag.name)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def __load_rag(self):
|
|
37
|
+
llm_options = LlmSettings(
|
|
38
|
+
cache=False,
|
|
39
|
+
temperature=0.1,
|
|
40
|
+
max_tokens=999,
|
|
41
|
+
model_name="gpt-3.5-turbo-16k",
|
|
42
|
+
n=1,
|
|
43
|
+
presence_penalty=0,
|
|
44
|
+
frequency_penalty=0,
|
|
45
|
+
provider="OpenAI",
|
|
46
|
+
stream=False,
|
|
47
|
+
top_p=1.0,
|
|
48
|
+
type=None,
|
|
49
|
+
verbose=True,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
retriever_options = RetrieverOptions(type="vectorStore")
|
|
53
|
+
|
|
54
|
+
search_options = SearchOptions(
|
|
55
|
+
history_count=2,
|
|
56
|
+
llm=llm_options,
|
|
57
|
+
search=Search(
|
|
58
|
+
k=5,
|
|
59
|
+
return_source_documents=False,
|
|
60
|
+
score_threshold=0,
|
|
61
|
+
prompt="Use {context} and {question}",
|
|
62
|
+
template="",
|
|
63
|
+
),
|
|
64
|
+
retriever=retriever_options,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
chunk_options = ChunkOptions(chunk_size=999, chunk_overlap=0)
|
|
68
|
+
|
|
69
|
+
index_options = IndexOptions(chunks=chunk_options)
|
|
70
|
+
|
|
71
|
+
welcome_data = WelcomeData(
|
|
72
|
+
title="Test Profile Welcome Data",
|
|
73
|
+
description="Test Profile with WelcomeData",
|
|
74
|
+
features=[],
|
|
75
|
+
examples_prompt=[],
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return RAGAssistant(
|
|
79
|
+
name=str(uuid.uuid4()),
|
|
80
|
+
description="Test Profile with WelcomeData",
|
|
81
|
+
search_options=search_options,
|
|
82
|
+
index_options=index_options,
|
|
83
|
+
welcome_data=welcome_data,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_create_rag_assistant(self):
|
|
88
|
+
rag_assistant = self.__load_rag()
|
|
89
|
+
self.created_rag = self.assistant_manager.create_assistant(rag_assistant)
|
|
90
|
+
|
|
91
|
+
self.assertIsInstance(self.created_rag, RAGAssistant, "Failed to create RAG assistant")
|
|
File without changes
|