ibm-watsonx-orchestrate 1.9.0b2__py3-none-any.whl → 1.10.0b1__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 +2 -1
- ibm_watsonx_orchestrate/agent_builder/agents/types.py +2 -0
- ibm_watsonx_orchestrate/agent_builder/connections/__init__.py +1 -1
- ibm_watsonx_orchestrate/agent_builder/connections/connections.py +1 -1
- ibm_watsonx_orchestrate/agent_builder/connections/types.py +16 -12
- ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +47 -3
- ibm_watsonx_orchestrate/agent_builder/toolkits/types.py +18 -15
- ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +19 -7
- ibm_watsonx_orchestrate/agent_builder/tools/types.py +1 -1
- ibm_watsonx_orchestrate/agent_builder/voice_configurations/__init__.py +1 -0
- ibm_watsonx_orchestrate/agent_builder/voice_configurations/types.py +98 -0
- ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +20 -0
- ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +170 -1
- ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +7 -7
- ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +36 -26
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +51 -22
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py +110 -16
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +43 -10
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +52 -25
- ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +5 -0
- ibm_watsonx_orchestrate/cli/commands/voice_configurations/voice_configurations_command.py +58 -0
- ibm_watsonx_orchestrate/cli/commands/voice_configurations/voice_configurations_controller.py +173 -0
- ibm_watsonx_orchestrate/cli/main.py +2 -0
- ibm_watsonx_orchestrate/client/agents/agent_client.py +64 -1
- ibm_watsonx_orchestrate/client/connections/connections_client.py +4 -3
- ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py +4 -4
- ibm_watsonx_orchestrate/client/voice_configurations/voice_configurations_client.py +75 -0
- ibm_watsonx_orchestrate/docker/compose-lite.yml +54 -5
- ibm_watsonx_orchestrate/docker/default.env +21 -13
- ibm_watsonx_orchestrate/flow_builder/flows/__init__.py +2 -0
- ibm_watsonx_orchestrate/flow_builder/flows/flow.py +115 -31
- ibm_watsonx_orchestrate/flow_builder/node.py +39 -15
- ibm_watsonx_orchestrate/flow_builder/types.py +114 -25
- ibm_watsonx_orchestrate/run/connections.py +2 -2
- {ibm_watsonx_orchestrate-1.9.0b2.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/METADATA +1 -1
- {ibm_watsonx_orchestrate-1.9.0b2.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/RECORD +39 -34
- {ibm_watsonx_orchestrate-1.9.0b2.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/WHEEL +0 -0
- {ibm_watsonx_orchestrate-1.9.0b2.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/entry_points.txt +0 -0
- {ibm_watsonx_orchestrate-1.9.0b2.dist-info → ibm_watsonx_orchestrate-1.10.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -77,6 +77,8 @@ class BaseAgentSpec(BaseModel):
|
|
77
77
|
description: Annotated[str, Field(json_schema_extra={"min_length_str":1})]
|
78
78
|
context_access_enabled: bool = True
|
79
79
|
context_variables: Optional[List[str]] = []
|
80
|
+
voice_configuration_id: Optional[str] = None
|
81
|
+
voice_configuration: Optional[str] = None
|
80
82
|
|
81
83
|
def dump_spec(self, file: str) -> None:
|
82
84
|
dumped = self.model_dump(mode='json', exclude_unset=True, exclude_none=True)
|
@@ -18,7 +18,7 @@ from .types import (
|
|
18
18
|
OAuth2AuthCodeCredentials,
|
19
19
|
OAuth2ClientCredentials,
|
20
20
|
# OAuth2ImplicitCredentials,
|
21
|
-
|
21
|
+
OAuth2PasswordCredentials,
|
22
22
|
OAuthOnBehalfOfCredentials,
|
23
23
|
KeyValueConnectionCredentials,
|
24
24
|
CONNECTION_KIND_SCHEME_MAPPING,
|
@@ -37,7 +37,7 @@ connection_type_security_schema_map = {
|
|
37
37
|
ConnectionType.OAUTH2_CLIENT_CREDS: ConnectionSecurityScheme.OAUTH2,
|
38
38
|
ConnectionType.OAUTH_ON_BEHALF_OF_FLOW: ConnectionSecurityScheme.OAUTH2,
|
39
39
|
# ConnectionType.OAUTH2_IMPLICIT: ConnectionSecurityScheme.OAUTH2,
|
40
|
-
|
40
|
+
ConnectionType.OAUTH2_PASSWORD: ConnectionSecurityScheme.OAUTH2
|
41
41
|
}
|
42
42
|
|
43
43
|
def _clean_env_vars(vars: dict[str:str], requirements: List[str], app_id: str) -> dict[str,str]:
|
@@ -8,7 +8,7 @@ class ConnectionKind(str, Enum):
|
|
8
8
|
api_key = 'api_key'
|
9
9
|
oauth_auth_code_flow = 'oauth_auth_code_flow'
|
10
10
|
# oauth_auth_implicit_flow = 'oauth_auth_implicit_flow'
|
11
|
-
|
11
|
+
oauth_auth_password_flow = 'oauth_auth_password_flow'
|
12
12
|
oauth_auth_client_credentials_flow = 'oauth_auth_client_credentials_flow'
|
13
13
|
oauth_auth_on_behalf_of_flow = 'oauth_auth_on_behalf_of_flow'
|
14
14
|
key_value = 'key_value'
|
@@ -34,7 +34,7 @@ class ConnectionPreference(str, Enum):
|
|
34
34
|
class ConnectionAuthType(str, Enum):
|
35
35
|
OAUTH2_AUTH_CODE = 'oauth2_auth_code'
|
36
36
|
# OAUTH2_IMPLICIT = 'oauth2_implicit'
|
37
|
-
|
37
|
+
OAUTH2_PASSWORD = 'oauth2_password'
|
38
38
|
OAUTH2_CLIENT_CREDS = 'oauth2_client_creds'
|
39
39
|
OAUTH_ON_BEHALF_OF_FLOW = 'oauth_on_behalf_of_flow'
|
40
40
|
|
@@ -65,7 +65,7 @@ class ConnectionType(str, Enum):
|
|
65
65
|
API_KEY_AUTH = ConnectionSecurityScheme.API_KEY_AUTH.value
|
66
66
|
OAUTH2_AUTH_CODE = ConnectionAuthType.OAUTH2_AUTH_CODE.value
|
67
67
|
# OAUTH2_IMPLICIT = ConnectionAuthType.OAUTH2_IMPLICIT.value
|
68
|
-
|
68
|
+
OAUTH2_PASSWORD = ConnectionAuthType.OAUTH2_PASSWORD.value
|
69
69
|
OAUTH2_CLIENT_CREDS = ConnectionAuthType.OAUTH2_CLIENT_CREDS.value
|
70
70
|
OAUTH_ON_BEHALF_OF_FLOW = ConnectionAuthType.OAUTH_ON_BEHALF_OF_FLOW.value
|
71
71
|
KEY_VALUE = ConnectionSecurityScheme.KEY_VALUE.value
|
@@ -90,7 +90,7 @@ OAUTH_CONNECTION_TYPES = {
|
|
90
90
|
ConnectionType.OAUTH2_AUTH_CODE,
|
91
91
|
ConnectionType.OAUTH2_CLIENT_CREDS,
|
92
92
|
# ConnectionType.OAUTH2_IMPLICIT,
|
93
|
-
|
93
|
+
ConnectionType.OAUTH2_PASSWORD,
|
94
94
|
ConnectionType.OAUTH_ON_BEHALF_OF_FLOW,
|
95
95
|
}
|
96
96
|
|
@@ -193,11 +193,15 @@ class OAuth2AuthCodeCredentials(BaseModel):
|
|
193
193
|
# client_id: str
|
194
194
|
# authorization_url: str
|
195
195
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
196
|
+
class OAuth2PasswordCredentials(BaseModel):
|
197
|
+
username: str
|
198
|
+
password: str
|
199
|
+
client_id: str
|
200
|
+
client_secret: str
|
201
|
+
token_url: str
|
202
|
+
scope: Optional[str] = None
|
203
|
+
grant_type: str = "password"
|
204
|
+
|
201
205
|
|
202
206
|
class OAuth2ClientCredentials(BaseModel):
|
203
207
|
client_id: str
|
@@ -226,7 +230,7 @@ CREDENTIALS_SET = Union[
|
|
226
230
|
APIKeyAuthCredentials,
|
227
231
|
OAuth2AuthCodeCredentials,
|
228
232
|
# OAuth2ImplicitCredentials,
|
229
|
-
|
233
|
+
OAuth2PasswordCredentials,
|
230
234
|
OAuth2ClientCredentials,
|
231
235
|
OAuthOnBehalfOfCredentials,
|
232
236
|
KeyValueConnectionCredentials
|
@@ -240,7 +244,7 @@ CONNECTION_KIND_SCHEME_MAPPING = {
|
|
240
244
|
ConnectionKind.api_key: ConnectionSecurityScheme.API_KEY_AUTH,
|
241
245
|
ConnectionKind.oauth_auth_code_flow: ConnectionSecurityScheme.OAUTH2,
|
242
246
|
# ConnectionKind.oauth_auth_implicit_flow: ConnectionSecurityScheme.OAUTH2,
|
243
|
-
|
247
|
+
ConnectionKind.oauth_auth_password_flow: ConnectionSecurityScheme.OAUTH2,
|
244
248
|
ConnectionKind.oauth_auth_client_credentials_flow: ConnectionSecurityScheme.OAUTH2,
|
245
249
|
ConnectionKind.oauth_auth_on_behalf_of_flow: ConnectionSecurityScheme.OAUTH2,
|
246
250
|
ConnectionKind.key_value: ConnectionSecurityScheme.KEY_VALUE,
|
@@ -250,7 +254,7 @@ CONNECTION_KIND_SCHEME_MAPPING = {
|
|
250
254
|
CONNECTION_KIND_OAUTH_TYPE_MAPPING = {
|
251
255
|
ConnectionKind.oauth_auth_code_flow: ConnectionAuthType.OAUTH2_AUTH_CODE,
|
252
256
|
# ConnectionKind.oauth_auth_implicit_flow: ConnectionAuthType.OAUTH2_IMPLICIT,
|
253
|
-
|
257
|
+
ConnectionKind.oauth_auth_password_flow: ConnectionAuthType.OAUTH2_PASSWORD,
|
254
258
|
ConnectionKind.oauth_auth_client_credentials_flow: ConnectionAuthType.OAUTH2_CLIENT_CREDS,
|
255
259
|
ConnectionKind.oauth_auth_on_behalf_of_flow: ConnectionAuthType.OAUTH_ON_BEHALF_OF_FLOW,
|
256
260
|
}
|
@@ -11,6 +11,7 @@ class SpecVersion(str, Enum):
|
|
11
11
|
class KnowledgeBaseKind(str, Enum):
|
12
12
|
KNOWLEDGE_BASE = "knowledge_base"
|
13
13
|
class RetrievalConfidenceThreshold(str, Enum):
|
14
|
+
Off = "Off"
|
14
15
|
Lowest = "Lowest"
|
15
16
|
Low = "Low"
|
16
17
|
High = "High"
|
@@ -24,6 +25,7 @@ class GeneratedResponseLength(str, Enum):
|
|
24
25
|
|
25
26
|
|
26
27
|
class ResponseConfidenceThreshold(str, Enum):
|
28
|
+
Off = "Off"
|
27
29
|
Lowest = "Lowest"
|
28
30
|
Low = "Low"
|
29
31
|
High = "High"
|
@@ -86,6 +88,8 @@ class GenerationConfiguration(BaseModel):
|
|
86
88
|
{
|
87
89
|
"model_id": "meta-llama/llama-3-1-70b-instruct",
|
88
90
|
"prompt_instruction": "When the documents are in different languages, you should respond in english.",
|
91
|
+
"max_docs_passed_to_llm": 10,
|
92
|
+
"retrieval_confidence_threshold": "Lowest",
|
89
93
|
"generated_response_length": "Moderate",
|
90
94
|
"display_text_no_results_found": "no docs found",
|
91
95
|
"display_text_connectivity_issue": "conn failed",
|
@@ -95,6 +99,7 @@ class GenerationConfiguration(BaseModel):
|
|
95
99
|
|
96
100
|
model_id: Optional[str] = None
|
97
101
|
prompt_instruction: Optional[str] = None
|
102
|
+
max_docs_passed_to_llm: Optional[int] = None
|
98
103
|
generated_response_length: Optional[GeneratedResponseLength] = None
|
99
104
|
display_text_no_results_found: Optional[str] = None
|
100
105
|
display_text_connectivity_issue: Optional[str] = None
|
@@ -134,12 +139,13 @@ class MilvusConnection(BaseModel):
|
|
134
139
|
}
|
135
140
|
"""
|
136
141
|
grpc_host: Optional[str] = None
|
142
|
+
grpc_port: Optional[str] = None
|
143
|
+
server_cert: Optional[str] = None
|
137
144
|
database: Optional[str] = None
|
138
145
|
collection: Optional[str] = None
|
139
146
|
index: Optional[str] = None
|
140
147
|
embedding_model_id: Optional[str] = None
|
141
148
|
limit : Optional[int] = None
|
142
|
-
grpc_port: Optional[str] = None
|
143
149
|
filter: Optional[str] = None
|
144
150
|
field_mapping: Optional[FieldMapping] = None
|
145
151
|
|
@@ -197,12 +203,46 @@ class CustomSearchConnection(BaseModel):
|
|
197
203
|
filter: Optional[str] = None
|
198
204
|
metadata: Optional[dict] = None
|
199
205
|
|
206
|
+
class AstraDBConnection(BaseModel):
|
207
|
+
"""
|
208
|
+
example:
|
209
|
+
{
|
210
|
+
"api_endpoint": "https://xxx-us-east-2.apps.astra.datastax.com",
|
211
|
+
"key_space": "default_keyspace",
|
212
|
+
"collection": "search_wa_docs",
|
213
|
+
"embedding_model_id": "sentence-transformers/all-minilm-l12-v2",
|
214
|
+
"port": "443",
|
215
|
+
"filter": "productType: \"boots\"",
|
216
|
+
"limit": 5,
|
217
|
+
"field_mapping": {
|
218
|
+
"title": "title",
|
219
|
+
"body": "text",
|
220
|
+
"url": "some-url"
|
221
|
+
}
|
222
|
+
}
|
223
|
+
"""
|
224
|
+
api_endpoint: str
|
225
|
+
port: Optional[str] = None
|
226
|
+
server_cert: Optional[str] = None
|
227
|
+
keyspace: Optional[str]
|
228
|
+
data_type: str
|
229
|
+
collection: Optional[str]
|
230
|
+
table: Optional[str]
|
231
|
+
index_column: Optional[str]
|
232
|
+
embedding_mode: str
|
233
|
+
embedding_model_id: Optional[str]
|
234
|
+
credentials: dict
|
235
|
+
search_mode: str
|
236
|
+
limit: Optional[int] = 5
|
237
|
+
filter: Optional[str] = None
|
238
|
+
field_mapping: Optional[FieldMapping] = None
|
239
|
+
|
200
240
|
class IndexConnection(BaseModel):
|
201
241
|
connection_id: Optional[str] = None
|
202
242
|
milvus: Optional[MilvusConnection] = None
|
203
243
|
elastic_search: Optional[ElasticSearchConnection] = None
|
204
244
|
custom_search: Optional[CustomSearchConnection] = None
|
205
|
-
|
245
|
+
astradb: Optional[AstraDBConnection] = None
|
206
246
|
|
207
247
|
class ConversationalSearchConfig(BaseModel):
|
208
248
|
language: Optional[str] = None
|
@@ -218,6 +258,10 @@ class KnowledgeBaseBuiltInVectorIndexConfig(BaseModel):
|
|
218
258
|
chunk_size: Optional[int] = None
|
219
259
|
chunk_overlap: Optional[int] = None
|
220
260
|
limit: Optional[int] = None
|
261
|
+
|
262
|
+
class FileUpload(BaseModel):
|
263
|
+
path: str
|
264
|
+
url: Optional[str] = None
|
221
265
|
|
222
266
|
class KnowledgeBaseSpec(BaseModel):
|
223
267
|
"""Schema for a complete knowledge-base."""
|
@@ -236,4 +280,4 @@ class KnowledgeBaseSpec(BaseModel):
|
|
236
280
|
created_on: Optional[datetime] = None
|
237
281
|
updated_at: Optional[datetime] = None
|
238
282
|
# For import/update
|
239
|
-
documents: list[str] = None
|
283
|
+
documents: list[str] | list[FileUpload] = None
|
@@ -1,27 +1,36 @@
|
|
1
|
-
from typing import List, Dict, Optional
|
1
|
+
from typing import List, Dict, Optional, Union
|
2
2
|
from enum import Enum
|
3
|
-
from pydantic import BaseModel
|
3
|
+
from pydantic import BaseModel
|
4
4
|
|
5
5
|
class ToolkitKind(str, Enum):
|
6
6
|
MCP = "mcp"
|
7
7
|
|
8
|
-
class Language(str, Enum):
|
9
|
-
NODE = "node"
|
10
|
-
PYTHON ="python"
|
11
|
-
|
12
8
|
class ToolkitSource(str, Enum):
|
13
9
|
FILES = "files"
|
14
10
|
PUBLIC_REGISTRY = "public-registry"
|
15
11
|
|
12
|
+
class ToolkitTransportKind(str, Enum):
|
13
|
+
STREAMABLE_HTTP = "streamable_http"
|
14
|
+
SSE = "sse"
|
16
15
|
|
16
|
+
class Language(str, Enum):
|
17
|
+
NODE = "node"
|
18
|
+
PYTHON ="python"
|
17
19
|
|
18
|
-
class
|
19
|
-
source:
|
20
|
+
class LocalMcpModel(BaseModel):
|
21
|
+
source: ToolkitSource
|
20
22
|
command: str
|
21
23
|
args: List[str]
|
22
24
|
tools: List[str]
|
23
25
|
connections: Dict[str, str]
|
24
26
|
|
27
|
+
class RemoteMcpModel(BaseModel):
|
28
|
+
server_url: str
|
29
|
+
transport: ToolkitTransportKind
|
30
|
+
tools: List[str]
|
31
|
+
connections: Dict[str, str]
|
32
|
+
|
33
|
+
McpModel = Union[LocalMcpModel, RemoteMcpModel]
|
25
34
|
|
26
35
|
class ToolkitSpec(BaseModel):
|
27
36
|
id: str
|
@@ -33,10 +42,4 @@ class ToolkitSpec(BaseModel):
|
|
33
42
|
created_by: str
|
34
43
|
created_by_username: str
|
35
44
|
tools: List[str] | None
|
36
|
-
mcp: McpModel
|
37
|
-
|
38
|
-
@model_validator(mode='after')
|
39
|
-
def validate_tools_and_mcp(self) -> 'ToolkitSpec':
|
40
|
-
if self.mcp.source not in {"files", "public-registry"}:
|
41
|
-
raise ValueError("MCP source must be either 'files' or 'public-registry'.")
|
42
|
-
return self
|
45
|
+
mcp: McpModel
|
@@ -187,15 +187,27 @@ def _fix_optional(schema):
|
|
187
187
|
replacements = {}
|
188
188
|
if schema.required is None:
|
189
189
|
schema.required = []
|
190
|
-
|
191
190
|
for k, v in schema.properties.items():
|
191
|
+
# Simple null type & required -> not required
|
192
192
|
if v.type == 'null' and k in schema.required:
|
193
193
|
not_required.append(k)
|
194
|
-
|
195
|
-
|
196
|
-
if
|
197
|
-
|
198
|
-
|
194
|
+
# Optional with null & required
|
195
|
+
if v.anyOf is not None and [x for x in v.anyOf if x.type == 'null']:
|
196
|
+
if k in schema.required:
|
197
|
+
# required with default -> not required
|
198
|
+
# required without default -> required & remove null from union
|
199
|
+
if v.default:
|
200
|
+
not_required.append(k)
|
201
|
+
else:
|
202
|
+
v.anyOf = list(filter(lambda x: x.type != 'null', v.anyOf))
|
203
|
+
if len(v.anyOf) == 1:
|
204
|
+
replacements[k] = v.anyOf[0]
|
205
|
+
else:
|
206
|
+
# not required with default -> no change
|
207
|
+
# not required without default -> means default input is 'None'
|
208
|
+
v.default = v.default if v.default else 'null'
|
209
|
+
|
210
|
+
|
199
211
|
schema.required = list(filter(lambda x: x not in not_required, schema.required if schema.required is not None else []))
|
200
212
|
for k, v in replacements.items():
|
201
213
|
combined = {
|
@@ -204,7 +216,7 @@ def _fix_optional(schema):
|
|
204
216
|
}
|
205
217
|
schema.properties[k] = JsonSchemaObject(**combined)
|
206
218
|
schema.properties[k].anyOf = None
|
207
|
-
|
219
|
+
|
208
220
|
for k in schema.properties.keys():
|
209
221
|
if schema.properties[k].type == 'object':
|
210
222
|
schema.properties[k] = _fix_optional(schema.properties[k])
|
@@ -0,0 +1 @@
|
|
1
|
+
from .types import VoiceConfiguration
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import json
|
2
|
+
from typing import Annotated, Optional, List, Dict
|
3
|
+
from pydantic import BaseModel, Field, model_validator
|
4
|
+
|
5
|
+
def _validate_exactly_one_of_fields(object: BaseModel, object_name: str, fields: list[str]):
|
6
|
+
present_fields = [getattr(object,field) for field in fields if getattr(object,field) is not None]
|
7
|
+
|
8
|
+
if len(present_fields) != 1:
|
9
|
+
raise ValueError(f"{object_name} requires exactly one of {','.join(fields)}")
|
10
|
+
|
11
|
+
|
12
|
+
def _validate_language_uniqueness(config: BaseModel):
|
13
|
+
if hasattr(config,'language') and hasattr(config,'additional_languages'):
|
14
|
+
if config.language and config.additional_languages and config.language in config.additional_languages:
|
15
|
+
raise ValueError(f"Language '{config.language}' cannot be in both the default language and additional_languages")
|
16
|
+
|
17
|
+
|
18
|
+
class WatsonSTTConfig(BaseModel):
|
19
|
+
api_url: Annotated[str, Field(min_length=1,max_length=2048)]
|
20
|
+
api_key: Optional[Annotated[str, Field(min_length=1,max_length=2048)]] = None
|
21
|
+
bearer_token: Optional[Annotated[str, Field(min_length=1,max_length=2048)]] = None
|
22
|
+
model: Annotated[str, Field(min_length=1,max_length=256)]
|
23
|
+
|
24
|
+
class EmotechSTTConfig(BaseModel):
|
25
|
+
api_key: Annotated[str,Field(min_length=1,max_length=2048)]
|
26
|
+
api_url: Annotated[str,Field(min_length=1,max_length=2048)]
|
27
|
+
|
28
|
+
|
29
|
+
class SpeechToTextConfig(BaseModel):
|
30
|
+
provider: Annotated[str, Field(min_length=1,max_length=128)]
|
31
|
+
watson_stt_config: Optional[WatsonSTTConfig] = None
|
32
|
+
emotech_stt_config: Optional[EmotechSTTConfig] = None
|
33
|
+
|
34
|
+
@model_validator(mode='after')
|
35
|
+
def validate_providers(self):
|
36
|
+
_validate_exactly_one_of_fields(self,'SpeechToTextConfig',['watson_stt_config','emotech_stt_config'])
|
37
|
+
return self
|
38
|
+
|
39
|
+
class WatsonTTSConfig(BaseModel):
|
40
|
+
api_url: Annotated[str, Field(min_length=1,max_length=2048)]
|
41
|
+
api_key: Optional[Annotated[str, Field(min_length=1,max_length=2048)]] = None
|
42
|
+
bearer_token: Optional[Annotated[str, Field(min_length=1,max_length=2048)]] = None
|
43
|
+
voice: Annotated[str, Field(min_length=1,max_length=128)]
|
44
|
+
rate_percentage: Optional[int] = None
|
45
|
+
pitch_percentage: Optional[int] = None
|
46
|
+
language: Optional[str] = None
|
47
|
+
|
48
|
+
class EmotechTTSConfig(BaseModel):
|
49
|
+
api_url: Annotated[str, Field(min_length=1,max_length=2048)]
|
50
|
+
api_key: Annotated[str, Field(min_length=1,max_length=2048)]
|
51
|
+
voice: Optional[Annotated[str, Field(min_length=1,max_length=128)]]
|
52
|
+
|
53
|
+
class TextToSpeechConfig(BaseModel):
|
54
|
+
provider: Annotated[str, Field(min_length=1,max_length=128)]
|
55
|
+
watson_tts_config: Optional[WatsonTTSConfig] = None
|
56
|
+
emotech_tts_config: Optional[EmotechTTSConfig] = None
|
57
|
+
|
58
|
+
@model_validator(mode='after')
|
59
|
+
def validate_providers(self):
|
60
|
+
_validate_exactly_one_of_fields(self,'TextToSpeechConfig',['watson_tts_config','emotech_tts_config'])
|
61
|
+
return self
|
62
|
+
|
63
|
+
class AdditionalProperties(BaseModel):
|
64
|
+
speech_to_text: Optional[SpeechToTextConfig] = None
|
65
|
+
text_to_speech: Optional[TextToSpeechConfig] = None
|
66
|
+
|
67
|
+
class DTMFInput(BaseModel):
|
68
|
+
inter_digit_timeout_ms: Optional[int] = None
|
69
|
+
termination_key: Optional[str] = None
|
70
|
+
maximum_count: Optional[int] = None
|
71
|
+
ignore_speech: Optional[bool] = None
|
72
|
+
|
73
|
+
class AttachedAgent(BaseModel):
|
74
|
+
id: str
|
75
|
+
name: Optional[str] = None
|
76
|
+
display_name: Optional[str] = None
|
77
|
+
|
78
|
+
class VoiceConfiguration(BaseModel):
|
79
|
+
name: Annotated[str, Field(min_length=1,max_length=128)]
|
80
|
+
speech_to_text: SpeechToTextConfig
|
81
|
+
text_to_speech: TextToSpeechConfig
|
82
|
+
language: Optional[Annotated[str,Field(min_length=2,max_length=16)]] = None
|
83
|
+
additional_languages: Optional[dict[str,AdditionalProperties]] = None
|
84
|
+
dtmf_input: Optional[DTMFInput] = None
|
85
|
+
voice_configuration_id: Optional[str] = None
|
86
|
+
tenant_id: Optional[Annotated[str, Field(min_length=1,max_length=128)]] = None
|
87
|
+
attached_agents: Optional[list[AttachedAgent]] = None
|
88
|
+
|
89
|
+
@model_validator(mode='after')
|
90
|
+
def validate_language(self):
|
91
|
+
_validate_language_uniqueness(self)
|
92
|
+
return self
|
93
|
+
|
94
|
+
def dumps_spec(self) -> str:
|
95
|
+
dumped = self.model_dump(mode='json', exclude_none=True)
|
96
|
+
return json.dumps(dumped, indent=2)
|
97
|
+
|
98
|
+
|
@@ -253,3 +253,23 @@ def export_agent(
|
|
253
253
|
):
|
254
254
|
agents_controller = AgentsController()
|
255
255
|
agents_controller.export_agent(name=name, kind=kind, output_path=output_file, agent_only_flag=agent_only_flag)
|
256
|
+
|
257
|
+
@agents_app.command(name="deploy", help="Deploy Agent")
|
258
|
+
def deploy_agent(
|
259
|
+
name: Annotated[
|
260
|
+
str,
|
261
|
+
typer.Option("--name", "-n", help="Name of the agent you wish to deploy"),
|
262
|
+
]
|
263
|
+
):
|
264
|
+
agents_controller = AgentsController()
|
265
|
+
agents_controller.deploy_agent(name=name)
|
266
|
+
|
267
|
+
@agents_app.command(name="undeploy", help="Undeploy Agent")
|
268
|
+
def undeploy_agent(
|
269
|
+
name: Annotated[
|
270
|
+
str,
|
271
|
+
typer.Option("--name", "-n", help="Name of the agent you wish to undeploy"),
|
272
|
+
]
|
273
|
+
):
|
274
|
+
agents_controller = AgentsController()
|
275
|
+
agents_controller.undeploy_agent(name=name)
|