vellum-ai 0.14.69__py3-none-any.whl → 0.14.70__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/core/client_wrapper.py +1 -1
- vellum/workflows/environment/__init__.py +2 -1
- vellum/workflows/environment/environment.py +5 -1
- vellum/workflows/nodes/experimental/tool_calling_node/tests/test_node.py +77 -1
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py +2 -2
- vellum/workflows/references/environment_variable.py +2 -3
- {vellum_ai-0.14.69.dist-info → vellum_ai-0.14.70.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.69.dist-info → vellum_ai-0.14.70.dist-info}/RECORD +42 -38
- vellum_cli/__init__.py +5 -2
- vellum_cli/image_push.py +24 -1
- vellum_cli/tests/test_image_push.py +103 -12
- vellum_ee/workflows/display/nodes/base_node_display.py +1 -1
- vellum_ee/workflows/display/nodes/utils.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/api_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/error_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/final_output_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +9 -1
- vellum_ee/workflows/display/nodes/vellum/map_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/merge_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/note_node.py +1 -0
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/search_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/tests/test_inline_subworkflow_node.py +88 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +16 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +9 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +59 -297
- vellum_ee/workflows/display/utils/auto_layout.py +130 -0
- vellum_ee/workflows/display/utils/expressions.py +7 -0
- vellum_ee/workflows/display/utils/tests/__init__.py +0 -0
- vellum_ee/workflows/display/utils/tests/test_auto_layout.py +56 -0
- vellum_ee/workflows/display/workflows/base_workflow_display.py +15 -10
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +41 -0
- {vellum_ai-0.14.69.dist-info → vellum_ai-0.14.70.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.69.dist-info → vellum_ai-0.14.70.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.69.dist-info → vellum_ai-0.14.70.dist-info}/entry_points.txt +0 -0
@@ -20,7 +20,7 @@ class BaseErrorNodeDisplay(BaseNodeDisplay[_ErrorNodeType], Generic[_ErrorNodeTy
|
|
20
20
|
|
21
21
|
__serializable_inputs__ = {ErrorNode.error}
|
22
22
|
|
23
|
-
def serialize(self, display_context: WorkflowDisplayContext, **
|
23
|
+
def serialize(self, display_context: WorkflowDisplayContext, **_kwargs) -> JsonObject:
|
24
24
|
node_id = self.node_id
|
25
25
|
error_source_input_id = self.node_input_ids_by_name.get(
|
26
26
|
ErrorNode.error.name,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from uuid import UUID
|
2
|
-
from typing import
|
2
|
+
from typing import ClassVar, Generic, Optional, TypeVar
|
3
3
|
|
4
4
|
from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
|
5
5
|
from vellum.workflows.types.core import JsonObject
|
@@ -19,7 +19,7 @@ NODE_INPUT_KEY = "node_input"
|
|
19
19
|
class BaseFinalOutputNodeDisplay(BaseNodeDisplay[_FinalOutputNodeType], Generic[_FinalOutputNodeType]):
|
20
20
|
output_name: ClassVar[Optional[str]] = None
|
21
21
|
|
22
|
-
def serialize(self, display_context: WorkflowDisplayContext, **
|
22
|
+
def serialize(self, display_context: WorkflowDisplayContext, **_kwargs) -> JsonObject:
|
23
23
|
node = self._node
|
24
24
|
node_id = self.node_id
|
25
25
|
|
@@ -15,7 +15,7 @@ class BaseGuardrailNodeDisplay(BaseNodeDisplay[_GuardrailNodeType], Generic[_Gua
|
|
15
15
|
__serializable_inputs__ = {GuardrailNode.metric_inputs}
|
16
16
|
|
17
17
|
def serialize(
|
18
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
18
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
19
19
|
) -> JsonObject:
|
20
20
|
node = self._node
|
21
21
|
node_id = self.node_id
|
@@ -28,7 +28,7 @@ class BaseInlinePromptNodeDisplay(BaseNodeDisplay[_InlinePromptNodeType], Generi
|
|
28
28
|
}
|
29
29
|
|
30
30
|
def serialize(
|
31
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
31
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
32
32
|
) -> JsonObject:
|
33
33
|
node = self._node
|
34
34
|
node_id = self.node_id
|
@@ -2,8 +2,10 @@ from uuid import UUID
|
|
2
2
|
from typing import ClassVar, Dict, Generic, List, Optional, Tuple, Type, TypeVar
|
3
3
|
|
4
4
|
from vellum import VellumVariable
|
5
|
+
from vellum.workflows.constants import undefined
|
5
6
|
from vellum.workflows.inputs.base import BaseInputs
|
6
7
|
from vellum.workflows.nodes import InlineSubworkflowNode
|
8
|
+
from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
|
7
9
|
from vellum.workflows.types.core import JsonObject
|
8
10
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
9
11
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
@@ -24,7 +26,7 @@ class BaseInlineSubworkflowNodeDisplay(
|
|
24
26
|
__serializable_inputs__ = {InlineSubworkflowNode.subworkflow_inputs}
|
25
27
|
|
26
28
|
def serialize(
|
27
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
29
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
28
30
|
) -> JsonObject:
|
29
31
|
node = self._node
|
30
32
|
node_id = self.node_id
|
@@ -100,6 +102,12 @@ class BaseInlineSubworkflowNodeDisplay(
|
|
100
102
|
id=node_inputs_by_key[descriptor.name].id,
|
101
103
|
key=descriptor.name,
|
102
104
|
type=infer_vellum_variable_type(descriptor),
|
105
|
+
required=descriptor.instance is undefined,
|
106
|
+
default=(
|
107
|
+
primitive_to_vellum_value(descriptor.instance).dict()
|
108
|
+
if descriptor.instance is not undefined
|
109
|
+
else None
|
110
|
+
),
|
103
111
|
)
|
104
112
|
for descriptor in subworkflow_inputs_class
|
105
113
|
]
|
@@ -17,7 +17,7 @@ class BaseMapNodeDisplay(BaseAdornmentNodeDisplay[_MapNodeType], Generic[_MapNod
|
|
17
17
|
__serializable_inputs__ = {MapNode.items} # type: ignore[misc]
|
18
18
|
|
19
19
|
def serialize(
|
20
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
20
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
21
21
|
) -> JsonObject:
|
22
22
|
node = self._node
|
23
23
|
node_id = self.node_id
|
@@ -17,7 +17,7 @@ class BaseMergeNodeDisplay(BaseNodeDisplay[_MergeNodeType], Generic[_MergeNodeTy
|
|
17
17
|
super().__init__()
|
18
18
|
self._target_handle_iterator = 0
|
19
19
|
|
20
|
-
def serialize(self, display_context: WorkflowDisplayContext, **
|
20
|
+
def serialize(self, display_context: WorkflowDisplayContext, **_kwargs: Any) -> JsonObject:
|
21
21
|
node = self._node
|
22
22
|
node_id = self.node_id
|
23
23
|
|
@@ -13,6 +13,7 @@ class BaseNoteNodeDisplay(BaseNodeDisplay[_NoteNodeType], Generic[_NoteNodeType]
|
|
13
13
|
style: ClassVar[Union[Dict[str, Any], None]] = None
|
14
14
|
|
15
15
|
def serialize(self, display_context: WorkflowDisplayContext, **kwargs: Any) -> JsonObject:
|
16
|
+
del display_context, kwargs # Unused parameters
|
16
17
|
node_id = self.node_id
|
17
18
|
|
18
19
|
return {
|
@@ -15,7 +15,7 @@ class BasePromptDeploymentNodeDisplay(BaseNodeDisplay[_PromptDeploymentNodeType]
|
|
15
15
|
__serializable_inputs__ = {PromptDeploymentNode.prompt_inputs}
|
16
16
|
|
17
17
|
def serialize(
|
18
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
18
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
19
19
|
) -> JsonObject:
|
20
20
|
node = self._node
|
21
21
|
node_id = self.node_id
|
@@ -18,7 +18,7 @@ _RetryNodeType = TypeVar("_RetryNodeType", bound=RetryNode)
|
|
18
18
|
|
19
19
|
|
20
20
|
class BaseRetryNodeDisplay(BaseAdornmentNodeDisplay[_RetryNodeType], Generic[_RetryNodeType]):
|
21
|
-
def serialize(self, display_context: WorkflowDisplayContext, **
|
21
|
+
def serialize(self, display_context: WorkflowDisplayContext, **_kwargs: Any) -> JsonObject:
|
22
22
|
node = self._node
|
23
23
|
node_id = self.node_id
|
24
24
|
|
@@ -42,7 +42,7 @@ class BaseSearchNodeDisplay(BaseNodeDisplay[_SearchNodeType], Generic[_SearchNod
|
|
42
42
|
}
|
43
43
|
|
44
44
|
def serialize(
|
45
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
45
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
46
46
|
) -> JsonObject:
|
47
47
|
node = self._node
|
48
48
|
node_id = self.node_id
|
@@ -17,7 +17,7 @@ class BaseSubworkflowDeploymentNodeDisplay(
|
|
17
17
|
__serializable_inputs__ = {SubworkflowDeploymentNode.subworkflow_inputs}
|
18
18
|
|
19
19
|
def serialize(
|
20
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
20
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
21
21
|
) -> JsonObject:
|
22
22
|
node = self._node
|
23
23
|
node_id = self.node_id
|
@@ -18,7 +18,7 @@ class BaseTemplatingNodeDisplay(BaseNodeDisplay[_TemplatingNodeType], Generic[_T
|
|
18
18
|
__serializable_inputs__ = {TemplatingNode.inputs}
|
19
19
|
|
20
20
|
def serialize(
|
21
|
-
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **
|
21
|
+
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
22
22
|
) -> JsonObject:
|
23
23
|
node = self._node
|
24
24
|
node_id = self.node_id
|
@@ -0,0 +1,88 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from vellum.workflows import BaseWorkflow
|
4
|
+
from vellum.workflows.inputs.base import BaseInputs
|
5
|
+
from vellum.workflows.nodes import InlineSubworkflowNode
|
6
|
+
from vellum.workflows.nodes.bases import BaseNode
|
7
|
+
from vellum.workflows.state.base import BaseState
|
8
|
+
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
9
|
+
|
10
|
+
|
11
|
+
def test_serialize_node__inline_subworkflow_inputs():
|
12
|
+
# GIVEN a main workflow with inputs
|
13
|
+
class MainInputs(BaseInputs):
|
14
|
+
pass
|
15
|
+
|
16
|
+
# AND an inline subworkflow with inputs
|
17
|
+
class NestedInputs(BaseInputs):
|
18
|
+
input: str
|
19
|
+
input_with_default: str = "default"
|
20
|
+
optional_input: Optional[str] = None
|
21
|
+
optional_input_with_default: Optional[str] = "optional_default"
|
22
|
+
|
23
|
+
class NestedNode(BaseNode):
|
24
|
+
input = NestedInputs.input
|
25
|
+
input_with_default = NestedInputs.input_with_default
|
26
|
+
|
27
|
+
class Outputs(BaseNode.Outputs):
|
28
|
+
result: str
|
29
|
+
|
30
|
+
def run(self) -> Outputs:
|
31
|
+
return self.Outputs(result=f"{self.input}-{self.input_with_default}")
|
32
|
+
|
33
|
+
class NestedWorkflow(BaseWorkflow[NestedInputs, BaseState]):
|
34
|
+
graph = NestedNode
|
35
|
+
|
36
|
+
class Outputs(BaseWorkflow.Outputs):
|
37
|
+
result = NestedNode.Outputs.result
|
38
|
+
|
39
|
+
class MyInlineSubworkflowNode(InlineSubworkflowNode):
|
40
|
+
subworkflow_inputs = {
|
41
|
+
"input": "input",
|
42
|
+
"input_with_default": "input_with_default",
|
43
|
+
"optional_input": "optional_input",
|
44
|
+
"optional_input_with_default": "optional_input_with_default",
|
45
|
+
}
|
46
|
+
subworkflow = NestedWorkflow
|
47
|
+
|
48
|
+
class MainWorkflow(BaseWorkflow[MainInputs, BaseState]):
|
49
|
+
graph = MyInlineSubworkflowNode
|
50
|
+
|
51
|
+
class Outputs(BaseWorkflow.Outputs):
|
52
|
+
result = MyInlineSubworkflowNode.Outputs.result
|
53
|
+
|
54
|
+
# WHEN the workflow is serialized
|
55
|
+
workflow_display = get_workflow_display(workflow_class=MainWorkflow)
|
56
|
+
serialized_workflow: dict = workflow_display.serialize()
|
57
|
+
|
58
|
+
# THEN the inline subworkflow node should have the correct input variables
|
59
|
+
inline_subworkflow_node = next(
|
60
|
+
node
|
61
|
+
for node in serialized_workflow["workflow_raw_data"]["nodes"]
|
62
|
+
if node["id"] == str(MyInlineSubworkflowNode.__id__)
|
63
|
+
)
|
64
|
+
|
65
|
+
input_variables = inline_subworkflow_node["data"]["input_variables"]
|
66
|
+
assert len(input_variables) == 4
|
67
|
+
|
68
|
+
input_var = next(var for var in input_variables if var["key"] == "input")
|
69
|
+
assert input_var["required"] is True
|
70
|
+
assert input_var["default"] is None
|
71
|
+
assert input_var["type"] == "STRING"
|
72
|
+
|
73
|
+
input_with_default_var = next(var for var in input_variables if var["key"] == "input_with_default")
|
74
|
+
assert input_with_default_var["required"] is False
|
75
|
+
assert input_with_default_var["default"] == {"type": "STRING", "value": "default"}
|
76
|
+
assert input_with_default_var["type"] == "STRING"
|
77
|
+
|
78
|
+
optional_input_var = next(var for var in input_variables if var["key"] == "optional_input")
|
79
|
+
assert optional_input_var["required"] is False
|
80
|
+
assert optional_input_var["default"] == {"type": "JSON", "value": None}
|
81
|
+
assert optional_input_var["type"] == "STRING"
|
82
|
+
|
83
|
+
optional_input_with_default_var = next(
|
84
|
+
var for var in input_variables if var["key"] == "optional_input_with_default"
|
85
|
+
)
|
86
|
+
assert optional_input_with_default_var["required"] is False
|
87
|
+
assert optional_input_with_default_var["default"] == {"type": "STRING", "value": "optional_default"}
|
88
|
+
assert optional_input_with_default_var["type"] == "STRING"
|
@@ -7,6 +7,7 @@ from vellum.client.types.chat_message import ChatMessage
|
|
7
7
|
from vellum.workflows.inputs.base import BaseInputs
|
8
8
|
from vellum.workflows.nodes.bases.base import BaseNode
|
9
9
|
from vellum.workflows.references.constant import ConstantValueReference
|
10
|
+
from vellum.workflows.references.environment_variable import EnvironmentVariableReference
|
10
11
|
from vellum.workflows.references.lazy import LazyReference
|
11
12
|
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
12
13
|
from vellum.workflows.state.base import BaseState
|
@@ -475,6 +476,21 @@ def test_serialize_node__node_execution(serialize_node):
|
|
475
476
|
)
|
476
477
|
|
477
478
|
|
479
|
+
def test_serialize_node__environment_variable(serialize_node):
|
480
|
+
class EnvironmentVariableGenericNode(BaseNode):
|
481
|
+
attr = EnvironmentVariableReference(name="API_KEY")
|
482
|
+
|
483
|
+
serialized_node = serialize_node(EnvironmentVariableGenericNode)
|
484
|
+
|
485
|
+
expected_value = {
|
486
|
+
"type": "ENVIRONMENT_VARIABLE",
|
487
|
+
"environment_variable": "API_KEY",
|
488
|
+
}
|
489
|
+
|
490
|
+
actual_value = serialized_node["attributes"][0]["value"]
|
491
|
+
assert actual_value == expected_value
|
492
|
+
|
493
|
+
|
478
494
|
def test_serialize_node__coalesce(serialize_node):
|
479
495
|
class CoalesceNodeA(BaseNode):
|
480
496
|
class Outputs(BaseNode.Outputs):
|
@@ -301,7 +301,15 @@ def test_serialize_workflow():
|
|
301
301
|
},
|
302
302
|
],
|
303
303
|
},
|
304
|
-
"input_variables": [
|
304
|
+
"input_variables": [
|
305
|
+
{
|
306
|
+
"id": "704c4640-bfda-44f0-8da3-e9cfc4f21cf2",
|
307
|
+
"key": "metro",
|
308
|
+
"type": "STRING",
|
309
|
+
"required": True,
|
310
|
+
"default": None,
|
311
|
+
}
|
312
|
+
],
|
305
313
|
"output_variables": [
|
306
314
|
{"id": "2fc57139-7420-49e5-96a6-dcbb3ff5d622", "key": "temperature", "type": "NUMBER"},
|
307
315
|
{"id": "fad5dd9f-3328-4e70-ad55-65a5325a4a82", "key": "reasoning", "type": "STRING"},
|