vellum-ai 0.14.39__py3-none-any.whl → 0.14.40__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 (67) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/workflows/nodes/bases/tests/test_base_node.py +24 -0
  3. vellum/workflows/nodes/core/try_node/node.py +1 -2
  4. vellum/workflows/nodes/experimental/tool_calling_node/__init__.py +3 -0
  5. vellum/workflows/nodes/experimental/tool_calling_node/node.py +147 -0
  6. vellum/workflows/nodes/experimental/tool_calling_node/utils.py +132 -0
  7. vellum/workflows/nodes/utils.py +4 -2
  8. vellum/workflows/outputs/base.py +3 -2
  9. vellum/workflows/references/output.py +20 -0
  10. vellum/workflows/state/base.py +36 -14
  11. vellum/workflows/state/tests/test_state.py +5 -2
  12. vellum/workflows/types/stack.py +11 -0
  13. vellum/workflows/workflows/base.py +5 -0
  14. vellum/workflows/workflows/tests/test_base_workflow.py +96 -9
  15. {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/METADATA +1 -1
  16. {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/RECORD +67 -62
  17. vellum_cli/push.py +0 -2
  18. vellum_ee/workflows/display/base.py +14 -1
  19. vellum_ee/workflows/display/nodes/base_node_display.py +56 -14
  20. vellum_ee/workflows/display/nodes/get_node_display_class.py +9 -15
  21. vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +36 -0
  22. vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +3 -2
  23. vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -2
  24. vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +1 -2
  25. vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py +1 -2
  26. vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +1 -2
  27. vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +55 -3
  28. vellum_ee/workflows/display/nodes/vellum/tests/test_retry_node.py +1 -2
  29. vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py +1 -2
  30. vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py +1 -2
  31. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +2 -2
  32. vellum_ee/workflows/display/nodes/vellum/try_node.py +1 -2
  33. vellum_ee/workflows/display/nodes/vellum/utils.py +7 -1
  34. vellum_ee/workflows/display/tests/{test_vellum_workflow_display.py → test_base_workflow_display.py} +10 -22
  35. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +4 -6
  36. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +7 -16
  37. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +2 -6
  38. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +1 -2
  39. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +3 -10
  40. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +4 -5
  41. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +1 -4
  42. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +1 -4
  43. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +2 -5
  44. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +7 -5
  45. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +1 -4
  46. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +1 -4
  47. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +1 -2
  48. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +1 -4
  49. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +1 -4
  50. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +7 -5
  51. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +1 -4
  52. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +1 -4
  53. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +1 -4
  54. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +2 -5
  55. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +2 -7
  56. vellum_ee/workflows/display/types.py +5 -4
  57. vellum_ee/workflows/display/utils/exceptions.py +7 -0
  58. vellum_ee/workflows/display/utils/registry.py +37 -0
  59. vellum_ee/workflows/display/utils/vellum.py +2 -1
  60. vellum_ee/workflows/display/workflows/base_workflow_display.py +281 -43
  61. vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +34 -21
  62. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +58 -20
  63. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +4 -257
  64. vellum_ee/workflows/tests/local_workflow/display/workflow.py +2 -2
  65. {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/LICENSE +0 -0
  66. {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/WHEEL +0 -0
  67. {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/entry_points.txt +0 -0
@@ -1,262 +1,9 @@
1
- import logging
2
- from uuid import UUID
3
- from typing import Optional, cast
1
+ from typing import Generic
4
2
 
5
- from vellum.workflows.constants import undefined
6
- from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
7
- from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
8
- from vellum.workflows.nodes.utils import get_unadorned_node, get_unadorned_port
9
- from vellum.workflows.references.output import OutputReference
10
- from vellum.workflows.types.core import JsonArray, JsonObject
11
3
  from vellum.workflows.types.generics import WorkflowType
12
- from vellum.workflows.utils.uuids import uuid4_from_hash
13
- from vellum_ee.workflows.display.editor.types import NodeDisplayData
14
- from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
15
- from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
16
- from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
17
- from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
18
4
  from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
19
5
 
20
- logger = logging.getLogger(__name__)
21
6
 
22
-
23
- class VellumWorkflowDisplay(BaseWorkflowDisplay[WorkflowType]):
24
- node_display_base_class = BaseNodeDisplay
25
-
26
- def serialize(self) -> JsonObject:
27
- input_variables: JsonArray = []
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
33
- )
34
- input_variables.append(
35
- {
36
- "id": str(workflow_input_display.id),
37
- "key": workflow_input_display.name or workflow_input_reference.name,
38
- "type": infer_vellum_variable_type(workflow_input_reference),
39
- "default": default.dict() if default else None,
40
- "required": workflow_input_reference.instance is undefined,
41
- "extensions": {"color": workflow_input_display.color},
42
- }
43
- )
44
-
45
- state_variables: JsonArray = []
46
- for state_value_reference, state_value_display in self.display_context.state_value_displays.items():
47
- default = (
48
- primitive_to_vellum_value(state_value_reference.instance) if state_value_reference.instance else None
49
- )
50
- state_variables.append(
51
- {
52
- "id": str(state_value_display.id),
53
- "key": state_value_display.name or state_value_reference.name,
54
- "type": infer_vellum_variable_type(state_value_reference),
55
- "default": default.dict() if default else None,
56
- "required": state_value_reference.instance is undefined,
57
- "extensions": {"color": state_value_display.color},
58
- }
59
- )
60
-
61
- nodes: JsonArray = []
62
- edges: JsonArray = []
63
-
64
- # Add a single synthetic node for the workflow entrypoint
65
- entrypoint_node_id = self.display_context.workflow_display.entrypoint_node_id
66
- entrypoint_node_source_handle_id = self.display_context.workflow_display.entrypoint_node_source_handle_id
67
- nodes.append(
68
- {
69
- "id": str(entrypoint_node_id),
70
- "type": "ENTRYPOINT",
71
- "inputs": [],
72
- "data": {
73
- "label": "Entrypoint Node",
74
- "source_handle_id": str(entrypoint_node_source_handle_id),
75
- },
76
- "display_data": self.display_context.workflow_display.entrypoint_node_display.dict(),
77
- "base": None,
78
- "definition": None,
79
- },
80
- )
81
-
82
- # Add all the nodes in the workflow
83
- for node in self._workflow.get_nodes():
84
- node_display = self.display_context.node_displays[node]
85
-
86
- try:
87
- serialized_node = node_display.serialize(self.display_context)
88
- except NotImplementedError as e:
89
- self.add_error(e)
90
- continue
91
-
92
- nodes.append(serialized_node)
93
-
94
- # Add all unused nodes in the workflow
95
- for node in self._workflow.get_unused_nodes():
96
- node_display = self.display_context.node_displays[node]
97
-
98
- try:
99
- serialized_node = node_display.serialize(self.display_context)
100
- except NotImplementedError as e:
101
- self.add_error(e)
102
- continue
103
-
104
- nodes.append(serialized_node)
105
-
106
- synthetic_output_edges: JsonArray = []
107
- output_variables: JsonArray = []
108
- final_output_nodes = [
109
- node for node in self.display_context.node_displays.keys() if issubclass(node, FinalOutputNode)
110
- ]
111
- final_output_node_outputs = {node.Outputs.value for node in final_output_nodes}
112
- unreferenced_final_output_node_outputs = final_output_node_outputs.copy()
113
- final_output_node_base: JsonObject = {
114
- "name": FinalOutputNode.__name__,
115
- "module": cast(JsonArray, FinalOutputNode.__module__.split(".")),
116
- }
117
-
118
- # Add a synthetic Terminal Node and track the Workflow's output variables for each Workflow output
119
- for workflow_output, workflow_output_display in self.display_context.workflow_output_displays.items():
120
- final_output_node_id = uuid4_from_hash(f"{self.workflow_id}|node_id|{workflow_output.name}")
121
- inferred_type = infer_vellum_variable_type(workflow_output)
122
-
123
- # Remove the terminal node output from the unreferenced set
124
- unreferenced_final_output_node_outputs.discard(cast(OutputReference, workflow_output.instance))
125
-
126
- if workflow_output.instance not in final_output_node_outputs:
127
- # Create a synthetic terminal node only if there is no terminal node for this output
128
- try:
129
- node_input = create_node_input(
130
- final_output_node_id,
131
- "node_input",
132
- # This is currently the wrapper node's output, but we want the wrapped node
133
- workflow_output.instance,
134
- self.display_context,
135
- )
136
- except ValueError as e:
137
- raise ValueError(f"Failed to serialize output '{workflow_output.name}': {str(e)}") from e
138
-
139
- source_node_display: Optional[BaseNodeDisplay]
140
- first_rule = node_input.value.rules[0]
141
- if first_rule.type == "NODE_OUTPUT":
142
- source_node_id = UUID(first_rule.data.node_id)
143
- try:
144
- source_node_display = [
145
- node_display
146
- for node_display in self.display_context.node_displays.values()
147
- if node_display.node_id == source_node_id
148
- ][0]
149
- except IndexError:
150
- source_node_display = None
151
-
152
- synthetic_target_handle_id = str(
153
- uuid4_from_hash(f"{self.workflow_id}|target_handle_id|{workflow_output_display.name}")
154
- )
155
- synthetic_display_data = NodeDisplayData().dict()
156
- synthetic_node_label = "Final Output"
157
- nodes.append(
158
- {
159
- "id": str(final_output_node_id),
160
- "type": "TERMINAL",
161
- "data": {
162
- "label": synthetic_node_label,
163
- "name": workflow_output_display.name,
164
- "target_handle_id": synthetic_target_handle_id,
165
- "output_id": str(workflow_output_display.id),
166
- "output_type": inferred_type,
167
- "node_input_id": str(node_input.id),
168
- },
169
- "inputs": [node_input.dict()],
170
- "display_data": synthetic_display_data,
171
- "base": final_output_node_base,
172
- "definition": None,
173
- }
174
- )
175
-
176
- if source_node_display:
177
- if isinstance(source_node_display, BaseNodeVellumDisplay):
178
- source_handle_id = source_node_display.get_source_handle_id(
179
- port_displays=self.display_context.port_displays
180
- )
181
- else:
182
- source_handle_id = source_node_display.get_node_port_display(
183
- source_node_display._node.Ports.default
184
- ).id
185
-
186
- synthetic_output_edges.append(
187
- {
188
- "id": str(uuid4_from_hash(f"{self.workflow_id}|edge_id|{workflow_output_display.name}")),
189
- "source_node_id": str(source_node_display.node_id),
190
- "source_handle_id": str(source_handle_id),
191
- "target_node_id": str(final_output_node_id),
192
- "target_handle_id": synthetic_target_handle_id,
193
- "type": "DEFAULT",
194
- }
195
- )
196
-
197
- output_variables.append(
198
- {
199
- "id": str(workflow_output_display.id),
200
- "key": workflow_output_display.name,
201
- "type": inferred_type,
202
- }
203
- )
204
-
205
- # If there are terminal nodes with no workflow output reference,
206
- # raise a serialization error
207
- if len(unreferenced_final_output_node_outputs) > 0:
208
- self.add_error(
209
- ValueError("Unable to serialize terminal nodes that are not referenced by workflow outputs.")
210
- )
211
-
212
- # Add an edge for each edge in the workflow
213
- for target_node, entrypoint_display in self.display_context.entrypoint_displays.items():
214
- unadorned_target_node = get_unadorned_node(target_node)
215
- target_node_display = self.display_context.node_displays[unadorned_target_node]
216
- edges.append(
217
- {
218
- "id": str(entrypoint_display.edge_display.id),
219
- "source_node_id": str(entrypoint_node_id),
220
- "source_handle_id": str(entrypoint_node_source_handle_id),
221
- "target_node_id": str(target_node_display.node_id),
222
- "target_handle_id": str(target_node_display.get_trigger_id()),
223
- "type": "DEFAULT",
224
- }
225
- )
226
-
227
- for (source_node_port, target_node), edge_display in self.display_context.edge_displays.items():
228
- unadorned_source_node_port = get_unadorned_port(source_node_port)
229
- unadorned_target_node = get_unadorned_node(target_node)
230
-
231
- source_node_port_display = self.display_context.port_displays[unadorned_source_node_port]
232
- target_node_display = self.display_context.node_displays[unadorned_target_node]
233
-
234
- edges.append(
235
- {
236
- "id": str(edge_display.id),
237
- "source_node_id": str(source_node_port_display.node_id),
238
- "source_handle_id": str(source_node_port_display.id),
239
- "target_node_id": str(target_node_display.node_id),
240
- "target_handle_id": str(
241
- target_node_display.get_target_handle_id_by_source_node_id(source_node_port_display.node_id)
242
- ),
243
- "type": "DEFAULT",
244
- }
245
- )
246
-
247
- edges.extend(synthetic_output_edges)
248
-
249
- return {
250
- "workflow_raw_data": {
251
- "nodes": nodes,
252
- "edges": edges,
253
- "display_data": self.display_context.workflow_display.display_data.dict(),
254
- "definition": {
255
- "name": self._workflow.__name__,
256
- "module": cast(JsonArray, self._workflow.__module__.split(".")),
257
- },
258
- },
259
- "input_variables": input_variables,
260
- "state_variables": state_variables,
261
- "output_variables": output_variables,
262
- }
7
+ # DEPRECATED: Use BaseWorkflowDisplay instead - This file will be removed in 0.15.0
8
+ class VellumWorkflowDisplay(BaseWorkflowDisplay[WorkflowType], Generic[WorkflowType]):
9
+ pass
@@ -11,7 +11,7 @@ from vellum_ee.workflows.display.vellum import (
11
11
  WorkflowMetaVellumDisplayOverrides,
12
12
  WorkflowOutputVellumDisplayOverrides,
13
13
  )
14
- from vellum_ee.workflows.display.workflows.vellum_workflow_display import VellumWorkflowDisplay
14
+ from vellum_ee.workflows.display.workflows import BaseWorkflowDisplay
15
15
 
16
16
  from ..inputs import Inputs
17
17
  from ..nodes.final_output import FinalOutput
@@ -19,7 +19,7 @@ from ..nodes.templating_node import TemplatingNode
19
19
  from ..workflow import Workflow
20
20
 
21
21
 
22
- class WorkflowDisplay(VellumWorkflowDisplay[Workflow]):
22
+ class WorkflowDisplay(BaseWorkflowDisplay[Workflow]):
23
23
  workflow_display = WorkflowMetaVellumDisplayOverrides(
24
24
  entrypoint_node_id=UUID("0bf86989-13f2-438c-ab9c-d172e5771d31"),
25
25
  entrypoint_node_source_handle_id=UUID("23448f09-81ad-4378-abbd-1cccff350627"),