ibm-watsonx-orchestrate 1.7.0a0__py3-none-any.whl → 1.8.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 +1 -1
- ibm_watsonx_orchestrate/agent_builder/agents/agent.py +3 -3
- ibm_watsonx_orchestrate/agent_builder/agents/assistant_agent.py +3 -2
- ibm_watsonx_orchestrate/agent_builder/agents/external_agent.py +3 -2
- ibm_watsonx_orchestrate/agent_builder/agents/types.py +38 -9
- ibm_watsonx_orchestrate/agent_builder/agents/webchat_customizations/prompts.py +1 -0
- ibm_watsonx_orchestrate/agent_builder/connections/connections.py +25 -10
- ibm_watsonx_orchestrate/agent_builder/connections/types.py +19 -11
- ibm_watsonx_orchestrate/agent_builder/knowledge_bases/knowledge_base_requests.py +1 -22
- ibm_watsonx_orchestrate/agent_builder/knowledge_bases/types.py +1 -17
- ibm_watsonx_orchestrate/agent_builder/tools/base_tool.py +2 -1
- ibm_watsonx_orchestrate/agent_builder/tools/openapi_tool.py +14 -13
- ibm_watsonx_orchestrate/agent_builder/tools/python_tool.py +136 -92
- ibm_watsonx_orchestrate/agent_builder/tools/types.py +10 -9
- ibm_watsonx_orchestrate/cli/commands/agents/agents_command.py +7 -7
- ibm_watsonx_orchestrate/cli/commands/agents/agents_controller.py +35 -7
- ibm_watsonx_orchestrate/cli/commands/channels/types.py +15 -2
- ibm_watsonx_orchestrate/cli/commands/channels/webchat/channels_webchat_controller.py +35 -25
- ibm_watsonx_orchestrate/cli/commands/chat/chat_command.py +2 -0
- ibm_watsonx_orchestrate/cli/commands/connections/connections_command.py +14 -6
- ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +12 -12
- ibm_watsonx_orchestrate/cli/commands/copilot/copilot_command.py +65 -0
- ibm_watsonx_orchestrate/cli/commands/copilot/copilot_controller.py +368 -0
- ibm_watsonx_orchestrate/cli/commands/copilot/copilot_server_controller.py +170 -0
- ibm_watsonx_orchestrate/cli/commands/environment/environment_controller.py +6 -6
- ibm_watsonx_orchestrate/cli/commands/environment/types.py +3 -1
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py +134 -36
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py +42 -11
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_command.py +0 -18
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +36 -20
- ibm_watsonx_orchestrate/cli/commands/models/models_command.py +1 -1
- ibm_watsonx_orchestrate/cli/commands/models/models_controller.py +5 -8
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py +59 -10
- ibm_watsonx_orchestrate/cli/commands/toolkit/toolkit_command.py +1 -1
- ibm_watsonx_orchestrate/cli/commands/tools/tools_controller.py +93 -14
- ibm_watsonx_orchestrate/cli/config.py +3 -3
- ibm_watsonx_orchestrate/cli/init_helper.py +10 -1
- ibm_watsonx_orchestrate/cli/main.py +5 -0
- ibm_watsonx_orchestrate/client/base_api_client.py +12 -0
- ibm_watsonx_orchestrate/client/connections/connections_client.py +5 -30
- ibm_watsonx_orchestrate/client/copilot/cpe/copilot_cpe_client.py +67 -0
- ibm_watsonx_orchestrate/client/knowledge_bases/knowledge_base_client.py +1 -1
- ibm_watsonx_orchestrate/client/local_service_instance.py +3 -1
- ibm_watsonx_orchestrate/client/service_instance.py +33 -7
- ibm_watsonx_orchestrate/client/utils.py +49 -8
- ibm_watsonx_orchestrate/docker/compose-lite.yml +25 -6
- ibm_watsonx_orchestrate/docker/default.env +26 -15
- ibm_watsonx_orchestrate/flow_builder/flows/__init__.py +9 -4
- ibm_watsonx_orchestrate/flow_builder/flows/decorators.py +4 -2
- ibm_watsonx_orchestrate/flow_builder/flows/events.py +10 -9
- ibm_watsonx_orchestrate/flow_builder/flows/flow.py +131 -20
- ibm_watsonx_orchestrate/flow_builder/node.py +18 -1
- ibm_watsonx_orchestrate/flow_builder/types.py +271 -15
- ibm_watsonx_orchestrate/flow_builder/utils.py +121 -6
- ibm_watsonx_orchestrate/utils/exceptions.py +23 -0
- {ibm_watsonx_orchestrate-1.7.0a0.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/METADATA +5 -5
- {ibm_watsonx_orchestrate-1.7.0a0.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/RECORD +60 -56
- ibm_watsonx_orchestrate/flow_builder/resources/flow_status.openapi.yml +0 -66
- {ibm_watsonx_orchestrate-1.7.0a0.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/WHEEL +0 -0
- {ibm_watsonx_orchestrate-1.7.0a0.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/entry_points.txt +0 -0
- {ibm_watsonx_orchestrate-1.7.0a0.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -6,6 +6,7 @@
|
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
8
|
from ibm_cloud_sdk_core.authenticators import MCSPAuthenticator
|
9
|
+
from ibm_cloud_sdk_core.authenticators import MCSPV2Authenticator
|
9
10
|
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
|
10
11
|
from ibm_cloud_sdk_core.authenticators import CloudPakForDataAuthenticator
|
11
12
|
|
@@ -51,24 +52,47 @@ class ServiceInstance(BaseServiceInstance):
|
|
51
52
|
def _create_token(self) -> str:
|
52
53
|
if not self._credentials.auth_type:
|
53
54
|
if ".cloud.ibm.com" in self._credentials.url:
|
54
|
-
logger.warning("Using IBM IAM Auth Type. If this is incorrect please use the '--type' flag to explicitly choose one of '
|
55
|
+
logger.warning("Using IBM IAM Auth Type. If this is incorrect please use the '--type' flag to explicitly choose one of 'mcsp', 'mcsp_v1', 'mcsp_v2' or 'cpd' ")
|
55
56
|
return self._authenticate(EnvironmentAuthType.IBM_CLOUD_IAM)
|
56
57
|
elif is_cpd_env(self._credentials.url):
|
57
|
-
logger.warning("Using CPD Auth Type. If this is incorrect please use the '--type' flag to explicitly choose one of 'ibm_iam'
|
58
|
+
logger.warning("Using CPD Auth Type. If this is incorrect please use the '--type' flag to explicitly choose one of 'ibm_iam', 'mcsp', 'mcsp_v1' or 'mcsp_v2' ")
|
58
59
|
return self._authenticate(EnvironmentAuthType.CPD)
|
59
60
|
else:
|
60
|
-
logger.warning("Using MCSP Auth Type. If this is incorrect please use the '--type' flag to explicitly choose one of 'ibm_iam'
|
61
|
-
|
61
|
+
logger.warning("Using MCSP Auth Type. If this is incorrect please use the '--type' flag to explicitly choose one of 'ibm_iam', 'mcsp_v1', 'mcsp_v2' or 'cpd' ")
|
62
|
+
try:
|
63
|
+
return self._authenticate(EnvironmentAuthType.MCSP_V1)
|
64
|
+
except:
|
65
|
+
return self._authenticate(EnvironmentAuthType.MCSP_V2)
|
66
|
+
auth_type = self._credentials.auth_type.lower()
|
67
|
+
if auth_type == "mcsp":
|
68
|
+
try:
|
69
|
+
return self._authenticate(EnvironmentAuthType.MCSP_V1)
|
70
|
+
except:
|
71
|
+
return self._authenticate(EnvironmentAuthType.MCSP_V2)
|
72
|
+
elif auth_type == "mcsp_v1":
|
73
|
+
return self._authenticate(EnvironmentAuthType.MCSP_V1)
|
74
|
+
elif auth_type == "mcsp_v2":
|
75
|
+
return self._authenticate(EnvironmentAuthType.MCSP_V2)
|
62
76
|
else:
|
63
|
-
return self._authenticate(
|
77
|
+
return self._authenticate(auth_type)
|
64
78
|
|
65
79
|
def _authenticate(self, auth_type: str) -> str:
|
66
80
|
"""Handles authentication based on the auth_type."""
|
67
81
|
try:
|
68
82
|
match auth_type:
|
69
|
-
case EnvironmentAuthType.MCSP:
|
83
|
+
case EnvironmentAuthType.MCSP | EnvironmentAuthType.MCSP_V1:
|
70
84
|
url = self._credentials.iam_url if self._credentials.iam_url is not None else "https://iam.platform.saas.ibm.com"
|
71
85
|
authenticator = MCSPAuthenticator(apikey=self._credentials.api_key, url=url)
|
86
|
+
case EnvironmentAuthType.MCSP_V2:
|
87
|
+
url = self._credentials.iam_url if self._credentials.iam_url is not None else "https://account-iam.platform.saas.ibm.com"
|
88
|
+
wxo_url = self._credentials.url
|
89
|
+
instance_id = wxo_url.split("instances/")[1]
|
90
|
+
authenticator = MCSPV2Authenticator(
|
91
|
+
apikey=self._credentials.api_key,
|
92
|
+
url=url,
|
93
|
+
scope_collection_type="services",
|
94
|
+
scope_id=instance_id
|
95
|
+
)
|
72
96
|
case EnvironmentAuthType.IBM_CLOUD_IAM:
|
73
97
|
authenticator = IAMAuthenticator(apikey=self._credentials.api_key, url=self._credentials.iam_url)
|
74
98
|
case EnvironmentAuthType.CPD:
|
@@ -100,8 +124,10 @@ class ServiceInstance(BaseServiceInstance):
|
|
100
124
|
raise ClientError(f"Unsupported authentication type: {auth_type}")
|
101
125
|
|
102
126
|
return authenticator.token_manager.get_token()
|
127
|
+
|
103
128
|
except Exception as e:
|
104
|
-
raise ClientError(f"Error getting {auth_type.upper()} Token",
|
129
|
+
raise ClientError(f"Error getting {auth_type.upper()} Token", logg_messages=False)
|
130
|
+
|
105
131
|
|
106
132
|
|
107
133
|
def _is_token_refresh_possible(self) -> bool:
|
@@ -16,22 +16,26 @@ from ibm_watsonx_orchestrate.cli.config import (
|
|
16
16
|
from threading import Lock
|
17
17
|
from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient
|
18
18
|
from ibm_watsonx_orchestrate.utils.utils import yaml_safe_load
|
19
|
+
from ibm_watsonx_orchestrate.cli.commands.channels.types import RuntimeEnvironmentType
|
19
20
|
import logging
|
20
21
|
from typing import TypeVar
|
21
22
|
import os
|
22
23
|
import jwt
|
23
24
|
import time
|
25
|
+
import sys
|
24
26
|
|
25
27
|
logger = logging.getLogger(__name__)
|
26
28
|
LOCK = Lock()
|
27
29
|
T = TypeVar("T", bound=BaseAPIClient)
|
28
30
|
|
31
|
+
def get_current_env_url() -> str:
|
32
|
+
cfg = Config()
|
33
|
+
active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
|
34
|
+
return cfg.get(ENVIRONMENTS_SECTION_HEADER, active_env, ENV_WXO_URL_OPT)
|
29
35
|
|
30
36
|
def is_local_dev(url: str | None = None) -> bool:
|
31
37
|
if url is None:
|
32
|
-
|
33
|
-
active_env = cfg.read(CONTEXT_SECTION_HEADER, CONTEXT_ACTIVE_ENV_OPT)
|
34
|
-
url = cfg.get(ENVIRONMENTS_SECTION_HEADER, active_env, ENV_WXO_URL_OPT)
|
38
|
+
url = get_current_env_url()
|
35
39
|
|
36
40
|
if url.startswith("http://localhost"):
|
37
41
|
return True
|
@@ -47,21 +51,58 @@ def is_local_dev(url: str | None = None) -> bool:
|
|
47
51
|
|
48
52
|
return False
|
49
53
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
+
def is_ga_platform(url: str | None = None) -> bool:
|
55
|
+
if url is None:
|
56
|
+
url = get_current_env_url()
|
57
|
+
|
58
|
+
if url.__contains__("orchestrate.ibm.com"):
|
59
|
+
return True
|
60
|
+
return False
|
61
|
+
|
62
|
+
def is_saas_env():
|
63
|
+
return is_ga_platform() or is_ibm_cloud_platform()
|
64
|
+
|
65
|
+
def is_ibm_cloud_platform(url:str | None = None) -> bool:
|
66
|
+
if url is None:
|
67
|
+
url = get_current_env_url()
|
54
68
|
|
55
69
|
if url.__contains__("cloud.ibm.com"):
|
56
70
|
return True
|
57
71
|
return False
|
58
72
|
|
73
|
+
def is_cpd_env(url: str | None = None) -> bool:
|
74
|
+
if url is None:
|
75
|
+
url = get_current_env_url()
|
59
76
|
|
60
|
-
def is_cpd_env(url: str) -> bool:
|
61
77
|
if url.lower().startswith("https://cpd"):
|
62
78
|
return True
|
63
79
|
return False
|
64
80
|
|
81
|
+
def get_cpd_instance_id_from_url(url: str | None = None) -> str:
|
82
|
+
if url is None:
|
83
|
+
url = get_current_env_url()
|
84
|
+
|
85
|
+
if not is_cpd_env(url):
|
86
|
+
logger.error(f"The host {url} is not a CPD instance")
|
87
|
+
sys.exit(1)
|
88
|
+
|
89
|
+
url_fragments = url.split('/')
|
90
|
+
return url_fragments[-1] if url_fragments[-1] else url_fragments[-2]
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
def get_environment() -> str:
|
96
|
+
if is_local_dev():
|
97
|
+
return RuntimeEnvironmentType.LOCAL
|
98
|
+
if is_cpd_env():
|
99
|
+
return RuntimeEnvironmentType.CPD
|
100
|
+
if is_ibm_cloud_platform():
|
101
|
+
return RuntimeEnvironmentType.IBM_CLOUD
|
102
|
+
if is_ga_platform():
|
103
|
+
return RuntimeEnvironmentType.AWS
|
104
|
+
return None
|
105
|
+
|
65
106
|
def check_token_validity(token: str) -> bool:
|
66
107
|
try:
|
67
108
|
token_claimset = jwt.decode(token, options={"verify_signature": False})
|
@@ -46,7 +46,7 @@ services:
|
|
46
46
|
WXO_SERVER_URL: http://wxo-server:4321
|
47
47
|
MAX_POOL: 60
|
48
48
|
DEPLOYMENT_MODE: laptop
|
49
|
-
SUFFIXLIST:
|
49
|
+
SUFFIXLIST: ${CM_SUFFIXLIST:-[]}
|
50
50
|
ports:
|
51
51
|
- 3001:3001
|
52
52
|
|
@@ -120,7 +120,7 @@ services:
|
|
120
120
|
TEMPUS_RUNTIME_ENDPOINT: http://wxo-tempus-runtime:9044
|
121
121
|
CONNECTIONS_MANAGER_ENDPOINT: http://wxo-server-connection-manager:3001
|
122
122
|
AGENT_OPS_API_KEY: ${AGENTOPS_API_KEY}
|
123
|
-
AGENTS_OPS_RUNTIME_ENDPOINT: https://
|
123
|
+
AGENTS_OPS_RUNTIME_ENDPOINT: https://frontend-server:443
|
124
124
|
IS_OBSERVABILITY_FEATURE_ENABLED: "true"
|
125
125
|
ALLOW_INSECURE_TLS: "true"
|
126
126
|
command: 'npm start'
|
@@ -751,8 +751,8 @@ services:
|
|
751
751
|
SERVER_HTTP_PORT: "9044"
|
752
752
|
SERVER_CONTEXT_PATH:
|
753
753
|
SERVER_JWK_URL: https://wo-ibm-dev.verify.ibm.com/v1.0/endpoint/default/jwks
|
754
|
-
SERVER_STANDALONE_TASK_CALLBACK_URL: http://
|
755
|
-
SERVER_FLOW_CALLBACK_URL: http://
|
754
|
+
SERVER_STANDALONE_TASK_CALLBACK_URL: http://wxo-tempus-runtime:9044/task/callback/{thread_id}/{requestId}
|
755
|
+
SERVER_FLOW_CALLBACK_URL: http://wxo-tempus-runtime:9044/v1/flows/{flow_instance_id}/{task_instance_id}/resume/async
|
756
756
|
JWT_SECRET: ${JWT_SECRET}
|
757
757
|
SERVER_INTERNAL_PROTOCOL: http
|
758
758
|
SERVER_INTERNAL_HOSTNAME: wxo-tempus-runtime
|
@@ -782,6 +782,7 @@ services:
|
|
782
782
|
LOG_LEVEL: info
|
783
783
|
DISABLE_FLOW_BINDING: true
|
784
784
|
DOCPROC_ENABLED: ${DOCPROC_ENABLED:-false}
|
785
|
+
DOCPROC_BASE_URL: http://wxo-doc-processing-infra-standalone:9080
|
785
786
|
WO_API_KEY: ${WO_API_KEY}
|
786
787
|
WO_INSTANCE: ${WO_INSTANCE}
|
787
788
|
AUTHORIZATION_URL: ${AUTHORIZATION_URL}
|
@@ -795,6 +796,23 @@ services:
|
|
795
796
|
- 9044:9044
|
796
797
|
depends_on:
|
797
798
|
- wxo-server-db
|
799
|
+
|
800
|
+
cpe:
|
801
|
+
image: ${CPE_REGISTRY:-us.icr.io/watson-orchestrate-private}/wxo-prompt-optimizer:${CPE_TAG:-latest}
|
802
|
+
platform: linux/amd64
|
803
|
+
restart: unless-stopped
|
804
|
+
environment:
|
805
|
+
WATSONX_APIKEY: ${WATSONX_APIKEY}
|
806
|
+
WATSONX_SPACE_ID: ${WATSONX_SPACE_ID}
|
807
|
+
WO_API_KEY: ${WO_API_KEY}
|
808
|
+
WO_USERNAME: ${WO_USERNAME}
|
809
|
+
WO_PASSWORD: ${WO_PASSWORD}
|
810
|
+
WO_INSTANCE: ${WO_INSTANCE}
|
811
|
+
USE_SAAS_ML_TOOLS_RUNTIME: ${USE_SAAS_ML_TOOLS_RUNTIME}
|
812
|
+
WO_AUTH_TYPE: ${WO_AUTH_TYPE}
|
813
|
+
AUTHORIZATION_URL: ${AUTHORIZATION_URL}
|
814
|
+
ports:
|
815
|
+
- 8081:8080
|
798
816
|
|
799
817
|
########################
|
800
818
|
# DOCPROC dependencies
|
@@ -863,7 +881,7 @@ services:
|
|
863
881
|
condition: service_completed_successfully
|
864
882
|
|
865
883
|
wdu-model-copy:
|
866
|
-
image: ${WDU_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wdu-
|
884
|
+
image: ${WDU_REGISTRY:-us.icr.io/watson-orchestrate-private}/document-processing/wdu-models:${WDU_TAG:-2.4.0}
|
867
885
|
platform: linux/amd64
|
868
886
|
user: root
|
869
887
|
profiles:
|
@@ -898,10 +916,11 @@ services:
|
|
898
916
|
ENRICHMENT_BATCH_SIZE: "1000"
|
899
917
|
CIPHER_AES_REALM_KEY: "dGVzdHRlc3R0ZXN0dGVzdA=="
|
900
918
|
SIDECAR_METERED_ENABLED: "false"
|
901
|
-
DPI_DEBUG:
|
919
|
+
DPI_DEBUG: "false"
|
902
920
|
DPI_WO_WDU_SERVER_ENDPOINT: https://wxo-doc-processing-service:8080
|
903
921
|
# DPI_RAG_SERVER_ENDPOINT: https://wxo-doc-processing-llm-service:8083
|
904
922
|
DISABLE_TLS: true
|
923
|
+
STANDALONE_DPI: "true"
|
905
924
|
depends_on:
|
906
925
|
wxo-doc-processing-dpi-minio-init:
|
907
926
|
condition: service_completed_successfully
|
@@ -53,16 +53,16 @@ EVENT_BROKER_TTL="-1"
|
|
53
53
|
REGISTRY_URL=
|
54
54
|
|
55
55
|
|
56
|
-
SERVER_TAG=
|
56
|
+
SERVER_TAG=10-07-2025-beb40a3a
|
57
57
|
SERVER_REGISTRY=
|
58
58
|
|
59
|
-
WORKER_TAG=
|
59
|
+
WORKER_TAG=10-07-2025-beb40a3a
|
60
60
|
WORKER_REGISTRY=
|
61
61
|
|
62
|
-
AI_GATEWAY_TAG=
|
62
|
+
AI_GATEWAY_TAG=01-07-2025
|
63
63
|
AI_GATEWAY_REGISTRY=
|
64
64
|
|
65
|
-
AGENT_GATEWAY_TAG=
|
65
|
+
AGENT_GATEWAY_TAG=07-07-2025
|
66
66
|
AGENT_GATEWAY_REGISTRY=
|
67
67
|
|
68
68
|
DB_REGISTRY=
|
@@ -73,41 +73,44 @@ AMDDBTAG=24-06-2025-v1
|
|
73
73
|
ARM64DBTAG=24-06-2025-v1
|
74
74
|
|
75
75
|
UI_REGISTRY=
|
76
|
-
UITAG=
|
76
|
+
UITAG=21-07-2025
|
77
77
|
|
78
78
|
CM_REGISTRY=
|
79
|
-
CM_TAG=
|
79
|
+
CM_TAG=27-06-2025
|
80
80
|
|
81
|
-
TRM_TAG=
|
81
|
+
TRM_TAG=08-07-2025
|
82
82
|
TRM_REGISTRY=
|
83
83
|
|
84
|
-
TR_TAG=
|
84
|
+
TR_TAG=08-07-2025
|
85
85
|
TR_REGISTRY=
|
86
86
|
|
87
|
-
BUILDER_TAG=
|
87
|
+
BUILDER_TAG=22-07-2025-v1
|
88
88
|
BUILDER_REGISTRY=
|
89
89
|
|
90
|
-
FLOW_RUNTIME_TAG=
|
90
|
+
FLOW_RUNTIME_TAG=15-07-2025
|
91
91
|
FLOW_RUMTIME_REGISTRY=
|
92
92
|
|
93
93
|
|
94
|
-
AGENT_ANALYTICS_TAG=
|
94
|
+
AGENT_ANALYTICS_TAG=02-07-2025-v1
|
95
95
|
AGENT_ANALYTICS_REGISTRY=
|
96
96
|
|
97
|
-
JAEGER_PROXY_TAG=
|
97
|
+
JAEGER_PROXY_TAG=01-07-2025
|
98
98
|
JAEGER_PROXY_REGISTRY=
|
99
99
|
|
100
100
|
SOCKET_HANDLER_TAG=29-05-2025
|
101
101
|
SOCKET_HANDLER_REGISTRY=
|
102
102
|
|
103
|
+
CPE_TAG=17-07-2025
|
104
|
+
CPE_REGISTRY=
|
105
|
+
|
103
106
|
# IBM Document Processing
|
104
|
-
WDU_TAG=2.5.0
|
107
|
+
WDU_TAG=2.5.0
|
105
108
|
WDU_REGISTRY=
|
106
109
|
|
107
110
|
DOCPROC_DPS_TAG=20250610-183301-248-865fbc1
|
108
111
|
DOCPROC_LLMSERVICE_TAG=20250604-192056-107-e1d4d66
|
109
112
|
DOCPROC_CACHE_TAG=20250610-214940-68-f3258f4
|
110
|
-
DOCPROC_DPI_TAG=
|
113
|
+
DOCPROC_DPI_TAG=20250702-000808-237-7b1e424d
|
111
114
|
DOCPROC_REGISTRY=
|
112
115
|
|
113
116
|
# END -- IMAGE REGISTRIES AND TAGS
|
@@ -161,6 +164,14 @@ DB_CONN_LIFE=
|
|
161
164
|
DB_MAX_IDLE_CONN=
|
162
165
|
DB_MAX_CONN=
|
163
166
|
SERVER_HOST=
|
167
|
+
WO_API_KEY=
|
168
|
+
WO_PASSWORD=
|
169
|
+
WO_USERNAME=
|
170
|
+
WO_INSTANCE=
|
171
|
+
AUTHORIZATION_URL=
|
172
|
+
WO_AUTH_TYPE=
|
173
|
+
PYTHONPATH=
|
174
|
+
CM_SUFFIXLIST=
|
164
175
|
|
165
176
|
# Use your machine's local IP address for external async tool communication.
|
166
177
|
CALLBACK_HOST_URL=
|
@@ -172,4 +183,4 @@ RUNTIME_MANAGER_API_KEY=example
|
|
172
183
|
|
173
184
|
|
174
185
|
# IBM Document Processing
|
175
|
-
SERVICE_URL=https://wxo-doc-processing-cache:8080
|
186
|
+
SERVICE_URL=https://wxo-doc-processing-cache:8080
|
@@ -1,6 +1,8 @@
|
|
1
1
|
from .constants import START, END, RESERVED
|
2
|
-
|
3
|
-
from ..
|
2
|
+
|
3
|
+
from ..types import FlowContext, TaskData, TaskEventType, File, DecisionsCondition, DecisionsRule
|
4
|
+
from ..node import UserNode, AgentNode, StartNode, EndNode, PromptNode, ToolNode, DecisionsNode
|
5
|
+
|
4
6
|
from .flow import Flow, CompiledFlow, FlowRun, FlowEvent, FlowEventType, FlowFactory, MatchPolicy, WaitPolicy, ForeachPolicy, Branch, Foreach, Loop
|
5
7
|
from .decorators import flow
|
6
8
|
from ..data_map import Assignment, DataMap
|
@@ -14,13 +16,16 @@ __all__ = [
|
|
14
16
|
"FlowContext",
|
15
17
|
"TaskData",
|
16
18
|
"TaskEventType",
|
19
|
+
"File",
|
17
20
|
|
21
|
+
"DocProcNode",
|
18
22
|
"UserNode",
|
19
23
|
"AgentNode",
|
20
24
|
"StartNode",
|
21
25
|
"EndNode",
|
22
26
|
"PromptNode",
|
23
27
|
"ToolNode",
|
28
|
+
"DecisionsNode",
|
24
29
|
"Assignment",
|
25
30
|
"DataMap",
|
26
31
|
|
@@ -36,8 +41,8 @@ __all__ = [
|
|
36
41
|
"Branch",
|
37
42
|
"Foreach",
|
38
43
|
"Loop",
|
44
|
+
"DecisionsCondition",
|
45
|
+
"DecisionsRule",
|
39
46
|
|
40
|
-
"user",
|
41
|
-
"flow_spec",
|
42
47
|
"flow"
|
43
48
|
]
|
@@ -33,7 +33,8 @@ def flow(*args,
|
|
33
33
|
description: str|None=None,
|
34
34
|
input_schema: type[BaseModel] | None = None,
|
35
35
|
output_schema: type[BaseModel] | None = None,
|
36
|
-
initiators: Sequence[str] = ()
|
36
|
+
initiators: Sequence[str] = (),
|
37
|
+
schedulable: bool = False):
|
37
38
|
"""Decorator to mark a function as a flow model builder."""
|
38
39
|
|
39
40
|
def decorator(func: Callable):
|
@@ -58,7 +59,8 @@ def flow(*args,
|
|
58
59
|
description = node_spec.description,
|
59
60
|
input_schema = input_schema,
|
60
61
|
output_schema = output_schema,
|
61
|
-
initiators = initiators
|
62
|
+
initiators = initiators,
|
63
|
+
schedulable = schedulable)
|
62
64
|
|
63
65
|
# logger.info("Creating flow model: %s", a_model.spec.name)
|
64
66
|
|
@@ -5,9 +5,11 @@ from dotenv import load_dotenv
|
|
5
5
|
import os
|
6
6
|
|
7
7
|
from typing import (
|
8
|
-
AsyncIterator, Union
|
8
|
+
AsyncIterator, TypeVar, Union
|
9
9
|
)
|
10
10
|
|
11
|
+
from enum import Enum
|
12
|
+
|
11
13
|
from ..types import (
|
12
14
|
FlowEventType, TaskEventType, FlowEvent, FlowContext
|
13
15
|
)
|
@@ -66,12 +68,11 @@ def deserialize_flow_event(byte_data: bytes) -> FlowEvent:
|
|
66
68
|
|
67
69
|
return flow_event
|
68
70
|
|
71
|
+
def is_valid_enum_value(value: str, enum_type: type[Enum]) -> bool:
|
72
|
+
return value in (item.value for item in enum_type)
|
73
|
+
|
69
74
|
def get_event_type(selected_event_type: str) -> Union[FlowEventType, TaskEventType]:
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
elif eventKind in TaskEventType.__members__:
|
75
|
-
return TaskEventType(selected_event_type)
|
76
|
-
else:
|
77
|
-
raise ValueError(f"Invalid event type: {eventKind}")
|
75
|
+
for enum_type in [FlowEventType, TaskEventType]:
|
76
|
+
if is_valid_enum_value(selected_event_type, enum_type):
|
77
|
+
return enum_type(selected_event_type)
|
78
|
+
raise ValueError(f"Invalid event type: {selected_event_type}")
|
@@ -15,6 +15,7 @@ import logging
|
|
15
15
|
import copy
|
16
16
|
import uuid
|
17
17
|
import pytz
|
18
|
+
import os
|
18
19
|
|
19
20
|
from typing_extensions import Self
|
20
21
|
from pydantic import BaseModel, Field, SerializeAsAny
|
@@ -25,11 +26,12 @@ from ibm_watsonx_orchestrate.client.tools.tempus_client import TempusClient
|
|
25
26
|
from ibm_watsonx_orchestrate.client.utils import instantiate_client
|
26
27
|
from ..types import (
|
27
28
|
EndNodeSpec, Expression, ForeachPolicy, ForeachSpec, LoopSpec, BranchNodeSpec, MatchPolicy, PromptLLMParameters, PromptNodeSpec,
|
28
|
-
StartNodeSpec, ToolSpec, JsonSchemaObject, ToolRequestBody, ToolResponseBody, UserFieldKind, UserFieldOption, UserFlowSpec, UserNodeSpec, WaitPolicy
|
29
|
+
StartNodeSpec, ToolSpec, JsonSchemaObject, ToolRequestBody, ToolResponseBody, UserFieldKind, UserFieldOption, UserFlowSpec, UserNodeSpec, WaitPolicy,
|
30
|
+
DocProcSpec, TextExtractionResponse, File, DecisionsNodeSpec, DecisionsRule
|
29
31
|
)
|
30
32
|
from .constants import CURRENT_USER, START, END, ANY_USER
|
31
33
|
from ..node import (
|
32
|
-
EndNode, Node, PromptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode
|
34
|
+
EndNode, Node, PromptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode, DocProcNode, DecisionsNode
|
33
35
|
)
|
34
36
|
from ..types import (
|
35
37
|
AgentNodeSpec, extract_node_spec, FlowContext, FlowEventType, FlowEvent, FlowSpec,
|
@@ -114,7 +116,7 @@ class Flow(Node):
|
|
114
116
|
# pydantic suppport nested comparison by default
|
115
117
|
|
116
118
|
schema.title = title
|
117
|
-
|
119
|
+
|
118
120
|
if schema == existing_schema:
|
119
121
|
return existing_schema
|
120
122
|
# we need to do a deep compare
|
@@ -354,6 +356,7 @@ class Flow(Node):
|
|
354
356
|
name: str,
|
355
357
|
agent: str,
|
356
358
|
display_name: str|None=None,
|
359
|
+
title: str | None = None,
|
357
360
|
message: str | None = "Follow the agent instructions.",
|
358
361
|
description: str | None = None,
|
359
362
|
input_schema: type[BaseModel]|None = None,
|
@@ -371,6 +374,7 @@ class Flow(Node):
|
|
371
374
|
display_name=display_name,
|
372
375
|
description=description,
|
373
376
|
agent=agent,
|
377
|
+
title=title,
|
374
378
|
message=message,
|
375
379
|
guidelines=guidelines,
|
376
380
|
input_schema=_get_tool_request_body(input_schema_obj),
|
@@ -428,6 +432,91 @@ class Flow(Node):
|
|
428
432
|
# add the node to the list of node
|
429
433
|
node = self._add_node(node)
|
430
434
|
return cast(PromptNode, node)
|
435
|
+
|
436
|
+
def decisions(self,
|
437
|
+
name: str,
|
438
|
+
display_name: str|None=None,
|
439
|
+
rules: list[DecisionsRule] | None = None,
|
440
|
+
default_actions: dict[str, Any] = None,
|
441
|
+
locale: str | None = None,
|
442
|
+
description: str | None = None,
|
443
|
+
input_schema: type[BaseModel]|None = None,
|
444
|
+
output_schema: type[BaseModel]|None=None,
|
445
|
+
input_map: DataMap = None) -> PromptNode:
|
446
|
+
|
447
|
+
if name is None:
|
448
|
+
raise ValueError("name must be provided.")
|
449
|
+
|
450
|
+
if rules is None:
|
451
|
+
raise ValueError("rules must be specified.")
|
452
|
+
|
453
|
+
# create input spec
|
454
|
+
input_schema_obj = _get_json_schema_obj(parameter_name = "input", type_def = input_schema)
|
455
|
+
output_schema_obj = _get_json_schema_obj("output", output_schema)
|
456
|
+
|
457
|
+
# Create the tool spec
|
458
|
+
task_spec = DecisionsNodeSpec(
|
459
|
+
name=name,
|
460
|
+
display_name=display_name if display_name is not None else name,
|
461
|
+
description=description,
|
462
|
+
rules=rules,
|
463
|
+
default_actions=default_actions,
|
464
|
+
locale=locale,
|
465
|
+
input_schema=_get_tool_request_body(input_schema_obj),
|
466
|
+
output_schema=_get_tool_response_body(output_schema_obj),
|
467
|
+
output_schema_object = output_schema_obj
|
468
|
+
)
|
469
|
+
|
470
|
+
node = DecisionsNode(spec=task_spec)
|
471
|
+
# setup input map
|
472
|
+
if input_map:
|
473
|
+
node.input_map = self._get_data_map(input_map)
|
474
|
+
|
475
|
+
# add the node to the list of node
|
476
|
+
node = self._add_node(node)
|
477
|
+
return cast(DecisionsNode, node)
|
478
|
+
|
479
|
+
def docproc(self,
|
480
|
+
name: str,
|
481
|
+
task: str,
|
482
|
+
display_name: str|None=None,
|
483
|
+
description: str | None = None,
|
484
|
+
input_map: DataMap = None) -> DocProcNode:
|
485
|
+
|
486
|
+
if name is None :
|
487
|
+
raise ValueError("name must be provided.")
|
488
|
+
|
489
|
+
if task is None:
|
490
|
+
raise ValueError("task must be provided.")
|
491
|
+
|
492
|
+
output_schema_dict = {
|
493
|
+
"text_extraction" : TextExtractionResponse
|
494
|
+
}
|
495
|
+
# create input spec
|
496
|
+
input_schema_obj = _get_json_schema_obj(parameter_name = "input", type_def = File)
|
497
|
+
output_schema_obj = _get_json_schema_obj("output", output_schema_dict[task])
|
498
|
+
if "$defs" in output_schema_obj.model_extra:
|
499
|
+
output_schema_obj.model_extra.pop("$defs")
|
500
|
+
# Create the docproc spec
|
501
|
+
task_spec = DocProcSpec(
|
502
|
+
name=name,
|
503
|
+
display_name=display_name if display_name is not None else name,
|
504
|
+
description=description,
|
505
|
+
input_schema=_get_tool_request_body(input_schema_obj),
|
506
|
+
output_schema=_get_tool_response_body(output_schema_obj),
|
507
|
+
output_schema_object = output_schema_obj,
|
508
|
+
task=task
|
509
|
+
)
|
510
|
+
|
511
|
+
node = DocProcNode(spec=task_spec)
|
512
|
+
# setup input map
|
513
|
+
if input_map:
|
514
|
+
node.input_map = self._get_data_map(input_map)
|
515
|
+
|
516
|
+
# add the node to the list of node
|
517
|
+
node = self._add_node(node)
|
518
|
+
return cast(DocProcNode, node)
|
519
|
+
|
431
520
|
|
432
521
|
def node_exists(self, node: Union[str, Node]):
|
433
522
|
|
@@ -921,7 +1010,8 @@ class FlowFactory(BaseModel):
|
|
921
1010
|
description: str|None=None,
|
922
1011
|
initiators: Sequence[str]|None=None,
|
923
1012
|
input_schema: type[BaseModel]|None=None,
|
924
|
-
output_schema: type[BaseModel]|None=None
|
1013
|
+
output_schema: type[BaseModel]|None=None,
|
1014
|
+
schedulable: bool=False) -> Flow:
|
925
1015
|
if isinstance(name, Callable):
|
926
1016
|
flow_spec = getattr(name, "__flow_spec__", None)
|
927
1017
|
if not flow_spec:
|
@@ -942,7 +1032,8 @@ class FlowFactory(BaseModel):
|
|
942
1032
|
initiators=initiators,
|
943
1033
|
input_schema=_get_tool_request_body(input_schema_obj),
|
944
1034
|
output_schema=_get_tool_response_body(output_schema_obj),
|
945
|
-
output_schema_object = output_schema_obj
|
1035
|
+
output_schema_object = output_schema_obj,
|
1036
|
+
schedulable=schedulable,
|
946
1037
|
)
|
947
1038
|
|
948
1039
|
return Flow(spec = flow_spec)
|
@@ -1228,10 +1319,12 @@ class UserFlow(Flow):
|
|
1228
1319
|
kind: UserFieldKind = UserFieldKind.Text,
|
1229
1320
|
display_name: str | None = None,
|
1230
1321
|
description: str | None = None,
|
1231
|
-
owners: list[str] = [],
|
1232
1322
|
default: Any | None = None,
|
1233
|
-
text: str = None,
|
1323
|
+
text: str = None, # The text used to ask question to the user, e.g. 'what is your name?'
|
1234
1324
|
option: UserFieldOption | None = None,
|
1325
|
+
is_list: bool = False,
|
1326
|
+
min: Any | None = None,
|
1327
|
+
max: Any | None = None,
|
1235
1328
|
input_map: DataMap = None,
|
1236
1329
|
custom: dict[str, Any] = {}) -> UserNode:
|
1237
1330
|
'''create a node in the flow'''
|
@@ -1246,20 +1339,42 @@ class UserFlow(Flow):
|
|
1246
1339
|
schema_obj.properties = {}
|
1247
1340
|
schema_obj.properties[name] = UserFieldKind.convert_kind_to_schema_property(kind, name, description, default, option, custom)
|
1248
1341
|
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1342
|
+
task_spec = UserNodeSpec(
|
1343
|
+
name=name,
|
1344
|
+
display_name=display_name,
|
1345
|
+
description=description,
|
1346
|
+
owners=[CURRENT_USER],
|
1347
|
+
input_schema=_get_tool_request_body(schema_obj),
|
1348
|
+
output_schema=_get_tool_response_body(schema_obj),
|
1349
|
+
text=text,
|
1350
|
+
output_schema_object = schema_obj
|
1351
|
+
)
|
1352
|
+
|
1353
|
+
node = UserNode(spec = task_spec)
|
1354
|
+
node.field(name = name,
|
1355
|
+
kind = kind,
|
1356
|
+
display_name = display_name,
|
1357
|
+
description = description,
|
1358
|
+
default = default,
|
1359
|
+
text = text,
|
1360
|
+
option = option,
|
1361
|
+
is_list = is_list,
|
1362
|
+
min = min,
|
1363
|
+
max = max,
|
1364
|
+
custom = custom)
|
1365
|
+
|
1366
|
+
# setup input map
|
1367
|
+
if input_map:
|
1368
|
+
node.input_map = self._get_data_map(input_map)
|
1369
|
+
|
1370
|
+
node = self._add_node(node)
|
1371
|
+
return cast(UserNode, node)
|
1256
1372
|
|
1257
1373
|
def user(
|
1258
1374
|
self,
|
1259
1375
|
name: str | None = None,
|
1260
1376
|
display_name: str | None = None,
|
1261
1377
|
description: str | None = None,
|
1262
|
-
owners: list[str] = [],
|
1263
1378
|
text: str | None = None,
|
1264
1379
|
output_schema: type[BaseModel] | JsonSchemaObject| None = None,
|
1265
1380
|
input_map: DataMap = None,
|
@@ -1273,16 +1388,12 @@ class UserFlow(Flow):
|
|
1273
1388
|
# input and output is always the same in an user node
|
1274
1389
|
output_schema_obj = output_schema_obj
|
1275
1390
|
|
1276
|
-
# identify owner
|
1277
|
-
if not owners:
|
1278
|
-
owners = [ANY_USER]
|
1279
|
-
|
1280
1391
|
# Create the tool spec
|
1281
1392
|
task_spec = UserNodeSpec(
|
1282
1393
|
name=name,
|
1283
1394
|
display_name=display_name,
|
1284
1395
|
description=description,
|
1285
|
-
owners=
|
1396
|
+
owners=[CURRENT_USER],
|
1286
1397
|
input_schema=_get_tool_request_body(output_schema_obj),
|
1287
1398
|
output_schema=_get_tool_response_body(output_schema_obj),
|
1288
1399
|
text=text,
|