ibm-watsonx-orchestrate 1.7.0b1__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 -2
- ibm_watsonx_orchestrate/agent_builder/agents/types.py +29 -1
- ibm_watsonx_orchestrate/agent_builder/connections/types.py +14 -2
- 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/connections/connections_command.py +14 -6
- ibm_watsonx_orchestrate/cli/commands/connections/connections_controller.py +6 -8
- 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/types.py +1 -1
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_command.py +16 -6
- ibm_watsonx_orchestrate/cli/commands/evaluations/evaluations_controller.py +20 -2
- ibm_watsonx_orchestrate/cli/commands/knowledge_bases/knowledge_bases_controller.py +10 -8
- ibm_watsonx_orchestrate/cli/commands/models/models_controller.py +5 -8
- ibm_watsonx_orchestrate/cli/commands/server/server_command.py +4 -10
- ibm_watsonx_orchestrate/cli/main.py +3 -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/utils.py +49 -8
- ibm_watsonx_orchestrate/docker/compose-lite.yml +19 -2
- ibm_watsonx_orchestrate/docker/default.env +11 -7
- ibm_watsonx_orchestrate/flow_builder/flows/__init__.py +8 -5
- ibm_watsonx_orchestrate/flow_builder/flows/flow.py +47 -7
- ibm_watsonx_orchestrate/flow_builder/node.py +7 -1
- ibm_watsonx_orchestrate/flow_builder/types.py +168 -65
- {ibm_watsonx_orchestrate-1.7.0b1.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/METADATA +2 -2
- {ibm_watsonx_orchestrate-1.7.0b1.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/RECORD +32 -28
- {ibm_watsonx_orchestrate-1.7.0b1.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/WHEEL +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/entry_points.txt +0 -0
- {ibm_watsonx_orchestrate-1.7.0b1.dist-info → ibm_watsonx_orchestrate-1.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -167,15 +167,12 @@ class ModelsController:
|
|
167
167
|
logger.error("Error: WATSONX_URL is required in the environment.")
|
168
168
|
sys.exit(1)
|
169
169
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
else:
|
174
|
-
logger.info("Retrieving virtual-model models list...")
|
175
|
-
virtual_models = models_client.list()
|
170
|
+
|
171
|
+
logger.info("Retrieving virtual-model models list...")
|
172
|
+
virtual_models = models_client.list()
|
176
173
|
|
177
|
-
|
178
|
-
|
174
|
+
logger.info("Retrieving virtual-policies models list...")
|
175
|
+
virtual_model_policies = model_policies_client.list()
|
179
176
|
|
180
177
|
logger.info("Retrieving watsonx.ai models list...")
|
181
178
|
found_models = _get_wxai_foundational_models()
|
@@ -46,15 +46,7 @@ _ALWAYS_UNSET: set[str] = {
|
|
46
46
|
|
47
47
|
def define_saas_wdu_runtime(value: str = "none") -> None:
|
48
48
|
cfg = Config()
|
49
|
-
|
50
|
-
current_config_file_values = cfg.get(USER_ENV_CACHE_HEADER)
|
51
|
-
current_config_file_values["SAAS_WDU_RUNTIME"] = value
|
52
|
-
|
53
|
-
cfg.save(
|
54
|
-
{
|
55
|
-
USER_ENV_CACHE_HEADER: current_config_file_values
|
56
|
-
}
|
57
|
-
)
|
49
|
+
cfg.write(USER_ENV_CACHE_HEADER,"SAAS_WDU_RUNTIME",value)
|
58
50
|
|
59
51
|
def ensure_docker_installed() -> None:
|
60
52
|
try:
|
@@ -390,6 +382,8 @@ def run_compose_lite(final_env_file: Path, experimental_with_langfuse=False, exp
|
|
390
382
|
"up",
|
391
383
|
"--scale",
|
392
384
|
"ui=0",
|
385
|
+
"--scale",
|
386
|
+
"cpe=0",
|
393
387
|
"-d",
|
394
388
|
"--remove-orphans",
|
395
389
|
]
|
@@ -883,7 +877,7 @@ def server_start(
|
|
883
877
|
if experimental_with_langfuse:
|
884
878
|
logger.info(f"You can access the observability platform Langfuse at http://localhost:3010, username: orchestrate@ibm.com, password: orchestrate")
|
885
879
|
if with_doc_processing:
|
886
|
-
logger.info(f"Document processing
|
880
|
+
logger.info(f"Document processing in Flows (Public Preview) has been enabled.")
|
887
881
|
|
888
882
|
@server_app.command(name="stop")
|
889
883
|
def server_stop(
|
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
import typer
|
2
3
|
import sys
|
3
4
|
|
@@ -14,6 +15,7 @@ from ibm_watsonx_orchestrate.cli.commands.channels.channels_command import chann
|
|
14
15
|
from ibm_watsonx_orchestrate.cli.commands.knowledge_bases.knowledge_bases_command import knowledge_bases_app
|
15
16
|
from ibm_watsonx_orchestrate.cli.commands.toolkit.toolkit_command import toolkits_app
|
16
17
|
from ibm_watsonx_orchestrate.cli.commands.evaluations.evaluations_command import evaluation_app
|
18
|
+
from ibm_watsonx_orchestrate.cli.commands.copilot.copilot_command import copilot_app
|
17
19
|
from ibm_watsonx_orchestrate.cli.init_helper import init_callback
|
18
20
|
|
19
21
|
import urllib3
|
@@ -38,6 +40,7 @@ app.add_typer(chat_app, name="chat", help='Launch the chat ui for your local Dev
|
|
38
40
|
app.add_typer(models_app, name="models", help='List the available large language models (llms) that can be used in your agent definitions')
|
39
41
|
app.add_typer(channel_app, name="channels", help="Configure channels where your agent can exist on (such as embedded webchat)")
|
40
42
|
app.add_typer(evaluation_app, name="evaluations", help='Evaluate the performance of your agents in your active env')
|
43
|
+
app.add_typer(copilot_app, name="copilot", help='Access AI powered assistance to help refine your agents')
|
41
44
|
app.add_typer(settings_app, name="settings", help='Configure the settings for your active env')
|
42
45
|
|
43
46
|
if __name__ == "__main__":
|
@@ -3,6 +3,7 @@ import json
|
|
3
3
|
import requests
|
4
4
|
from abc import ABC, abstractmethod
|
5
5
|
from ibm_cloud_sdk_core.authenticators import MCSPAuthenticator
|
6
|
+
from typing_extensions import List
|
6
7
|
|
7
8
|
|
8
9
|
class ClientAPIException(requests.HTTPError):
|
@@ -62,6 +63,17 @@ class BaseAPIClient:
|
|
62
63
|
self._check_response(response)
|
63
64
|
return response.json() if response.text else {}
|
64
65
|
|
66
|
+
def _post_nd_json(self, path: str, data: dict = None, files: dict = None) -> List[dict]:
|
67
|
+
url = f"{self.base_url}{path}"
|
68
|
+
response = requests.post(url, headers=self._get_headers(), json=data, files=files)
|
69
|
+
self._check_response(response)
|
70
|
+
|
71
|
+
res = []
|
72
|
+
if response.text:
|
73
|
+
for line in response.text.splitlines():
|
74
|
+
res.append(json.loads(line))
|
75
|
+
return res
|
76
|
+
|
65
77
|
def _post_form_data(self, path: str, data: dict = None, files: dict = None) -> dict:
|
66
78
|
url = f"{self.base_url}{path}"
|
67
79
|
# Use data argument instead of json so data is encoded as application/x-www-form-urlencoded
|
@@ -63,12 +63,7 @@ class ConnectionsClient(BaseAPIClient):
|
|
63
63
|
# GET /api/v1/connections/applications/{app_id}
|
64
64
|
def get(self, app_id: str) -> GetConnectionResponse | None:
|
65
65
|
try:
|
66
|
-
|
67
|
-
f"/connections/applications/{app_id}"
|
68
|
-
if is_cpd_env(self.base_url)
|
69
|
-
else f"/connections/applications?app_id={app_id}"
|
70
|
-
)
|
71
|
-
return GetConnectionResponse.model_validate(self._get(path))
|
66
|
+
return GetConnectionResponse.model_validate(self._get(f"/connections/applications?app_id={app_id}"))
|
72
67
|
except ClientAPIException as e:
|
73
68
|
if e.response.status_code == 404:
|
74
69
|
return None
|
@@ -78,12 +73,7 @@ class ConnectionsClient(BaseAPIClient):
|
|
78
73
|
# GET api/v1/connections/applications
|
79
74
|
def list(self) -> List[ListConfigsResponse]:
|
80
75
|
try:
|
81
|
-
|
82
|
-
f"/connections/applications"
|
83
|
-
if is_cpd_env(self.base_url)
|
84
|
-
else f"/connections/applications?include_details=true"
|
85
|
-
)
|
86
|
-
res = self._get(path)
|
76
|
+
res = self._get(f"/connections/applications?include_details=true")
|
87
77
|
import json
|
88
78
|
json.dumps(res)
|
89
79
|
return [ListConfigsResponse.model_validate(conn) for conn in res.get("applications", [])]
|
@@ -135,19 +125,9 @@ class ConnectionsClient(BaseAPIClient):
|
|
135
125
|
def get_credentials(self, app_id: str, env: ConnectionEnvironment, use_app_credentials: bool) -> dict:
|
136
126
|
try:
|
137
127
|
if use_app_credentials:
|
138
|
-
|
139
|
-
f"/connections/applications/{app_id}/credentials?env={env}"
|
140
|
-
if is_cpd_env(self.base_url)
|
141
|
-
else f"/connections/applications/{app_id}/credentials/{env}"
|
142
|
-
)
|
143
|
-
return self._get(path)
|
128
|
+
return self._get(f"/connections/applications/{app_id}/credentials/{env}")
|
144
129
|
else:
|
145
|
-
|
146
|
-
f"/connections/applications/{app_id}/configs/runtime_credentials?env={env}"
|
147
|
-
if is_cpd_env(self.base_url)
|
148
|
-
else f"/connections/applications/runtime_credentials?app_id={app_id}&env={env}"
|
149
|
-
)
|
150
|
-
return self._get(path)
|
130
|
+
return self._get(f"/connections/applications/runtime_credentials?app_id={app_id}&env={env}")
|
151
131
|
except ClientAPIException as e:
|
152
132
|
if e.response.status_code == 404:
|
153
133
|
return None
|
@@ -177,12 +157,7 @@ class ConnectionsClient(BaseAPIClient):
|
|
177
157
|
if conn_id is None:
|
178
158
|
return ""
|
179
159
|
try:
|
180
|
-
|
181
|
-
f"/connections/applications/id/{conn_id}"
|
182
|
-
if is_cpd_env(self.base_url)
|
183
|
-
else f"/connections/applications?connection_id={conn_id}"
|
184
|
-
)
|
185
|
-
app_details = self._get(path)
|
160
|
+
app_details = self._get(f"/connections/applications?connection_id={conn_id}")
|
186
161
|
return app_details.get("app_id")
|
187
162
|
except ClientAPIException as e:
|
188
163
|
if e.response.status_code == 404:
|
@@ -0,0 +1,67 @@
|
|
1
|
+
from typing import Dict, Any
|
2
|
+
from uuid import uuid4
|
3
|
+
|
4
|
+
from ibm_watsonx_orchestrate.client.base_api_client import BaseAPIClient
|
5
|
+
|
6
|
+
|
7
|
+
class CPEClient(BaseAPIClient):
|
8
|
+
"""
|
9
|
+
Client to handle CRUD operations for Conversational Prompt Engineering Service
|
10
|
+
"""
|
11
|
+
|
12
|
+
def __init__(self, *args, **kwargs):
|
13
|
+
self.chat_id = str(uuid4())
|
14
|
+
super().__init__(*args, **kwargs)
|
15
|
+
self.base_url = kwargs.get("base_url", self.base_url)
|
16
|
+
self.chat_model_name = 'llama-3-3-70b-instruct'
|
17
|
+
|
18
|
+
def _get_headers(self) -> dict:
|
19
|
+
return {
|
20
|
+
"chat_id": self.chat_id
|
21
|
+
}
|
22
|
+
|
23
|
+
|
24
|
+
def submit_pre_cpe_chat(self, user_message: str | None =None, tools: Dict[str, Any] = None, agents: Dict[str, Any] = None) -> dict:
|
25
|
+
payload = {
|
26
|
+
"message": user_message,
|
27
|
+
"tools": tools,
|
28
|
+
"agents": agents,
|
29
|
+
"chat_id": self.chat_id,
|
30
|
+
"chat_model_name": self.chat_model_name
|
31
|
+
}
|
32
|
+
|
33
|
+
response = self._post_nd_json("/wxo-cpe/create-agent", data=payload)
|
34
|
+
|
35
|
+
if response:
|
36
|
+
return response[-1]
|
37
|
+
|
38
|
+
|
39
|
+
def init_with_context(self, model: str | None = None, context_data: Dict[str, Any] = None) -> dict:
|
40
|
+
payload = {
|
41
|
+
"context_data": context_data,
|
42
|
+
"chat_id": self.chat_id
|
43
|
+
}
|
44
|
+
|
45
|
+
if model:
|
46
|
+
payload["target_model_name"] = model
|
47
|
+
|
48
|
+
response = self._post_nd_json("/wxo-cpe/init_cpe_from_wxo", data=payload)
|
49
|
+
|
50
|
+
if response:
|
51
|
+
return response[-1]
|
52
|
+
|
53
|
+
|
54
|
+
def invoke(self, prompt: str, model: str | None = None, context_data: Dict[str, Any] = None) -> dict:
|
55
|
+
payload = {
|
56
|
+
"prompt": prompt,
|
57
|
+
"context_data": context_data,
|
58
|
+
"chat_id": self.chat_id
|
59
|
+
}
|
60
|
+
|
61
|
+
if model:
|
62
|
+
payload["target_model_name"] = model
|
63
|
+
|
64
|
+
response = self._post_nd_json("/wxo-cpe/invoke", data=payload)
|
65
|
+
|
66
|
+
if response:
|
67
|
+
return response[-1]
|
@@ -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
|
|
@@ -796,6 +796,23 @@ services:
|
|
796
796
|
- 9044:9044
|
797
797
|
depends_on:
|
798
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
|
799
816
|
|
800
817
|
########################
|
801
818
|
# DOCPROC dependencies
|
@@ -899,7 +916,7 @@ services:
|
|
899
916
|
ENRICHMENT_BATCH_SIZE: "1000"
|
900
917
|
CIPHER_AES_REALM_KEY: "dGVzdHRlc3R0ZXN0dGVzdA=="
|
901
918
|
SIDECAR_METERED_ENABLED: "false"
|
902
|
-
DPI_DEBUG:
|
919
|
+
DPI_DEBUG: "false"
|
903
920
|
DPI_WO_WDU_SERVER_ENDPOINT: https://wxo-doc-processing-service:8080
|
904
921
|
# DPI_RAG_SERVER_ENDPOINT: https://wxo-doc-processing-llm-service:8083
|
905
922
|
DISABLE_TLS: true
|
@@ -53,10 +53,10 @@ 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
62
|
AI_GATEWAY_TAG=01-07-2025
|
@@ -73,21 +73,21 @@ 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
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
|
|
@@ -100,6 +100,9 @@ JAEGER_PROXY_REGISTRY=
|
|
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
107
|
WDU_TAG=2.5.0
|
105
108
|
WDU_REGISTRY=
|
@@ -168,6 +171,7 @@ WO_INSTANCE=
|
|
168
171
|
AUTHORIZATION_URL=
|
169
172
|
WO_AUTH_TYPE=
|
170
173
|
PYTHONPATH=
|
174
|
+
CM_SUFFIXLIST=
|
171
175
|
|
172
176
|
# Use your machine's local IP address for external async tool communication.
|
173
177
|
CALLBACK_HOST_URL=
|
@@ -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,7 +16,7 @@ __all__ = [
|
|
14
16
|
"FlowContext",
|
15
17
|
"TaskData",
|
16
18
|
"TaskEventType",
|
17
|
-
"
|
19
|
+
"File",
|
18
20
|
|
19
21
|
"DocProcNode",
|
20
22
|
"UserNode",
|
@@ -23,6 +25,7 @@ __all__ = [
|
|
23
25
|
"EndNode",
|
24
26
|
"PromptNode",
|
25
27
|
"ToolNode",
|
28
|
+
"DecisionsNode",
|
26
29
|
"Assignment",
|
27
30
|
"DataMap",
|
28
31
|
|
@@ -38,8 +41,8 @@ __all__ = [
|
|
38
41
|
"Branch",
|
39
42
|
"Foreach",
|
40
43
|
"Loop",
|
44
|
+
"DecisionsCondition",
|
45
|
+
"DecisionsRule",
|
41
46
|
|
42
|
-
"user",
|
43
|
-
"flow_spec",
|
44
47
|
"flow"
|
45
48
|
]
|
@@ -27,12 +27,11 @@ from ibm_watsonx_orchestrate.client.utils import instantiate_client
|
|
27
27
|
from ..types import (
|
28
28
|
EndNodeSpec, Expression, ForeachPolicy, ForeachSpec, LoopSpec, BranchNodeSpec, MatchPolicy, PromptLLMParameters, PromptNodeSpec,
|
29
29
|
StartNodeSpec, ToolSpec, JsonSchemaObject, ToolRequestBody, ToolResponseBody, UserFieldKind, UserFieldOption, UserFlowSpec, UserNodeSpec, WaitPolicy,
|
30
|
-
DocProcSpec, TextExtractionResponse,
|
31
|
-
DocumentContent
|
30
|
+
DocProcSpec, TextExtractionResponse, File, DecisionsNodeSpec, DecisionsRule
|
32
31
|
)
|
33
32
|
from .constants import CURRENT_USER, START, END, ANY_USER
|
34
33
|
from ..node import (
|
35
|
-
EndNode, Node, PromptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode, DocProcNode
|
34
|
+
EndNode, Node, PromptNode, StartNode, UserNode, AgentNode, DataMap, ToolNode, DocProcNode, DecisionsNode
|
36
35
|
)
|
37
36
|
from ..types import (
|
38
37
|
AgentNodeSpec, extract_node_spec, FlowContext, FlowEventType, FlowEvent, FlowSpec,
|
@@ -434,6 +433,49 @@ class Flow(Node):
|
|
434
433
|
node = self._add_node(node)
|
435
434
|
return cast(PromptNode, node)
|
436
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
|
+
|
437
479
|
def docproc(self,
|
438
480
|
name: str,
|
439
481
|
task: str,
|
@@ -448,12 +490,10 @@ class Flow(Node):
|
|
448
490
|
raise ValueError("task must be provided.")
|
449
491
|
|
450
492
|
output_schema_dict = {
|
451
|
-
"text_extraction" : TextExtractionResponse
|
452
|
-
"kvp_invoices_extraction" : KVPInvoicesExtractionResponse,
|
453
|
-
"kvp_utility_bills_extraction" : KVPUtilityBillsExtractionResponse
|
493
|
+
"text_extraction" : TextExtractionResponse
|
454
494
|
}
|
455
495
|
# create input spec
|
456
|
-
input_schema_obj = _get_json_schema_obj(parameter_name = "input", type_def =
|
496
|
+
input_schema_obj = _get_json_schema_obj(parameter_name = "input", type_def = File)
|
457
497
|
output_schema_obj = _get_json_schema_obj("output", output_schema_dict[task])
|
458
498
|
if "$defs" in output_schema_obj.model_extra:
|
459
499
|
output_schema_obj.model_extra.pop("$defs")
|
@@ -5,7 +5,7 @@ import uuid
|
|
5
5
|
import yaml
|
6
6
|
from pydantic import BaseModel, Field, SerializeAsAny
|
7
7
|
|
8
|
-
from .types import EndNodeSpec, NodeSpec, AgentNodeSpec, PromptNodeSpec, StartNodeSpec, ToolNodeSpec, UserFieldKind, UserFieldOption, UserNodeSpec, DocProcSpec
|
8
|
+
from .types import EndNodeSpec, NodeSpec, AgentNodeSpec, PromptNodeSpec, StartNodeSpec, ToolNodeSpec, UserFieldKind, UserFieldOption, UserNodeSpec, DocProcSpec, DecisionsNodeSpec
|
9
9
|
from .data_map import DataMap
|
10
10
|
|
11
11
|
class Node(BaseModel):
|
@@ -116,7 +116,13 @@ class DocProcNode(Node):
|
|
116
116
|
|
117
117
|
def get_spec(self) -> DocProcSpec:
|
118
118
|
return cast(DocProcSpec, self.spec)
|
119
|
+
class DecisionsNode(Node):
|
120
|
+
def __repr__(self):
|
121
|
+
return f"DecisionsNode(name='{self.spec.name}', description='{self.spec.description}')"
|
119
122
|
|
123
|
+
def get_spec(self) -> DecisionsNodeSpec:
|
124
|
+
return cast(DecisionsNodeSpec, self.spec)
|
125
|
+
|
120
126
|
class NodeInstance(BaseModel):
|
121
127
|
node: Node
|
122
128
|
id: str # unique id of this task instance
|