vellum-ai 0.14.36__py3-none-any.whl → 0.14.37__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.
Files changed (27) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/client/types/logical_operator.py +1 -0
  3. vellum/workflows/inputs/base.py +2 -1
  4. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +2 -0
  5. vellum/workflows/nodes/displayable/guardrail_node/node.py +14 -6
  6. vellum/workflows/nodes/displayable/guardrail_node/test_node.py +25 -0
  7. vellum/workflows/state/base.py +31 -2
  8. vellum/workflows/workflows/base.py +17 -0
  9. vellum/workflows/workflows/tests/test_base_workflow.py +39 -0
  10. {vellum_ai-0.14.36.dist-info → vellum_ai-0.14.37.dist-info}/METADATA +1 -1
  11. {vellum_ai-0.14.36.dist-info → vellum_ai-0.14.37.dist-info}/RECORD +27 -26
  12. vellum_ee/workflows/display/base.py +9 -7
  13. vellum_ee/workflows/display/nodes/__init__.py +2 -2
  14. vellum_ee/workflows/display/nodes/vellum/note_node.py +1 -2
  15. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +2 -0
  16. vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +33 -0
  17. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +3 -4
  18. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +1 -1
  19. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +0 -1
  20. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +1 -0
  21. vellum_ee/workflows/display/types.py +6 -7
  22. vellum_ee/workflows/display/vellum.py +5 -4
  23. vellum_ee/workflows/display/workflows/base_workflow_display.py +20 -19
  24. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +11 -37
  25. {vellum_ai-0.14.36.dist-info → vellum_ai-0.14.37.dist-info}/LICENSE +0 -0
  26. {vellum_ai-0.14.36.dist-info → vellum_ai-0.14.37.dist-info}/WHEEL +0 -0
  27. {vellum_ai-0.14.36.dist-info → vellum_ai-0.14.37.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,7 @@ class BaseClientWrapper:
18
18
  headers: typing.Dict[str, str] = {
19
19
  "X-Fern-Language": "Python",
20
20
  "X-Fern-SDK-Name": "vellum-ai",
21
- "X-Fern-SDK-Version": "0.14.36",
21
+ "X-Fern-SDK-Version": "0.14.37",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -29,6 +29,7 @@ LogicalOperator = typing.Union[
29
29
  "parseJson",
30
30
  "and",
31
31
  "or",
32
+ "isError",
32
33
  ],
33
34
  typing.Any,
34
35
  ]
@@ -4,6 +4,7 @@ from typing_extensions import dataclass_transform
4
4
  from pydantic import GetCoreSchemaHandler
5
5
  from pydantic_core import core_schema
6
6
 
7
+ from vellum.workflows.constants import undefined
7
8
  from vellum.workflows.errors.types import WorkflowErrorCode
8
9
  from vellum.workflows.exceptions import WorkflowInitializationException
9
10
  from vellum.workflows.references import ExternalInputReference, WorkflowInputReference
@@ -15,7 +16,7 @@ from vellum.workflows.types.utils import get_class_attr_names, infer_types
15
16
  class _BaseInputsMeta(type):
16
17
  def __getattribute__(cls, name: str) -> Any:
17
18
  if not name.startswith("_") and name in cls.__annotations__ and issubclass(cls, BaseInputs):
18
- instance = vars(cls).get(name)
19
+ instance = vars(cls).get(name, undefined)
19
20
  types = infer_types(cls, name)
20
21
 
21
22
  if getattr(cls, "__descriptor_class__", None) is ExternalInputReference:
@@ -38,6 +38,7 @@ class BasePromptDeploymentNode(BasePromptNode, Generic[StateType]):
38
38
  expand_raw: Optional[Sequence[str]] - Expandable raw fields to include in the response
39
39
  metadata: Optional[Dict[str, Optional[Any]]] - The metadata to use for the Prompt Execution
40
40
  request_options: Optional[RequestOptions] - The request options to use for the Prompt Execution
41
+ ml_model_fallback: Optional[Sequence[str]] - ML model fallbacks to use
41
42
  """
42
43
 
43
44
  # Either the Prompt Deployment's UUID or its name.
@@ -50,6 +51,7 @@ class BasePromptDeploymentNode(BasePromptNode, Generic[StateType]):
50
51
  raw_overrides: Optional[RawPromptExecutionOverridesRequest] = OMIT
51
52
  expand_raw: Optional[Sequence[str]] = OMIT
52
53
  metadata: Optional[Dict[str, Optional[Any]]] = OMIT
54
+ ml_model_fallbacks: Optional[Sequence[str]] = OMIT
53
55
 
54
56
  class Trigger(BasePromptNode.Trigger):
55
57
  merge_behavior = MergeBehavior.AWAIT_ANY
@@ -2,6 +2,7 @@ from uuid import UUID
2
2
  from typing import Any, ClassVar, Dict, Generic, List, Optional, Union, cast
3
3
 
4
4
  from vellum import ChatHistoryInput, ChatMessage, JsonInput, MetricDefinitionInput, NumberInput, StringInput
5
+ from vellum.client import ApiError
5
6
  from vellum.core import RequestOptions
6
7
  from vellum.workflows.constants import LATEST_RELEASE_TAG
7
8
  from vellum.workflows.errors.types import WorkflowErrorCode
@@ -38,12 +39,19 @@ class GuardrailNode(BaseNode[StateType], Generic[StateType]):
38
39
  log: Optional[str]
39
40
 
40
41
  def run(self) -> Outputs:
41
- metric_execution = self._context.vellum_client.metric_definitions.execute_metric_definition(
42
- self.metric_definition if isinstance(self.metric_definition, str) else str(self.metric_definition),
43
- inputs=self._compile_metric_inputs(),
44
- release_tag=self.release_tag,
45
- request_options=self.request_options,
46
- )
42
+ try:
43
+ metric_execution = self._context.vellum_client.metric_definitions.execute_metric_definition(
44
+ self.metric_definition if isinstance(self.metric_definition, str) else str(self.metric_definition),
45
+ inputs=self._compile_metric_inputs(),
46
+ release_tag=self.release_tag,
47
+ request_options=self.request_options,
48
+ )
49
+
50
+ except ApiError:
51
+ raise NodeException(
52
+ code=WorkflowErrorCode.NODE_EXECUTION,
53
+ message="Failed to execute metric definition",
54
+ )
47
55
 
48
56
  metric_outputs = {output.name: output.value for output in metric_execution.outputs}
49
57
 
@@ -1,6 +1,7 @@
1
1
  import pytest
2
2
 
3
3
  from vellum import TestSuiteRunMetricNumberOutput
4
+ from vellum.client import ApiError
4
5
  from vellum.client.types.metric_definition_execution import MetricDefinitionExecution
5
6
  from vellum.client.types.test_suite_run_metric_string_output import TestSuiteRunMetricStringOutput
6
7
  from vellum.workflows.errors import WorkflowErrorCode
@@ -99,3 +100,27 @@ def test_run_guardrail_node__normalized_score_null(vellum_client):
99
100
  # THEN we get an exception
100
101
  assert exc_info.value.message == "Metric execution must have one output named 'normalized_score' with type 'float'"
101
102
  assert exc_info.value.code == WorkflowErrorCode.INVALID_OUTPUTS
103
+
104
+
105
+ def test_run_guardrail_node__api_error(vellum_client):
106
+ # GIVEN a Guardrail Node
107
+ class MyGuard(GuardrailNode):
108
+ metric_definition = "example_metric_definition"
109
+ metric_inputs = {}
110
+
111
+ # AND the API client raises an ApiError when called
112
+ api_error = ApiError(status_code=503)
113
+ vellum_client.metric_definitions.execute_metric_definition.side_effect = api_error
114
+
115
+ # WHEN we run the Guardrail Node
116
+ with pytest.raises(NodeException) as exc_info:
117
+ MyGuard().run()
118
+
119
+ # THEN we get a NodeException with the appropriate error code
120
+ assert exc_info.value.code == WorkflowErrorCode.NODE_EXECUTION
121
+ assert "Failed to execute metric definition" in exc_info.value.message
122
+
123
+ # Verify the mock was called with the expected arguments
124
+ vellum_client.metric_definitions.execute_metric_definition.assert_called_once_with(
125
+ "example_metric_definition", inputs=[], release_tag="LATEST", request_options=None
126
+ )
@@ -9,13 +9,14 @@ from uuid import UUID, uuid4
9
9
  from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, cast
10
10
  from typing_extensions import dataclass_transform
11
11
 
12
- from pydantic import GetCoreSchemaHandler, field_serializer
12
+ from pydantic import GetCoreSchemaHandler, ValidationInfo, field_serializer, field_validator
13
13
  from pydantic_core import core_schema
14
14
 
15
15
  from vellum.core.pydantic_utilities import UniversalBaseModel
16
16
  from vellum.workflows.constants import undefined
17
17
  from vellum.workflows.edges.edge import Edge
18
18
  from vellum.workflows.inputs.base import BaseInputs
19
+ from vellum.workflows.outputs.base import BaseOutputs
19
20
  from vellum.workflows.references import ExternalInputReference, OutputReference, StateValueReference
20
21
  from vellum.workflows.types.generics import StateType
21
22
  from vellum.workflows.types.stack import Stack
@@ -50,7 +51,7 @@ class _Snapshottable:
50
51
  class _BaseStateMeta(type):
51
52
  def __getattribute__(cls, name: str) -> Any:
52
53
  if not name.startswith("_"):
53
- instance = vars(cls).get(name)
54
+ instance = vars(cls).get(name, undefined)
54
55
  types = infer_types(cls, name)
55
56
  return StateValueReference(name=name, types=types, instance=instance)
56
57
 
@@ -240,6 +241,34 @@ class StateMeta(UniversalBaseModel):
240
241
  def serialize_node_outputs(self, node_outputs: Dict[OutputReference, Any], _info: Any) -> Dict[str, Any]:
241
242
  return {str(descriptor): value for descriptor, value in node_outputs.items()}
242
243
 
244
+ @field_validator("node_outputs", mode="before")
245
+ @classmethod
246
+ def deserialize_node_outputs(cls, node_outputs: Any, info: ValidationInfo):
247
+ if isinstance(node_outputs, dict) and isinstance(info.context, dict):
248
+ raw_workflow_nodes = info.context.get("nodes")
249
+ workflow_node_outputs = {}
250
+ if isinstance(raw_workflow_nodes, list):
251
+ for node in raw_workflow_nodes:
252
+ Outputs = getattr(node, "Outputs", None)
253
+ if not isinstance(Outputs, type) or not issubclass(Outputs, BaseOutputs):
254
+ continue
255
+
256
+ for output in Outputs:
257
+ workflow_node_outputs[str(output)] = output
258
+
259
+ node_output_keys = list(node_outputs.keys())
260
+ deserialized_node_outputs = {}
261
+ for node_output_key in node_output_keys:
262
+ output_reference = workflow_node_outputs.get(node_output_key)
263
+ if not output_reference:
264
+ continue
265
+
266
+ deserialized_node_outputs[output_reference] = node_outputs[node_output_key]
267
+
268
+ return deserialized_node_outputs
269
+
270
+ return node_outputs
271
+
243
272
  @field_serializer("external_inputs")
244
273
  def serialize_external_inputs(
245
274
  self, external_inputs: Dict[ExternalInputReference, Any], _info: Any
@@ -530,6 +530,23 @@ class BaseWorkflow(Generic[InputsType, StateType], metaclass=_BaseWorkflowMeta):
530
530
 
531
531
  return most_recent_state_snapshot
532
532
 
533
+ @classmethod
534
+ def deserialize_state(cls, state: dict, workflow_inputs: Optional[InputsType] = None) -> StateType:
535
+ state_class = cls.get_state_class()
536
+ if "meta" in state:
537
+ nodes = list(cls.get_nodes())
538
+ state["meta"] = StateMeta.model_validate(
539
+ {
540
+ **state["meta"],
541
+ "workflow_inputs": workflow_inputs,
542
+ },
543
+ context={
544
+ "nodes": nodes,
545
+ },
546
+ )
547
+
548
+ return state_class(**state)
549
+
533
550
  @staticmethod
534
551
  def load_from_module(module_path: str) -> Type["BaseWorkflow"]:
535
552
  workflow_path = f"{module_path}.workflow"
@@ -314,3 +314,42 @@ def test_workflow__unsupported_graph_item():
314
314
 
315
315
  # THEN it should raise an error
316
316
  assert "Unexpected graph type: <class 'int'>" in str(exc_info.value)
317
+
318
+
319
+ def test_base_workflow__deserialize_state():
320
+
321
+ # GIVEN a state definition
322
+ class State(BaseState):
323
+ bar: str
324
+
325
+ # AND an inputs definition
326
+ class Inputs(BaseInputs):
327
+ baz: str
328
+
329
+ # AND a node
330
+ class NodeA(BaseNode):
331
+ class Outputs(BaseNode.Outputs):
332
+ foo: str
333
+
334
+ # AND a workflow that uses all three
335
+ class TestWorkflow(BaseWorkflow[Inputs, State]):
336
+ graph = NodeA
337
+
338
+ # WHEN we deserialize the state
339
+ state = TestWorkflow.deserialize_state(
340
+ {
341
+ "bar": "My state bar",
342
+ "meta": {
343
+ "node_outputs": {
344
+ "test_base_workflow__deserialize_state.<locals>.NodeA.Outputs.foo": "My node A output foo"
345
+ }
346
+ },
347
+ },
348
+ workflow_inputs=Inputs(baz="My input baz"),
349
+ )
350
+
351
+ # THEN the state should be correct
352
+ assert state.bar == "My state bar"
353
+ assert state.meta.node_outputs == {NodeA.Outputs.foo: "My node A output foo"}
354
+ assert isinstance(state.meta.workflow_inputs, Inputs)
355
+ assert state.meta.workflow_inputs.baz == "My input baz"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.14.36
3
+ Version: 0.14.37
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -22,10 +22,10 @@ vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  vellum_ee/workflows/display/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
- vellum_ee/workflows/display/base.py,sha256=swJqgFOhlbe7-FzdPYE1GgX4oq0t2UoyXZs_yM0JIY4,2307
25
+ vellum_ee/workflows/display/base.py,sha256=em2kgLWBk74fiDoDDp-smL0IFmDjMPtd8F4mx10NPTg,2229
26
26
  vellum_ee/workflows/display/editor/__init__.py,sha256=MSAgY91xCEg2neH5d8jXx5wRdR962ftZVa6vO9BGq9k,167
27
27
  vellum_ee/workflows/display/editor/types.py,sha256=x-tOOCJ6CF4HmiKDfCmcc3bOVfc1EBlP5o6u5WEfLoY,567
28
- vellum_ee/workflows/display/nodes/__init__.py,sha256=436iSAh_Ex5tC68oEYvNgPu05ZVIAVXnS4PKGrQeZ0Y,321
28
+ vellum_ee/workflows/display/nodes/__init__.py,sha256=jI1aPBQf8DkmrYoZ4O-wR1duqZByOf5mDFmo_wFJPE4,307
29
29
  vellum_ee/workflows/display/nodes/base_node_display.py,sha256=cHK2OxeM2gWOshMHjaDHxWbRxvjkNHxOXbajjkrgk1w,19094
30
30
  vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=WXbfVoGHTfl_owas2WKHwcRhfLeu0cAI4qLmKxfxjOs,1707
31
31
  vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=59Nht1XAxMcNESFV1VmECrF01lZMnGkB_9JWaTAFnv0,2214
@@ -45,8 +45,8 @@ vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=86hkneLIBS
45
45
  vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py,sha256=MU9I8CB1X1TgL1aa1eT6DHWwNJ-2v79t74xl0oy-fBo,5510
46
46
  vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=8CPnn06HIBxBOiECevUffeVmQmCpec6WtPQnNl9gj9Y,3748
47
47
  vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=xtyecs9mJ_WEwVpP12jxYwvehLXynhqLrPJ-Ahdk2GA,3232
48
- vellum_ee/workflows/display/nodes/vellum/note_node.py,sha256=TMb8txILu2uWjzoxaghjgjlzeBAgzn4vkP_8zSh2qoE,1151
49
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=9YR6MtxVq8Bavb0ud2lZX0t2Y_NUd-dY9kRgq8WBz-Y,3093
48
+ vellum_ee/workflows/display/nodes/vellum/note_node.py,sha256=DQzzhVGVZf812DkpQZoVYJcDsIOtjkm_sCX3oDLks2Y,1103
49
+ vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=yAiWMeKs6jEecRdWfTjqxLmnGLeBPguaVsBD7xcOV94,3263
50
50
  vellum_ee/workflows/display/nodes/vellum/retry_node.py,sha256=LgokATi7sSS38Fil-XjqoR4t7AMOJ-GzXRw6p606Svo,3397
51
51
  vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=Hn55mKO1Q6BBspQtbsurvJJqX7RjSSuEyRjUW29xvg0,9279
52
52
  vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=62baAElKoRKIoba0lLhnrXGWWx96B73VxKGxh7BaIxc,2612
@@ -54,6 +54,7 @@ vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=5EWzdA3TSUPlb
54
54
  vellum_ee/workflows/display/nodes/vellum/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py,sha256=p0fCvbKzpGvVrg67QmJd14m9E8_DG0u5s6SYIhzlkNA,4018
56
56
  vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py,sha256=ulrpoYUW-5kIxfG4Lf5F2p0k_EoYKhmahEbF3P_eruM,1648
57
+ vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py,sha256=Xx_2qi956tc6QoWr3MxlTBp48xJEErj8LHIsMfEi1vU,1356
57
58
  vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py,sha256=fu9nxD4FInSfKbipJJ7UE617VkeUWs_uS6SeEz_8-Iw,4691
58
59
  vellum_ee/workflows/display/nodes/vellum/tests/test_retry_node.py,sha256=NuIw8Yb42KUdoGi3Ur8_7VPg50IC4hNrwAkCociwqNk,2091
59
60
  vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py,sha256=Us32jf_FQnLuT4Bs2o5JyHxihCTAN8ozZghWIR0pl9k,3459
@@ -65,7 +66,7 @@ vellum_ee/workflows/display/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
65
66
  vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=VD-4USiRlCcdC3Qe9WfdkxwFdircai0vqvuZCbELR84,9556
66
67
  vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
68
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=f3EKg65yq5TgyK9yx6D2XmTYLgAF5eYp5gWKS4x-Fhc,2229
69
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=GzDx9JX9yBDgsHk1x58cmjChC9tPMUtlaqOSxO5CJxQ,2069
69
70
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=4R8cZ98JsGmIq-kmt3q519c4nCI7wCy5ynAUCUNnvuI,15605
70
71
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=PXoNUAgqfyNCAoYGWoo5D-_5SLEannn7SD08nxZmVe8,19781
71
72
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=s6_mnk0pkztU59wYpSfOFpMhAJaRjmyfxM6WJGtnD4Y,6456
@@ -74,31 +75,31 @@ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trig
74
75
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=EdLwx6iUEMrQd68UIlACa9DQguomcu621MOYuXmunig,15908
75
76
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=V__y7uu-dy6TJjPeu4UDvaoO2yYwBRbPiW9uJdzWRx4,29828
76
77
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=6ejs_C1cuaRHtc8Qb2qh8-b-juDwLwdfTBd-6CSDDYw,47672
77
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py,sha256=WebMmamSwRykxcilhiNG1XTxI88VydCgPFavF-gSqWk,8820
78
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py,sha256=FKojL_YddJ-PEZ9n0IKedD2qI0JQtnXRTfMXBPPB9HU,8821
78
79
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=wgedEa2IVP2ssH_FLghoEmLgpJR41AY-iNIw1SESeqA,6106
79
80
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=THQB73vAgdiRRk7GKWwzw99G-X3LLgEEVCb4QCQrrMQ,5773
80
81
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py,sha256=aWZ3XIquyKeS199VayYVA7qVjXdvPepGG8UkNt0osIU,7446
81
82
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py,sha256=XRtXTWtNXHe1g8E_mNcAhYZVjc0UcGlJRjq34_sd0jo,787
82
83
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=nZ3IOZSX3cOg4XV5-PW-Hsu806vfzmOZyCpZyl1I50w,20605
83
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=8GakAJmf140XzQRZyr-BbZUt22h0lZKUFhNZY4zlD4g,16172
84
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=3uWphk9TeyZ5Ila2wBIDIjQfbr62bHQ6TNpRgBVIP98,16150
84
85
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=QifoIZja04F1ulMhKlfZHtOqhAWrbUXlnQpybBBzNdw,8449
85
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py,sha256=-bGp82C5_XgcVxeM80zWL9viogxvE4DGk7-5H__wwxA,8649
86
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py,sha256=J7BQnYNjS8EFy6y4hYRFKoh33EGXz7vFSCKPOM6v2Zk,8713
86
87
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py,sha256=elc4ak2OyI4y5P6GPnK2RwuZLcx4FL6hHlmhY3ARk6k,13008
87
88
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py,sha256=BzFNl9ECeGh0krm-CUjbBQQq0g7krANsp0Sh-j5dAkc,11322
88
89
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py,sha256=qjaXGw0JTnPnQmDAFm7jkB3bVkApf-WQ0Gd6kptqdPA,7818
89
90
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=UrueKI15Ez-DRfZpZH82o127v0LRXLP-s308kjDTPMI,4084
90
91
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=eD5686C9nWC5s6t08vbAnm9qf9t53gYQM-E1FwAa75c,3035
91
92
  vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=zXTjfjUdji0WBu6ZhocvM4UiXEWFJIpds24sxV9TZT0,7714
92
- vellum_ee/workflows/display/types.py,sha256=XNudHX8AyvU3657QQ37_sDULwf-EnLAOS3aQZGq7Zmw,2495
93
+ vellum_ee/workflows/display/types.py,sha256=nERYzMC-TqoQuRN8QtF2ZLr-56G7XgXJqLtn8qQMQqs,2442
93
94
  vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
95
  vellum_ee/workflows/display/utils/expressions.py,sha256=2u2o8Fqr-2C45FII01ej5rt6i8n2EEGiliXugK7buVw,1210
95
96
  vellum_ee/workflows/display/utils/vellum.py,sha256=Pzmg9Xiq-hRaYxbOSDaJhIAQ4A0apQN6dURn_h5DnWI,9364
96
- vellum_ee/workflows/display/vellum.py,sha256=s1ARDF8miRDwFXFIMsmFzyyUOTE5MNjri8fGhfpZeF4,3701
97
+ vellum_ee/workflows/display/vellum.py,sha256=niAiU3KVvkCd3Jp8esRxgvP0fhivu5ENNQzxeT-NKys,3664
97
98
  vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
98
- vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=6YIUU1KiKdVdpAzjaACOlMPxFmqhLCWNh8-1Qj8fEfI,20879
99
+ vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=UbUalLL_CDFIEnqN-uFv8Ms06AMxDmQPx9HQ1oocBno,20979
99
100
  vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=kp0u8LN_2IwshLrhMImhpZx1hRyAcD5gXY-kDuuaGMQ,1269
100
101
  vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=nD6_lZnNp56siVJwhlWzSEHdMaSKjvWlsJa31SqfQAE,10623
101
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=AzGZ7ApiwXAHuymTJoXJketUegyC1dmB1blzoni5eh8,13423
102
+ vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=f-Js7M_WbFp_3mPTv191xC4GoGyWbITrvZSGdiqDcU4,12436
102
103
  vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
103
104
  vellum_ee/workflows/server/virtual_file_loader.py,sha256=7JphJcSO3H85qiC2DpFfBWjC3JjrbRmoynBC6KKHVsA,2710
104
105
  vellum_ee/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -128,7 +129,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
128
129
  vellum/client/__init__.py,sha256=Z-JHK2jGxhtTtmkLeOaUGGJWIUNYGNVBLvUewC6lp6w,118148
129
130
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
130
131
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
131
- vellum/client/core/client_wrapper.py,sha256=xLCZEpnqwYGxZRQKKBufqucpuc1GH4onEtUKV7qvzdM,1869
132
+ vellum/client/core/client_wrapper.py,sha256=O2ona-RY5QBlx_tQsGG9B7ftfYuk-y7iQ0vJD7hL9Z4,1869
132
133
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
133
134
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
134
135
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -380,7 +381,7 @@ vellum/client/types/json_input.py,sha256=ZUA2O9YueBCx0IMMdB8uYNSWJiSDZxMm5ogwbwC
380
381
  vellum/client/types/json_input_request.py,sha256=x5sA-VXxF4QH-98xRcIKPZhsMVbnJNUQofiUQqyfGk4,768
381
382
  vellum/client/types/json_vellum_value.py,sha256=8irlw6NkRRVafysfTc1Q5BFFhRrWJYzdwrDYTdJK4JY,689
382
383
  vellum/client/types/json_vellum_value_request.py,sha256=IUlkdwFGgBeLl9sCmAJhoaxomWiEMpWgRcLa_WnlK8g,696
383
- vellum/client/types/logical_operator.py,sha256=_3-gBnfsz4g5-sw5_ThRuS0NdNLQ2n2vV2Dl1RqbXe4,617
384
+ vellum/client/types/logical_operator.py,sha256=mfRXK3dWLcqt2tHTgNXynEXdMDh32yI4MUade3smI7Q,636
384
385
  vellum/client/types/logprobs_enum.py,sha256=D_458cZX2CAb6dX_ovrQ6HARlJkYcZRadKwsi1Cr-JM,151
385
386
  vellum/client/types/map_node_result.py,sha256=e2YqEP-aKig2TbbZIlfn5LCeVEVhEJJBR7o7xTBKXaY,752
386
387
  vellum/client/types/map_node_result_data.py,sha256=3xJXC1JrS9lo3-3_u1S79sYwLxMknNntDyspN24vQzY,699
@@ -1517,7 +1518,7 @@ vellum/workflows/graph/graph.py,sha256=GGR8cGpSuNWPIiTWNWsj6l70upb5nIxAyFcn7VdaJ
1517
1518
  vellum/workflows/graph/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1518
1519
  vellum/workflows/graph/tests/test_graph.py,sha256=q0wxLvPPxc-6en4a_XuAZwVfLURMd9Ikvoreq4bpJ9s,11839
1519
1520
  vellum/workflows/inputs/__init__.py,sha256=AbFEteIYEvCb14fM3EK7bhM-40-6s494rSlIhQ4Dsss,62
1520
- vellum/workflows/inputs/base.py,sha256=eVTjtn6GielKYogQ-LPA6n4iZO3-WIfyxWpBKkN-dPs,3959
1521
+ vellum/workflows/inputs/base.py,sha256=n5jqDpIEl-jf7z3ohwSUtIq2YfHH-GJ9Qn8KZzzMxIM,4019
1521
1522
  vellum/workflows/inputs/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1522
1523
  vellum/workflows/inputs/tests/test_inputs.py,sha256=g--YqWTNWzMk5Ktoj__gq988kvBReefc2tsyUl6H2kg,1775
1523
1524
  vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
@@ -1564,7 +1565,7 @@ vellum/workflows/nodes/displayable/bases/inline_prompt_node/constants.py,sha256=
1564
1565
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=rga24gkK9_STRhFwhBwGL7oHhTTZvLWS_rXHHrp85p4,8386
1565
1566
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1566
1567
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py,sha256=ZCXCZs-_OyPk4nqCpuWY-vw87lg92TDZ2tK_gckJ7mg,10450
1567
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=mjTAN2GERUaoKVsr5h1ecW60Hw_fZ-EYzgaKMZ33P-s,5674
1568
+ vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=14ONjhpgDaLSIthhLnWDKv79rysU2VsZDNakY4kDSzI,5804
1568
1569
  vellum/workflows/nodes/displayable/bases/search_node.py,sha256=3UtbqY3QO4kzfJHbmUNZGnEEfJmaoiF892u8H6TGjp8,5381
1569
1570
  vellum/workflows/nodes/displayable/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1570
1571
  vellum/workflows/nodes/displayable/bases/tests/test_utils.py,sha256=eqdqbKNRWVMDPevgwLg1i6YK0g4L4bCy-7xCBN5yYZI,3156
@@ -1585,8 +1586,8 @@ vellum/workflows/nodes/displayable/final_output_node/node.py,sha256=PuQ0RvtAmoSI
1585
1586
  vellum/workflows/nodes/displayable/final_output_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1586
1587
  vellum/workflows/nodes/displayable/final_output_node/tests/test_node.py,sha256=E6LQ74qZjY4Xi4avx2qdOCgGhF8pEcNLBh8cqYRkzMI,709
1587
1588
  vellum/workflows/nodes/displayable/guardrail_node/__init__.py,sha256=Ab5eXmOoBhyV4dMWdzh32HLUmnPIBEK_zFCT38C4Fng,68
1588
- vellum/workflows/nodes/displayable/guardrail_node/node.py,sha256=AHyqBiP9_XZx9jI-EbPY2dHDRwKrpo_SS6DAdrPBulA,5086
1589
- vellum/workflows/nodes/displayable/guardrail_node/test_node.py,sha256=gpaa7fmVPLH2dDjlNTbjutF3SBXa_aearI3xYvZ4ekg,3533
1589
+ vellum/workflows/nodes/displayable/guardrail_node/node.py,sha256=WzwE0CzKK2NLd1C-wHHDlm2C5bUbrPGp7-UpyE_5rkA,5349
1590
+ vellum/workflows/nodes/displayable/guardrail_node/test_node.py,sha256=KkLog-bjvPaUZUBciMH25lRHA5pDIrmUxNLVWY6oU34,4526
1590
1591
  vellum/workflows/nodes/displayable/inline_prompt_node/__init__.py,sha256=gSUOoEZLlrx35-tQhSAd3An8WDwBqyiQh-sIebLU9wU,74
1591
1592
  vellum/workflows/nodes/displayable/inline_prompt_node/node.py,sha256=8RXZqWMzViUjFfbpmcy1gkSsKnEpci8BGwsuPYv4xMQ,3380
1592
1593
  vellum/workflows/nodes/displayable/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1645,7 +1646,7 @@ vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8v
1645
1646
  vellum/workflows/runner/runner.py,sha256=ww4fjZJBENkB5HJxdj92kTz7k_EyifCeAreupy5qIxs,31813
1646
1647
  vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
1647
1648
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
1648
- vellum/workflows/state/base.py,sha256=LOQ2UCnpVLWISryfJwbicFCrRmothJQ7OQGJElgKlvg,15675
1649
+ vellum/workflows/state/base.py,sha256=uQcWWgW-a0rUbfGnkgm5qtEonP4OkZusDRcKEP7PtPA,16970
1649
1650
  vellum/workflows/state/context.py,sha256=KOAI1wEGn8dGmhmAemJaf4SZbitP3jpIBcwKfznQaRE,3076
1650
1651
  vellum/workflows/state/encoder.py,sha256=TnOQojc5lTQ83g9QbpA4UCqShJvutmTMxbpKt-9gNe4,1911
1651
1652
  vellum/workflows/state/store.py,sha256=uVe-oN73KwGV6M6YLhwZMMUQhzTQomsVfVnb8V91gVo,1147
@@ -1673,13 +1674,13 @@ vellum/workflows/utils/uuids.py,sha256=DFzPv9RCvsKhvdTEIQyfSek2A31D6S_QcmeLPbgrg
1673
1674
  vellum/workflows/utils/vellum_variables.py,sha256=UiGlUh0a8vel2FbW3w-xbHxSv_jNutkDdqMVtP_b42A,3385
1674
1675
  vellum/workflows/vellum_client.py,sha256=GxOy3dX6A04xiY69vPv1S4YGuQ_TMxwHi6WRMimQBBE,762
1675
1676
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1676
- vellum/workflows/workflows/base.py,sha256=DycL6YgN8CyaHub2gG8r9NB5PVxR9jP0wV4J09iaBnE,22749
1677
+ vellum/workflows/workflows/base.py,sha256=ezmWRtgY6mQjU-u_iQchj8qYrw1txE-Q5E4PxWgvvfI,23301
1677
1678
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1678
1679
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1679
- vellum/workflows/workflows/tests/test_base_workflow.py,sha256=tCxrV3QBHL8wfdEO3bvKteDdw32xBlUl1_WxkAwaONw,8344
1680
+ vellum/workflows/workflows/tests/test_base_workflow.py,sha256=Xbk30MaW8sW6XUNEgIhhJRGvX3sc0aorLh_tY8W2xiQ,9445
1680
1681
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
1681
- vellum_ai-0.14.36.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1682
- vellum_ai-0.14.36.dist-info/METADATA,sha256=8nijTIGNJWT-D2j9VvMW7PARaKyi1lKH76DMnGPzXoY,5484
1683
- vellum_ai-0.14.36.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1684
- vellum_ai-0.14.36.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1685
- vellum_ai-0.14.36.dist-info/RECORD,,
1682
+ vellum_ai-0.14.37.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1683
+ vellum_ai-0.14.37.dist-info/METADATA,sha256=8eaeLLw8xcvlKlxhZMTGTpog1_azd7KIGDXX1d-mPBg,5484
1684
+ vellum_ai-0.14.37.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1685
+ vellum_ai-0.14.37.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1686
+ vellum_ai-0.14.37.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass, field
2
2
  from uuid import UUID
3
- from typing import Optional, TypeVar
3
+ from typing import Optional
4
4
 
5
5
  from pydantic import Field
6
6
 
@@ -36,17 +36,19 @@ class WorkflowMetaDisplayOverrides(WorkflowMetaDisplay):
36
36
 
37
37
 
38
38
  @dataclass
39
- class WorkflowInputsDisplayOverrides:
39
+ class WorkflowInputsDisplay:
40
40
  id: UUID
41
+ name: Optional[str] = None
42
+ color: Optional[str] = None
41
43
 
42
44
 
43
45
  @dataclass
44
- class WorkflowInputsDisplay(WorkflowInputsDisplayOverrides):
45
- pass
46
-
46
+ class WorkflowInputsDisplayOverrides(WorkflowInputsDisplay):
47
+ """
48
+ DEPRECATED: Use WorkflowInputsDisplay instead. Will be removed in 0.15.0
49
+ """
47
50
 
48
- WorkflowInputsDisplayType = TypeVar("WorkflowInputsDisplayType", bound=WorkflowInputsDisplay)
49
- WorkflowInputsDisplayOverridesType = TypeVar("WorkflowInputsDisplayOverridesType", bound=WorkflowInputsDisplayOverrides)
51
+ pass
50
52
 
51
53
 
52
54
  @dataclass
@@ -1,8 +1,8 @@
1
- # flake8: noqa: F401
1
+ # flake8: noqa: F403
2
2
 
3
3
  # Force an import to ensure that all display classes are registered with the BaseNodeDisplay registry
4
4
  from .base_node_display import BaseNodeDisplay
5
- from .vellum import * # noqa: F401
5
+ from .vellum import *
6
6
  from .vellum import __all__ as all_vellum_display_nodes
7
7
 
8
8
  __all__ = ["BaseNodeDisplay"] + all_vellum_display_nodes
@@ -1,4 +1,3 @@
1
- import json
2
1
  from typing import Any, ClassVar, Dict, Generic, TypeVar, Union
3
2
 
4
3
  from vellum.workflows.nodes import NoteNode
@@ -23,7 +22,7 @@ class BaseNoteNodeDisplay(BaseNodeVellumDisplay[_NoteNodeType], Generic[_NoteNod
23
22
  "data": {
24
23
  "label": self.label,
25
24
  "text": self.text,
26
- "style": json.dumps(self.style) if self.style else None,
25
+ "style": self.style,
27
26
  },
28
27
  "display_data": self.get_display_data().dict(),
29
28
  "base": self.get_base().dict(),
@@ -47,6 +47,7 @@ class BasePromptDeploymentNodeDisplay(
47
47
  deployment = vellum_client.deployments.retrieve(
48
48
  id=str(raise_if_descriptor(node.deployment)),
49
49
  )
50
+ ml_model_fallbacks = raise_if_descriptor(node.ml_model_fallbacks)
50
51
 
51
52
  return {
52
53
  "id": str(node_id),
@@ -62,6 +63,7 @@ class BasePromptDeploymentNodeDisplay(
62
63
  "variant": "DEPLOYMENT",
63
64
  "prompt_deployment_id": str(deployment.id),
64
65
  "release_tag": raise_if_descriptor(node.release_tag),
66
+ "ml_model_fallbacks": list(ml_model_fallbacks) if ml_model_fallbacks else None,
65
67
  },
66
68
  "display_data": self.get_display_data().dict(),
67
69
  "base": self.get_base().dict(),
@@ -0,0 +1,33 @@
1
+ from vellum.workflows import BaseWorkflow
2
+ from vellum.workflows.nodes.displayable.note_node.node import NoteNode
3
+ from vellum_ee.workflows.display.nodes.vellum.note_node import BaseNoteNodeDisplay
4
+ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
5
+ from vellum_ee.workflows.display.workflows.vellum_workflow_display import VellumWorkflowDisplay
6
+
7
+
8
+ def test_serialize_node__note_node():
9
+ # GIVEN a note node
10
+ class MyNoteNode(NoteNode):
11
+ pass
12
+
13
+ # AND a display class for the note node
14
+ class MyNoteNodeDisplay(BaseNoteNodeDisplay[MyNoteNode]):
15
+ text = "This makes sense"
16
+ style = {
17
+ "fontSize": 24,
18
+ }
19
+
20
+ # AND a workflow with the code node
21
+ class Workflow(BaseWorkflow):
22
+ graph = MyNoteNode
23
+
24
+ # WHEN the workflow is serialized
25
+ workflow_display = get_workflow_display(base_display_class=VellumWorkflowDisplay, workflow_class=Workflow)
26
+ serialized_workflow: dict = workflow_display.serialize()
27
+
28
+ # THEN the node should properly serialize the inputs
29
+ my_note_node = next(node for node in serialized_workflow["workflow_raw_data"]["nodes"] if node["type"] == "NOTE")
30
+
31
+ assert my_note_node["inputs"] == []
32
+ assert my_note_node["data"]["text"] == "This makes sense"
33
+ assert my_note_node["data"]["style"] == {"fontSize": 24}
@@ -1,11 +1,9 @@
1
1
  import pytest
2
2
  from uuid import uuid4
3
- from typing import Any, Dict, Type
3
+ from typing import Any, Type
4
4
 
5
- from vellum.workflows.references.workflow_input import WorkflowInputReference
6
5
  from vellum.workflows.types.core import JsonObject
7
6
  from vellum.workflows.types.generics import NodeType
8
- from vellum_ee.workflows.display.base import WorkflowInputsDisplayType
9
7
  from vellum_ee.workflows.display.editor.types import NodeDisplayData
10
8
  from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
11
9
  from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
@@ -14,6 +12,7 @@ from vellum_ee.workflows.display.types import (
14
12
  NodeOutputDisplays,
15
13
  StateValueDisplays,
16
14
  WorkflowDisplayContext,
15
+ WorkflowInputsDisplays,
17
16
  )
18
17
  from vellum_ee.workflows.display.vellum import WorkflowMetaVellumDisplay
19
18
  from vellum_ee.workflows.display.workflows.vellum_workflow_display import VellumWorkflowDisplay
@@ -24,7 +23,7 @@ def serialize_node():
24
23
  def _serialize_node(
25
24
  node_class: Type[NodeType],
26
25
  base_class: type[BaseNodeDisplay[Any]] = BaseNodeDisplay,
27
- global_workflow_input_displays: Dict[WorkflowInputReference, WorkflowInputsDisplayType] = {},
26
+ global_workflow_input_displays: WorkflowInputsDisplays = {},
28
27
  global_state_value_displays: StateValueDisplays = {},
29
28
  global_node_displays: NodeDisplays = {},
30
29
  global_node_output_displays: NodeOutputDisplays = {},
@@ -32,7 +32,7 @@ def test_serialize_workflow():
32
32
  "key": "example",
33
33
  "type": "STRING",
34
34
  "default": {"type": "STRING", "value": "hello"},
35
- "required": True,
35
+ "required": False,
36
36
  "extensions": {"color": None},
37
37
  },
38
38
  ],
@@ -70,7 +70,6 @@ def test_serialize_workflow():
70
70
  "source_handle_id": "844d992e-60ab-4af2-a8ff-52cd858386f7",
71
71
  },
72
72
  "base": None,
73
- "base": None,
74
73
  "definition": None,
75
74
  "display_data": {
76
75
  "position": {"x": 0.0, "y": 0.0},
@@ -144,6 +144,7 @@ def test_serialize_workflow(vellum_client):
144
144
  "variant": "DEPLOYMENT",
145
145
  "prompt_deployment_id": deployment.id,
146
146
  "release_tag": "LATEST",
147
+ "ml_model_fallbacks": ["gpt-4o", "gemini-1.5-pro"],
147
148
  },
148
149
  "display_data": {
149
150
  "position": {
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import TYPE_CHECKING, Dict, Generic, Tuple, Type, TypeVar
2
+ from typing import TYPE_CHECKING, Dict, Tuple, Type, TypeVar
3
3
 
4
4
  from vellum.workflows.descriptors.base import BaseDescriptor
5
5
  from vellum.workflows.events.workflow import WorkflowEventDisplayContext # noqa: F401
@@ -10,7 +10,7 @@ from vellum_ee.workflows.display.base import (
10
10
  EdgeDisplay,
11
11
  EntrypointDisplay,
12
12
  StateValueDisplay,
13
- WorkflowInputsDisplayType,
13
+ WorkflowInputsDisplay,
14
14
  WorkflowMetaDisplay,
15
15
  WorkflowOutputDisplay,
16
16
  )
@@ -22,6 +22,7 @@ if TYPE_CHECKING:
22
22
 
23
23
  WorkflowDisplayType = TypeVar("WorkflowDisplayType", bound="BaseWorkflowDisplay")
24
24
 
25
+ WorkflowInputsDisplays = Dict[WorkflowInputReference, WorkflowInputsDisplay]
25
26
  StateValueDisplays = Dict[StateValueReference, StateValueDisplay]
26
27
  NodeDisplays = Dict[Type[BaseNode], BaseNodeDisplay]
27
28
  NodeOutputDisplays = Dict[OutputReference, Tuple[Type[BaseNode], NodeOutputDisplay]]
@@ -32,13 +33,11 @@ PortDisplays = Dict[Port, PortDisplay]
32
33
 
33
34
 
34
35
  @dataclass
35
- class WorkflowDisplayContext(Generic[WorkflowInputsDisplayType,]):
36
+ class WorkflowDisplayContext:
36
37
  workflow_display_class: Type["BaseWorkflowDisplay"]
37
38
  workflow_display: WorkflowMetaDisplay
38
- workflow_input_displays: Dict[WorkflowInputReference, WorkflowInputsDisplayType] = field(default_factory=dict)
39
- global_workflow_input_displays: Dict[WorkflowInputReference, WorkflowInputsDisplayType] = field(
40
- default_factory=dict
41
- )
39
+ workflow_input_displays: WorkflowInputsDisplays = field(default_factory=dict)
40
+ global_workflow_input_displays: WorkflowInputsDisplays = field(default_factory=dict)
42
41
  state_value_displays: StateValueDisplays = field(default_factory=dict)
43
42
  global_state_value_displays: StateValueDisplays = field(default_factory=dict)
44
43
  node_displays: NodeDisplays = field(default_factory=dict)
@@ -8,7 +8,6 @@ from vellum_ee.workflows.display.base import (
8
8
  EntrypointDisplayOverrides,
9
9
  StateValueDisplayOverrides,
10
10
  WorkflowInputsDisplay,
11
- WorkflowInputsDisplayOverrides,
12
11
  WorkflowMetaDisplayOverrides,
13
12
  WorkflowOutputDisplayOverrides,
14
13
  )
@@ -44,10 +43,12 @@ class WorkflowMetaVellumDisplay(WorkflowMetaVellumDisplayOverrides):
44
43
 
45
44
 
46
45
  @dataclass
47
- class WorkflowInputsVellumDisplayOverrides(WorkflowInputsDisplay, WorkflowInputsDisplayOverrides):
48
- name: Optional[str] = None
46
+ class WorkflowInputsVellumDisplayOverrides(WorkflowInputsDisplay):
47
+ """
48
+ DEPRECATED: Use WorkflowInputsDisplay instead. Will be removed in 0.15.0
49
+ """
50
+
49
51
  required: Optional[bool] = None
50
- color: Optional[str] = None
51
52
 
52
53
 
53
54
  @dataclass
@@ -21,8 +21,7 @@ from vellum_ee.workflows.display.base import (
21
21
  EdgeDisplay,
22
22
  EntrypointDisplay,
23
23
  StateValueDisplay,
24
- WorkflowInputsDisplayOverridesType,
25
- WorkflowInputsDisplayType,
24
+ WorkflowInputsDisplay,
26
25
  WorkflowMetaDisplay,
27
26
  WorkflowOutputDisplay,
28
27
  )
@@ -40,6 +39,7 @@ from vellum_ee.workflows.display.types import (
40
39
  PortDisplays,
41
40
  StateValueDisplays,
42
41
  WorkflowDisplayContext,
42
+ WorkflowInputsDisplays,
43
43
  WorkflowOutputDisplays,
44
44
  )
45
45
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
@@ -47,18 +47,12 @@ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class imp
47
47
  logger = logging.getLogger(__name__)
48
48
 
49
49
 
50
- class BaseWorkflowDisplay(
51
- Generic[
52
- WorkflowType,
53
- WorkflowInputsDisplayType,
54
- WorkflowInputsDisplayOverridesType,
55
- ]
56
- ):
50
+ class BaseWorkflowDisplay(Generic[WorkflowType]):
57
51
  # Used to specify the display data for a workflow.
58
52
  workflow_display: Optional[WorkflowMetaDisplay] = None
59
53
 
60
54
  # Used to explicitly specify display data for a workflow's inputs.
61
- inputs_display: Dict[WorkflowInputReference, WorkflowInputsDisplayOverridesType] = {}
55
+ inputs_display: WorkflowInputsDisplays = {}
62
56
 
63
57
  # Used to explicitly specify display data for a workflow's state values.
64
58
  state_value_displays: StateValueDisplays = {}
@@ -86,7 +80,7 @@ class BaseWorkflowDisplay(
86
80
  self,
87
81
  workflow: Type[WorkflowType],
88
82
  *,
89
- parent_display_context: Optional[WorkflowDisplayContext[WorkflowInputsDisplayType,]] = None,
83
+ parent_display_context: Optional[WorkflowDisplayContext] = None,
90
84
  dry_run: bool = False,
91
85
  ):
92
86
  self._workflow = workflow
@@ -174,9 +168,7 @@ class BaseWorkflowDisplay(
174
168
  return node_display
175
169
 
176
170
  @cached_property
177
- def display_context(
178
- self,
179
- ) -> WorkflowDisplayContext[WorkflowInputsDisplayType]:
171
+ def display_context(self) -> WorkflowDisplayContext:
180
172
  workflow_meta_display = self._generate_workflow_meta_display()
181
173
 
182
174
  global_node_output_displays: NodeOutputDisplays = (
@@ -209,7 +201,7 @@ class BaseWorkflowDisplay(
209
201
  port_displays=port_displays,
210
202
  )
211
203
 
212
- workflow_input_displays: Dict[WorkflowInputReference, WorkflowInputsDisplayType] = {}
204
+ workflow_input_displays: WorkflowInputsDisplays = {}
213
205
  # If we're dealing with a nested workflow, then it should have access to the inputs of its parents.
214
206
  global_workflow_input_displays = (
215
207
  copy(self._parent_display_context.workflow_input_displays) if self._parent_display_context else {}
@@ -311,11 +303,20 @@ class BaseWorkflowDisplay(
311
303
  entrypoint_node_display=NodeDisplayData(),
312
304
  )
313
305
 
314
- @abstractmethod
315
306
  def _generate_workflow_input_display(
316
- self, workflow_input: WorkflowInputReference, overrides: Optional[WorkflowInputsDisplayOverridesType] = None
317
- ) -> WorkflowInputsDisplayType:
318
- pass
307
+ self, workflow_input: WorkflowInputReference, overrides: Optional[WorkflowInputsDisplay] = None
308
+ ) -> WorkflowInputsDisplay:
309
+ workflow_input_id: UUID
310
+ name = None
311
+ color = None
312
+ if overrides:
313
+ workflow_input_id = overrides.id
314
+ name = overrides.name
315
+ color = overrides.color
316
+ else:
317
+ workflow_input_id = uuid4_from_hash(f"{self.workflow_id}|inputs|id|{workflow_input.name}")
318
+
319
+ return WorkflowInputsDisplay(id=workflow_input_id, name=name, color=color)
319
320
 
320
321
  def _generate_state_value_display(
321
322
  self, state_value: BaseDescriptor, overrides: Optional[StateValueDisplay] = None
@@ -2,10 +2,10 @@ import logging
2
2
  from uuid import UUID
3
3
  from typing import Optional, cast
4
4
 
5
+ from vellum.workflows.constants import undefined
5
6
  from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
6
7
  from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
7
8
  from vellum.workflows.nodes.utils import get_unadorned_node, get_unadorned_port
8
- from vellum.workflows.references import WorkflowInputReference
9
9
  from vellum.workflows.references.output import OutputReference
10
10
  from vellum.workflows.types.core import JsonArray, JsonObject
11
11
  from vellum.workflows.types.generics import WorkflowType
@@ -15,38 +15,29 @@ from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
15
15
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
16
16
  from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
17
17
  from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
18
- from vellum_ee.workflows.display.vellum import WorkflowInputsVellumDisplay, WorkflowInputsVellumDisplayOverrides
19
18
  from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
20
19
 
21
20
  logger = logging.getLogger(__name__)
22
21
 
23
22
 
24
- class VellumWorkflowDisplay(
25
- BaseWorkflowDisplay[
26
- WorkflowType,
27
- WorkflowInputsVellumDisplay,
28
- WorkflowInputsVellumDisplayOverrides,
29
- ]
30
- ):
23
+ class VellumWorkflowDisplay(BaseWorkflowDisplay[WorkflowType]):
31
24
  node_display_base_class = BaseNodeDisplay
32
25
 
33
26
  def serialize(self) -> JsonObject:
34
27
  input_variables: JsonArray = []
35
- for workflow_input, workflow_input_display in self.display_context.workflow_input_displays.items():
36
- default = primitive_to_vellum_value(workflow_input.instance) if workflow_input.instance else None
37
- required = (
38
- workflow_input_display.required
39
- if workflow_input_display.required is not None
40
- else type(None) not in workflow_input.types
28
+ for workflow_input_reference, workflow_input_display in self.display_context.workflow_input_displays.items():
29
+ default = (
30
+ primitive_to_vellum_value(workflow_input_reference.instance)
31
+ if workflow_input_reference.instance
32
+ else None
41
33
  )
42
-
43
34
  input_variables.append(
44
35
  {
45
36
  "id": str(workflow_input_display.id),
46
- "key": workflow_input_display.name or workflow_input.name,
47
- "type": infer_vellum_variable_type(workflow_input),
37
+ "key": workflow_input_display.name or workflow_input_reference.name,
38
+ "type": infer_vellum_variable_type(workflow_input_reference),
48
39
  "default": default.dict() if default else None,
49
- "required": required,
40
+ "required": workflow_input_reference.instance is undefined,
50
41
  "extensions": {"color": workflow_input_display.color},
51
42
  }
52
43
  )
@@ -62,7 +53,7 @@ class VellumWorkflowDisplay(
62
53
  "key": state_value_display.name or state_value_reference.name,
63
54
  "type": infer_vellum_variable_type(state_value_reference),
64
55
  "default": default.dict() if default else None,
65
- "required": state_value_reference.instance is None,
56
+ "required": state_value_reference.instance is undefined,
66
57
  "extensions": {"color": state_value_display.color},
67
58
  }
68
59
  )
@@ -269,20 +260,3 @@ class VellumWorkflowDisplay(
269
260
  "state_variables": state_variables,
270
261
  "output_variables": output_variables,
271
262
  }
272
-
273
- def _generate_workflow_input_display(
274
- self, workflow_input: WorkflowInputReference, overrides: Optional[WorkflowInputsVellumDisplayOverrides] = None
275
- ) -> WorkflowInputsVellumDisplay:
276
- workflow_input_id: UUID
277
- name = None
278
- required = None
279
- color = None
280
- if overrides:
281
- workflow_input_id = overrides.id
282
- name = overrides.name
283
- required = overrides.required
284
- color = overrides.color
285
- else:
286
- workflow_input_id = uuid4_from_hash(f"{self.workflow_id}|inputs|id|{workflow_input.name}")
287
-
288
- return WorkflowInputsVellumDisplay(id=workflow_input_id, name=name, required=required, color=color)