ibm-watsonx-orchestrate 1.3.0__py3-none-any.whl → 1.4.2__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 +1 -1
- ibm_watsonx_orchestrate/agent_builder/agents/types.py +2 -0
- ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +9 -2
- ibm_watsonx_orchestrate/agent_builder/toolkits/base_toolkit.py +32 -0
- ibm_watsonx_orchestrate/agent_builder/toolkits/types.py +42 -0
- ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +10 -1
- ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +4 -2
- ibm_watsonx_orchestrate/agent_builder/tools/types.py +2 -1
- ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +29 -0
- ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +271 -12
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +17 -2
- ibm_watsonx_orchestrate/cli/commands/models/env_file_model_provider_mapper.py +180 -0
- ibm_watsonx_orchestrate/cli/commands/models/models_command.py +194 -8
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py +117 -48
- ibm_watsonx_orchestrate/cli/commands/server/types.py +105 -0
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +55 -7
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_controller.py +123 -42
- ibm_watsonx_orchestrate/cli/commands/tools/tools_command.py +22 -1
- ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +197 -12
- ibm_watsonx_orchestrate/client/agents/agent_client.py +4 -1
- ibm_watsonx_orchestrate/client/agents/assistant_agent_client.py +5 -1
- ibm_watsonx_orchestrate/client/agents/external_agent_client.py +5 -1
- ibm_watsonx_orchestrate/client/analytics/llm/analytics_llm_client.py +2 -6
- ibm_watsonx_orchestrate/client/base_api_client.py +5 -2
- ibm_watsonx_orchestrate/client/connections/connections_client.py +3 -9
- ibm_watsonx_orchestrate/client/model_policies/__init__.py +0 -0
- ibm_watsonx_orchestrate/client/model_policies/model_policies_client.py +47 -0
- ibm_watsonx_orchestrate/client/model_policies/types.py +36 -0
- ibm_watsonx_orchestrate/client/models/__init__.py +0 -0
- ibm_watsonx_orchestrate/client/models/models_client.py +46 -0
- ibm_watsonx_orchestrate/client/models/types.py +177 -0
- ibm_watsonx_orchestrate/client/toolkit/toolkit_client.py +15 -6
- ibm_watsonx_orchestrate/client/tools/tempus_client.py +40 -0
- ibm_watsonx_orchestrate/client/tools/tool_client.py +8 -0
- ibm_watsonx_orchestrate/docker/compose-lite.yml +68 -13
- ibm_watsonx_orchestrate/docker/default.env +22 -12
- ibm_watsonx_orchestrate/docker/tempus/common-config.yaml +1 -1
- ibm_watsonx_orchestrate/experimental/flow_builder/__init__.py +0 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/flows/__init__.py +41 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/flows/constants.py +17 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/flows/data_map.py +91 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/flows/decorators.py +143 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/flows/events.py +72 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/flows/flow.py +1288 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/node.py +97 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/resources/flow_status.openapi.yml +98 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/types.py +492 -0
- ibm_watsonx_orchestrate/experimental/flow_builder/utils.py +113 -0
- ibm_watsonx_orchestrate/utils/utils.py +5 -2
- {ibm_watsonx_orchestrate-1.3.0.dist-info → ibm_watsonx_orchestrate-1.4.2.dist-info}/METADATA +4 -1
- {ibm_watsonx_orchestrate-1.3.0.dist-info → ibm_watsonx_orchestrate-1.4.2.dist-info}/RECORD +54 -32
- {ibm_watsonx_orchestrate-1.3.0.dist-info → ibm_watsonx_orchestrate-1.4.2.dist-info}/WHEEL +0 -0
- {ibm_watsonx_orchestrate-1.3.0.dist-info → ibm_watsonx_orchestrate-1.4.2.dist-info}/entry_points.txt +0 -0
- {ibm_watsonx_orchestrate-1.3.0.dist-info → ibm_watsonx_orchestrate-1.4.2.dist-info}/licenses/LICENSE +0 -0
@@ -147,16 +147,10 @@ class ConnectionsClient(BaseAPIClient):
|
|
147
147
|
if conn_id is None:
|
148
148
|
return ""
|
149
149
|
try:
|
150
|
-
|
150
|
+
app_details = self._get(f"/connections/applications/id/{conn_id}")
|
151
|
+
return app_details.get("app_id")
|
151
152
|
except ClientAPIException as e:
|
152
153
|
if e.response.status_code == 404:
|
153
154
|
logger.warning(f"Connections not found. Returning connection ID: {conn_id}")
|
154
155
|
return conn_id
|
155
|
-
raise
|
156
|
-
|
157
|
-
app_id = next((conn.app_id for conn in connections if conn.connection_id == conn_id), None)
|
158
|
-
|
159
|
-
if app_id is None:
|
160
|
-
logger.warning(f"Connection with ID {conn_id} not found. Returning connection ID.")
|
161
|
-
return conn_id
|
162
|
-
return app_id
|
156
|
+
raise e
|
File without changes
|
@@ -0,0 +1,47 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from pydantic import ValidationError
|
4
|
+
from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient, ClientAPIException
|
5
|
+
|
6
|
+
import logging
|
7
|
+
|
8
|
+
from ibm_watsonx_orchestrate.client.model_policies.types import ModelPolicy
|
9
|
+
from ibm_watsonx_orchestrate.client.models.types import ListVirtualModel, CreateVirtualModel
|
10
|
+
|
11
|
+
logger = logging.getLogger(__name__)
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
class ModelPoliciesClient(BaseAPIClient):
|
18
|
+
"""
|
19
|
+
Client to handle CRUD operations for ModelPolicies endpoint
|
20
|
+
"""
|
21
|
+
# POST api/v1/model_policy
|
22
|
+
def create(self, model: ModelPolicy) -> None:
|
23
|
+
self._post("/model_policy", data=model.model_dump())
|
24
|
+
|
25
|
+
# DELETE api/v1/model_policy/{model_policy_id}
|
26
|
+
def delete(self, model_policy_id: str) -> dict:
|
27
|
+
return self._delete(f"/model_policy/{model_policy_id}")
|
28
|
+
|
29
|
+
# GET /api/v1/model_policy/{app_id}
|
30
|
+
def get(self, model_policy_id: str):
|
31
|
+
raise NotImplementedError
|
32
|
+
|
33
|
+
|
34
|
+
# GET api/v1/model_policy
|
35
|
+
def list(self) -> List[ModelPolicy]:
|
36
|
+
try:
|
37
|
+
res = self._get(f"/model_policy")
|
38
|
+
return [ModelPolicy.model_validate(policy) for policy in res]
|
39
|
+
except ValidationError as e:
|
40
|
+
logger.error("Received unexpected response from server")
|
41
|
+
raise e
|
42
|
+
except ClientAPIException as e:
|
43
|
+
if e.response.status_code == 404:
|
44
|
+
return []
|
45
|
+
raise e
|
46
|
+
|
47
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
from typing import Optional, List, Dict, Any, Union
|
3
|
+
|
4
|
+
from pydantic import Field, BaseModel, ConfigDict
|
5
|
+
|
6
|
+
class ModelPolicyStrategyMode(str, Enum):
|
7
|
+
LOAD_BALANCED = "loadbalance"
|
8
|
+
FALL_BACK = "fallback"
|
9
|
+
SINGLE = "single"
|
10
|
+
|
11
|
+
class ModelPolicyStrategy(BaseModel):
|
12
|
+
mode: ModelPolicyStrategyMode = None
|
13
|
+
on_status_codes: List[int] = None
|
14
|
+
|
15
|
+
class ModelPolicyRetry(BaseModel):
|
16
|
+
attempts: int = None
|
17
|
+
on_status_codes: List[int] = None
|
18
|
+
|
19
|
+
class ModelPolicyTarget(BaseModel):
|
20
|
+
model_id: str = None
|
21
|
+
weight: int = None
|
22
|
+
|
23
|
+
|
24
|
+
class ModelPolicyInner(BaseModel):
|
25
|
+
strategy: ModelPolicyStrategy = None
|
26
|
+
retry: ModelPolicyRetry = None
|
27
|
+
targets: List[Union[ModelPolicyTarget, 'ModelPolicyInner']] = None
|
28
|
+
|
29
|
+
|
30
|
+
class ModelPolicy(BaseModel):
|
31
|
+
model_config = ConfigDict(extra='allow')
|
32
|
+
|
33
|
+
name: str
|
34
|
+
display_name: str
|
35
|
+
policy: ModelPolicyInner
|
36
|
+
|
File without changes
|
@@ -0,0 +1,46 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from pydantic import ValidationError
|
4
|
+
from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient, ClientAPIException
|
5
|
+
|
6
|
+
import logging
|
7
|
+
|
8
|
+
from ibm_watsonx_orchestrate.client.models.types import ListVirtualModel, CreateVirtualModel
|
9
|
+
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
class ModelsClient(BaseAPIClient):
|
17
|
+
"""
|
18
|
+
Client to handle CRUD operations for Models endpoint
|
19
|
+
"""
|
20
|
+
# POST api/v1/models
|
21
|
+
def create(self, model: CreateVirtualModel) -> None:
|
22
|
+
self._post("/models", data=model.model_dump())
|
23
|
+
|
24
|
+
# DELETE api/v1/models/{model_id}
|
25
|
+
def delete(self, model_id: str) -> dict:
|
26
|
+
return self._delete(f"/models/{model_id}")
|
27
|
+
|
28
|
+
# GET /api/v1/models/{app_id}
|
29
|
+
def get(self, model_id: str):
|
30
|
+
raise NotImplementedError
|
31
|
+
|
32
|
+
|
33
|
+
# GET api/v1/models
|
34
|
+
def list(self) -> List[ListVirtualModel]:
|
35
|
+
try:
|
36
|
+
res = self._get(f"/models")
|
37
|
+
return [ListVirtualModel.model_validate(conn) for conn in res]
|
38
|
+
except ValidationError as e:
|
39
|
+
logger.error("Received unexpected response from server")
|
40
|
+
raise e
|
41
|
+
except ClientAPIException as e:
|
42
|
+
if e.response.status_code == 404:
|
43
|
+
return []
|
44
|
+
raise e
|
45
|
+
|
46
|
+
|
@@ -0,0 +1,177 @@
|
|
1
|
+
from typing import Optional, List, Dict, Any, Union
|
2
|
+
from enum import Enum
|
3
|
+
from pydantic import Field, BaseModel, ConfigDict
|
4
|
+
|
5
|
+
class ModelProvider(str, Enum):
|
6
|
+
OPENAI = 'openai'
|
7
|
+
A21 = 'a21'
|
8
|
+
ANTHROPIC = 'anthropic'
|
9
|
+
ANYSCALE = 'anyscale'
|
10
|
+
AZURE_OPENAI = 'azure-openai'
|
11
|
+
AZURE_AI = 'azure-ai'
|
12
|
+
BEDROCK = 'bedrock'
|
13
|
+
CEREBRAS = 'cerebras'
|
14
|
+
COHERE = 'cohere'
|
15
|
+
GOOGLE = 'google'
|
16
|
+
VERTEX_AI = 'vertex-ai'
|
17
|
+
GROQ = 'groq'
|
18
|
+
HUGGINGFACE = 'huggingface'
|
19
|
+
MISTRAL_AI = 'mistral-ai'
|
20
|
+
JINA = 'jina'
|
21
|
+
OLLAMA = 'ollama'
|
22
|
+
OPENROUTER = 'openrouter'
|
23
|
+
STABILITY_AI = 'stability-ai'
|
24
|
+
TOGETHER_AI = 'together-ai'
|
25
|
+
WATSONX = 'watsonx'
|
26
|
+
|
27
|
+
def __str__(self):
|
28
|
+
return self.value
|
29
|
+
|
30
|
+
def __repr__(self):
|
31
|
+
return self.value
|
32
|
+
|
33
|
+
|
34
|
+
class ProviderConfig(BaseModel):
|
35
|
+
# Required fields
|
36
|
+
provider: Optional[str]=''
|
37
|
+
|
38
|
+
|
39
|
+
api_key: Optional[str] = '' # this is not optional
|
40
|
+
url_to_fetch: Optional[str] = Field(None, alias="urlToFetch")
|
41
|
+
|
42
|
+
# Misc
|
43
|
+
custom_host: Optional[str] = Field(None, alias="customHost")
|
44
|
+
forward_headers: Optional[List[str]] = Field(None, alias="forwardHeaders")
|
45
|
+
index: Optional[int] = None
|
46
|
+
cache: Optional[Union[str, Dict[str, Any]]] = None # Define CacheSettings if needed
|
47
|
+
metadata: Optional[Dict[str, str]] = None
|
48
|
+
request_timeout: Optional[int] = Field(None, alias="requestTimeout")
|
49
|
+
transform_to_form_data: Optional[bool] = Field(None, alias="transformToFormData")
|
50
|
+
|
51
|
+
# Azure specific
|
52
|
+
azure_resource_name: Optional[str] = Field(None, alias="resourceName")
|
53
|
+
azure_deployment_id: Optional[str] = Field(None, alias="deploymentId")
|
54
|
+
azure_api_version: Optional[str] = Field(None, alias="apiVersion")
|
55
|
+
ad_auth: Optional[str] = Field(None, alias="adAuth")
|
56
|
+
azure_auth_mode: Optional[str] = Field(None, alias="azureAuthMode")
|
57
|
+
azure_managed_client_id: Optional[str] = Field(None, alias="azureManagedClientId")
|
58
|
+
azure_entra_client_id: Optional[str] = Field(None, alias="azureEntraClientId")
|
59
|
+
azure_entra_client_secret: Optional[str] = Field(None, alias="azureEntraClientSecret")
|
60
|
+
azure_entra_tenant_id: Optional[str] = Field(None, alias="azureEntraTenantId")
|
61
|
+
azure_ad_token: Optional[str] = Field(None, alias="azureAdToken")
|
62
|
+
azure_model_name: Optional[str] = Field(None, alias="azureModelName")
|
63
|
+
|
64
|
+
# Workers AI specific
|
65
|
+
workers_ai_account_id: Optional[str] = Field(None, alias="workersAiAccountId")
|
66
|
+
|
67
|
+
|
68
|
+
# AWS
|
69
|
+
aws_secret_access_key: Optional[str] = Field(None, alias="awsSecretAccessKey")
|
70
|
+
aws_access_key_id: Optional[str] = Field(None, alias="awsAccessKeyId")
|
71
|
+
aws_session_token: Optional[str] = Field(None, alias="awsSessionToken")
|
72
|
+
aws_region: Optional[str] = Field(None, alias="awsRegion")
|
73
|
+
aws_auth_type: Optional[str] = Field(None, alias="awsAuthType")
|
74
|
+
aws_role_arn: Optional[str] = Field(None, alias="awsRoleArn")
|
75
|
+
aws_external_id: Optional[str] = Field(None, alias="awsExternalId")
|
76
|
+
aws_s3_bucket: Optional[str] = Field(None, alias="awsS3Bucket")
|
77
|
+
aws_s3_object_key: Optional[str] = Field(None, alias="awsS3ObjectKey")
|
78
|
+
aws_bedrock_model: Optional[str] = Field(None, alias="awsBedrockModel")
|
79
|
+
aws_server_side_encryption: Optional[str] = Field(None, alias="awsServerSideEncryption")
|
80
|
+
aws_server_side_encryption_kms_key_id: Optional[str] = Field(None, alias="awsServerSideEncryptionKMSKeyId")
|
81
|
+
|
82
|
+
# Sagemaker
|
83
|
+
amzn_sagemaker_custom_attributes: Optional[str] = Field(None, alias="amznSagemakerCustomAttributes")
|
84
|
+
amzn_sagemaker_target_model: Optional[str] = Field(None, alias="amznSagemakerTargetModel")
|
85
|
+
amzn_sagemaker_target_variant: Optional[str] = Field(None, alias="amznSagemakerTargetVariant")
|
86
|
+
amzn_sagemaker_target_container_hostname: Optional[str] = Field(None, alias="amznSagemakerTargetContainerHostname")
|
87
|
+
amzn_sagemaker_inference_id: Optional[str] = Field(None, alias="amznSagemakerInferenceId")
|
88
|
+
amzn_sagemaker_enable_explanations: Optional[str] = Field(None, alias="amznSagemakerEnableExplanations")
|
89
|
+
amzn_sagemaker_inference_component: Optional[str] = Field(None, alias="amznSagemakerInferenceComponent")
|
90
|
+
amzn_sagemaker_session_id: Optional[str] = Field(None, alias="amznSagemakerSessionId")
|
91
|
+
amzn_sagemaker_model_name: Optional[str] = Field(None, alias="amznSagemakerModelName")
|
92
|
+
|
93
|
+
# Stability AI
|
94
|
+
stability_client_id: Optional[str] = Field(None, alias="stabilityClientId")
|
95
|
+
stability_client_user_id: Optional[str] = Field(None, alias="stabilityClientUserId")
|
96
|
+
stability_client_version: Optional[str] = Field(None, alias="stabilityClientVersion")
|
97
|
+
|
98
|
+
# Hugging Face
|
99
|
+
huggingface_base_url: Optional[str] = Field(None, alias="huggingfaceBaseUrl")
|
100
|
+
|
101
|
+
# Google Vertex AI
|
102
|
+
vertex_region: Optional[str] = Field(None, alias="vertexRegion")
|
103
|
+
vertex_project_id: Optional[str] = Field(None, alias="vertexProjectId")
|
104
|
+
vertex_service_account_json: Optional[Dict[str, Any]] = Field(None, alias="vertexServiceAccountJson")
|
105
|
+
vertex_storage_bucket_name: Optional[str] = Field(None, alias="vertexStorageBucketName")
|
106
|
+
vertex_model_name: Optional[str] = Field(None, alias="vertexModelName")
|
107
|
+
|
108
|
+
filename: Optional[str] = None
|
109
|
+
|
110
|
+
after_request_hooks: Optional[List[Dict[str, Any]]] = Field(None, alias="afterRequestHooks")
|
111
|
+
before_request_hooks: Optional[List[Dict[str, Any]]] = Field(None, alias="beforeRequestHooks")
|
112
|
+
default_input_guardrails: Optional[List[Dict[str, Any]]] = Field(None, alias="defaultInputGuardrails")
|
113
|
+
default_output_guardrails: Optional[List[Dict[str, Any]]] = Field(None, alias="defaultOutputGuardrails")
|
114
|
+
|
115
|
+
# OpenAI
|
116
|
+
openai_project: Optional[str] = Field(None, alias="openaiProject")
|
117
|
+
openai_organization: Optional[str] = Field(None, alias="openaiOrganization")
|
118
|
+
openai_beta: Optional[str] = Field(None, alias="openaiBeta")
|
119
|
+
|
120
|
+
# Azure Inference
|
121
|
+
azure_deployment_name: Optional[str] = Field(None, alias="azureDeploymentName")
|
122
|
+
azure_api_version: Optional[str] = Field(None, alias="azureApiVersion")
|
123
|
+
azure_extra_params: Optional[str] = Field(None, alias="azureExtraParams")
|
124
|
+
azure_foundry_url: Optional[str] = Field(None, alias="azureFoundryUrl")
|
125
|
+
|
126
|
+
strict_open_ai_compliance: Optional[bool] = Field(False, alias="strictOpenAiCompliance")
|
127
|
+
mistral_fim_completion: Optional[str] = Field(None, alias="mistralFimCompletion")
|
128
|
+
|
129
|
+
# Anthropic
|
130
|
+
anthropic_beta: Optional[str] = Field(None, alias="anthropicBeta")
|
131
|
+
anthropic_version: Optional[str] = Field(None, alias="anthropicVersion")
|
132
|
+
|
133
|
+
# Fireworks
|
134
|
+
fireworks_account_id: Optional[str] = Field(None, alias="fireworksAccountId")
|
135
|
+
|
136
|
+
# Cortex
|
137
|
+
snowflake_account: Optional[str] = Field(None, alias="snowflakeAccount")
|
138
|
+
|
139
|
+
# WatsonX
|
140
|
+
watsonx_version: Optional[str] = Field(None, alias="watsonxVersion")
|
141
|
+
watsonx_space_id: Optional[str] = Field(None, alias="watsonxSpaceId")
|
142
|
+
watsonx_project_id: Optional[str] = Field(None, alias="watsonxProjectId")
|
143
|
+
|
144
|
+
model_config = {
|
145
|
+
"populate_by_name": True, # Replaces allow_population_by_field_name
|
146
|
+
"extra": "forbid", # Same as before
|
147
|
+
"json_schema_extra": lambda schema: schema.get("properties", {}).pop("provider", None)
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
class CreateVirtualModel(BaseModel):
|
153
|
+
model_config = ConfigDict(extra='allow')
|
154
|
+
|
155
|
+
name: str
|
156
|
+
display_name: Optional[str]
|
157
|
+
description: Optional[str]
|
158
|
+
config: Optional[dict] = None
|
159
|
+
provider_config: ProviderConfig
|
160
|
+
tags: List[str]
|
161
|
+
model_type: str = 'chat'
|
162
|
+
|
163
|
+
|
164
|
+
class ListVirtualModel(BaseModel):
|
165
|
+
model_config = ConfigDict(extra='allow')
|
166
|
+
|
167
|
+
id: Optional[str] = None
|
168
|
+
name: Optional[str] = None
|
169
|
+
display_name: Optional[str] = None
|
170
|
+
description: Optional[str] = None
|
171
|
+
provider: Optional[str] = None
|
172
|
+
# model_configuration: Optional[dict] = None
|
173
|
+
provider_config: Optional[ProviderConfig] = None
|
174
|
+
tags: Optional[List[str]] = None
|
175
|
+
model_type: Optional[str] = None
|
176
|
+
|
177
|
+
ANTHROPIC_DEFAULT_MAX_TOKENS = 4096
|
@@ -1,9 +1,18 @@
|
|
1
1
|
from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient, ClientAPIException
|
2
|
+
from ibm_watsonx_orchestrate.client.utils import is_local_dev
|
2
3
|
from typing_extensions import List
|
3
4
|
import os
|
4
5
|
import json
|
5
6
|
|
6
7
|
class ToolKitClient(BaseAPIClient):
|
8
|
+
|
9
|
+
def __init__(self, *args, **kwargs):
|
10
|
+
super().__init__(*args, **kwargs)
|
11
|
+
self.base_endpoint = "/orchestrate/toolkits" if is_local_dev(self.base_url) else "/toolkits"
|
12
|
+
|
13
|
+
def get(self) -> dict:
|
14
|
+
return self._get(self.base_endpoint)
|
15
|
+
|
7
16
|
# POST /toolkits/prepare/list-tools
|
8
17
|
def list_tools(self, zip_file_path: str, command: str, args: List[str]) -> List[str]:
|
9
18
|
"""
|
@@ -24,7 +33,7 @@ class ToolKitClient(BaseAPIClient):
|
|
24
33
|
"file": (filename, f, "application/zip"),
|
25
34
|
}
|
26
35
|
|
27
|
-
response = self._post("/
|
36
|
+
response = self._post(f"{self.base_endpoint}/prepare/list-tools", files=files)
|
28
37
|
|
29
38
|
return response.get("tools", [])
|
30
39
|
|
@@ -35,7 +44,7 @@ class ToolKitClient(BaseAPIClient):
|
|
35
44
|
Creates new toolkit metadata
|
36
45
|
"""
|
37
46
|
try:
|
38
|
-
return self._post(
|
47
|
+
return self._post(self.base_endpoint, data=payload)
|
39
48
|
except ClientAPIException as e:
|
40
49
|
if e.response.status_code == 400 and "already exists" in e.response.text:
|
41
50
|
raise ClientAPIException(
|
@@ -54,25 +63,25 @@ class ToolKitClient(BaseAPIClient):
|
|
54
63
|
files = {
|
55
64
|
"file": (filename, f, "application/zip", {"Expires": "0"})
|
56
65
|
}
|
57
|
-
return self._post(f"/
|
66
|
+
return self._post(f"{self.base_endpoint}/{toolkit_id}/upload", files=files)
|
58
67
|
|
59
68
|
# DELETE /toolkits/{toolkit-id}
|
60
69
|
def delete(self, toolkit_id: str) -> dict:
|
61
|
-
return self._delete(f"/
|
70
|
+
return self._delete(f"{self.base_endpoint}/{toolkit_id}")
|
62
71
|
|
63
72
|
def get_draft_by_name(self, toolkit_name: str) -> List[dict]:
|
64
73
|
return self.get_drafts_by_names([toolkit_name])
|
65
74
|
|
66
75
|
def get_drafts_by_names(self, toolkit_names: List[str]) -> List[dict]:
|
67
76
|
formatted_toolkit_names = [f"names={x}" for x in toolkit_names]
|
68
|
-
return self._get(f"
|
77
|
+
return self._get(f"{self.base_endpoint}?{'&'.join(formatted_toolkit_names)}")
|
69
78
|
|
70
79
|
def get_draft_by_id(self, toolkit_id: str) -> dict:
|
71
80
|
if toolkit_id is None:
|
72
81
|
return ""
|
73
82
|
else:
|
74
83
|
try:
|
75
|
-
toolkit = self._get(f"/
|
84
|
+
toolkit = self._get(f"{self.base_endpoint}/{toolkit_id}")
|
76
85
|
return toolkit
|
77
86
|
except ClientAPIException as e:
|
78
87
|
if e.response.status_code == 404 and "not found with the given name" in e.response.text:
|
@@ -0,0 +1,40 @@
|
|
1
|
+
from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient, ClientAPIException
|
2
|
+
from typing_extensions import List
|
3
|
+
from urllib.parse import urlparse, urlunparse
|
4
|
+
from ibm_cloud_sdk_core.authenticators import MCSPAuthenticator
|
5
|
+
|
6
|
+
DEFAULT_TEMPUS_PORT= 9044
|
7
|
+
|
8
|
+
class TempusClient(BaseAPIClient):
|
9
|
+
"""
|
10
|
+
Client to handle CRUD operations for Tempus endpoint
|
11
|
+
|
12
|
+
This may be temporary and may want to create a proxy API in wxo-server
|
13
|
+
to redirect to the internal tempus runtime, and add a new operation in the ToolClient instead
|
14
|
+
"""
|
15
|
+
def __init__(self, base_url: str, api_key: str = None, is_local: bool = False, authenticator: MCSPAuthenticator = None):
|
16
|
+
parsed_url = urlparse(base_url)
|
17
|
+
|
18
|
+
# Reconstruct netloc with new port - use default above - eventually we need to open up a way through the wxo-server API
|
19
|
+
new_netloc = f"{parsed_url.hostname}:{DEFAULT_TEMPUS_PORT}"
|
20
|
+
|
21
|
+
# Replace netloc and rebuild the URL
|
22
|
+
new_url = urlunparse(parsed_url._replace(netloc=new_netloc))
|
23
|
+
# remove trailing slash
|
24
|
+
|
25
|
+
super().__init__(
|
26
|
+
base_url=new_url,
|
27
|
+
api_key=api_key,
|
28
|
+
is_local=is_local,
|
29
|
+
authenticator=authenticator
|
30
|
+
)
|
31
|
+
|
32
|
+
def create_update_flow_model(self, flow_id: str, model: dict) -> dict:
|
33
|
+
return self._post(f"/v1/flow-models/{flow_id}", data=model)
|
34
|
+
|
35
|
+
def run_flow(self, flow_id: str, input: dict) -> dict:
|
36
|
+
return self._post(f"/v1/flows/{flow_id}/versions/TIP/run", data=input)
|
37
|
+
|
38
|
+
def arun_flow(self, flow_id: str, input: dict) -> dict:
|
39
|
+
return self._post(f"/v1/flows/{flow_id}/versions/TIP/run/async", data=input)
|
40
|
+
|
@@ -21,6 +21,10 @@ class ToolClient(BaseAPIClient):
|
|
21
21
|
def upload_tools_artifact(self, tool_id: str, file_path: str) -> dict:
|
22
22
|
return self._post(f"/tools/{tool_id}/upload", files={"file": (f"{tool_id}.zip", open(file_path, "rb"), "application/zip", {"Expires": "0"})})
|
23
23
|
|
24
|
+
def download_tools_artifact(self, tool_id: str) -> bytes:
|
25
|
+
response = self._get(f"/tools/{tool_id}/download", return_raw=True)
|
26
|
+
return response.content
|
27
|
+
|
24
28
|
def get_draft_by_name(self, tool_name: str) -> List[dict]:
|
25
29
|
return self.get_drafts_by_names([tool_name])
|
26
30
|
|
@@ -39,3 +43,7 @@ class ToolClient(BaseAPIClient):
|
|
39
43
|
if e.response.status_code == 404 and "not found with the given name" in e.response.text:
|
40
44
|
return ""
|
41
45
|
raise(e)
|
46
|
+
|
47
|
+
def get_drafts_by_ids(self, tool_ids: List[str]) -> List[dict]:
|
48
|
+
formatted_tool_ids = [f"ids={x}" for x in tool_ids]
|
49
|
+
return self._get(f"/tools?{'&'.join(formatted_tool_ids)}")
|
@@ -49,6 +49,17 @@ services:
|
|
49
49
|
ports:
|
50
50
|
- 3001:3001
|
51
51
|
|
52
|
+
ai-gateway:
|
53
|
+
image: ${AI_GATEWAY_REGISTRY:-us.icr.io/watson-orchestrate-private}/ai-gateway:${AI_GATEWAY_TAG:-latest}
|
54
|
+
platform: linux/amd64
|
55
|
+
restart: unless-stopped
|
56
|
+
ports:
|
57
|
+
- "8787:8787"
|
58
|
+
environment:
|
59
|
+
WATSONX_API_KEY: ${WATSONX_APIKEY}
|
60
|
+
WATSONX_URL: ${WATSONX_URL}
|
61
|
+
WATSONX_SPACE_ID: ${WATSONX_SPACE_ID}
|
62
|
+
|
52
63
|
ui:
|
53
64
|
image: ${UI_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-chat:${UITAG:-latest}
|
54
65
|
platform: linux/amd64
|
@@ -95,6 +106,7 @@ services:
|
|
95
106
|
environment:
|
96
107
|
WXO_DEPLOYMENT_TYPE: 'laptop'
|
97
108
|
AGENT_RUNTIME_ENDPOINT: http://wxo-server:4321
|
109
|
+
TEMPUS_RUNTIME_ENDPOINT: http://wxo-tempus-runtime:9044
|
98
110
|
command: 'npm start'
|
99
111
|
ports:
|
100
112
|
- '4025:4025'
|
@@ -210,14 +222,21 @@ services:
|
|
210
222
|
volumes:
|
211
223
|
- ./sdk:/packages
|
212
224
|
- tools:/tools
|
225
|
+
|
213
226
|
command: >
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
227
|
+
bash -c '
|
228
|
+
export PYTHONPATH="/tmp/monkey:$PYTHONPATH"
|
229
|
+
mkdir -p /tmp/monkey &&
|
230
|
+
|
231
|
+
echo -e "from uvicorn.supervisors.multiprocess import Process\n_original_is_alive = Process.is_alive\ndef patched_is_alive(self, timeout: float = 30):\n return _original_is_alive(self, timeout=30)\nProcess.is_alive = patched_is_alive" > /tmp/monkey/sitecustomize.py &&
|
232
|
+
|
233
|
+
uvicorn --host 0.0.0.0 --port 4321 --log-config /app/config/logs/log_conf.yaml --log-level debug --workers 5 wo_archer.api.main:app &
|
234
|
+
|
235
|
+
for i in {1..40}; do curl --silent --fail http://127.0.0.1:4321/health/alive && echo "[INFO] HTTP Service ready" && break || echo "[INFO] Waiting for HTTP service..." && sleep 10; done;
|
236
|
+
curl --silent --fail http://127.0.0.1:4321/health/alive || (echo "[ERROR] HTTP service failed to start" && exit 1);
|
237
|
+
|
238
|
+
wait
|
239
|
+
'
|
221
240
|
depends_on:
|
222
241
|
wxo-server-redis:
|
223
242
|
condition: service_started
|
@@ -294,6 +313,15 @@ services:
|
|
294
313
|
MILVUS_DB_NAME: default
|
295
314
|
MILVUS_USERNAME: root
|
296
315
|
MILVUS_PASSWORD: Milvus
|
316
|
+
WO_API_KEY: ${WO_API_KEY}
|
317
|
+
WO_USERNAME: ${WO_USERNAME}
|
318
|
+
WO_PASSWORD: ${WO_PASSWORD}
|
319
|
+
WO_INSTANCE: ${WO_INSTANCE}
|
320
|
+
USE_SAAS_ML_TOOLS_RUNTIME: ${USE_SAAS_ML_TOOLS_RUNTIME}
|
321
|
+
AUTHORIZATION_URL: ${AUTHORIZATION_URL}
|
322
|
+
WO_AUTH_TYPE: ${WO_AUTH_TYPE}
|
323
|
+
AI_GATEWAY_BASE_URL: ${AI_GATEWAY_BASE_URL}
|
324
|
+
AI_GATEWAY_ENABLED : ${AI_GATEWAY_ENABLED}
|
297
325
|
|
298
326
|
wxo-server-worker:
|
299
327
|
image: ${WORKER_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-server-conversation_controller:${WORKER_TAG:-latest}
|
@@ -311,6 +339,8 @@ services:
|
|
311
339
|
- ./sdk:/packages
|
312
340
|
- tools:/tools
|
313
341
|
environment:
|
342
|
+
AI_GATEWAY_ENABLED : ${AI_GATEWAY_ENABLED}
|
343
|
+
AI_GATEWAY_BASE_URL: ${AI_GATEWAY_BASE_URL}
|
314
344
|
IS_WXO_LITE: 'TRUE'
|
315
345
|
TRM_BASE_URL: http://tools-runtime-manager:8080
|
316
346
|
AGENT_STEP_DETAILS: redis://wxo-server-redis:6379/0
|
@@ -372,6 +402,13 @@ services:
|
|
372
402
|
MILVUS_DB_NAME: default
|
373
403
|
MILVUS_USERNAME: root
|
374
404
|
MILVUS_PASSWORD: Milvus
|
405
|
+
WO_API_KEY: ${WO_API_KEY}
|
406
|
+
WO_USERNAME: ${WO_USERNAME}
|
407
|
+
WO_PASSWORD: ${WO_PASSWORD}
|
408
|
+
WO_INSTANCE: ${WO_INSTANCE}
|
409
|
+
USE_SAAS_ML_TOOLS_RUNTIME: ${USE_SAAS_ML_TOOLS_RUNTIME}
|
410
|
+
AUTHORIZATION_URL: ${AUTHORIZATION_URL}
|
411
|
+
WO_AUTH_TYPE: ${WO_AUTH_TYPE}
|
375
412
|
|
376
413
|
tools-runtime-manager:
|
377
414
|
image: ${TRM_REGISTRY:-us.icr.io/watson-orchestrate-private}/tools-runtime-manager:${TRM_TAG:-latest}
|
@@ -407,6 +444,12 @@ services:
|
|
407
444
|
VOLUME_MOUNT_PATH: "/shared-data"
|
408
445
|
TOOLS_RUNTIME_MANAGER_BASE_URL: ${TOOLS_RUNTIME_MANAGER_BASE_URL}
|
409
446
|
CONNECTION_SERVICE_BASE_URL: http://wxo-server-connection-manager:3001
|
447
|
+
STORAGE_S3_BUCKET: ${STORAGE_S3_BUCKET:-wxo-server-storage-bucket}
|
448
|
+
STORAGE_S3_ENDPOINT: http://wxo-server-minio:9000
|
449
|
+
STORAGE_S3_FORCE_PATH_STYLE: 'true'
|
450
|
+
STORAGE_S3_REGION: us-east-1
|
451
|
+
AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minioadmin}
|
452
|
+
AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:-watsonxorchestrate}
|
410
453
|
extra_hosts:
|
411
454
|
- "host.docker.internal:host-gateway"
|
412
455
|
|
@@ -432,6 +475,12 @@ services:
|
|
432
475
|
DB_PASSWORD: ${DB_PASSWORD:-postgres}
|
433
476
|
DB_NAME: ${DB_NAME:-postgres}
|
434
477
|
DB_SSLMODE: ${DB_SSLMODE:-disable} # Disable SSL if not configured
|
478
|
+
STORAGE_S3_BUCKET: ${STORAGE_S3_BUCKET:-wxo-server-storage-bucket}
|
479
|
+
STORAGE_S3_ENDPOINT: http://wxo-server-minio:9000
|
480
|
+
STORAGE_S3_FORCE_PATH_STYLE: 'true'
|
481
|
+
STORAGE_S3_REGION: us-east-1
|
482
|
+
AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minioadmin}
|
483
|
+
AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:-watsonxorchestrate}
|
435
484
|
|
436
485
|
########################
|
437
486
|
# LANGFUSE dependencies
|
@@ -531,11 +580,8 @@ services:
|
|
531
580
|
wxo-tempus-runtime:
|
532
581
|
image: ${FLOW_RUMTIME_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-tempus-runtime:${FLOW_RUNTIME_TAG:-latest}
|
533
582
|
restart: unless-stopped
|
534
|
-
platform: linux/amd64
|
535
|
-
profiles: [with-tempus-runtime]
|
536
583
|
environment:
|
537
584
|
NODE_TLS_REJECT_UNAUTHORIZED: "0"
|
538
|
-
COMMON_CONFIG_FILE: "/shared/common-config.yaml"
|
539
585
|
SERVER_MODE: production
|
540
586
|
SERVER_ENVIRONMENT: SDK
|
541
587
|
SERVER_HTTP_PORT: "9044"
|
@@ -557,6 +603,17 @@ services:
|
|
557
603
|
PG_DATABASE: ${POSTGRES_USER:-postgres}
|
558
604
|
USER_MGMT_BASE_URL: "" # TODO
|
559
605
|
WXO_SERVER_BASE_URL: http://wxo-server:4321
|
606
|
+
TRM_SERVER_BASE_URL: http://tools-runtime-manager:8080
|
607
|
+
CONNECTION_MANAGER_SERVER_BASE_URL: http://wxo-server-connection-manager:3001
|
608
|
+
REDIS_ENDPOINT: wxo-server-redis:6379
|
609
|
+
REDIS_USER:
|
610
|
+
REDIS_PASSWORD:
|
611
|
+
REDIS_TLS: false
|
612
|
+
LANGFUSE_ENABLED: ${LANGFUSE_ENABLED:-false}
|
613
|
+
LANGFUSE_HOST: ${LANGFUSE_HOST:-http://langfuse-web:3000}
|
614
|
+
LANGFUSE_PUBLIC_KEY: ${LANGFUSE_PUBLIC_KEY:-pk-lf-7417757e-d6df-421b-957e-683b76acb5df}
|
615
|
+
LANGFUSE_SECRET_KEY: ${LANGFUSE_PRIVATE_KEY:-sk-lf-7bc4da63-7b2b-40c0-b5eb-1e0cf64f9af2}
|
616
|
+
LOG_LEVEL: info
|
560
617
|
healthcheck:
|
561
618
|
test: curl -k http://localhost:9044/readiness --fail
|
562
619
|
interval: 5s
|
@@ -564,8 +621,6 @@ services:
|
|
564
621
|
retries: 5
|
565
622
|
ports:
|
566
623
|
- 9044:9044
|
567
|
-
volumes:
|
568
|
-
- ./tempus/common-config.yaml:/shared/common-config.yaml
|
569
624
|
depends_on:
|
570
625
|
- wxo-server-db
|
571
626
|
|
@@ -595,4 +650,4 @@ volumes:
|
|
595
650
|
networks:
|
596
651
|
default:
|
597
652
|
name: wxo-server
|
598
|
-
|
653
|
+
|