vellum-ai 0.14.16__py3-none-any.whl → 0.14.18__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 (39) hide show
  1. vellum/__init__.py +2 -0
  2. vellum/client/core/client_wrapper.py +1 -1
  3. vellum/client/types/__init__.py +2 -0
  4. vellum/client/types/release.py +21 -0
  5. vellum/client/types/workflow_release_tag_read.py +7 -1
  6. vellum/prompts/blocks/compilation.py +14 -0
  7. vellum/types/release.py +3 -0
  8. vellum/workflows/events/workflow.py +15 -1
  9. vellum/workflows/nodes/bases/base.py +7 -7
  10. vellum/workflows/nodes/bases/base_adornment_node.py +2 -0
  11. vellum/workflows/nodes/core/retry_node/node.py +60 -40
  12. vellum/workflows/nodes/core/templating_node/node.py +2 -2
  13. vellum/workflows/nodes/core/try_node/node.py +1 -1
  14. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +4 -0
  15. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +27 -1
  16. vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/__init__.py +0 -0
  17. vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py +298 -0
  18. vellum/workflows/nodes/displayable/inline_prompt_node/node.py +24 -1
  19. vellum/workflows/nodes/experimental/openai_chat_completion_node/node.py +7 -1
  20. vellum/workflows/runner/runner.py +16 -1
  21. vellum/workflows/utils/tests/test_vellum_variables.py +7 -1
  22. vellum/workflows/utils/vellum_variables.py +4 -0
  23. {vellum_ai-0.14.16.dist-info → vellum_ai-0.14.18.dist-info}/METADATA +1 -1
  24. {vellum_ai-0.14.16.dist-info → vellum_ai-0.14.18.dist-info}/RECORD +39 -34
  25. vellum_ee/workflows/display/nodes/base_node_display.py +35 -29
  26. vellum_ee/workflows/display/nodes/get_node_display_class.py +0 -9
  27. vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +38 -18
  28. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +6 -0
  29. vellum_ee/workflows/display/nodes/vellum/templating_node.py +6 -7
  30. vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py +97 -0
  31. vellum_ee/workflows/display/nodes/vellum/utils.py +1 -1
  32. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +1 -1
  33. vellum_ee/workflows/display/vellum.py +1 -148
  34. vellum_ee/workflows/display/workflows/base_workflow_display.py +1 -1
  35. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +61 -17
  36. vellum_ee/workflows/tests/test_display_meta.py +10 -10
  37. {vellum_ai-0.14.16.dist-info → vellum_ai-0.14.18.dist-info}/LICENSE +0 -0
  38. {vellum_ai-0.14.16.dist-info → vellum_ai-0.14.18.dist-info}/WHEEL +0 -0
  39. {vellum_ai-0.14.16.dist-info → vellum_ai-0.14.18.dist-info}/entry_points.txt +0 -0
@@ -54,7 +54,7 @@ def create_node_input_value_pointer_rules(
54
54
 
55
55
  if isinstance(value, BaseDescriptor):
56
56
  if isinstance(value, NodeReference):
57
- if not value.instance:
57
+ if value.instance is None:
58
58
  raise ValueError(f"Expected NodeReference {value.name} to have an instance")
59
59
  value = cast(BaseDescriptor, value.instance)
60
60
 
@@ -85,7 +85,7 @@ def test_serialize_workflow():
85
85
  },
86
86
  },
