select-ai 1.1.0rc1__py3-none-any.whl → 1.2.0rc1__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 select-ai might be problematic. Click here for more details.

@@ -0,0 +1,24 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Copyright (c) 2025, Oracle and/or its affiliates.
3
+ #
4
+ # Licensed under the Universal Permissive License v 1.0 as shown at
5
+ # http://oss.oracle.com/licenses/upl.
6
+ # -----------------------------------------------------------------------------
7
+
8
+
9
+ from .core import Agent, AgentAttributes
10
+ from .task import Task, TaskAttributes
11
+ from .team import Team, TeamAttributes
12
+ from .tool import (
13
+ EmailNotificationToolParams,
14
+ HTTPToolParams,
15
+ HumanToolParams,
16
+ RAGToolParams,
17
+ SlackNotificationToolParams,
18
+ SQLToolParams,
19
+ Tool,
20
+ ToolAttributes,
21
+ ToolParams,
22
+ ToolType,
23
+ WebSearchToolParams,
24
+ )
@@ -0,0 +1,235 @@
1
+ # ------------------------------------------------------------------------------
2
+ # Copyright (c) 2025, Oracle and/or its affiliates.
3
+ #
4
+ # Licensed under the Universal Permissive License v 1.0 as shown at
5
+ # http://oss.oracle.com/licenses/upl.
6
+ # -----------------------------------------------------------------------------
7
+
8
+ import json
9
+ from abc import ABC
10
+ from dataclasses import dataclass
11
+ from typing import (
12
+ Any,
13
+ AsyncGenerator,
14
+ Iterator,
15
+ List,
16
+ Mapping,
17
+ Optional,
18
+ Union,
19
+ )
20
+
21
+ import oracledb
22
+
23
+ from select_ai import BaseProfile
24
+ from select_ai._abc import SelectAIDataClass
25
+ from select_ai._enums import StrEnum
26
+ from select_ai.agent.sql import (
27
+ GET_USER_AI_AGENT,
28
+ GET_USER_AI_AGENT_ATTRIBUTES,
29
+ LIST_USER_AI_AGENTS,
30
+ )
31
+ from select_ai.async_profile import AsyncProfile
32
+ from select_ai.db import async_cursor, cursor
33
+ from select_ai.errors import AgentNotFoundError
34
+ from select_ai.profile import Profile
35
+
36
+
37
+ @dataclass
38
+ class AgentAttributes(SelectAIDataClass):
39
+ """AI Agent Attributes
40
+
41
+ :param str profile_name: Name of the AI Profile which agent will
42
+ use to send request to LLM
43
+ :param str role: Agent's role also sent to LLM
44
+ :param bool enable_human_tool: Enable human tool support. Agent
45
+ will ask question to the user for any clarification
46
+ """
47
+
48
+ profile_name: str
49
+ role: str
50
+ enable_human_tool: Optional[bool] = True
51
+
52
+
53
+ class BaseAgent(ABC):
54
+
55
+ def __init__(
56
+ self,
57
+ agent_name: Optional[str] = None,
58
+ description: Optional[str] = None,
59
+ attributes: Optional[AgentAttributes] = None,
60
+ ):
61
+ if attributes is not None and not isinstance(
62
+ attributes, AgentAttributes
63
+ ):
64
+ raise TypeError(
65
+ "attributes must be an object of type "
66
+ "select_ai.agent.AgentAttributes"
67
+ )
68
+ self.agent_name = agent_name
69
+ self.description = description
70
+ self.attributes = attributes
71
+
72
+ def __repr__(self):
73
+ return (
74
+ f"{self.__class__.__name__}("
75
+ f"agent_name={self.agent_name}, "
76
+ f"attributes={self.attributes}, description={self.description})"
77
+ )
78
+
79
+
80
+ class Agent(BaseAgent):
81
+ """
82
+ select_ai.agent.Agent class lets you create, delete, enable, disable
83
+ and list AI agents
84
+
85
+ :param str agent_name: The name of the AI Agent
86
+ :param str description: Optional description of the AI agent
87
+ :param select_ai.agent.AgentAttributes attributes: AI agent attributes
88
+
89
+ """
90
+
91
+ @staticmethod
92
+ def _get_attributes(agent_name: str) -> AgentAttributes:
93
+ with cursor() as cr:
94
+ cr.execute(GET_USER_AI_AGENT, agent_name=agent_name.upper())
95
+ attributes = cr.fetchall()
96
+ if attributes:
97
+ post_processed_attributes = {}
98
+ for k, v in attributes:
99
+ if isinstance(v, oracledb.LOB):
100
+ post_processed_attributes[k] = v.read()
101
+ else:
102
+ post_processed_attributes[k] = v
103
+ return AgentAttributes(**post_processed_attributes)
104
+ else:
105
+ raise AgentNotFoundError(agent_name=agent_name)
106
+
107
+ def create(
108
+ self, enabled: Optional[bool] = True, replace: Optional[bool] = False
109
+ ):
110
+ """
111
+ Register a new AI Agent within the Select AI framework
112
+
113
+ :param bool enabled: Whether the AI Agent should be enabled.
114
+ Default value is True.
115
+
116
+ :param bool replace: Whether the AI Agent should be replaced.
117
+ Default value is False.
118
+
119
+ """
120
+ if self.agent_name is None:
121
+ raise AttributeError("Agent must have a name")
122
+ if self.attributes is None:
123
+ raise AttributeError("Agent must have attributes")
124
+
125
+ parameters = {
126
+ "agent_name": self.agent_name,
127
+ "attributes": self.attributes.json(),
128
+ }
129
+ if self.description:
130
+ parameters["description"] = self.description
131
+
132
+ if not enabled:
133
+ parameters["status"] = "disabled"
134
+
135
+ with cursor() as cr:
136
+ try:
137
+ cr.callproc(
138
+ "DBMS_CLOUD_AI_AGENT.CREATE_AGENT",
139
+ keyword_parameters=parameters,
140
+ )
141
+ except oracledb.Error as err:
142
+ (err_obj,) = err.args
143
+ if err_obj.code in (20050, 20052) and replace:
144
+ self.delete(force=True)
145
+ cr.callproc(
146
+ "DBMS_CLOUD_AI_AGENT.CREATE_AGENT",
147
+ keyword_parameters=parameters,
148
+ )
149
+ else:
150
+ raise
151
+
152
+ def delete(self, force: Optional[bool] = False):
153
+ """
154
+ Delete AI Agent from the database
155
+
156
+ :param bool force: Force the deletion. Default value is False.
157
+
158
+ """
159
+ with cursor() as cr:
160
+ cr.callproc(
161
+ "DBMS_CLOUD_AI_AGENT.DROP_AGENT",
162
+ keyword_parameters={
163
+ "agent_name": self.agent_name,
164
+ "force": force,
165
+ },
166
+ )
167
+
168
+ def disable(self):
169
+ """
170
+ Disable AI Agent
171
+
172
+ """
173
+ pass
174
+
175
+ def enable(self):
176
+ """
177
+ Enable AI Agent
178
+ """
179
+ pass
180
+
181
+ @classmethod
182
+ def fetch(cls, agent_name: str) -> "Agent":
183
+ """
184
+ Fetch AI Agent attributes from the Database and build a proxy object in
185
+ the Python layer
186
+
187
+ :param str agent_name: The name of the AI Agent
188
+
189
+ :return: select_ai.agent.Agent
190
+
191
+ :raises select_ai.errors.AgentNotFoundError:
192
+ If the AI Agent is not found
193
+
194
+ """
195
+ pass
196
+
197
+ @classmethod
198
+ def list(
199
+ cls, agent_name_pattern: Optional[str] = ".*"
200
+ ) -> Iterator["Agent"]:
201
+ """
202
+ List AI agents matching a pattern
203
+
204
+ :param str agent_name_pattern: Regular expressions can be used
205
+ to specify a pattern. Function REGEXP_LIKE is used to perform the
206
+ match. Default value is ".*" i.e. match all agent names.
207
+
208
+ :return: Iterator[Agent]
209
+ """
210
+ with cursor() as cr:
211
+ cr.execute(
212
+ LIST_USER_AI_AGENTS,
213
+ agent_name_pattern=agent_name_pattern,
214
+ )
215
+ for row in cr.fetchall():
216
+ agent_name = row[0]
217
+ if row[1]:
218
+ description = row[1].read() # Oracle.LOB
219
+ else:
220
+ description = None
221
+ attributes = cls._get_attributes(agent_name=agent_name)
222
+ yield cls(
223
+ agent_name=agent_name,
224
+ description=description,
225
+ attributes=attributes,
226
+ )
227
+
228
+ def set_attributes(self, attributes: AgentAttributes) -> None:
229
+ """
230
+ Set AI Agent attributes
231
+ """
232
+ pass
233
+
234
+ def set_attribute(self, attribute_name: str, attribute_value: Any) -> None:
235
+ pass
select_ai/agent/sql.py ADDED
@@ -0,0 +1,80 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Copyright (c) 2025, Oracle and/or its affiliates.
3
+ #
4
+ # Licensed under the Universal Permissive License v 1.0 as shown at
5
+ # http://oss.oracle.com/licenses/upl.
6
+ # -----------------------------------------------------------------------------
7
+
8
+
9
+ GET_USER_AI_AGENT = """
10
+ SELECT a.agent_name, a.description
11
+ from USER_AI_AGENTS a
12
+ where a.agent_name = :agent_name
13
+ """
14
+
15
+ GET_USER_AI_AGENT_ATTRIBUTES = """
16
+ SELECT attribute_name, attribute_value
17
+ FROM USER_AI_AGENT_ATTRIBUTES
18
+ WHERE agent_name = :agent_name
19
+ """
20
+
21
+ LIST_USER_AI_AGENTS = """
22
+ SELECT a.agent_name, a.description
23
+ from USER_AI_AGENTS a
24
+ where REGEXP_LIKE(a.agent_name, :agent_name_pattern, 'i')
25
+ """
26
+
27
+ GET_USER_AI_AGENT_TASK = """
28
+ SELECT t.task_name, t.description
29
+ FROM USER_AI_AGENT_TASKS t
30
+ WHERE t.task_name= :task_name
31
+ """
32
+
33
+ GET_USER_AI_AGENT_TASK_ATTRIBUTES = """
34
+ SELECT attribute_name, attribute_value
35
+ FROM USER_AI_AGENT_TASK_ATTRIBUTES
36
+ WHERE task_name= :task_name
37
+ """
38
+
39
+ LIST_USER_AI_AGENT_TASKS = """
40
+ SELECT t.task_name, t.description
41
+ FROM USER_AI_AGENT_TASKS t
42
+ WHERE REGEXP_LIKE(t.task_name, :task_name_pattern, 'i')
43
+ """
44
+
45
+ GET_USER_AI_TOOL = """
46
+ SELECT t.tool_name, t.description
47
+ FROM USER_AI_AGENT_TOOLS t
48
+ WHERE t.tool_name = :tool_name
49
+ """
50
+
51
+ GET_USER_AI_AGENT_TOOL_ATTRIBUTES = """
52
+ SELECT attribute_name, attribute_value
53
+ FROM USER_AI_AGENT_TOOL_ATTRIBUTES
54
+ WHERE tool_name = :tool_name
55
+ """
56
+
57
+ LIST_USER_AI_AGENT_TOOLS = """
58
+ SELECT t.tool_name, t.description
59
+ FROM USER_AI_AGENT_TOOLS t
60
+ WHERE REGEXP_LIKE(t.tool_name, :tool_name_pattern, 'i')
61
+ """
62
+
63
+
64
+ GET_USER_AI_AGENT_TEAM = """
65
+ SELECT t.tool_name, t.description
66
+ FROM USER_AI_AGENT_TEAMS t
67
+ WHERE t.team_name = :team_name
68
+ """
69
+
70
+ GET_USER_AI_AGENT_TEAM_ATTRIBUTES = """
71
+ SELECT attribute_name, attribute_value
72
+ FROM USER_AI_AGENT_TEAM_ATTRIBUTES
73
+ WHERE team_name = :team_name
74
+ """
75
+
76
+ LIST_USER_AI_AGENT_TEAMS = """
77
+ SELECT t.tool_name, t.description
78
+ FROM USER_AI_AGENT_TEAMS t
79
+ WHERE REGEXP_LIKE(t.team_name, :team_name_pattern, 'i')
80
+ """
@@ -0,0 +1,247 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Copyright (c) 2025, Oracle and/or its affiliates.
3
+ #
4
+ # Licensed under the Universal Permissive License v 1.0 as shown at
5
+ # http://oss.oracle.com/licenses/upl.
6
+ # -----------------------------------------------------------------------------
7
+
8
+ import json
9
+ from abc import ABC
10
+ from dataclasses import dataclass
11
+ from typing import (
12
+ Any,
13
+ AsyncGenerator,
14
+ Iterator,
15
+ List,
16
+ Mapping,
17
+ Optional,
18
+ Union,
19
+ )
20
+
21
+ import oracledb
22
+
23
+ from select_ai import BaseProfile
24
+ from select_ai._abc import SelectAIDataClass
25
+ from select_ai._enums import StrEnum
26
+ from select_ai.agent.sql import (
27
+ GET_USER_AI_AGENT_TASK,
28
+ GET_USER_AI_AGENT_TASK_ATTRIBUTES,
29
+ LIST_USER_AI_AGENT_TASKS,
30
+ )
31
+ from select_ai.async_profile import AsyncProfile
32
+ from select_ai.db import async_cursor, cursor
33
+ from select_ai.errors import AgentTaskNotFoundError
34
+ from select_ai.profile import Profile
35
+
36
+
37
+ @dataclass
38
+ class TaskAttributes(SelectAIDataClass):
39
+ """AI Task attributes
40
+
41
+ :param str instruction: Statement describing what the task is
42
+ meant to accomplish
43
+
44
+ :param List[str] tools: List of tools the agent can use to
45
+ execute the task
46
+
47
+ :param str input: Task name whose output will be automatically
48
+ provided by select ai to LLM
49
+
50
+ :param bool enable_human_tool: Enable agent to ask question
51
+ to user when it requires information or clarification
52
+ during a task. Default value is True.
53
+
54
+ """
55
+
56
+ instruction: str
57
+ tools: Optional[List[str]] = None
58
+ input: Optional[str] = None
59
+ enable_human_tool: Optional[bool] = True
60
+
61
+
62
+ class BaseTask(ABC):
63
+
64
+ def __init__(
65
+ self,
66
+ task_name: Optional[str] = None,
67
+ description: Optional[str] = None,
68
+ attributes: Optional[TaskAttributes] = None,
69
+ ):
70
+ if attributes and not isinstance(attributes, TaskAttributes):
71
+ raise TypeError(
72
+ "'attributes' must be an object of type "
73
+ "select_ai.agent.TaskAttributes"
74
+ )
75
+ self.task_name = task_name
76
+ self.description = description
77
+ self.attributes = attributes
78
+
79
+ def __repr__(self):
80
+ return (
81
+ f"{self.__class__.__name__}("
82
+ f"task_name={self.task_name}, "
83
+ f"attributes={self.attributes}, description={self.description})"
84
+ )
85
+
86
+
87
+ class Task(BaseTask):
88
+ """
89
+ select_ai.agent.Task class lets you create, delete, enable, disable and
90
+ list AI Tasks
91
+
92
+ :param str task_name: The name of the AI task
93
+ :param str description: Optional description of the AI task
94
+ :param select_ai.agent.TaskAttributes attributes: AI task attributes
95
+
96
+ """
97
+
98
+ @staticmethod
99
+ def _get_attributes(task_name: str) -> TaskAttributes:
100
+ with cursor() as cr:
101
+ cr.execute(
102
+ GET_USER_AI_AGENT_TASK_ATTRIBUTES, task_name=task_name.upper()
103
+ )
104
+ attributes = cr.fetchall()
105
+ if attributes:
106
+ post_processed_attributes = {}
107
+ for k, v in attributes:
108
+ if isinstance(v, oracledb.LOB):
109
+ post_processed_attributes[k] = v.read()
110
+ else:
111
+ post_processed_attributes[k] = v
112
+ return TaskAttributes(**post_processed_attributes)
113
+ else:
114
+ raise AgentTaskNotFoundError(task_name=task_name)
115
+
116
+ def create(
117
+ self, enabled: Optional[bool] = True, replace: Optional[bool] = False
118
+ ):
119
+ """
120
+ Create a task that a Select AI agent can include in its
121
+ reasoning process
122
+
123
+ :param bool enabled: Whether the AI Task should be enabled.
124
+ Default value is True.
125
+
126
+ :param bool replace: Whether the AI Task should be replaced.
127
+ Default value is False.
128
+
129
+ """
130
+ if self.task_name is None:
131
+ raise AttributeError("Task must have a name")
132
+ if self.attributes is None:
133
+ raise AttributeError("Task must have attributes")
134
+
135
+ parameters = {
136
+ "task_name": self.task_name,
137
+ "attributes": self.attributes.json(),
138
+ }
139
+
140
+ if self.description:
141
+ parameters["description"] = self.description
142
+
143
+ if not enabled:
144
+ parameters["status"] = "disabled"
145
+
146
+ with cursor() as cr:
147
+ try:
148
+ cr.callproc(
149
+ "DBMS_CLOUD_AI_AGENT.CREATE_TASK",
150
+ keyword_parameters=parameters,
151
+ )
152
+ except oracledb.Error as err:
153
+ (err_obj,) = err.args
154
+ if err_obj.code in (20051, 20052) and replace:
155
+ self.delete(force=True)
156
+ cr.callproc(
157
+ "DBMS_CLOUD_AI_AGENT.CREATE_TASK",
158
+ keyword_parameters=parameters,
159
+ )
160
+ else:
161
+ raise
162
+
163
+ def delete(self, force: bool = False):
164
+ """
165
+ Delete AI Task from the database
166
+
167
+ :param bool force: Force the deletion. Default value is False.
168
+ """
169
+ with cursor() as cr:
170
+ cr.callproc(
171
+ "DBMS_CLOUD_AI_AGENT.DROP_TASK",
172
+ keyword_parameters={
173
+ "task_name": self.task_name,
174
+ "force": force,
175
+ },
176
+ )
177
+
178
+ def disable(self):
179
+ """
180
+ Disable AI Task
181
+ """
182
+ pass
183
+
184
+ def enable(self):
185
+ """
186
+ Enable AI Task
187
+ """
188
+ pass
189
+
190
+ @classmethod
191
+ def list(cls, task_name_pattern: Optional[str] = ".*") -> Iterator["Task"]:
192
+ """List AI Tasks
193
+
194
+ :param str task_name_pattern: Regular expressions can be used
195
+ to specify a pattern. Function REGEXP_LIKE is used to perform the
196
+ match. Default value is ".*" i.e. match all tasks.
197
+
198
+ :return: Iterator[Task]
199
+ """
200
+ with cursor() as cr:
201
+ cr.execute(
202
+ LIST_USER_AI_AGENT_TASKS,
203
+ task_name_pattern=task_name_pattern,
204
+ )
205
+ for row in cr.fetchall():
206
+ task_name = row[0]
207
+ if row[1]:
208
+ description = row[1].read() # Oracle.LOB
209
+ else:
210
+ description = None
211
+ attributes = cls._get_attributes(task_name=task_name)
212
+ yield cls(
213
+ task_name=task_name,
214
+ description=description,
215
+ attributes=attributes,
216
+ )
217
+
218
+ @classmethod
219
+ def fetch(cls, task_name: str) -> "Task":
220
+ """
221
+ Fetch AI Task attributes from the Database and build a proxy object in
222
+ the Python layer
223
+
224
+ :param str task_name: The name of the AI Task
225
+
226
+ :return: select_ai.agent.Task
227
+
228
+ :raises select_ai.errors.AgentTaskNotFoundError:
229
+ If the AI Task is not found
230
+ """
231
+ pass
232
+
233
+ def set_attributes(self, attributes: TaskAttributes):
234
+ """
235
+ Set AI Task attributes
236
+ """
237
+ pass
238
+
239
+ def set_attribute(self, attribute_name: str, attribute_value: Any):
240
+ """
241
+ Set a single AI Task attribute specified using name and value
242
+ """
243
+ pass
244
+
245
+
246
+ class AsyncTask(BaseTask):
247
+ pass