ibm-watsonx-orchestrate 1.0.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.
- ibm_watsonx_orchestrate/__init__.py +28 -0
- ibm_watsonx_orchestrate/agent_builder/__init__.py +0 -0
- ibm_watsonx_orchestrate/agent_builder/agents/__init__.py +5 -0
- ibm_watsonx_orchestrate/agent_builder/agents/agent.py +27 -0
- ibm_watsonx_orchestrate/agent_builder/agents/assistant_agent.py +28 -0
- ibm_watsonx_orchestrate/agent_builder/agents/external_agent.py +28 -0
- ibm_watsonx_orchestrate/agent_builder/agents/types.py +204 -0
- ibm_watsonx_orchestrate/agent_builder/connections/__init__.py +27 -0
- ibm_watsonx_orchestrate/agent_builder/connections/connections.py +123 -0
- ibm_watsonx_orchestrate/agent_builder/connections/types.py +260 -0
- ibm_watsonx_orchestrate/agent_builder/knowledge_bases/knowledge_base.py +27 -0
- ibm_watsonx_orchestrate/agent_builder/knowledge_bases/knowledge_base_requests.py +59 -0
- ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +243 -0
- ibm_watsonx_orchestrate/agent_builder/tools/__init__.py +4 -0
- ibm_watsonx_orchestrate/agent_builder/tools/base_tool.py +36 -0
- ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +332 -0
- ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +195 -0
- ibm_watsonx_orchestrate/agent_builder/tools/types.py +162 -0
- ibm_watsonx_orchestrate/agent_builder/utils/__init__.py +0 -0
- ibm_watsonx_orchestrate/agent_builder/utils/pydantic_utils.py +149 -0
- ibm_watsonx_orchestrate/cli/__init__.py +0 -0
- ibm_watsonx_orchestrate/cli/commands/__init__.py +0 -0
- ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +192 -0
- ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +660 -0
- ibm_watsonx_orchestrate/cli/commands/channels/channels_command.py +15 -0
- ibm_watsonx_orchestrate/cli/commands/channels/channels_controller.py +16 -0
- ibm_watsonx_orchestrate/cli/commands/channels/types.py +15 -0
- ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_command.py +32 -0
- ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py +141 -0
- ibm_watsonx_orchestrate/cli/commands/chat/chat_command.py +43 -0
- ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +307 -0
- ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +517 -0
- ibm_watsonx_orchestrate/cli/commands/environment/environment_command.py +78 -0
- ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +189 -0
- ibm_watsonx_orchestrate/cli/commands/environment/types.py +9 -0
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py +79 -0
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +201 -0
- ibm_watsonx_orchestrate/cli/commands/login/login_command.py +17 -0
- ibm_watsonx_orchestrate/cli/commands/models/models_command.py +128 -0
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py +623 -0
- ibm_watsonx_orchestrate/cli/commands/settings/__init__.py +0 -0
- ibm_watsonx_orchestrate/cli/commands/settings/observability/__init__.py +0 -0
- ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/__init__.py +0 -0
- ibm_watsonx_orchestrate/cli/commands/settings/observability/langfuse/langfuse_command.py +175 -0
- ibm_watsonx_orchestrate/cli/commands/settings/observability/observability_command.py +11 -0
- ibm_watsonx_orchestrate/cli/commands/settings/settings_command.py +10 -0
- ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py +85 -0
- ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +564 -0
- ibm_watsonx_orchestrate/cli/commands/tools/types.py +10 -0
- ibm_watsonx_orchestrate/cli/config.py +226 -0
- ibm_watsonx_orchestrate/cli/main.py +32 -0
- ibm_watsonx_orchestrate/client/__init__.py +0 -0
- ibm_watsonx_orchestrate/client/agents/agent_client.py +46 -0
- ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py +38 -0
- ibm_watsonx_orchestrate/client/agents/external_agent_client.py +38 -0
- ibm_watsonx_orchestrate/client/analytics/__init__.py +0 -0
- ibm_watsonx_orchestrate/client/analytics/llm/__init__.py +0 -0
- ibm_watsonx_orchestrate/client/analytics/llm/analytics_llm_client.py +50 -0
- ibm_watsonx_orchestrate/client/base_api_client.py +113 -0
- ibm_watsonx_orchestrate/client/base_service_instance.py +10 -0
- ibm_watsonx_orchestrate/client/client.py +71 -0
- ibm_watsonx_orchestrate/client/client_errors.py +359 -0
- ibm_watsonx_orchestrate/client/connections/__init__.py +10 -0
- ibm_watsonx_orchestrate/client/connections/connections_client.py +162 -0
- ibm_watsonx_orchestrate/client/connections/utils.py +27 -0
- ibm_watsonx_orchestrate/client/credentials.py +123 -0
- ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py +46 -0
- ibm_watsonx_orchestrate/client/local_service_instance.py +91 -0
- ibm_watsonx_orchestrate/client/service_instance.py +73 -0
- ibm_watsonx_orchestrate/client/tools/tool_client.py +41 -0
- ibm_watsonx_orchestrate/client/utils.py +95 -0
- ibm_watsonx_orchestrate/docker/compose-lite.yml +595 -0
- ibm_watsonx_orchestrate/docker/default.env +125 -0
- ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0-py3-none-any.whl +0 -0
- ibm_watsonx_orchestrate/docker/sdk/ibm_watsonx_orchestrate-0.6.0.tar.gz +0 -0
- ibm_watsonx_orchestrate/docker/start-up.sh +61 -0
- ibm_watsonx_orchestrate/docker/tempus/common-config.yaml +1 -0
- ibm_watsonx_orchestrate/run/__init__.py +0 -0
- ibm_watsonx_orchestrate/run/connections.py +40 -0
- ibm_watsonx_orchestrate/utils/__init__.py +0 -0
- ibm_watsonx_orchestrate/utils/logging/__init__.py +0 -0
- ibm_watsonx_orchestrate/utils/logging/logger.py +26 -0
- ibm_watsonx_orchestrate/utils/logging/logging.yaml +18 -0
- ibm_watsonx_orchestrate/utils/utils.py +15 -0
- ibm_watsonx_orchestrate-1.0.0.dist-info/METADATA +34 -0
- ibm_watsonx_orchestrate-1.0.0.dist-info/RECORD +89 -0
- ibm_watsonx_orchestrate-1.0.0.dist-info/WHEEL +4 -0
- ibm_watsonx_orchestrate-1.0.0.dist-info/entry_points.txt +2 -0
- ibm_watsonx_orchestrate-1.0.0.dist-info/licenses/LICENSE +22 -0
@@ -0,0 +1,260 @@
|
|
1
|
+
from pydantic import BaseModel, Field, AliasChoices, model_validator
|
2
|
+
from typing import Optional, Union, TypeVar, List
|
3
|
+
from enum import Enum
|
4
|
+
|
5
|
+
class ConnectionKind(str, Enum):
|
6
|
+
basic = 'basic'
|
7
|
+
bearer = 'bearer'
|
8
|
+
api_key = 'api_key'
|
9
|
+
# oauth_auth_code_flow = 'oauth_auth_code_flow'
|
10
|
+
# oauth_auth_implicit_flow = 'oauth_auth_implicit_flow'
|
11
|
+
# oauth_auth_password_flow = 'oauth_auth_password_flow'
|
12
|
+
# oauth_auth_client_credentials_flow = 'oauth_auth_client_credentials_flow'
|
13
|
+
oauth_auth_on_behalf_of_flow = 'oauth_auth_on_behalf_of_flow'
|
14
|
+
key_value = 'key_value'
|
15
|
+
kv = 'kv'
|
16
|
+
|
17
|
+
def __str__(self):
|
18
|
+
return self.value
|
19
|
+
|
20
|
+
class ConnectionEnvironment(str, Enum):
|
21
|
+
DRAFT = 'draft'
|
22
|
+
LIVE = 'live'
|
23
|
+
|
24
|
+
def __str__(self):
|
25
|
+
return self.value
|
26
|
+
|
27
|
+
class ConnectionPreference(str, Enum):
|
28
|
+
MEMBER = 'member'
|
29
|
+
TEAM = 'team'
|
30
|
+
|
31
|
+
def __str__(self):
|
32
|
+
return self.value
|
33
|
+
|
34
|
+
class ConnectionAuthType(str, Enum):
|
35
|
+
# OAUTH2_AUTH_CODE = 'oauth2_auth_code'
|
36
|
+
# OAUTH2_IMPLICIT = 'oauth2_implicit'
|
37
|
+
# OAUTH2_PASSWORD = 'oauth2_password'
|
38
|
+
# OAUTH2_CLIENT_CREDS = 'oauth2_client_creds'
|
39
|
+
OAUTH_ON_BEHALF_OF_FLOW = 'oauth_on_behalf_of_flow'
|
40
|
+
|
41
|
+
def __str__(self):
|
42
|
+
return self.value
|
43
|
+
|
44
|
+
def __repr__(self):
|
45
|
+
return repr(self.value)
|
46
|
+
|
47
|
+
class ConnectionSecurityScheme(str, Enum):
|
48
|
+
BASIC_AUTH = 'basic_auth'
|
49
|
+
BEARER_TOKEN = 'bearer_token'
|
50
|
+
API_KEY_AUTH = 'api_key_auth'
|
51
|
+
OAUTH2 = 'oauth2'
|
52
|
+
KEY_VALUE = 'key_value_creds'
|
53
|
+
|
54
|
+
def __str__(self):
|
55
|
+
return self.value
|
56
|
+
|
57
|
+
def __repr__(self):
|
58
|
+
return repr(self.value)
|
59
|
+
|
60
|
+
# Values for python tool expected credentials
|
61
|
+
# Line up with what the Security_Schema env var is
|
62
|
+
class ConnectionType(str, Enum):
|
63
|
+
BASIC_AUTH = ConnectionSecurityScheme.BASIC_AUTH.value
|
64
|
+
BEARER_TOKEN = ConnectionSecurityScheme.BEARER_TOKEN.value
|
65
|
+
API_KEY_AUTH = ConnectionSecurityScheme.API_KEY_AUTH.value
|
66
|
+
# OAUTH2_AUTH_CODE = ConnectionAuthType.OAUTH2_AUTH_CODE.value
|
67
|
+
# OAUTH2_IMPLICIT = ConnectionAuthType.OAUTH2_IMPLICIT.value
|
68
|
+
# OAUTH2_PASSWORD = ConnectionAuthType.OAUTH2_PASSWORD.value
|
69
|
+
# OAUTH2_CLIENT_CREDS = ConnectionAuthType.OAUTH2_CLIENT_CREDS.value
|
70
|
+
OAUTH_ON_BEHALF_OF_FLOW = ConnectionAuthType.OAUTH_ON_BEHALF_OF_FLOW.value
|
71
|
+
KEY_VALUE = ConnectionSecurityScheme.KEY_VALUE.value
|
72
|
+
|
73
|
+
def __str__(self):
|
74
|
+
return self.value
|
75
|
+
|
76
|
+
def __repr__(self):
|
77
|
+
return repr(self.value)
|
78
|
+
|
79
|
+
OAUTH_CONNECTION_TYPES = {
|
80
|
+
# ConnectionType.OAUTH2_AUTH_CODE,
|
81
|
+
# ConnectionType.OAUTH2_CLIENT_CREDS,
|
82
|
+
# ConnectionType.OAUTH2_IMPLICIT,
|
83
|
+
# ConnectionType.OAUTH2_PASSWORD,
|
84
|
+
ConnectionType.OAUTH_ON_BEHALF_OF_FLOW,
|
85
|
+
}
|
86
|
+
|
87
|
+
class IdpConfigDataBody(BaseModel):
|
88
|
+
requested_token_use: str
|
89
|
+
requested_token_type: str
|
90
|
+
|
91
|
+
class IdpConfigData(BaseModel):
|
92
|
+
header: Optional[dict] = None
|
93
|
+
body: IdpConfigDataBody
|
94
|
+
|
95
|
+
@model_validator(mode="after")
|
96
|
+
def set_default_values(self):
|
97
|
+
self.header = self.header or {
|
98
|
+
"content-type": "application/x-www-form-urlencoded"
|
99
|
+
}
|
100
|
+
return self
|
101
|
+
|
102
|
+
class AppConfigData(BaseModel):
|
103
|
+
header: Optional[dict] = None
|
104
|
+
|
105
|
+
@model_validator(mode="after")
|
106
|
+
def set_default_values(self):
|
107
|
+
self.header = self.header or {
|
108
|
+
"content-type": "application/x-www-form-urlencoded"
|
109
|
+
}
|
110
|
+
return self
|
111
|
+
|
112
|
+
|
113
|
+
class ConnectionConfiguration(BaseModel):
|
114
|
+
app_id: str
|
115
|
+
environment: ConnectionEnvironment
|
116
|
+
preference: ConnectionPreference = Field(validation_alias=AliasChoices('preference', 'type'), serialization_alias='preference')
|
117
|
+
security_scheme: ConnectionSecurityScheme
|
118
|
+
auth_type: Optional[ConnectionAuthType] = None
|
119
|
+
sso: bool = False
|
120
|
+
server_url: str | None = None
|
121
|
+
idp_config_data: Optional[IdpConfigData] = Field(None, validation_alias=AliasChoices('idp_config_data', 'idp_config'), serialization_alias='idp_config_data')
|
122
|
+
app_config_data: Optional[AppConfigData] = Field(None, validation_alias=AliasChoices('app_config_data', 'app_config'), serialization_alias='app_config_data')
|
123
|
+
config_id: str = None
|
124
|
+
tenant_id: str = None
|
125
|
+
|
126
|
+
def __init__(self, *args, **kwargs):
|
127
|
+
kind = kwargs.get("kind")
|
128
|
+
|
129
|
+
if kind:
|
130
|
+
if not kwargs.get("auth_type"):
|
131
|
+
kwargs["auth_type"] = CONNECTION_KIND_OAUTH_TYPE_MAPPING.get(kind)
|
132
|
+
|
133
|
+
if not kwargs.get("security_scheme"):
|
134
|
+
kwargs["security_scheme"] = CONNECTION_KIND_SCHEME_MAPPING.get(kind)
|
135
|
+
|
136
|
+
super().__init__(*args, **kwargs)
|
137
|
+
|
138
|
+
@model_validator(mode="after")
|
139
|
+
def validate_config(self):
|
140
|
+
if self.sso and self.security_scheme != ConnectionSecurityScheme.OAUTH2:
|
141
|
+
raise ValueError(f"SSO not supported for auth scheme '{self.security_scheme}'. SSO can only be used with OAuth auth types")
|
142
|
+
if not self.sso and self.security_scheme == ConnectionSecurityScheme.OAUTH2:
|
143
|
+
raise ValueError(f"SSO required for OAuth auth schemes. Please enable SSO.")
|
144
|
+
if self.sso:
|
145
|
+
if not self.idp_config_data:
|
146
|
+
raise ValueError("For SSO auth 'idp_config_data' is a required field")
|
147
|
+
if not self.app_config_data:
|
148
|
+
self.app_config_data = AppConfigData()
|
149
|
+
if self.security_scheme == ConnectionSecurityScheme.KEY_VALUE and self.preference == ConnectionPreference.MEMBER:
|
150
|
+
raise ValueError("Connection of type 'key_value' cannot be configured at the 'member' level. Key value connections must be of type 'team'")
|
151
|
+
return self
|
152
|
+
|
153
|
+
class BasicAuthCredentials(BaseModel):
|
154
|
+
username: str
|
155
|
+
password: str
|
156
|
+
url: Optional[str] = None
|
157
|
+
|
158
|
+
class BearerTokenAuthCredentials(BaseModel):
|
159
|
+
token: str
|
160
|
+
url: Optional[str] = None
|
161
|
+
|
162
|
+
class APIKeyAuthCredentials(BaseModel):
|
163
|
+
api_key: str
|
164
|
+
url: Optional[str] = None
|
165
|
+
|
166
|
+
class OAuth2TokenCredentials(BaseModel):
|
167
|
+
access_token: str
|
168
|
+
url: Optional[str] = None
|
169
|
+
|
170
|
+
# class OAuth2AuthCodeCredentials(BaseModel):
|
171
|
+
# client_id: str
|
172
|
+
# client_secret: str
|
173
|
+
# token_url: str
|
174
|
+
# authorization_url: str
|
175
|
+
|
176
|
+
# class OAuth2ImplicitCredentials(BaseModel):
|
177
|
+
# client_id: str
|
178
|
+
# authorization_url: str
|
179
|
+
|
180
|
+
# class OAuth2PasswordCredentials(BaseModel):
|
181
|
+
# client_id: str
|
182
|
+
# client_secret: str
|
183
|
+
# token_url: str
|
184
|
+
# authorization_url: str
|
185
|
+
|
186
|
+
# class OAuth2ClientCredentials(BaseModel):
|
187
|
+
# client_id: str
|
188
|
+
# client_secret: str
|
189
|
+
# token_url: str
|
190
|
+
|
191
|
+
class OAuthOnBehalfOfCredentials(BaseModel):
|
192
|
+
client_id: str
|
193
|
+
access_token_url: str
|
194
|
+
grant_type: str
|
195
|
+
|
196
|
+
# KeyValue is just an alias of dictionary
|
197
|
+
class KeyValueConnectionCredentials(dict):
|
198
|
+
def __init__(self, *args, **kwargs):
|
199
|
+
super().__init__(*args, **kwargs)
|
200
|
+
|
201
|
+
def model_dump(self, *args, **kwargs):
|
202
|
+
return self
|
203
|
+
|
204
|
+
CREDENTIALS_SET = Union[
|
205
|
+
BasicAuthCredentials,
|
206
|
+
BearerTokenAuthCredentials,
|
207
|
+
APIKeyAuthCredentials,
|
208
|
+
# OAuth2AuthCodeCredentials,
|
209
|
+
# OAuth2ImplicitCredentials,
|
210
|
+
# OAuth2PasswordCredentials,
|
211
|
+
# OAuth2ClientCredentials,
|
212
|
+
OAuthOnBehalfOfCredentials,
|
213
|
+
KeyValueConnectionCredentials
|
214
|
+
]
|
215
|
+
|
216
|
+
CREDENTIALS = TypeVar("CREDENTIALS", bound=CREDENTIALS_SET)
|
217
|
+
|
218
|
+
CONNECTION_KIND_SCHEME_MAPPING = {
|
219
|
+
ConnectionKind.basic: ConnectionSecurityScheme.BASIC_AUTH,
|
220
|
+
ConnectionKind.bearer: ConnectionSecurityScheme.BEARER_TOKEN,
|
221
|
+
ConnectionKind.api_key: ConnectionSecurityScheme.API_KEY_AUTH,
|
222
|
+
# ConnectionKind.oauth_auth_code_flow: ConnectionSecurityScheme.OAUTH2,
|
223
|
+
# ConnectionKind.oauth_auth_implicit_flow: ConnectionSecurityScheme.OAUTH2,
|
224
|
+
# ConnectionKind.oauth_auth_password_flow: ConnectionSecurityScheme.OAUTH2,
|
225
|
+
# ConnectionKind.oauth_auth_client_credentials_flow: ConnectionSecurityScheme.OAUTH2,
|
226
|
+
ConnectionKind.oauth_auth_on_behalf_of_flow: ConnectionSecurityScheme.OAUTH2,
|
227
|
+
ConnectionKind.key_value: ConnectionSecurityScheme.KEY_VALUE,
|
228
|
+
ConnectionKind.kv: ConnectionSecurityScheme.KEY_VALUE,
|
229
|
+
}
|
230
|
+
|
231
|
+
CONNECTION_KIND_OAUTH_TYPE_MAPPING = {
|
232
|
+
# ConnectionKind.oauth_auth_code_flow: ConnectionAuthType.OAUTH2_AUTH_CODE,
|
233
|
+
# ConnectionKind.oauth_auth_implicit_flow: ConnectionAuthType.OAUTH2_IMPLICIT,
|
234
|
+
# ConnectionKind.oauth_auth_password_flow: ConnectionAuthType.OAUTH2_PASSWORD,
|
235
|
+
# ConnectionKind.oauth_auth_client_credentials_flow: ConnectionAuthType.OAUTH2_CLIENT_CREDS,
|
236
|
+
ConnectionKind.oauth_auth_on_behalf_of_flow: ConnectionAuthType.OAUTH_ON_BEHALF_OF_FLOW,
|
237
|
+
}
|
238
|
+
|
239
|
+
CONNECTION_TYPE_CREDENTIAL_MAPPING = {
|
240
|
+
ConnectionType.BASIC_AUTH: BasicAuthCredentials,
|
241
|
+
ConnectionType.BEARER_TOKEN: BearerTokenAuthCredentials,
|
242
|
+
ConnectionType.API_KEY_AUTH: APIKeyAuthCredentials,
|
243
|
+
# ConnectionType.OAUTH2_AUTH_CODE: BearerTokenAuthCredentials,
|
244
|
+
# ConnectionType.OAUTH2_IMPLICIT: BearerTokenAuthCredentials,
|
245
|
+
# ConnectionType.OAUTH2_PASSWORD: BearerTokenAuthCredentials,
|
246
|
+
# ConnectionType.OAUTH2_CLIENT_CREDS: BearerTokenAuthCredentials,
|
247
|
+
ConnectionType.OAUTH_ON_BEHALF_OF_FLOW: OAuth2TokenCredentials,
|
248
|
+
ConnectionType.KEY_VALUE: KeyValueConnectionCredentials,
|
249
|
+
}
|
250
|
+
|
251
|
+
class IdentityProviderCredentials(BaseModel):
|
252
|
+
idp_url: str = Field(validation_alias=AliasChoices('idp_url', 'url'), serialization_alias='idp_url')
|
253
|
+
client_id: str
|
254
|
+
client_secret: str
|
255
|
+
scope: str
|
256
|
+
grant_type: str
|
257
|
+
|
258
|
+
class ExpectedCredentials(BaseModel):
|
259
|
+
app_id: str
|
260
|
+
type: ConnectionType | List[ConnectionType]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import json
|
2
|
+
from ibm_watsonx_orchestrate.utils.utils import yaml_safe_load
|
3
|
+
from .types import KnowledgeBaseSpec
|
4
|
+
|
5
|
+
|
6
|
+
class KnowledgeBase(KnowledgeBaseSpec):
|
7
|
+
|
8
|
+
@staticmethod
|
9
|
+
def from_spec(file: str) -> 'KnowledgeBase':
|
10
|
+
with open(file, 'r') as f:
|
11
|
+
if file.endswith('.yaml') or file.endswith('.yml'):
|
12
|
+
content = yaml_safe_load(f)
|
13
|
+
elif file.endswith('.json'):
|
14
|
+
content = json.load(f)
|
15
|
+
else:
|
16
|
+
raise ValueError('file must end in .json, .yaml, or .yml')
|
17
|
+
if not content.get("spec_version"):
|
18
|
+
raise ValueError(f"Field 'spec_version' not provided. Please ensure provided spec conforms to a valid spec format")
|
19
|
+
knowledge_base = KnowledgeBase.model_validate(content)
|
20
|
+
|
21
|
+
return knowledge_base
|
22
|
+
|
23
|
+
def __repr__(self):
|
24
|
+
return f"KnowledgeBase(id='{self.id}', name='{self.name}', description='{self.description}')"
|
25
|
+
|
26
|
+
def __str__(self):
|
27
|
+
return self.__repr__()
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import json
|
2
|
+
from ibm_watsonx_orchestrate.utils.utils import yaml_safe_load
|
3
|
+
from .types import CreateKnowledgeBase, PatchKnowledgeBase, KnowledgeBaseKind
|
4
|
+
|
5
|
+
|
6
|
+
class KnowledgeBaseCreateRequest(CreateKnowledgeBase):
|
7
|
+
|
8
|
+
@staticmethod
|
9
|
+
def from_spec(file: str) -> 'CreateKnowledgeBase':
|
10
|
+
with open(file, 'r') as f:
|
11
|
+
if file.endswith('.yaml') or file.endswith('.yml'):
|
12
|
+
content = yaml_safe_load(f)
|
13
|
+
elif file.endswith('.json'):
|
14
|
+
content = json.load(f)
|
15
|
+
else:
|
16
|
+
raise ValueError('file must end in .json, .yaml, or .yml')
|
17
|
+
|
18
|
+
if (content.get('documents') and content.get("conversational_search_tool", {}).get("index_config")) or \
|
19
|
+
(not content.get('documents') and not content.get("conversational_search_tool", {}).get("index_config")):
|
20
|
+
raise ValueError("Must provide either \"documents\" or \"conversational_search_tool.index_config\", but not both")
|
21
|
+
|
22
|
+
if not content.get("spec_version"):
|
23
|
+
raise ValueError(f"Field 'spec_version' not provided. Please ensure provided spec conforms to a valid spec format")
|
24
|
+
|
25
|
+
if not content.get("kind"):
|
26
|
+
raise ValueError(f"Field 'kind' not provided. Should be 'knowledge_base'")
|
27
|
+
|
28
|
+
if content.get("kind") != KnowledgeBaseKind.KNOWLEDGE_BASE:
|
29
|
+
raise ValueError(f"Field 'kind' should be 'knowledge_base', but is set to '{content.get('kind')}'")
|
30
|
+
|
31
|
+
knowledge_base = CreateKnowledgeBase.model_validate(content)
|
32
|
+
|
33
|
+
return knowledge_base
|
34
|
+
|
35
|
+
|
36
|
+
class KnowledgeBaseUpdateRequest(PatchKnowledgeBase):
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
def from_spec(file: str) -> 'PatchKnowledgeBase':
|
40
|
+
with open(file, 'r') as f:
|
41
|
+
if file.endswith('.yaml') or file.endswith('.yml'):
|
42
|
+
content = yaml_safe_load(f)
|
43
|
+
elif file.endswith('.json'):
|
44
|
+
content = json.load(f)
|
45
|
+
else:
|
46
|
+
raise ValueError('file must end in .json, .yaml, or .yml')
|
47
|
+
|
48
|
+
if not content.get("spec_version"):
|
49
|
+
raise ValueError(f"Field 'spec_version' not provided. Please ensure provided spec conforms to a valid spec format")
|
50
|
+
|
51
|
+
if not content.get("kind"):
|
52
|
+
raise ValueError(f"Field 'kind' not provided. Should be 'knowledge_base'")
|
53
|
+
|
54
|
+
if content.get("kind") != KnowledgeBaseKind.KNOWLEDGE_BASE:
|
55
|
+
raise ValueError(f"Field 'kind' should be 'knowledge_base', but is set to '{content.get('kind')}'")
|
56
|
+
|
57
|
+
patch = PatchKnowledgeBase.model_validate(content)
|
58
|
+
|
59
|
+
return patch
|
@@ -0,0 +1,243 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
from datetime import datetime
|
3
|
+
from uuid import UUID
|
4
|
+
from enum import Enum
|
5
|
+
|
6
|
+
from pydantic import BaseModel, Field
|
7
|
+
|
8
|
+
|
9
|
+
class SpecVersion(str, Enum):
|
10
|
+
V1 = "v1"
|
11
|
+
|
12
|
+
class KnowledgeBaseKind(str, Enum):
|
13
|
+
KNOWLEDGE_BASE = "knowledge_base"
|
14
|
+
class RetrievalConfidenceThreshold(str, Enum):
|
15
|
+
Lowest = "Lowest"
|
16
|
+
Low = "Low"
|
17
|
+
High = "High"
|
18
|
+
Highest = "Highest"
|
19
|
+
|
20
|
+
|
21
|
+
class GeneratedResponseLength(str, Enum):
|
22
|
+
Concise = "Concise"
|
23
|
+
Moderate = "Moderate"
|
24
|
+
Verbose = "Verbose"
|
25
|
+
|
26
|
+
|
27
|
+
class ResponseConfidenceThreshold(str, Enum):
|
28
|
+
Lowest = "Lowest"
|
29
|
+
Low = "Low"
|
30
|
+
High = "High"
|
31
|
+
Highest = "Highest"
|
32
|
+
|
33
|
+
class KnowledgeBaseRepresentation(str, Enum):
|
34
|
+
auto = "auto"
|
35
|
+
tool = "tool"
|
36
|
+
|
37
|
+
class ConfidenceThresholds(BaseModel):
|
38
|
+
retrieval_confidence_threshold: Optional[RetrievalConfidenceThreshold] = None
|
39
|
+
response_confidence_threshold: Optional[ResponseConfidenceThreshold] = None
|
40
|
+
|
41
|
+
class CitationsConfig(BaseModel):
|
42
|
+
"""
|
43
|
+
example:
|
44
|
+
{
|
45
|
+
"citation_title": "how do i know",
|
46
|
+
"citations_shown": 5,
|
47
|
+
}
|
48
|
+
"""
|
49
|
+
citation_title: Optional[str] = None
|
50
|
+
citations_shown: Optional[int] = None
|
51
|
+
|
52
|
+
|
53
|
+
class HAPFilteringConfig(BaseModel):
|
54
|
+
enabled: Optional[bool] = None
|
55
|
+
threshold: Optional[float] = None
|
56
|
+
|
57
|
+
|
58
|
+
class HAPFiltering(BaseModel):
|
59
|
+
"""
|
60
|
+
example
|
61
|
+
{
|
62
|
+
"output": {
|
63
|
+
"enabled": True,
|
64
|
+
"threshold": 0.7,
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
"""
|
69
|
+
output: Optional[HAPFilteringConfig] = None
|
70
|
+
|
71
|
+
class QueryRewriteConfig(BaseModel):
|
72
|
+
"""
|
73
|
+
example
|
74
|
+
|
75
|
+
{
|
76
|
+
"enabled": True,
|
77
|
+
"model_id": "meta-llama/llama-3-1-70b-instruct"
|
78
|
+
}
|
79
|
+
|
80
|
+
"""
|
81
|
+
enabled: Optional[bool] = None
|
82
|
+
model_id: Optional[str] = None
|
83
|
+
|
84
|
+
class GenerationConfiguration(BaseModel):
|
85
|
+
"""
|
86
|
+
example
|
87
|
+
{
|
88
|
+
"model_id": "meta-llama/llama-3-1-70b-instruct",
|
89
|
+
"prompt_instruction": "When the documents are in different languages, you should respond in english.",
|
90
|
+
"retrieval_confidence_threshold": "Lowest",
|
91
|
+
"generated_response_length": "Moderate",
|
92
|
+
"response_confidence_threshold": "Low",
|
93
|
+
"display_text_no_results_found": "no docs found",
|
94
|
+
"display_text_connectivity_issue": "conn failed",
|
95
|
+
}
|
96
|
+
"""
|
97
|
+
|
98
|
+
model_id: Optional[str] = None
|
99
|
+
prompt_instruction: Optional[str] = None
|
100
|
+
generated_response_length: Optional[GeneratedResponseLength] = None
|
101
|
+
display_text_no_results_found: Optional[str] = None
|
102
|
+
display_text_connectivity_issue: Optional[str] = None
|
103
|
+
|
104
|
+
class FieldMapping(BaseModel):
|
105
|
+
"""
|
106
|
+
example
|
107
|
+
|
108
|
+
{
|
109
|
+
"title": "title",
|
110
|
+
"body": "text",
|
111
|
+
"url": "some-url"
|
112
|
+
}
|
113
|
+
"""
|
114
|
+
title: Optional[str] = None
|
115
|
+
body: Optional[str] = None
|
116
|
+
url: Optional[str] = None
|
117
|
+
|
118
|
+
class MilvusConnection(BaseModel):
|
119
|
+
"""
|
120
|
+
example:
|
121
|
+
{
|
122
|
+
"grpc_host": "https://xxxx.lakehouse.appdomain.cloud",
|
123
|
+
"database": "test_db",
|
124
|
+
"collection": "search_wa_docs",
|
125
|
+
"index": "dense",
|
126
|
+
"embedding_model_id": "sentence-transformers/all-minilm-l12-v2",
|
127
|
+
"grpc_port": "30564",
|
128
|
+
"filter": "title like \"%action%\"",
|
129
|
+
"limit": 10,
|
130
|
+
"field_mapping": {
|
131
|
+
"title": "title",
|
132
|
+
"body": "text",
|
133
|
+
"url": "some-url"
|
134
|
+
}
|
135
|
+
}
|
136
|
+
"""
|
137
|
+
grpc_host: Optional[str] = None
|
138
|
+
database: Optional[str] = None
|
139
|
+
collection: Optional[str] = None
|
140
|
+
index: Optional[str] = None
|
141
|
+
embedding_model_id: Optional[str] = None
|
142
|
+
limit : Optional[int] = None
|
143
|
+
grpc_port: Optional[str] = None
|
144
|
+
filter: Optional[str] = None
|
145
|
+
field_mapping: Optional[FieldMapping] = None
|
146
|
+
|
147
|
+
|
148
|
+
class ElasticSearchConnection(BaseModel):
|
149
|
+
"""
|
150
|
+
example:
|
151
|
+
|
152
|
+
{
|
153
|
+
"url": "https://xxxx.databases.appdomain.cloud",
|
154
|
+
"index": "search-wa-docs",
|
155
|
+
"port": "31871",
|
156
|
+
"query_body": {"size":5,"query":{"text_expansion":{"ml.tokens":{"model_id":".elser_model_2_linux-x86_64","model_text": "$QUERY"}}}},
|
157
|
+
"result_filter": [
|
158
|
+
{
|
159
|
+
"match": {
|
160
|
+
"title": "A_keyword_in_title"
|
161
|
+
}
|
162
|
+
},
|
163
|
+
{
|
164
|
+
"match": {
|
165
|
+
"text": "A_keyword_in_text"
|
166
|
+
}
|
167
|
+
},
|
168
|
+
{
|
169
|
+
"match": {
|
170
|
+
"id": "A_specific_ID"
|
171
|
+
}
|
172
|
+
}
|
173
|
+
] = None,
|
174
|
+
"field_mapping": {
|
175
|
+
"title": "title",
|
176
|
+
"body": "text",
|
177
|
+
"url": "some-url"
|
178
|
+
}
|
179
|
+
}
|
180
|
+
"""
|
181
|
+
url: Optional[str] = None
|
182
|
+
index: Optional[str] = None
|
183
|
+
port: Optional[str] = None
|
184
|
+
query_body: Optional[dict] = None
|
185
|
+
result_filter: Optional[list] = None
|
186
|
+
field_mapping: Optional[FieldMapping] = None
|
187
|
+
|
188
|
+
|
189
|
+
class IndexConnection(BaseModel):
|
190
|
+
connection_id: Optional[str] = None
|
191
|
+
milvus: Optional[MilvusConnection] = None
|
192
|
+
elastic_search: Optional[ElasticSearchConnection] = None
|
193
|
+
|
194
|
+
|
195
|
+
class ConversationalSearchConfig(BaseModel):
|
196
|
+
language: Optional[str] = None
|
197
|
+
index_config: list[IndexConnection] = None
|
198
|
+
generation: Optional[GenerationConfiguration] = None
|
199
|
+
query_rewrite: Optional[QueryRewriteConfig] = None
|
200
|
+
citations: Optional[CitationsConfig] = None
|
201
|
+
hap_filtering: Optional[HAPFiltering] = None
|
202
|
+
confidence_thresholds: Optional[ConfidenceThresholds] = None
|
203
|
+
|
204
|
+
class KnowledgeBaseBuiltInVectorIndexConfig(BaseModel):
|
205
|
+
chunk_size: Optional[int] = None
|
206
|
+
chunk_overlap: Optional[int] = None
|
207
|
+
limit: Optional[int] = None
|
208
|
+
|
209
|
+
class CreateKnowledgeBase(BaseModel):
|
210
|
+
"""request payload schema"""
|
211
|
+
name: Optional[str] = None
|
212
|
+
description: Optional[str] = None
|
213
|
+
documents: list[str] = None
|
214
|
+
vector_index: Optional[KnowledgeBaseBuiltInVectorIndexConfig] = None
|
215
|
+
conversational_search_tool: Optional[ConversationalSearchConfig] = None
|
216
|
+
prioritize_built_in_index: Optional[bool] = None
|
217
|
+
|
218
|
+
|
219
|
+
class PatchKnowledgeBase(BaseModel):
|
220
|
+
"""request payload schema"""
|
221
|
+
description: Optional[str] = None
|
222
|
+
documents: list[str] = None
|
223
|
+
conversational_search_tool: Optional[ConversationalSearchConfig] = None
|
224
|
+
prioritize_built_in_index: Optional[bool] = None
|
225
|
+
representation: Optional[KnowledgeBaseRepresentation] = None
|
226
|
+
|
227
|
+
|
228
|
+
class KnowledgeBaseSpec(BaseModel):
|
229
|
+
"""Schema for a complete knowledge-base."""
|
230
|
+
spec_version: SpecVersion = None
|
231
|
+
kind: KnowledgeBaseKind = KnowledgeBaseKind.KNOWLEDGE_BASE
|
232
|
+
id: Optional[UUID] = None
|
233
|
+
tenant_id: Optional[str] = None
|
234
|
+
name: Optional[str] = None
|
235
|
+
description: Optional[str] = None
|
236
|
+
vector_index: Optional[KnowledgeBaseBuiltInVectorIndexConfig] = None
|
237
|
+
conversational_search_tool: Optional[ConversationalSearchConfig] | Optional[UUID] = None
|
238
|
+
prioritize_built_in_index: Optional[bool] = None
|
239
|
+
vector_index_id: Optional[UUID] = None
|
240
|
+
created_by: Optional[str] = None
|
241
|
+
created_on: Optional[datetime] = None
|
242
|
+
updated_at: Optional[datetime] = None
|
243
|
+
|
@@ -0,0 +1,4 @@
|
|
1
|
+
from .base_tool import BaseTool
|
2
|
+
from .python_tool import tool, PythonTool, get_all_python_tools
|
3
|
+
from .openapi_tool import create_openapi_json_tool, create_openapi_json_tool_from_uri, create_openapi_json_tools_from_uri, OpenAPITool, HTTPException
|
4
|
+
from .types import ToolPermission, JsonSchemaObject, ToolRequestBody, ToolResponseBody, OpenApiSecurityScheme, OpenApiToolBinding, PythonToolBinding, WxFlowsToolBinding, SkillToolBinding, ClientSideToolBinding, ToolBinding, ToolSpec
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import json
|
2
|
+
|
3
|
+
import yaml
|
4
|
+
|
5
|
+
from .types import ToolSpec
|
6
|
+
|
7
|
+
|
8
|
+
class BaseTool:
|
9
|
+
__tool_spec__: ToolSpec
|
10
|
+
|
11
|
+
def __init__(self, spec: ToolSpec):
|
12
|
+
self.__tool_spec__ = spec
|
13
|
+
|
14
|
+
def __call__(self, **kwargs):
|
15
|
+
pass
|
16
|
+
|
17
|
+
def dump_spec(self, file: str) -> None:
|
18
|
+
dumped = self.__tool_spec__.model_dump(mode='json', exclude_unset=True, exclude_none=True, by_alias=True)
|
19
|
+
with open(file, 'w') as f:
|
20
|
+
if file.endswith('.yaml') or file.endswith('.yml'):
|
21
|
+
yaml.dump(dumped, f)
|
22
|
+
elif file.endswith('.json'):
|
23
|
+
json.dump(dumped, f, indent=2)
|
24
|
+
else:
|
25
|
+
raise ValueError('file must end in .json, .yaml, or .yml')
|
26
|
+
|
27
|
+
def dumps_spec(self) -> str:
|
28
|
+
dumped = self.__tool_spec__.model_dump(mode='json', exclude_unset=True, exclude_none=True, by_alias=True)
|
29
|
+
return json.dumps(dumped, indent=2)
|
30
|
+
|
31
|
+
def to_langchain_tool(self):
|
32
|
+
from .integrations.langchain import as_langchain_tool
|
33
|
+
return as_langchain_tool(self)
|
34
|
+
|
35
|
+
def __repr__(self):
|
36
|
+
return f"Tool(name='{self.__tool_spec__.name}', description='{self.__tool_spec__.description}')"
|