vellum-ai 0.14.45__py3-none-any.whl → 0.14.47__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.
- vellum/client/README.md +2 -2
- vellum/client/__init__.py +72 -6
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/core/file.py +13 -8
- vellum/client/core/http_client.py +26 -14
- vellum/client/core/pydantic_utilities.py +2 -2
- vellum/client/core/request_options.py +3 -0
- vellum/client/resources/ad_hoc/client.py +14 -2
- vellum/client/resources/container_images/client.py +6 -0
- vellum/client/resources/deployments/client.py +12 -0
- vellum/client/resources/document_indexes/client.py +18 -0
- vellum/client/resources/documents/client.py +6 -0
- vellum/client/resources/folder_entities/client.py +6 -0
- vellum/client/resources/metric_definitions/client.py +6 -0
- vellum/client/resources/prompts/client.py +6 -0
- vellum/client/resources/sandboxes/client.py +12 -0
- vellum/client/resources/test_suite_runs/client.py +6 -0
- vellum/client/resources/test_suites/client.py +2 -2
- vellum/client/resources/workflow_deployments/client.py +6 -0
- vellum/client/resources/workflow_sandboxes/client.py +6 -0
- vellum/client/resources/workflows/client.py +6 -4
- vellum/client/resources/workspace_secrets/client.py +6 -0
- vellum/client/types/api_request_parent_context.py +0 -6
- vellum/client/types/array_input.py +0 -5
- vellum/client/types/code_execution_node_array_result.py +0 -5
- vellum/client/types/code_execution_node_result.py +0 -5
- vellum/client/types/code_execution_node_result_data.py +0 -5
- vellum/client/types/code_executor_response.py +0 -5
- vellum/client/types/create_test_suite_test_case_request.py +0 -5
- vellum/client/types/deployment_history_item.py +0 -5
- vellum/client/types/deployment_read.py +0 -5
- vellum/client/types/execute_workflow_response.py +0 -5
- vellum/client/types/execution_array_vellum_value.py +0 -5
- vellum/client/types/external_test_case_execution.py +0 -5
- vellum/client/types/external_test_case_execution_request.py +0 -5
- vellum/client/types/fulfilled_execute_workflow_workflow_result_event.py +0 -7
- vellum/client/types/fulfilled_workflow_node_result_event.py +0 -5
- vellum/client/types/initiated_workflow_node_result_event.py +0 -5
- vellum/client/types/metadata_filter_config_request.py +0 -5
- vellum/client/types/metric_definition_execution.py +0 -5
- vellum/client/types/metric_definition_history_item.py +0 -5
- vellum/client/types/named_test_case_array_variable_value.py +0 -5
- vellum/client/types/named_test_case_array_variable_value_request.py +0 -7
- vellum/client/types/node_execution_fulfilled_event.py +0 -11
- vellum/client/types/node_execution_initiated_event.py +0 -11
- vellum/client/types/node_execution_paused_event.py +0 -11
- vellum/client/types/node_execution_rejected_event.py +0 -11
- vellum/client/types/node_execution_resumed_event.py +0 -11
- vellum/client/types/node_execution_span.py +0 -11
- vellum/client/types/node_execution_streaming_event.py +0 -11
- vellum/client/types/node_input_compiled_array_value.py +0 -5
- vellum/client/types/node_output_compiled_array_value.py +0 -5
- vellum/client/types/node_parent_context.py +0 -6
- vellum/client/types/paginated_slim_deployment_read_list.py +0 -5
- vellum/client/types/paginated_slim_workflow_deployment_list.py +0 -5
- vellum/client/types/paginated_test_suite_run_execution_list.py +0 -5
- vellum/client/types/paginated_test_suite_test_case_list.py +0 -5
- vellum/client/types/prompt_deployment_parent_context.py +0 -6
- vellum/client/types/prompt_exec_config.py +0 -6
- vellum/client/types/rejected_workflow_node_result_event.py +0 -5
- vellum/client/types/replace_test_suite_test_case_request.py +0 -5
- vellum/client/types/search_filters_request.py +0 -7
- vellum/client/types/search_request_options_request.py +0 -7
- vellum/client/types/slim_deployment_read.py +0 -5
- vellum/client/types/slim_workflow_deployment.py +0 -5
- vellum/client/types/slim_workflow_execution_read.py +0 -12
- vellum/client/types/span_link.py +0 -6
- vellum/client/types/streaming_workflow_node_result_event.py +0 -5
- vellum/client/types/templating_node_array_result.py +0 -5
- vellum/client/types/templating_node_result.py +0 -5
- vellum/client/types/templating_node_result_data.py +0 -5
- vellum/client/types/terminal_node_array_result.py +0 -5
- vellum/client/types/terminal_node_result.py +0 -5
- vellum/client/types/terminal_node_result_data.py +0 -5
- vellum/client/types/test_case_array_variable_value.py +0 -5
- vellum/client/types/test_suite_run_execution.py +0 -5
- vellum/client/types/test_suite_run_execution_array_output.py +0 -5
- vellum/client/types/test_suite_run_execution_metric_result.py +0 -5
- vellum/client/types/test_suite_run_external_exec_config.py +0 -5
- vellum/client/types/test_suite_run_external_exec_config_data.py +0 -5
- vellum/client/types/test_suite_run_external_exec_config_data_request.py +0 -7
- vellum/client/types/test_suite_run_external_exec_config_request.py +0 -7
- vellum/client/types/test_suite_run_metric_array_output.py +0 -5
- vellum/client/types/test_suite_run_read.py +0 -5
- vellum/client/types/test_suite_test_case.py +0 -5
- vellum/client/types/test_suite_test_case_create_bulk_operation_request.py +0 -7
- vellum/client/types/test_suite_test_case_replace_bulk_operation_request.py +0 -7
- vellum/client/types/test_suite_test_case_upsert_bulk_operation_request.py +0 -7
- vellum/client/types/upsert_test_suite_test_case_request.py +0 -5
- vellum/client/types/vellum_value_logical_condition_group_request.py +0 -3
- vellum/client/types/vellum_value_logical_condition_request.py +0 -5
- vellum/client/types/vellum_variable.py +0 -5
- vellum/client/types/workflow_deployment_event_executions_response.py +0 -26
- vellum/client/types/workflow_deployment_history_item.py +0 -5
- vellum/client/types/workflow_deployment_parent_context.py +0 -6
- vellum/client/types/workflow_deployment_read.py +0 -5
- vellum/client/types/workflow_deployment_release.py +0 -5
- vellum/client/types/workflow_deployment_release_workflow_version.py +0 -5
- vellum/client/types/workflow_event_execution_read.py +0 -12
- vellum/client/types/workflow_execution_actual.py +0 -5
- vellum/client/types/workflow_execution_fulfilled_event.py +0 -11
- vellum/client/types/workflow_execution_initiated_event.py +0 -11
- vellum/client/types/workflow_execution_node_result_event.py +0 -5
- vellum/client/types/workflow_execution_paused_event.py +0 -11
- vellum/client/types/workflow_execution_rejected_event.py +0 -11
- vellum/client/types/workflow_execution_resumed_event.py +0 -11
- vellum/client/types/workflow_execution_snapshotted_event.py +0 -13
- vellum/client/types/workflow_execution_span.py +0 -11
- vellum/client/types/workflow_execution_streaming_event.py +0 -11
- vellum/client/types/workflow_execution_view_online_eval_metric_result.py +0 -7
- vellum/client/types/workflow_execution_workflow_result_event.py +0 -5
- vellum/client/types/workflow_output_array.py +0 -5
- vellum/client/types/workflow_parent_context.py +0 -6
- vellum/client/types/workflow_result_event.py +0 -5
- vellum/client/types/workflow_result_event_output_data_array.py +0 -5
- vellum/client/types/workflow_sandbox_parent_context.py +0 -6
- vellum/workflows/nodes/bases/base.py +26 -6
- vellum/workflows/nodes/bases/tests/test_base_node.py +30 -0
- vellum/workflows/nodes/core/try_node/node.py +3 -6
- vellum/workflows/nodes/core/try_node/tests/test_node.py +0 -24
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +8 -14
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +112 -0
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -54
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +5 -6
- vellum/workflows/nodes/utils.py +8 -0
- vellum/workflows/types/code_execution_node_wrappers.py +69 -0
- vellum/workflows/vellum_client.py +19 -7
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.47.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.47.dist-info}/RECORD +162 -161
- vellum_cli/config.py +7 -2
- vellum_cli/push.py +5 -1
- vellum_cli/tests/test_push.py +192 -8
- vellum_ee/workflows/display/nodes/base_node_display.py +17 -6
- vellum_ee/workflows/display/nodes/get_node_display_class.py +4 -5
- vellum_ee/workflows/display/nodes/vellum/api_node.py +11 -0
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +5 -0
- vellum_ee/workflows/display/nodes/vellum/error_node.py +22 -16
- vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +46 -12
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +3 -5
- vellum_ee/workflows/display/nodes/vellum/search_node.py +8 -0
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +2 -5
- vellum_ee/workflows/display/nodes/vellum/templating_node.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py +4 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_deployment_node.py +4 -3
- vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +36 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py +5 -4
- vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py +1 -1
- vellum_ee/workflows/display/tests/test_base_workflow_display.py +44 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +2 -4
- vellum_ee/workflows/display/types.py +3 -0
- vellum_ee/workflows/display/utils/expressions.py +3 -3
- vellum_ee/workflows/display/utils/vellum.py +1 -3
- vellum_ee/workflows/display/workflows/base_workflow_display.py +10 -0
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +3 -0
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +53 -0
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.47.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.47.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.47.dist-info}/entry_points.txt +0 -0
@@ -4,7 +4,6 @@ from typing import Generic, Optional, TypeVar, cast
|
|
4
4
|
from vellum.workflows.nodes.displayable.prompt_deployment_node import PromptDeploymentNode
|
5
5
|
from vellum.workflows.references import OutputReference
|
6
6
|
from vellum.workflows.types.core import JsonObject
|
7
|
-
from vellum.workflows.vellum_client import create_vellum_client
|
8
7
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
9
8
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
10
9
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
@@ -14,6 +13,8 @@ _PromptDeploymentNodeType = TypeVar("_PromptDeploymentNodeType", bound=PromptDep
|
|
14
13
|
|
15
14
|
|
16
15
|
class BasePromptDeploymentNodeDisplay(BaseNodeDisplay[_PromptDeploymentNodeType], Generic[_PromptDeploymentNodeType]):
|
16
|
+
__serializable_inputs__ = {PromptDeploymentNode.prompt_inputs}
|
17
|
+
|
17
18
|
def serialize(
|
18
19
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **kwargs
|
19
20
|
) -> JsonObject:
|
@@ -42,10 +43,7 @@ class BasePromptDeploymentNodeDisplay(BaseNodeDisplay[_PromptDeploymentNodeType]
|
|
42
43
|
_, output_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.text)]
|
43
44
|
_, array_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.results)]
|
44
45
|
|
45
|
-
|
46
|
-
# https://app.shortcut.com/vellum/story/4702
|
47
|
-
vellum_client = create_vellum_client()
|
48
|
-
deployment = vellum_client.deployments.retrieve(
|
46
|
+
deployment = display_context.client.deployments.retrieve(
|
49
47
|
id=str(raise_if_descriptor(node.deployment)),
|
50
48
|
)
|
51
49
|
ml_model_fallbacks = raise_if_descriptor(node.ml_model_fallbacks)
|
@@ -32,6 +32,14 @@ class BaseSearchNodeDisplay(BaseNodeDisplay[_SearchNodeType], Generic[_SearchNod
|
|
32
32
|
# A mapping between the id of the operand (e.g. "lhs_variable_id" or "rhs_variable_id") and the id of the node input
|
33
33
|
# that the operand is pointing to.
|
34
34
|
metadata_filter_input_id_by_operand_id: Dict[UUID, UUID] = {}
|
35
|
+
__serializable_inputs__ = {
|
36
|
+
SearchNode.query,
|
37
|
+
SearchNode.document_index,
|
38
|
+
SearchNode.weights,
|
39
|
+
SearchNode.chunk_separator,
|
40
|
+
SearchNode.limit,
|
41
|
+
SearchNode.result_merging,
|
42
|
+
}
|
35
43
|
|
36
44
|
def serialize(
|
37
45
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **kwargs
|
@@ -3,7 +3,6 @@ from typing import Generic, Optional, TypeVar
|
|
3
3
|
|
4
4
|
from vellum.workflows.nodes import SubworkflowDeploymentNode
|
5
5
|
from vellum.workflows.types.core import JsonObject
|
6
|
-
from vellum.workflows.vellum_client import create_vellum_client
|
7
6
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
8
7
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
9
8
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
@@ -15,6 +14,7 @@ _SubworkflowDeploymentNodeType = TypeVar("_SubworkflowDeploymentNodeType", bound
|
|
15
14
|
class BaseSubworkflowDeploymentNodeDisplay(
|
16
15
|
BaseNodeDisplay[_SubworkflowDeploymentNodeType], Generic[_SubworkflowDeploymentNodeType]
|
17
16
|
):
|
17
|
+
__serializable_inputs__ = {SubworkflowDeploymentNode.subworkflow_inputs}
|
18
18
|
|
19
19
|
def serialize(
|
20
20
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **kwargs
|
@@ -37,10 +37,7 @@ class BaseSubworkflowDeploymentNodeDisplay(
|
|
37
37
|
for variable_name, variable_value in subworkflow_inputs.items()
|
38
38
|
]
|
39
39
|
|
40
|
-
|
41
|
-
# https://app.shortcut.com/vellum/story/4702
|
42
|
-
vellum_client = create_vellum_client()
|
43
|
-
deployment = vellum_client.workflow_deployments.retrieve(
|
40
|
+
deployment = display_context.client.workflow_deployments.retrieve(
|
44
41
|
id=str(raise_if_descriptor(node.deployment)),
|
45
42
|
)
|
46
43
|
|
@@ -15,6 +15,8 @@ TEMPLATE_INPUT_NAME = TemplatingNode.template.name
|
|
15
15
|
|
16
16
|
|
17
17
|
class BaseTemplatingNodeDisplay(BaseNodeDisplay[_TemplatingNodeType], Generic[_TemplatingNodeType]):
|
18
|
+
__serializable_inputs__ = {TemplatingNode.inputs}
|
19
|
+
|
18
20
|
def serialize(
|
19
21
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **kwargs
|
20
22
|
) -> JsonObject:
|
@@ -29,7 +29,7 @@ def _display_class_with_node_input_ids_by_name_with_inputs_prefix(Node: Type[Cod
|
|
29
29
|
@pytest.mark.parametrize(
|
30
30
|
["GetDisplayClass", "expected_input_id"],
|
31
31
|
[
|
32
|
-
(_no_display_class, "
|
32
|
+
(_no_display_class, "a5dbe403-0b00-4df6-b8f7-ed5f7794b003"),
|
33
33
|
(_display_class_with_node_input_ids_by_name, "fba6a4d5-835a-4e99-afb7-f6a4aed15110"),
|
34
34
|
(_display_class_with_node_input_ids_by_name_with_inputs_prefix, "fba6a4d5-835a-4e99-afb7-f6a4aed15110"),
|
35
35
|
],
|
@@ -5,6 +5,7 @@ from typing import Type
|
|
5
5
|
|
6
6
|
from vellum.workflows import BaseWorkflow
|
7
7
|
from vellum.workflows.nodes import PromptDeploymentNode
|
8
|
+
from vellum_ee.workflows.display.nodes.vellum.prompt_deployment_node import BasePromptDeploymentNodeDisplay
|
8
9
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
9
10
|
|
10
11
|
|
@@ -13,14 +14,14 @@ def _no_display_class(Node: Type[PromptDeploymentNode]): # type: ignore
|
|
13
14
|
|
14
15
|
|
15
16
|
def _display_class_with_node_input_ids_by_name(Node: Type[PromptDeploymentNode]):
|
16
|
-
class PromptDeploymentNodeDisplay(
|
17
|
+
class PromptDeploymentNodeDisplay(BasePromptDeploymentNodeDisplay[Node]): # type: ignore[valid-type]
|
17
18
|
node_input_ids_by_name = {"foo": UUID("6037747a-1d35-4094-b363-4369fc92c5d4")}
|
18
19
|
|
19
20
|
return PromptDeploymentNodeDisplay
|
20
21
|
|
21
22
|
|
22
23
|
def _display_class_with_node_input_ids_by_name_with_inputs_prefix(Node: Type[PromptDeploymentNode]):
|
23
|
-
class PromptDeploymentNodeDisplay(
|
24
|
+
class PromptDeploymentNodeDisplay(BasePromptDeploymentNodeDisplay[Node]): # type: ignore[valid-type]
|
24
25
|
node_input_ids_by_name = {"prompt_inputs.foo": UUID("6037747a-1d35-4094-b363-4369fc92c5d4")}
|
25
26
|
|
26
27
|
return PromptDeploymentNodeDisplay
|
@@ -51,7 +52,7 @@ def mock_fetch_deployment(mocker):
|
|
51
52
|
@pytest.mark.parametrize(
|
52
53
|
["GetDisplayClass", "expected_input_id"],
|
53
54
|
[
|
54
|
-
(_no_display_class, "
|
55
|
+
(_no_display_class, "016187d6-2830-4256-a61d-e52f9bf6355e"),
|
55
56
|
(_display_class_with_node_input_ids_by_name, "6037747a-1d35-4094-b363-4369fc92c5d4"),
|
56
57
|
(_display_class_with_node_input_ids_by_name_with_inputs_prefix, "6037747a-1d35-4094-b363-4369fc92c5d4"),
|
57
58
|
],
|
@@ -2,6 +2,7 @@ import pytest
|
|
2
2
|
from uuid import UUID
|
3
3
|
from typing import Type
|
4
4
|
|
5
|
+
from vellum.client.types.variable_prompt_block import VariablePromptBlock
|
5
6
|
from vellum.workflows import BaseWorkflow
|
6
7
|
from vellum.workflows.nodes import BaseNode
|
7
8
|
from vellum.workflows.nodes.displayable.inline_prompt_node.node import InlinePromptNode
|
@@ -78,7 +79,7 @@ def _display_class_with_node_input_ids_by_name_with_inputs_prefix(Node: Type[Inl
|
|
78
79
|
@pytest.mark.parametrize(
|
79
80
|
["GetDisplayClass", "expected_input_id"],
|
80
81
|
[
|
81
|
-
(_no_display_class, "
|
82
|
+
(_no_display_class, "9b036991-67ff-4cd0-a4d7-b4ed581e8b6d"),
|
82
83
|
(_display_class_with_node_input_ids_by_name, "fba6a4d5-835a-4e99-afb7-f6a4aed15110"),
|
83
84
|
(_display_class_with_node_input_ids_by_name_with_inputs_prefix, "fba6a4d5-835a-4e99-afb7-f6a4aed15110"),
|
84
85
|
],
|
@@ -165,7 +166,7 @@ def test_serialize_node__prompt_inputs__state_reference():
|
|
165
166
|
},
|
166
167
|
},
|
167
168
|
{
|
168
|
-
"id": "
|
169
|
+
"id": "b83c40f7-0159-442f-af03-e80870363c52",
|
169
170
|
"key": "bar",
|
170
171
|
"value": {
|
171
172
|
"rules": [
|
@@ -181,3 +182,36 @@ def test_serialize_node__prompt_inputs__state_reference():
|
|
181
182
|
},
|
182
183
|
},
|
183
184
|
]
|
185
|
+
|
186
|
+
|
187
|
+
def test_serialize_node__unreferenced_variable_block__still_serializes():
|
188
|
+
# GIVEN a prompt node with an unreferenced variable block
|
189
|
+
class MyPromptNode(InlinePromptNode):
|
190
|
+
blocks = [VariablePromptBlock(input_variable="foo")]
|
191
|
+
|
192
|
+
# AND a workflow with the prompt node
|
193
|
+
class MyWorkflow(BaseWorkflow):
|
194
|
+
graph = MyPromptNode
|
195
|
+
|
196
|
+
# WHEN the prompt node is serialized
|
197
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
198
|
+
serialized_workflow: dict = workflow_display.serialize()
|
199
|
+
|
200
|
+
# THEN the node should skip the state reference input rule
|
201
|
+
assert serialized_workflow["workflow_raw_data"]["nodes"][1]["data"]["exec_config"]["prompt_template_block_data"][
|
202
|
+
"blocks"
|
203
|
+
] == [
|
204
|
+
{
|
205
|
+
"id": "fecbb5f3-e0a3-42ed-9774-6c68fd5db50c",
|
206
|
+
"block_type": "VARIABLE",
|
207
|
+
"input_variable_id": "ea3f6348-8553-4375-bd27-527df4e4f3c2",
|
208
|
+
"state": "ENABLED",
|
209
|
+
"cache_config": None,
|
210
|
+
}
|
211
|
+
]
|
212
|
+
|
213
|
+
# AND we should have a warning of the invalid reference
|
214
|
+
# TODO: Come up with a proposal for how nodes should propagate warnings
|
215
|
+
# warnings = list(workflow_display.errors)
|
216
|
+
# assert len(warnings) == 1
|
217
|
+
# assert "Missing input variable 'foo' for prompt block 0" in str(warnings[0])
|
@@ -4,7 +4,8 @@ from uuid import UUID, uuid4
|
|
4
4
|
from typing import Type
|
5
5
|
|
6
6
|
from vellum.workflows import BaseWorkflow
|
7
|
-
from vellum.workflows.nodes import SubworkflowDeploymentNode
|
7
|
+
from vellum.workflows.nodes.displayable.subworkflow_deployment_node.node import SubworkflowDeploymentNode
|
8
|
+
from vellum_ee.workflows.display.nodes.vellum.subworkflow_deployment_node import BaseSubworkflowDeploymentNodeDisplay
|
8
9
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
9
10
|
|
10
11
|
|
@@ -13,14 +14,14 @@ def _no_display_class(Node: Type[SubworkflowDeploymentNode]): # type: ignore
|
|
13
14
|
|
14
15
|
|
15
16
|
def _display_class_with_node_input_ids_by_name(Node: Type[SubworkflowDeploymentNode]):
|
16
|
-
class SubworkflowNodeDisplay(
|
17
|
+
class SubworkflowNodeDisplay(BaseSubworkflowDeploymentNodeDisplay[Node]): # type: ignore[valid-type]
|
17
18
|
node_input_ids_by_name = {"foo": UUID("aff4f838-577e-44b9-ac5c-6d8213abbb9c")}
|
18
19
|
|
19
20
|
return SubworkflowNodeDisplay
|
20
21
|
|
21
22
|
|
22
23
|
def _display_class_with_node_input_ids_by_name_with_inputs_prefix(Node: Type[SubworkflowDeploymentNode]):
|
23
|
-
class SubworkflowNodeDisplay(
|
24
|
+
class SubworkflowNodeDisplay(BaseSubworkflowDeploymentNodeDisplay[Node]): # type: ignore[valid-type]
|
24
25
|
node_input_ids_by_name = {"subworkflow_inputs.foo": UUID("aff4f838-577e-44b9-ac5c-6d8213abbb9c")}
|
25
26
|
|
26
27
|
return SubworkflowNodeDisplay
|
@@ -55,7 +56,7 @@ def mock_fetch_deployment(mocker):
|
|
55
56
|
@pytest.mark.parametrize(
|
56
57
|
["GetDisplayClass", "expected_input_id"],
|
57
58
|
[
|
58
|
-
(_no_display_class, "
|
59
|
+
(_no_display_class, "394132c2-1817-455e-9f3f-b7073eb63a2b"),
|
59
60
|
(_display_class_with_node_input_ids_by_name, "aff4f838-577e-44b9-ac5c-6d8213abbb9c"),
|
60
61
|
(_display_class_with_node_input_ids_by_name_with_inputs_prefix, "aff4f838-577e-44b9-ac5c-6d8213abbb9c"),
|
61
62
|
],
|
@@ -29,7 +29,7 @@ def _display_class_with_node_input_ids_by_name_with_inputs_prefix(Node: Type[Tem
|
|
29
29
|
@pytest.mark.parametrize(
|
30
30
|
["GetDisplayClass", "expected_input_id"],
|
31
31
|
[
|
32
|
-
(_no_display_class, "
|
32
|
+
(_no_display_class, "91d982a9-6c41-42ac-aff9-7b623c450a55"),
|
33
33
|
(_display_class_with_node_input_ids_by_name, "fba6a4d5-835a-4e99-afb7-f6a4aed15110"),
|
34
34
|
(_display_class_with_node_input_ids_by_name_with_inputs_prefix, "fba6a4d5-835a-4e99-afb7-f6a4aed15110"),
|
35
35
|
],
|
@@ -3,6 +3,8 @@ from typing import Dict
|
|
3
3
|
|
4
4
|
from vellum.workflows.inputs import BaseInputs
|
5
5
|
from vellum.workflows.nodes import BaseNode
|
6
|
+
from vellum.workflows.ports.port import Port
|
7
|
+
from vellum.workflows.references.lazy import LazyReference
|
6
8
|
from vellum.workflows.state import BaseState
|
7
9
|
from vellum.workflows.workflows.base import BaseWorkflow
|
8
10
|
from vellum_ee.workflows.display.vellum import WorkflowInputsVellumDisplayOverrides
|
@@ -285,3 +287,45 @@ def test_vellum_workflow_display__serialize_with_parse_json_expression():
|
|
285
287
|
"operator": "parseJson",
|
286
288
|
},
|
287
289
|
}
|
290
|
+
|
291
|
+
|
292
|
+
def test_serialize__port_with_lazy_reference():
|
293
|
+
# GIVEN a node with a lazy reference in a Port
|
294
|
+
class MyNode(BaseNode):
|
295
|
+
class Ports(BaseNode.Ports):
|
296
|
+
foo = Port.on_if(LazyReference(lambda: MyNode.Outputs.bar))
|
297
|
+
|
298
|
+
class Outputs(BaseNode.Outputs):
|
299
|
+
bar: bool
|
300
|
+
|
301
|
+
# AND a workflow that uses the node
|
302
|
+
class Workflow(BaseWorkflow):
|
303
|
+
graph = MyNode
|
304
|
+
|
305
|
+
# WHEN we serialize the workflow
|
306
|
+
workflow_display = get_workflow_display(workflow_class=Workflow)
|
307
|
+
exec_config = workflow_display.serialize()
|
308
|
+
|
309
|
+
# THEN the lazy reference should be serialized correctly
|
310
|
+
raw_data = exec_config["workflow_raw_data"]
|
311
|
+
assert isinstance(raw_data, dict)
|
312
|
+
|
313
|
+
nodes = raw_data["nodes"]
|
314
|
+
assert isinstance(nodes, list)
|
315
|
+
|
316
|
+
my_node = nodes[1]
|
317
|
+
assert isinstance(my_node, dict)
|
318
|
+
ports = my_node.get("ports")
|
319
|
+
assert isinstance(ports, list)
|
320
|
+
assert ports == [
|
321
|
+
{
|
322
|
+
"id": "6c26bc2b-6469-47c1-b858-d63f0d311ea6",
|
323
|
+
"name": "foo",
|
324
|
+
"type": "IF",
|
325
|
+
"expression": {
|
326
|
+
"type": "NODE_OUTPUT",
|
327
|
+
"node_id": str(MyNode.__id__),
|
328
|
+
"node_output_id": str(MyNode.__output_ids__["bar"]),
|
329
|
+
},
|
330
|
+
}
|
331
|
+
]
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py
CHANGED
@@ -87,7 +87,7 @@ def test_serialize_workflow():
|
|
87
87
|
"type": "ERROR",
|
88
88
|
"inputs": [
|
89
89
|
{
|
90
|
-
"id": "
|
90
|
+
"id": "8e4c8d76-2e02-4d7e-a7bf-d71af392dc49",
|
91
91
|
"key": "error_source_input_id",
|
92
92
|
"value": {
|
93
93
|
"rules": [
|
@@ -101,11 +101,9 @@ def test_serialize_workflow():
|
|
101
101
|
}
|
102
102
|
],
|
103
103
|
"data": {
|
104
|
-
"name": "error-node",
|
105
104
|
"label": "Fail Node",
|
106
105
|
"target_handle_id": "70c19f1c-309c-4a5d-ba65-664c0bb2fedf",
|
107
|
-
"error_source_input_id": "
|
108
|
-
"error_output_id": "None",
|
106
|
+
"error_source_input_id": "8e4c8d76-2e02-4d7e-a7bf-d71af392dc49",
|
109
107
|
},
|
110
108
|
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
111
109
|
"base": {
|
@@ -1,11 +1,13 @@
|
|
1
1
|
from dataclasses import dataclass, field
|
2
2
|
from typing import TYPE_CHECKING, Dict, Tuple, Type
|
3
3
|
|
4
|
+
from vellum.client import Vellum as VellumClient
|
4
5
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
6
|
from vellum.workflows.events.workflow import WorkflowEventDisplayContext # noqa: F401
|
6
7
|
from vellum.workflows.nodes import BaseNode
|
7
8
|
from vellum.workflows.ports import Port
|
8
9
|
from vellum.workflows.references import OutputReference, StateValueReference, WorkflowInputReference
|
10
|
+
from vellum.workflows.vellum_client import create_vellum_client
|
9
11
|
from vellum.workflows.workflows.base import BaseWorkflow
|
10
12
|
from vellum_ee.workflows.display.base import (
|
11
13
|
EdgeDisplay,
|
@@ -35,6 +37,7 @@ PortDisplays = Dict[Port, PortDisplay]
|
|
35
37
|
|
36
38
|
@dataclass
|
37
39
|
class WorkflowDisplayContext:
|
40
|
+
client: VellumClient = field(default_factory=create_vellum_client)
|
38
41
|
workflow_display_class: Type["BaseWorkflowDisplay"] = field(default_factory=get_default_workflow_display_class)
|
39
42
|
workflow_display: WorkflowMetaDisplay = field(default_factory=lambda: WorkflowMetaDisplay.get_default(BaseWorkflow))
|
40
43
|
workflow_input_displays: WorkflowInputsDisplays = field(default_factory=dict)
|
@@ -107,7 +107,7 @@ def get_child_descriptor(value: LazyReference, display_context: "WorkflowDisplay
|
|
107
107
|
)
|
108
108
|
|
109
109
|
node_class_name = ".".join(reference_parts[:-2])
|
110
|
-
for node in display_context.
|
110
|
+
for node in display_context.global_node_displays.keys():
|
111
111
|
if node.__name__ == node_class_name:
|
112
112
|
return getattr(node.Outputs, output_name)
|
113
113
|
|
@@ -116,7 +116,7 @@ def get_child_descriptor(value: LazyReference, display_context: "WorkflowDisplay
|
|
116
116
|
return value._get()
|
117
117
|
|
118
118
|
|
119
|
-
def
|
119
|
+
def _serialize_condition(display_context: "WorkflowDisplayContext", condition: BaseDescriptor) -> JsonObject:
|
120
120
|
if isinstance(
|
121
121
|
condition,
|
122
122
|
(
|
@@ -247,4 +247,4 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
|
|
247
247
|
|
248
248
|
# If it's not any of the references we know about,
|
249
249
|
# then try to serialize it as a nested value
|
250
|
-
return
|
250
|
+
return _serialize_condition(display_context, value)
|
@@ -13,7 +13,6 @@ from vellum.workflows.references.lazy import LazyReference
|
|
13
13
|
from vellum.workflows.references.node import NodeReference
|
14
14
|
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
15
15
|
from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_variable_type
|
16
|
-
from vellum.workflows.vellum_client import create_vellum_client
|
17
16
|
from vellum_ee.workflows.display.utils.exceptions import UnsupportedSerializationException
|
18
17
|
from vellum_ee.workflows.display.utils.expressions import get_child_descriptor
|
19
18
|
|
@@ -118,8 +117,7 @@ def create_node_input_value_pointer_rule(
|
|
118
117
|
workflow_input_display = display_context.global_workflow_input_displays[value]
|
119
118
|
return InputVariablePointer(data=InputVariableData(input_variable_id=str(workflow_input_display.id)))
|
120
119
|
if isinstance(value, VellumSecretReference):
|
121
|
-
|
122
|
-
workspace_secret = vellum_client.workspace_secrets.retrieve(
|
120
|
+
workspace_secret = display_context.client.workspace_secrets.retrieve(
|
123
121
|
id=value.name,
|
124
122
|
)
|
125
123
|
return WorkspaceSecretPointer(
|
@@ -6,6 +6,7 @@ import logging
|
|
6
6
|
from uuid import UUID
|
7
7
|
from typing import Any, Dict, ForwardRef, Generic, Iterator, List, Optional, Tuple, Type, TypeVar, Union, cast, get_args
|
8
8
|
|
9
|
+
from vellum.client import Vellum as VellumClient
|
9
10
|
from vellum.workflows import BaseWorkflow
|
10
11
|
from vellum.workflows.constants import undefined
|
11
12
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
@@ -21,6 +22,7 @@ from vellum.workflows.types.core import JsonArray, JsonObject
|
|
21
22
|
from vellum.workflows.types.generics import WorkflowType
|
22
23
|
from vellum.workflows.types.utils import get_original_base
|
23
24
|
from vellum.workflows.utils.uuids import uuid4_from_hash
|
25
|
+
from vellum.workflows.vellum_client import create_vellum_client
|
24
26
|
from vellum_ee.workflows.display.base import (
|
25
27
|
EdgeDisplay,
|
26
28
|
EntrypointDisplay,
|
@@ -84,9 +86,16 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
84
86
|
self,
|
85
87
|
*,
|
86
88
|
parent_display_context: Optional[WorkflowDisplayContext] = None,
|
89
|
+
client: Optional[VellumClient] = None,
|
87
90
|
dry_run: bool = False,
|
88
91
|
):
|
89
92
|
self._parent_display_context = parent_display_context
|
93
|
+
self._client = client or (
|
94
|
+
# propagate the client from the parent display context if it is not provided
|
95
|
+
self._parent_display_context.client
|
96
|
+
if self._parent_display_context
|
97
|
+
else create_vellum_client()
|
98
|
+
)
|
90
99
|
self._errors: List[Exception] = []
|
91
100
|
self._dry_run = dry_run
|
92
101
|
|
@@ -494,6 +503,7 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
494
503
|
)
|
495
504
|
|
496
505
|
return WorkflowDisplayContext(
|
506
|
+
client=self._client,
|
497
507
|
workflow_display=workflow_meta_display,
|
498
508
|
workflow_input_displays=workflow_input_displays,
|
499
509
|
global_workflow_input_displays=global_workflow_input_displays,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import types
|
2
2
|
from typing import TYPE_CHECKING, Generic, Optional, Type, TypeVar
|
3
3
|
|
4
|
+
from vellum.client import Vellum as VellumClient
|
4
5
|
from vellum.workflows.types.generics import WorkflowType
|
5
6
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
6
7
|
from vellum_ee.workflows.display.utils.registry import get_from_workflow_display_registry
|
@@ -35,6 +36,7 @@ def get_workflow_display(
|
|
35
36
|
*,
|
36
37
|
workflow_class: Type[WorkflowType],
|
37
38
|
parent_display_context: Optional[WorkflowDisplayContext] = None,
|
39
|
+
client: Optional[VellumClient] = None,
|
38
40
|
dry_run: bool = False,
|
39
41
|
# DEPRECATED: The following arguments will be removed in 0.15.0
|
40
42
|
root_workflow_class: Optional[Type[WorkflowType]] = None,
|
@@ -42,5 +44,6 @@ def get_workflow_display(
|
|
42
44
|
) -> "BaseWorkflowDisplay":
|
43
45
|
return _get_workflow_display_class(workflow_class=workflow_class)(
|
44
46
|
parent_display_context=parent_display_context,
|
47
|
+
client=client,
|
45
48
|
dry_run=dry_run,
|
46
49
|
)
|
@@ -7,6 +7,7 @@ from vellum.workflows.nodes.core.retry_node.node import RetryNode
|
|
7
7
|
from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
|
8
8
|
from vellum.workflows.nodes.core.try_node.node import TryNode
|
9
9
|
from vellum.workflows.nodes.displayable.final_output_node.node import FinalOutputNode
|
10
|
+
from vellum.workflows.references.lazy import LazyReference
|
10
11
|
from vellum.workflows.workflows.base import BaseWorkflow
|
11
12
|
from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDisplayPosition
|
12
13
|
from vellum_ee.workflows.display.nodes import BaseNodeDisplay
|
@@ -372,3 +373,55 @@ def test_serialize_workflow__terminal_node_mismatches_workflow_output_name():
|
|
372
373
|
"node_id": str(ExitNode.__id__),
|
373
374
|
"node_output_id": str(ExitNode.__output_ids__["value"]),
|
374
375
|
}
|
376
|
+
|
377
|
+
|
378
|
+
def test_serialize_workflow__nested_lazy_reference():
|
379
|
+
# GIVEN an inner node that references the output of an outer node
|
380
|
+
class InnerNode(BaseNode):
|
381
|
+
foo = LazyReference[str]("OuterNode.Outputs.bar")
|
382
|
+
|
383
|
+
class Outputs(BaseNode.Outputs):
|
384
|
+
foo = "foo"
|
385
|
+
|
386
|
+
# AND a workflow that uses the inner node
|
387
|
+
class InnerWorkflow(BaseWorkflow):
|
388
|
+
graph = InnerNode
|
389
|
+
|
390
|
+
class Outputs(BaseWorkflow.Outputs):
|
391
|
+
foo = InnerNode.Outputs.foo
|
392
|
+
|
393
|
+
# AND a subworkflow that uses the inner workflow
|
394
|
+
class SubworkflowNode(InlineSubworkflowNode):
|
395
|
+
subworkflow = InnerWorkflow
|
396
|
+
|
397
|
+
# AND the outer node
|
398
|
+
class OuterNode(BaseNode):
|
399
|
+
class Outputs(BaseNode.Outputs):
|
400
|
+
bar: str
|
401
|
+
|
402
|
+
# AND a workflow that uses the subworkflow node and the outer node
|
403
|
+
class MyWorkflow(BaseWorkflow):
|
404
|
+
graph = SubworkflowNode >> OuterNode
|
405
|
+
|
406
|
+
class Outputs(BaseWorkflow.Outputs):
|
407
|
+
answer = SubworkflowNode.Outputs.foo
|
408
|
+
|
409
|
+
# WHEN we serialize it
|
410
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
411
|
+
data: dict = workflow_display.serialize()
|
412
|
+
|
413
|
+
# THEN it should have properly serialized the lazy reference
|
414
|
+
subworkflow_node = next(
|
415
|
+
node for node in data["workflow_raw_data"]["nodes"] if isinstance(node, dict) and node["type"] == "SUBWORKFLOW"
|
416
|
+
)
|
417
|
+
inner_node = next(
|
418
|
+
node
|
419
|
+
for node in subworkflow_node["data"]["workflow_raw_data"]["nodes"]
|
420
|
+
if isinstance(node, dict) and node["type"] == "GENERIC"
|
421
|
+
)
|
422
|
+
|
423
|
+
assert inner_node["attributes"][0]["value"] == {
|
424
|
+
"type": "NODE_OUTPUT",
|
425
|
+
"node_id": str(OuterNode.__id__),
|
426
|
+
"node_output_id": str(OuterNode.__output_ids__["bar"]),
|
427
|
+
}
|
File without changes
|
File without changes
|
File without changes
|