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.
- vellum/client/core/client_wrapper.py +1 -1
- vellum/workflows/nodes/bases/tests/test_base_node.py +24 -0
- vellum/workflows/nodes/core/try_node/node.py +1 -2
- vellum/workflows/nodes/experimental/tool_calling_node/__init__.py +3 -0
- vellum/workflows/nodes/experimental/tool_calling_node/node.py +147 -0
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py +132 -0
- vellum/workflows/nodes/utils.py +4 -2
- vellum/workflows/outputs/base.py +3 -2
- vellum/workflows/references/output.py +20 -0
- vellum/workflows/state/base.py +36 -14
- vellum/workflows/state/tests/test_state.py +5 -2
- vellum/workflows/types/stack.py +11 -0
- vellum/workflows/workflows/base.py +5 -0
- vellum/workflows/workflows/tests/test_base_workflow.py +96 -9
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/RECORD +67 -62
- vellum_cli/push.py +0 -2
- vellum_ee/workflows/display/base.py +14 -1
- vellum_ee/workflows/display/nodes/base_node_display.py +56 -14
- vellum_ee/workflows/display/nodes/get_node_display_class.py +9 -15
- vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +36 -0
- vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +3 -2
- vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +55 -3
- vellum_ee/workflows/display/nodes/vellum/tests/test_retry_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/try_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/utils.py +7 -1
- vellum_ee/workflows/display/tests/{test_vellum_workflow_display.py → test_base_workflow_display.py} +10 -22
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +4 -6
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +7 -16
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +2 -6
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +1 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +3 -10
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +4 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +2 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +7 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +1 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +7 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +2 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +2 -7
- vellum_ee/workflows/display/types.py +5 -4
- vellum_ee/workflows/display/utils/exceptions.py +7 -0
- vellum_ee/workflows/display/utils/registry.py +37 -0
- vellum_ee/workflows/display/utils/vellum.py +2 -1
- vellum_ee/workflows/display/workflows/base_workflow_display.py +281 -43
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +34 -21
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +58 -20
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py +4 -257
- vellum_ee/workflows/tests/local_workflow/display/workflow.py +2 -2
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.40.dist-info}/WHEEL +0 -0
- {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
|
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
|
-
|
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
|
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(
|
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"),
|
File without changes
|
File without changes
|
File without changes
|