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
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
from unittest import TestCase
|
|
2
|
+
from pygeai.chat.clients import ChatClient
|
|
3
|
+
|
|
4
|
+
chat_client: ChatClient
|
|
5
|
+
|
|
6
|
+
class TestChatGenerateImageIntegration(TestCase):
|
|
7
|
+
|
|
8
|
+
def setUp(self):
|
|
9
|
+
self.chat_client = ChatClient(alias="beta")
|
|
10
|
+
self.new_image = self.__load_image()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def __load_image(self):
|
|
14
|
+
return {
|
|
15
|
+
"model": "openai/gpt-image-1",
|
|
16
|
+
"prompt": "generate an image of a futuristic city skyline at sunset",
|
|
17
|
+
"n": 1,
|
|
18
|
+
"quality": "high",
|
|
19
|
+
"size": "1024x1536"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def __generate_image(self, image = None):
|
|
24
|
+
image = image if image is not None else self.new_image
|
|
25
|
+
return self.chat_client.generate_image(
|
|
26
|
+
model=image["model"],
|
|
27
|
+
prompt=image["prompt"],
|
|
28
|
+
n=image["n"],
|
|
29
|
+
quality=image["quality"],
|
|
30
|
+
size=image["size"],
|
|
31
|
+
aspect_ratio= image["aspect_ratio"] if "aspect_ratio" in image else None
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_generate_image(self):
|
|
36
|
+
created_image = self.__generate_image()
|
|
37
|
+
self.assertEqual(len(created_image["data"]), 1, "Expected an image to be generated")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_generate_image_invalid_model(self):
|
|
41
|
+
self.new_image["model"] = "openai/gpt-image-10",
|
|
42
|
+
created_image = self.__generate_image()
|
|
43
|
+
|
|
44
|
+
self.assertEqual(
|
|
45
|
+
created_image["error"]["code"], 400,
|
|
46
|
+
"Expected a 400 code for invalid model"
|
|
47
|
+
)
|
|
48
|
+
self.assertEqual(
|
|
49
|
+
created_image["error"]["message"],
|
|
50
|
+
'Provider \'["openai\' does not exists.',
|
|
51
|
+
"Expected an error message when model does not exists"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_generate_image_no_model(self):
|
|
56
|
+
self.new_image["model"] = ""
|
|
57
|
+
created_image = self.__generate_image()
|
|
58
|
+
|
|
59
|
+
self.assertEqual(
|
|
60
|
+
created_image["error"]["message"],
|
|
61
|
+
"LLM Provider NOT provided. Pass in the LLM provider you are trying to call",
|
|
62
|
+
"Expected an error message when no model is provided"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_generate_image_no_prompt(self):
|
|
67
|
+
self.new_image["prompt"] = ""
|
|
68
|
+
created_image = self.__generate_image()
|
|
69
|
+
|
|
70
|
+
self.assertEqual(
|
|
71
|
+
created_image["error"]["type"],
|
|
72
|
+
"invalid_request_error",
|
|
73
|
+
"Expected a 400 code for no model"
|
|
74
|
+
)
|
|
75
|
+
self.assertEqual(
|
|
76
|
+
created_image["error"]["param"], "prompt",
|
|
77
|
+
"Expected an error message when no model is provided"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_generate_image_specific_n(self):
|
|
82
|
+
self.new_image["n"] = 2
|
|
83
|
+
|
|
84
|
+
created_image = self.__generate_image()
|
|
85
|
+
self.assertEqual(len(created_image["data"]), 2, "Expected two images to be generated")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_generate_image_no_n(self):
|
|
89
|
+
self.new_image["n"] = None # default is 1
|
|
90
|
+
|
|
91
|
+
created_image = self.__generate_image()
|
|
92
|
+
self.assertEqual(len(created_image["data"]), 1, "Expected an image to be generated")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_generate_image_no_supported_n(self):
|
|
96
|
+
self.new_image["model"] = "openai/dall-e-3"
|
|
97
|
+
self.new_image["n"] = 5
|
|
98
|
+
|
|
99
|
+
created_image = self.__generate_image()
|
|
100
|
+
self.assertIn(
|
|
101
|
+
"Invalid 'n': integer above maximum value",
|
|
102
|
+
created_image["error"]["message"],
|
|
103
|
+
"Expected an error message when n is not supported by the model"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_generate_image_no_quality(self):
|
|
108
|
+
self.new_image["quality"] = ""
|
|
109
|
+
|
|
110
|
+
created_image = self.__generate_image()
|
|
111
|
+
self.assertIn(
|
|
112
|
+
"Invalid value: ''. Supported values are: 'low', 'medium', 'high', and 'auto'",
|
|
113
|
+
created_image["error"]["message"],
|
|
114
|
+
"Expected an error message when quality is not provided"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_generate_image_no_supported_quality(self):
|
|
119
|
+
self.new_image["model"] = "openai/dall-e-3"
|
|
120
|
+
|
|
121
|
+
created_image = self.__generate_image()
|
|
122
|
+
self.assertIn(
|
|
123
|
+
"Invalid value: 'high'. Supported values are: 'standard' and 'hd'",
|
|
124
|
+
created_image["error"]["message"],
|
|
125
|
+
"Expected an error message when quality is not supported by the model"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_generate_image_no_size(self):
|
|
130
|
+
self.new_image["size"] = ""
|
|
131
|
+
|
|
132
|
+
created_image = self.__generate_image()
|
|
133
|
+
self.assertIn(
|
|
134
|
+
"Invalid value: ''. Supported values are: '1024x1024', '1024x1536', '1536x1024', and 'auto'",
|
|
135
|
+
created_image["error"]["message"],
|
|
136
|
+
"Expected an error message when no size is provided"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_generate_image_no_supported_size(self):
|
|
141
|
+
self.new_image["size"] = 1024
|
|
142
|
+
self.new_image["quality"] = None
|
|
143
|
+
|
|
144
|
+
created_image = self.__generate_image()
|
|
145
|
+
self.assertIn(
|
|
146
|
+
"Invalid type for 'size': expected one of '1024x1024', '1024x1536', '1536x1024', or 'auto', but got an integer instead",
|
|
147
|
+
created_image["error"]["message"],
|
|
148
|
+
"Expected an error message when no size is provided"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_generate_image_with_aspect_ratio(self):
|
|
153
|
+
self.new_image["model"] = "vertex_ai/imagen-3.0-generate-001"
|
|
154
|
+
self.new_image["aspect_ratio"] = "4:3"
|
|
155
|
+
self.new_image["quality"] = None
|
|
156
|
+
|
|
157
|
+
created_image = self.__generate_image()
|
|
158
|
+
self.assertEqual(len(created_image["data"]), 1, "Expected an image to be generated")
|
|
@@ -33,7 +33,6 @@ class TestAILabCreateAgentIntegration(TestCase):
|
|
|
33
33
|
access_scope="public",
|
|
34
34
|
public_name=f"public_{random_str}",
|
|
35
35
|
job_description="Translator",
|
|
36
|
-
avatar_image="https://www.shareicon.net/data/128x128/2016/11/09/851442_logo_512x512.png",
|
|
37
36
|
description="Agent that translates from any language to english.",
|
|
38
37
|
agent_data=AgentData(
|
|
39
38
|
prompt=Prompt(
|
|
@@ -142,7 +141,6 @@ class TestAILabCreateAgentIntegration(TestCase):
|
|
|
142
141
|
self.assertEqual(prompt.inputs, agent.agent_data.prompt.inputs)
|
|
143
142
|
|
|
144
143
|
|
|
145
|
-
@unittest.skip("Skipping test due to mismatch in expected behavior")
|
|
146
144
|
def test_create_agent_without_required_data(self):
|
|
147
145
|
test_params = [ True, False ]
|
|
148
146
|
|
|
@@ -152,12 +150,19 @@ class TestAILabCreateAgentIntegration(TestCase):
|
|
|
152
150
|
self.new_agent = Agent(
|
|
153
151
|
name=str(uuid.uuid4())
|
|
154
152
|
)
|
|
155
|
-
|
|
156
|
-
|
|
153
|
+
if auto_publish:
|
|
154
|
+
|
|
155
|
+
with self.assertRaises(APIError) as exception:
|
|
156
|
+
self.__create_agent(automatic_publish=auto_publish)
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
#TODO: Change validation error to a more specific one
|
|
159
|
+
self.assertIn(
|
|
160
|
+
"A valid prompt is required. To be valid, it must provide clear instructions to the model",
|
|
161
|
+
str(exception.exception)
|
|
162
|
+
)
|
|
163
|
+
else:
|
|
164
|
+
created_agent = self.__create_agent(automatic_publish=auto_publish)
|
|
165
|
+
self.assertTrue(isinstance(created_agent, Agent), "Expected a created agent")
|
|
161
166
|
|
|
162
167
|
|
|
163
168
|
def test_create_agent_no_name(self):
|
|
@@ -287,21 +292,18 @@ class TestAILabCreateAgentIntegration(TestCase):
|
|
|
287
292
|
)
|
|
288
293
|
|
|
289
294
|
|
|
290
|
-
@unittest.skip("Agent is getting created regardless of the prompt instructions being empty")
|
|
291
295
|
def test_create_agent_no_prompt_instructions(self):
|
|
292
296
|
self.new_agent.agent_data.prompt.instructions = ""
|
|
293
|
-
|
|
294
|
-
self.__create_agent()
|
|
295
|
-
self.assertIn(
|
|
296
|
-
"instructions",
|
|
297
|
-
str(exception.exception),
|
|
298
|
-
"Expected a validation error about allowed values for instructions"
|
|
299
|
-
)
|
|
297
|
+
self.created_agent = self.__create_agent()
|
|
300
298
|
|
|
301
|
-
self.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
299
|
+
self.assertTrue(
|
|
300
|
+
isinstance(self.created_agent, Agent),
|
|
301
|
+
"Expected a created agent"
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
self.assertIsNone(
|
|
305
|
+
self.created_agent.agent_data.prompt.instructions,
|
|
306
|
+
"Expected the created agent to not have prompt instructions"
|
|
305
307
|
)
|
|
306
308
|
|
|
307
309
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from unittest import TestCase
|
|
2
|
+
import unittest
|
|
2
3
|
from pygeai.lab.managers import AILabManager
|
|
3
4
|
from pygeai.lab.models import SharingLink
|
|
4
5
|
from pygeai.core.common.exceptions import APIError, MissingRequirementException
|
|
@@ -16,7 +17,7 @@ class TestAILabCreateSharingLinkIntegration(TestCase):
|
|
|
16
17
|
agent_id=self.agent_id if agent_id is None else agent_id
|
|
17
18
|
)
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
@unittest.skip("Endpoint is not found. Validate if it was deleted")
|
|
20
21
|
def test_create_sharing_link(self):
|
|
21
22
|
shared_link = self.__create_sharing_link()
|
|
22
23
|
self.assertIsInstance(shared_link, SharingLink, "Expected response to be an instance of SharingLink")
|
|
@@ -46,6 +47,7 @@ class TestAILabCreateSharingLinkIntegration(TestCase):
|
|
|
46
47
|
)
|
|
47
48
|
|
|
48
49
|
|
|
50
|
+
@unittest.skip("Endpoint is not found. Validate if it was deleted")
|
|
49
51
|
def test_create_sharing_link_no_agent_id(self):
|
|
50
52
|
with self.assertRaises(MissingRequirementException) as context:
|
|
51
53
|
self.__create_sharing_link(agent_id="")
|
|
@@ -56,6 +58,7 @@ class TestAILabCreateSharingLinkIntegration(TestCase):
|
|
|
56
58
|
)
|
|
57
59
|
|
|
58
60
|
|
|
61
|
+
@unittest.skip("Endpoint is not found. Validate if it was deleted")
|
|
59
62
|
def test_create_sharing_link_invalid_agent_id(self):
|
|
60
63
|
with self.assertRaises(APIError) as exception:
|
|
61
64
|
invalid_id = "0026e53d-ea78-4cac-af9f-12650invalid"
|
|
@@ -28,7 +28,6 @@ class TestAILabPublishAgentRevisionIntegration(TestCase):
|
|
|
28
28
|
access_scope="public",
|
|
29
29
|
public_name=f"public_{random_str}",
|
|
30
30
|
job_description=f"SummarizerAgent{random_str}",
|
|
31
|
-
avatar_image="https://www.shareicon.net/data/128x128/2016/11/09/851442_logo_512x512.png",
|
|
32
31
|
description=f"Agent that summarized documents. {random_str}",
|
|
33
32
|
agent_data=AgentData(
|
|
34
33
|
prompt=Prompt(
|
|
@@ -25,7 +25,6 @@ class TestAILabUpdateAgentIntegration(TestCase):
|
|
|
25
25
|
access_scope="public",
|
|
26
26
|
public_name=f"public_{random_str}",
|
|
27
27
|
job_description=f"SummarizerAgent{random_str}",
|
|
28
|
-
avatar_image="https://www.shareicon.net/data/128x128/2016/11/09/851442_logo_512x512.png",
|
|
29
28
|
description=f"Agent that summarized documents. {random_str}",
|
|
30
29
|
agent_data=AgentData(
|
|
31
30
|
prompt=Prompt(
|
|
@@ -192,43 +191,32 @@ class TestAILabUpdateAgentIntegration(TestCase):
|
|
|
192
191
|
self.agent_to_update.agent_data.prompt.instructions = ""
|
|
193
192
|
|
|
194
193
|
for auto_publish in test_params:
|
|
195
|
-
with self.subTest(input=auto_publish):
|
|
196
|
-
|
|
197
|
-
self.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
f"Expected a validation error about allowed values for instructions when autopublish is {'enabled' if auto_publish else 'disabled'}"
|
|
208
|
-
)
|
|
194
|
+
with self.subTest(input=auto_publish):
|
|
195
|
+
if auto_publish == True:
|
|
196
|
+
with self.assertRaises(ValidationError) as exception:
|
|
197
|
+
self.__update_agent(automatic_publish=auto_publish)
|
|
198
|
+
self.assertIn(
|
|
199
|
+
"agent_data.prompt must have at least instructions for publication",
|
|
200
|
+
str(exception.exception),
|
|
201
|
+
f"Expected a validation error about allowed values for instructions when autopublish is {'enabled' if auto_publish else 'disabled'}"
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
updated_agent = self.__update_agent(automatic_publish=auto_publish)
|
|
205
|
+
self.assertTrue(isinstance(updated_agent, Agent))
|
|
209
206
|
|
|
210
|
-
|
|
211
|
-
def test_update_agent_no_model(self):
|
|
207
|
+
|
|
208
|
+
def test_update_agent_no_model(self):
|
|
212
209
|
test_params = [ True, False ]
|
|
213
210
|
self.agent_to_update.agent_data.models[0].name = ""
|
|
214
211
|
|
|
215
212
|
for auto_publish in test_params:
|
|
216
213
|
with self.subTest(input=auto_publish):
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
214
|
+
|
|
215
|
+
# If the agent is not published, the API returns a warning message for invalid model name. However, the sdk mapping is not returning it.
|
|
216
|
+
if auto_publish == False:
|
|
217
|
+
updated_agent = self.__update_agent(automatic_publish=auto_publish)
|
|
221
218
|
|
|
222
|
-
self.
|
|
223
|
-
"name",
|
|
224
|
-
error_msg,
|
|
225
|
-
"Expected a validation error about empty model name"
|
|
226
|
-
)
|
|
227
|
-
self.assertIn(
|
|
228
|
-
"Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]",
|
|
229
|
-
error_msg,
|
|
230
|
-
"Expected a validation error about empty model name"
|
|
231
|
-
)
|
|
219
|
+
self.assertTrue(isinstance(updated_agent, Agent))
|
|
232
220
|
else:
|
|
233
221
|
with self.assertRaises(APIError) as exception:
|
|
234
222
|
self.__update_agent(automatic_publish=auto_publish)
|
|
File without changes
|