87
87
  {
88
- "id": "bb712499-4265-4d71-bc14-0c3d8ca6a7de",
88
+ "id": "e6c9d062-1a4f-4d4d-a258-59b75c6062fc",
89
89
  "key": "info",
90
90
  "value": {
91
91
  "rules": [
@@ -1,11 +1,10 @@
1
1
  from dataclasses import dataclass, field
2
- from enum import Enum
3
2
  from uuid import UUID
4
3
  from typing import List, Literal, Optional, Union
5
4
 
6
5
  from pydantic import Field
7
6
 
8
- from vellum import PromptParameters, VellumVariable, VellumVariableType
7
+ from vellum import VellumVariableType
9
8
  from vellum.client.types.array_vellum_value import ArrayVellumValue
10
9
  from vellum.client.types.vellum_value import VellumValue
11
10
  from vellum.core import UniversalBaseModel
@@ -138,24 +137,6 @@ class WorkflowOutputVellumDisplay(WorkflowOutputVellumDisplayOverrides):
138
137
  pass
139
138
 
140
139
 
141
- class WorkflowNodeType(str, Enum):
142
- PROMPT = "PROMPT"
143
- TEMPLATING = "TEMPLATING"
144
- NOTE = "NOTE"
145
- CODE_EXECUTION = "CODE_EXECUTION"
146
- METRIC = "METRIC"
147
- SEARCH = "SEARCH"
148
- WEBHOOK = "WEBHOOK"
149
- MERGE = "MERGE"
150
- CONDITIONAL = "CONDITIONAL"
151
- API = "API"
152
- ENTRYPOINT = "ENTRYPOINT"
153
- TERMINAL = "TERMINAL"
154
- SUBWORKFLOW = "SUBWORKFLOW"
155
- MAP = "MAP"
156
- ERROR = "ERROR"
157
-
158
-
159
140
  class ConstantValuePointer(UniversalBaseModel):
160
141
  type: Literal["CONSTANT_VALUE"] = "CONSTANT_VALUE"
161
142
  data: VellumValue
@@ -220,131 +201,3 @@ class NodeInput(UniversalBaseModel):
220
201
  id: str
221
202
  key: str
222
203
  value: NodeInputValuePointer
223
-
224
-
225
- class BaseWorkflowNode(UniversalBaseModel):
226
- id: str
227
- inputs: List[NodeInput]
228
- type: str
229
- display_data: Optional[NodeDisplayData] = None
230
- base: CodeResourceDefinition
231
- definition: CodeResourceDefinition
232
-
233
-
234
- class EntrypointNodeData(UniversalBaseModel):
235
- source_handle_id: str
236
-
237
-
238
- class EntrypointNode(BaseWorkflowNode):
239
- type: Literal[WorkflowNodeType.ENTRYPOINT] = WorkflowNodeType.ENTRYPOINT
240
- data: EntrypointNodeData
241
-
242
-
243
- class PromptTemplateBlockData(UniversalBaseModel):
244
- version: Literal[1] = 1
245
- # blocks: List[PromptBlockRequest]
246
-
247
-
248
- class PromptVersionExecConfig(UniversalBaseModel):
249
- parameters: PromptParameters
250
- input_variables: List[VellumVariable]
251
- prompt_template_block_data: PromptTemplateBlockData
252
-
253
-
254
- class BasePromptNodeData(UniversalBaseModel):
255
- label: str
256
- output_id: str
257
- error_output_id: Optional[str] = None
258
- array_output_id: str
259
- source_handle_id: str
260
- target_handle_id: str
261
-
262
-
263
- class InlinePromptNodeData(BasePromptNodeData):
264
- variant: Literal["INLINE"] = "INLINE"
265
- exec_config: PromptVersionExecConfig
266
- ml_model_name: str
267
-
268
-
269
- class DeploymentPromptNodeData(BasePromptNodeData):
270
- variant: Literal["DEPLOYMENT"] = "DEPLOYMENT"
271
- deployment_id: str
272
- release_tag: str
273
-
274
-
275
- PromptNodeData = Union[
276
- InlinePromptNodeData,
277
- DeploymentPromptNodeData,
278
- ]
279
-
280
-
281
- class PromptNode(BaseWorkflowNode):
282
- type: Literal[WorkflowNodeType.PROMPT] = WorkflowNodeType.PROMPT
283
- data: PromptNodeData
284
-
285
-
286
- class SearchNodeData(UniversalBaseModel):
287
- label: str
288
-
289
- results_output_id: str
290
- text_output_id: str
291
- error_output_id: Optional[str] = None
292
-
293
- source_handle_id: str
294
- target_handle_id: str
295
-
296
- query_node_input_id: str
297
- document_index_node_input_id: str
298
- weights_node_input_id: str
299
- limit_node_input_id: str
300
- separator_node_input_id: str
301
- result_merging_enabled_node_input_id: str
302
- external_id_filters_node_input_id: str
303
- metadata_filters_node_input_id: str
304
-
305
-
306
- class SearchNode(BaseWorkflowNode):
307
- type: Literal[WorkflowNodeType.SEARCH] = WorkflowNodeType.SEARCH
308
- data: SearchNodeData
309
-
310
-
311
- class FinalOutputNodeData(UniversalBaseModel):
312
- label: str
313
- name: str
314
- target_handle_id: str
315
- output_id: str
316
- output_type: VellumVariableType
317
- node_input_id: str
318
-
319
-
320
- class FinalOutputNode(BaseWorkflowNode):
321
- type: Literal[WorkflowNodeType.TERMINAL] = WorkflowNodeType.TERMINAL
322
- data: FinalOutputNodeData
323
-
324
-
325
- WorkflowNode = Union[
326
- EntrypointNode,
327
- PromptNode,
328
- SearchNode,
329
- FinalOutputNode,
330
- ]
331
-
332
-
333
- class WorkflowEdge(UniversalBaseModel):
334
- id: str
335
- source_node_id: str
336
- source_handle_id: str
337
- target_node_id: str
338
- target_handle_id: str
339
-
340
-
341
- class WorkflowRawData(UniversalBaseModel):
342
- nodes: List[WorkflowNode]
343
- edges: List[WorkflowEdge]
344
- display_data: Optional[WorkflowDisplayData] = None
345
-
346
-
347
- class WorkflowVersionExecConfig(UniversalBaseModel):
348
- workflow_raw_data: WorkflowRawData
349
- input_variables: List[VellumVariable]
350
- output_variables: List[VellumVariable]
@@ -429,7 +429,7 @@ class BaseWorkflowDisplay(
429
429
  )
430
430
  subworkflow_display_context = subworkflow_display.get_event_display_context()
431
431
 
432
- node_event_displays[str(node_id)] = NodeEventDisplayContext(
432
+ node_event_displays[node_id] = NodeEventDisplayContext(
433
433
  input_display=input_display,
434
434
  output_display=output_display,
435
435
  port_display=port_display_meta,
@@ -5,9 +5,11 @@ from vellum.workflows.nodes.bases.base import BaseNode
5
5
  from vellum.workflows.nodes.core.inline_subworkflow_node.node import InlineSubworkflowNode
6
6
  from vellum.workflows.nodes.core.retry_node.node import RetryNode
7
7
  from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
8
+ from vellum.workflows.nodes.core.try_node.node import TryNode
8
9
  from vellum.workflows.workflows.base import BaseWorkflow
9
10
  from vellum_ee.workflows.display.nodes import BaseNodeDisplay
10
11
  from vellum_ee.workflows.display.nodes.vellum.retry_node import BaseRetryNodeDisplay
12
+ from vellum_ee.workflows.display.nodes.vellum.try_node import BaseTryNodeDisplay
11
13
  from vellum_ee.workflows.display.vellum import NodeDisplayData, NodeDisplayPosition
12
14
  from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
13
15
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
@@ -112,13 +114,36 @@ def test_get_event_display_context__node_display_filled_without_base_display():
112
114
  display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
113
115
 
114
116
  # THEN the node display should be included
115
- assert str(StartNode.__id__) in display_context.node_displays
116
- node_event_display = display_context.node_displays[str(StartNode.__id__)]
117
+ assert StartNode.__id__ in display_context.node_displays
118
+ node_event_display = display_context.node_displays[StartNode.__id__]
117
119
 
118
120
  # AND so should their output ids
119
121
  assert StartNode.__output_ids__ == node_event_display.output_display
120
122
 
121
123
 
124
+ def test_get_event_display_context__node_display_filled_without_output_display():
125
+ # GIVEN a simple workflow
126
+ class StartNode(BaseNode):
127
+ class Outputs(BaseNode.Outputs):
128
+ foo: str
129
+
130
+ class MyWorkflow(BaseWorkflow):
131
+ graph = StartNode
132
+
133
+ class StartNodeDisplay(BaseNodeDisplay[StartNode]):
134
+ pass
135
+
136
+ # WHEN we gather the event display context
137
+ display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
138
+
139
+ # THEN the node display should be included
140
+ assert StartNode.__id__ in display_context.node_displays
141
+ node_event_display = display_context.node_displays[StartNode.__id__]
142
+
143
+ # AND so should their output ids
144
+ assert node_event_display.output_display.keys() == {"foo"}
145
+
146
+
122
147
  def test_get_event_display_context__node_display_to_include_subworkflow_display():
123
148
  # GIVEN a simple workflow
124
149
  class InnerNode(BaseNode):
@@ -138,26 +163,40 @@ def test_get_event_display_context__node_display_to_include_subworkflow_display(
138
163
  display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
139
164
 
140
165
  # THEN the subworkflow display should be included
141
- assert str(SubworkflowNode.__id__) in display_context.node_displays
142
- node_event_display = display_context.node_displays[str(SubworkflowNode.__id__)]
166
+ assert SubworkflowNode.__id__ in display_context.node_displays
167
+ node_event_display = display_context.node_displays[SubworkflowNode.__id__]
143
168
 
144
169
  assert node_event_display.subworkflow_display is not None
145
- assert str(InnerNode.__id__) in node_event_display.subworkflow_display.node_displays
146
-
147
-
148
- def test_get_event_display_context__node_display_for_adornment_nodes():
149
- # GIVEN a simple workflow with a retry node adornment
150
- @RetryNode.wrap(max_attempts=4)
170
+ assert InnerNode.__id__ in node_event_display.subworkflow_display.node_displays
171
+
172
+
173
+ @pytest.mark.parametrize(
174
+ ["AdornmentNode", "AdornmentNodeDisplay", "expected_adornment_output_names"],
175
+ [
176
+ [RetryNode, BaseRetryNodeDisplay, {"foo"}],
177
+ [TryNode, BaseTryNodeDisplay, {"foo", "error"}],
178
+ ],
179
+ ids=["retry_node", "try_node"],
180
+ )
181
+ def test_get_event_display_context__node_display_for_adornment_nodes(
182
+ AdornmentNode,
183
+ AdornmentNodeDisplay,
184
+ expected_adornment_output_names,
185
+ ):
186
+ # GIVEN a simple workflow with an adornment
187
+ @AdornmentNode.wrap()
151
188
  class MyNode(BaseNode):
152
- pass
189
+ class Outputs(BaseNode.Outputs):
190
+ foo: str
153
191
 
154
192
  class MyWorkflow(BaseWorkflow):
155
193
  graph = MyNode
156
194
 
157
195
  # AND a display class for the node
196
+ adornment_node_id = uuid4()
158
197
  inner_node_id = uuid4()
159
198
 
160
- @BaseRetryNodeDisplay.wrap()
199
+ @AdornmentNodeDisplay.wrap(node_id=adornment_node_id)
161
200
  class MyNodeDisplay(BaseNodeDisplay[MyNode]):
162
201
  node_id = inner_node_id
163
202
 
@@ -165,10 +204,15 @@ def test_get_event_display_context__node_display_for_adornment_nodes():
165
204
  display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
166
205
 
167
206
  # THEN the subworkflow display should be included
168
- assert str(MyNode.__id__) in display_context.node_displays
169
- node_event_display = display_context.node_displays[str(MyNode.__id__)]
207
+ assert adornment_node_id in display_context.node_displays
208
+ node_event_display = display_context.node_displays[adornment_node_id]
170
209
  assert node_event_display.subworkflow_display is not None
171
- assert str(inner_node_id) in node_event_display.subworkflow_display.node_displays
210
+ assert inner_node_id in node_event_display.subworkflow_display.node_displays
211
+
212
+ # AND the inner node should have the correct outputs
213
+ inner_node_display = node_event_display.subworkflow_display.node_displays[inner_node_id]
214
+ assert inner_node_display.output_display.keys() == {"foo"}
215
+ assert node_event_display.output_display.keys() == expected_adornment_output_names
172
216
 
173
217
 
174
218
  def test_get_event_display_context__templating_node_input_display():
@@ -187,7 +231,7 @@ def test_get_event_display_context__templating_node_input_display():
187
231
  display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
188
232
 
189
233
  # THEN the subworkflow display should be included
190
- assert str(MyNode.__id__) in display_context.node_displays
191
- node_event_display = display_context.node_displays[str(MyNode.__id__)]
234
+ assert MyNode.__id__ in display_context.node_displays
235
+ node_event_display = display_context.node_displays[MyNode.__id__]
192
236
 
193
237
  assert node_event_display.input_display.keys() == {"inputs.foo"}
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
  import os
3
3
  import sys
4
- from uuid import UUID, uuid4
4
+ from uuid import uuid4
5
5
 
6
6
  from vellum.workflows import BaseWorkflow
7
7
  from vellum_ee.workflows.display.workflows import BaseWorkflowDisplay
@@ -35,22 +35,22 @@ def test_base_class_dynamic_import(files):
35
35
  "node_displays": {
36
36
  "533c6bd8-6088-4abc-a168-8c1758abcd33": {
37
37
  "input_display": {
38
- "example_var_1": UUID("a0d1d7cf-242a-4bd9-a437-d308a7ced9b3"),
39
- "template": UUID("f97d721a-e685-498e-90c3-9c3d9358fdad"),
38
+ "example_var_1": "a0d1d7cf-242a-4bd9-a437-d308a7ced9b3",
39
+ "template": "f97d721a-e685-498e-90c3-9c3d9358fdad",
40
40
  },
41
- "output_display": {"result": UUID("423bc529-1a1a-4f72-af4d-cbdb5f0a5929")},
42
- "port_display": {"default": UUID("afda9a19-0618-42e1-9b63-5d0db2a88f62")},
41
+ "output_display": {"result": "423bc529-1a1a-4f72-af4d-cbdb5f0a5929"},
42
+ "port_display": {"default": "afda9a19-0618-42e1-9b63-5d0db2a88f62"},
43
43
  "subworkflow_display": None,
44
44
  },
45
45
  "f3ef4b2b-fec9-4026-9cc6-e5eac295307f": {
46
- "input_display": {"node_input": UUID("fe6cba85-2423-4b5e-8f85-06311a8be5fb")},
47
- "output_display": {"value": UUID("5469b810-6ea6-4362-9e79-e360d44a1405")},
46
+ "input_display": {"node_input": "fe6cba85-2423-4b5e-8f85-06311a8be5fb"},
47
+ "output_display": {"value": "5469b810-6ea6-4362-9e79-e360d44a1405"},
48
48
  "port_display": {},
49
49
  "subworkflow_display": None,
50
50
  },
51
51
  },
52
- "workflow_inputs": {"input_value": UUID("2268a996-bd17-4832-b3ff-f5662d54b306")},
53
- "workflow_outputs": {"final_output": UUID("5469b810-6ea6-4362-9e79-e360d44a1405")},
52
+ "workflow_inputs": {"input_value": "2268a996-bd17-4832-b3ff-f5662d54b306"},
53
+ "workflow_outputs": {"final_output": "5469b810-6ea6-4362-9e79-e360d44a1405"},
54
54
  }
55
55
  assert display_meta
56
- assert display_meta.dict() == expected_result
56
+ assert display_meta.model_dump(mode="json") == expected_result