vellum-ai 0.14.71__py3-none-any.whl → 0.14.73__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/__init__.py +8 -0
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/core/serialization.py +1 -0
- vellum/client/types/__init__.py +8 -0
- vellum/client/types/build_status_enum.py +5 -0
- vellum/client/types/container_image_build_config.py +20 -0
- vellum/client/types/container_image_read.py +4 -0
- vellum/client/types/execute_api_response.py +2 -2
- vellum/client/types/folder_entity.py +2 -0
- vellum/client/types/folder_entity_dataset.py +26 -0
- vellum/client/types/folder_entity_dataset_data.py +25 -0
- vellum/plugins/vellum_mypy.py +1 -1
- vellum/types/build_status_enum.py +3 -0
- vellum/types/container_image_build_config.py +3 -0
- vellum/types/folder_entity_dataset.py +3 -0
- vellum/types/folder_entity_dataset_data.py +3 -0
- vellum/workflows/events/__init__.py +2 -0
- vellum/workflows/events/stream.py +28 -0
- vellum/workflows/events/workflow.py +3 -2
- vellum/workflows/nodes/core/retry_node/tests/test_node.py +1 -1
- vellum/workflows/nodes/displayable/api_node/node.py +2 -0
- vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +43 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +6 -0
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +30 -4
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py +43 -3
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +68 -58
- vellum/workflows/nodes/experimental/tool_calling_node/node.py +11 -11
- vellum/workflows/nodes/experimental/tool_calling_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/experimental/tool_calling_node/tests/test_utils.py +49 -0
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py +69 -8
- vellum/workflows/ports/utils.py +26 -6
- vellum/workflows/runner/runner.py +56 -6
- vellum/workflows/types/core.py +12 -0
- vellum/workflows/types/definition.py +6 -0
- vellum/workflows/utils/functions.py +64 -10
- vellum/workflows/utils/pydantic_schema.py +38 -0
- vellum/workflows/utils/tests/test_functions.py +161 -11
- vellum/workflows/utils/tests/test_vellum_variables.py +25 -1
- vellum/workflows/utils/vellum_variables.py +30 -0
- vellum/workflows/workflows/base.py +11 -5
- {vellum_ai-0.14.71.dist-info → vellum_ai-0.14.73.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.71.dist-info → vellum_ai-0.14.73.dist-info}/RECORD +77 -64
- vellum_cli/image_push.py +1 -5
- vellum_cli/push.py +12 -7
- vellum_cli/tests/test_image_push.py +1 -2
- vellum_cli/tests/test_push.py +33 -2
- vellum_ee/workflows/display/nodes/utils.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +8 -1
- vellum_ee/workflows/display/tests/test_base_workflow_display.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +5 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +12 -12
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +10 -10
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +20 -9
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +8 -8
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +6 -6
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +8 -8
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +4 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +2 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +5 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +2 -2
- vellum_ee/workflows/display/utils/auto_layout.py +1 -1
- vellum_ee/workflows/display/workflows/base_workflow_display.py +179 -4
- vellum_ee/workflows/tests/test_serialize_module.py +47 -0
- {vellum_ai-0.14.71.dist-info → vellum_ai-0.14.73.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.71.dist-info → vellum_ai-0.14.73.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.71.dist-info → vellum_ai-0.14.73.dist-info}/entry_points.txt +0 -0
@@ -1,12 +1,14 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import inspect
|
3
|
-
from typing import TYPE_CHECKING, Any, Callable, Optional, Type, Union, get_args, get_origin
|
3
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Type, Union, get_args, get_origin
|
4
4
|
|
5
5
|
from pydantic import BaseModel
|
6
6
|
from pydantic_core import PydanticUndefined
|
7
7
|
from pydash import snake_case
|
8
8
|
|
9
|
+
from vellum import Vellum
|
9
10
|
from vellum.client.types.function_definition import FunctionDefinition
|
11
|
+
from vellum.workflows.utils.vellum_variables import vellum_variable_type_to_openapi_type
|
10
12
|
|
11
13
|
if TYPE_CHECKING:
|
12
14
|
from vellum.workflows.workflows.base import BaseWorkflow
|
@@ -24,27 +26,27 @@ type_map = {
|
|
24
26
|
}
|
25
27
|
|
26
28
|
|
27
|
-
def
|
29
|
+
def compile_annotation(annotation: Optional[Any], defs: dict[str, Any]) -> dict:
|
28
30
|
if annotation is None:
|
29
31
|
return {"type": "null"}
|
30
32
|
|
31
33
|
if get_origin(annotation) is Union:
|
32
|
-
return {"anyOf": [
|
34
|
+
return {"anyOf": [compile_annotation(a, defs) for a in get_args(annotation)]}
|
33
35
|
|
34
36
|
if get_origin(annotation) is dict:
|
35
37
|
_, value_type = get_args(annotation)
|
36
|
-
return {"type": "object", "additionalProperties":
|
38
|
+
return {"type": "object", "additionalProperties": compile_annotation(value_type, defs)}
|
37
39
|
|
38
40
|
if get_origin(annotation) is list:
|
39
41
|
item_type = get_args(annotation)[0]
|
40
|
-
return {"type": "array", "items":
|
42
|
+
return {"type": "array", "items": compile_annotation(item_type, defs)}
|
41
43
|
|
42
44
|
if dataclasses.is_dataclass(annotation):
|
43
45
|
if annotation.__name__ not in defs:
|
44
46
|
properties = {}
|
45
47
|
required = []
|
46
48
|
for field in dataclasses.fields(annotation):
|
47
|
-
properties[field.name] =
|
49
|
+
properties[field.name] = compile_annotation(field.type, defs)
|
48
50
|
if field.default is dataclasses.MISSING:
|
49
51
|
required.append(field.name)
|
50
52
|
else:
|
@@ -59,7 +61,7 @@ def _compile_annotation(annotation: Optional[Any], defs: dict[str, Any]) -> dict
|
|
59
61
|
for field_name, field in annotation.model_fields.items():
|
60
62
|
# Mypy is incorrect here, the `annotation` attribute is defined on `FieldInfo`
|
61
63
|
field_annotation = field.annotation # type: ignore[attr-defined]
|
62
|
-
properties[field_name] =
|
64
|
+
properties[field_name] = compile_annotation(field_annotation, defs)
|
63
65
|
if field.default is PydanticUndefined:
|
64
66
|
required.append(field_name)
|
65
67
|
else:
|
@@ -86,6 +88,19 @@ def _compile_default_value(default: Any) -> Any:
|
|
86
88
|
return default
|
87
89
|
|
88
90
|
|
91
|
+
def _compile_deployment_workflow_input(input_var: Any) -> dict[str, Any]:
|
92
|
+
"""
|
93
|
+
Converts a deployment workflow input variable to a JSON schema type definition.
|
94
|
+
"""
|
95
|
+
primitive_type = vellum_variable_type_to_openapi_type(input_var.type)
|
96
|
+
input_schema = {"type": primitive_type}
|
97
|
+
|
98
|
+
if input_var.default is not None:
|
99
|
+
input_schema["default"] = input_var.default.value
|
100
|
+
|
101
|
+
return input_schema
|
102
|
+
|
103
|
+
|
89
104
|
def compile_function_definition(function: Callable) -> FunctionDefinition:
|
90
105
|
"""
|
91
106
|
Converts a Python function into our Vellum-native FunctionDefinition type.
|
@@ -100,7 +115,7 @@ def compile_function_definition(function: Callable) -> FunctionDefinition:
|
|
100
115
|
required = []
|
101
116
|
defs: dict[str, Any] = {}
|
102
117
|
for param in signature.parameters.values():
|
103
|
-
properties[param.name] =
|
118
|
+
properties[param.name] = compile_annotation(param.annotation, defs)
|
104
119
|
if param.default is inspect.Parameter.empty:
|
105
120
|
required.append(param.name)
|
106
121
|
else:
|
@@ -117,7 +132,7 @@ def compile_function_definition(function: Callable) -> FunctionDefinition:
|
|
117
132
|
)
|
118
133
|
|
119
134
|
|
120
|
-
def
|
135
|
+
def compile_inline_workflow_function_definition(workflow_class: Type["BaseWorkflow"]) -> FunctionDefinition:
|
121
136
|
"""
|
122
137
|
Converts a base workflow class into our Vellum-native FunctionDefinition type.
|
123
138
|
"""
|
@@ -133,7 +148,7 @@ def compile_workflow_function_definition(workflow_class: Type["BaseWorkflow"]) -
|
|
133
148
|
if name.startswith("__"):
|
134
149
|
continue
|
135
150
|
|
136
|
-
properties[name] =
|
151
|
+
properties[name] = compile_annotation(field_type, defs)
|
137
152
|
|
138
153
|
# Check if the field has a default value
|
139
154
|
if name not in vars_inputs_class:
|
@@ -151,3 +166,42 @@ def compile_workflow_function_definition(workflow_class: Type["BaseWorkflow"]) -
|
|
151
166
|
description=workflow_class.__doc__,
|
152
167
|
parameters=parameters,
|
153
168
|
)
|
169
|
+
|
170
|
+
|
171
|
+
def compile_deployment_workflow_function_definition(
|
172
|
+
deployment_config: Dict[str, str],
|
173
|
+
vellum_client: Vellum,
|
174
|
+
) -> FunctionDefinition:
|
175
|
+
"""
|
176
|
+
Converts a deployment workflow config into our Vellum-native FunctionDefinition type.
|
177
|
+
|
178
|
+
Args:
|
179
|
+
deployment_config: Dict with 'deployment' and 'release_tag' keys
|
180
|
+
vellum_client: Vellum client instance
|
181
|
+
"""
|
182
|
+
deployment = deployment_config["deployment"]
|
183
|
+
release_tag = deployment_config["release_tag"]
|
184
|
+
|
185
|
+
workflow_deployment_release = vellum_client.release_reviews.retrieve_workflow_deployment_release(
|
186
|
+
deployment, release_tag
|
187
|
+
)
|
188
|
+
|
189
|
+
input_variables = workflow_deployment_release.workflow_version.input_variables
|
190
|
+
description = workflow_deployment_release.description
|
191
|
+
|
192
|
+
properties = {}
|
193
|
+
required = []
|
194
|
+
|
195
|
+
for input_var in input_variables:
|
196
|
+
properties[input_var.key] = _compile_deployment_workflow_input(input_var)
|
197
|
+
|
198
|
+
if input_var.required and input_var.default is None:
|
199
|
+
required.append(input_var.key)
|
200
|
+
|
201
|
+
parameters = {"type": "object", "properties": properties, "required": required}
|
202
|
+
|
203
|
+
return FunctionDefinition(
|
204
|
+
name=deployment,
|
205
|
+
description=description,
|
206
|
+
parameters=parameters,
|
207
|
+
)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import inspect
|
2
|
+
from typing import Any, Dict
|
3
|
+
|
4
|
+
from pydantic import BaseModel
|
5
|
+
|
6
|
+
from vellum.workflows.utils.functions import compile_annotation
|
7
|
+
|
8
|
+
|
9
|
+
def normalize_json(schema_input: Any) -> Any:
|
10
|
+
"""
|
11
|
+
Recursively normalize JSON data by converting Pydantic models to JSON schema.
|
12
|
+
|
13
|
+
This function processes dictionaries recursively to find and convert any
|
14
|
+
Pydantic model classes or instances to their JSON schema representation.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
schema_input: Can be a Pydantic model class, instance, dict, or any other value
|
18
|
+
|
19
|
+
Returns:
|
20
|
+
Normalized JSON data with Pydantic models converted to JSON schema
|
21
|
+
"""
|
22
|
+
if isinstance(schema_input, dict):
|
23
|
+
return {key: normalize_json(value) for key, value in schema_input.items()}
|
24
|
+
|
25
|
+
if inspect.isclass(schema_input) and issubclass(schema_input, BaseModel):
|
26
|
+
defs: Dict[str, Any] = {}
|
27
|
+
result = compile_annotation(schema_input, defs)
|
28
|
+
|
29
|
+
if "$ref" in result and defs:
|
30
|
+
ref_name = result["$ref"].split("/")[-1]
|
31
|
+
if ref_name in defs:
|
32
|
+
return defs[ref_name]
|
33
|
+
|
34
|
+
return result
|
35
|
+
elif isinstance(schema_input, BaseModel):
|
36
|
+
return {key: normalize_json(getattr(schema_input, key)) for key in schema_input.__class__.model_fields.keys()}
|
37
|
+
else:
|
38
|
+
return schema_input
|
@@ -1,14 +1,21 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
+
from unittest.mock import Mock
|
2
3
|
from typing import Dict, List, Optional, Union
|
3
4
|
|
4
5
|
from pydantic import BaseModel
|
5
6
|
|
6
7
|
from vellum.client.types.function_definition import FunctionDefinition
|
8
|
+
from vellum.client.types.string_vellum_value import StringVellumValue
|
9
|
+
from vellum.client.types.vellum_variable import VellumVariable
|
7
10
|
from vellum.workflows import BaseWorkflow
|
8
11
|
from vellum.workflows.inputs.base import BaseInputs
|
9
12
|
from vellum.workflows.nodes.bases.base import BaseNode
|
10
13
|
from vellum.workflows.state.base import BaseState
|
11
|
-
from vellum.workflows.utils.functions import
|
14
|
+
from vellum.workflows.utils.functions import (
|
15
|
+
compile_deployment_workflow_function_definition,
|
16
|
+
compile_function_definition,
|
17
|
+
compile_inline_workflow_function_definition,
|
18
|
+
)
|
12
19
|
|
13
20
|
|
14
21
|
def test_compile_function_definition__just_name():
|
@@ -299,7 +306,7 @@ def test_compile_function_definition__lambda():
|
|
299
306
|
)
|
300
307
|
|
301
308
|
|
302
|
-
def
|
309
|
+
def test_compile_inline_workflow_function_definition():
|
303
310
|
class MyNode(BaseNode):
|
304
311
|
pass
|
305
312
|
|
@@ -307,7 +314,7 @@ def test_compile_workflow_function_definition():
|
|
307
314
|
graph = MyNode
|
308
315
|
|
309
316
|
# WHEN compiling the function
|
310
|
-
compiled_function =
|
317
|
+
compiled_function = compile_inline_workflow_function_definition(MyWorkflow)
|
311
318
|
|
312
319
|
# THEN it should return the compiled function definition
|
313
320
|
assert compiled_function == FunctionDefinition(
|
@@ -316,7 +323,7 @@ def test_compile_workflow_function_definition():
|
|
316
323
|
)
|
317
324
|
|
318
325
|
|
319
|
-
def
|
326
|
+
def test_compile_inline_workflow_function_definition__docstring():
|
320
327
|
class MyNode(BaseNode):
|
321
328
|
pass
|
322
329
|
|
@@ -328,7 +335,7 @@ def test_compile_workflow_function_definition__docstring():
|
|
328
335
|
graph = MyNode
|
329
336
|
|
330
337
|
# WHEN compiling the function
|
331
|
-
compiled_function =
|
338
|
+
compiled_function = compile_inline_workflow_function_definition(MyWorkflow)
|
332
339
|
|
333
340
|
# THEN it should return the compiled function definition
|
334
341
|
assert compiled_function == FunctionDefinition(
|
@@ -338,7 +345,7 @@ def test_compile_workflow_function_definition__docstring():
|
|
338
345
|
)
|
339
346
|
|
340
347
|
|
341
|
-
def
|
348
|
+
def test_compile_inline_workflow_function_definition__all_args():
|
342
349
|
class MyInputs(BaseInputs):
|
343
350
|
a: str
|
344
351
|
b: int
|
@@ -354,7 +361,7 @@ def test_compile_workflow_function_definition__all_args():
|
|
354
361
|
graph = MyNode
|
355
362
|
|
356
363
|
# WHEN compiling the workflow
|
357
|
-
compiled_function =
|
364
|
+
compiled_function = compile_inline_workflow_function_definition(MyWorkflow)
|
358
365
|
|
359
366
|
# THEN it should return the compiled function definition
|
360
367
|
assert compiled_function == FunctionDefinition(
|
@@ -374,7 +381,7 @@ def test_compile_workflow_function_definition__all_args():
|
|
374
381
|
)
|
375
382
|
|
376
383
|
|
377
|
-
def
|
384
|
+
def test_compile_inline_workflow_function_definition__unions():
|
378
385
|
# GIVEN a workflow with a union
|
379
386
|
class MyInputs(BaseInputs):
|
380
387
|
a: Union[str, int]
|
@@ -386,7 +393,7 @@ def test_compile_workflow_function_definition__unions():
|
|
386
393
|
graph = MyNode
|
387
394
|
|
388
395
|
# WHEN compiling the workflow
|
389
|
-
compiled_function =
|
396
|
+
compiled_function = compile_inline_workflow_function_definition(MyWorkflow)
|
390
397
|
|
391
398
|
# THEN it should return the compiled function definition
|
392
399
|
assert compiled_function == FunctionDefinition(
|
@@ -399,7 +406,7 @@ def test_compile_workflow_function_definition__unions():
|
|
399
406
|
)
|
400
407
|
|
401
408
|
|
402
|
-
def
|
409
|
+
def test_compile_inline_workflow_function_definition__optionals():
|
403
410
|
class MyInputs(BaseInputs):
|
404
411
|
a: str
|
405
412
|
b: Optional[str]
|
@@ -414,7 +421,7 @@ def test_compile_workflow_function_definition__optionals():
|
|
414
421
|
graph = MyNode
|
415
422
|
|
416
423
|
# WHEN compiling the workflow
|
417
|
-
compiled_function =
|
424
|
+
compiled_function = compile_inline_workflow_function_definition(MyWorkflow)
|
418
425
|
|
419
426
|
# THEN it should return the compiled function definition
|
420
427
|
assert compiled_function == FunctionDefinition(
|
@@ -431,3 +438,146 @@ def test_compile_workflow_function_definition__optionals():
|
|
431
438
|
"required": ["a", "b", "c"],
|
432
439
|
},
|
433
440
|
)
|
441
|
+
|
442
|
+
|
443
|
+
def test_compile_deployment_workflow_function_definition__just_name():
|
444
|
+
# GIVEN a mock Vellum client and deployment
|
445
|
+
mock_client = Mock()
|
446
|
+
mock_release = Mock()
|
447
|
+
mock_release.workflow_version.input_variables = []
|
448
|
+
mock_release.description = "This is a test deployment"
|
449
|
+
mock_client.release_reviews.retrieve_workflow_deployment_release.return_value = mock_release
|
450
|
+
|
451
|
+
deployment_config = {"deployment": "my_deployment", "release_tag": "latest"}
|
452
|
+
|
453
|
+
# WHEN compiling the deployment workflow function
|
454
|
+
compiled_function = compile_deployment_workflow_function_definition(deployment_config, mock_client)
|
455
|
+
|
456
|
+
# THEN it should return the compiled function definition (same structure as function test)
|
457
|
+
assert compiled_function == FunctionDefinition(
|
458
|
+
name="my_deployment",
|
459
|
+
description="This is a test deployment",
|
460
|
+
parameters={"type": "object", "properties": {}, "required": []},
|
461
|
+
)
|
462
|
+
|
463
|
+
|
464
|
+
def test_compile_deployment_workflow_function_definition__all_args():
|
465
|
+
# GIVEN a mock Vellum client and deployment
|
466
|
+
mock_client = Mock()
|
467
|
+
mock_release = Mock()
|
468
|
+
|
469
|
+
mock_inputs = []
|
470
|
+
for key, vellum_type in [
|
471
|
+
("a", "STRING"),
|
472
|
+
("b", "NUMBER"),
|
473
|
+
("c", "JSON"),
|
474
|
+
("d", "CHAT_HISTORY"),
|
475
|
+
("e", "SEARCH_RESULTS"),
|
476
|
+
("f", "ERROR"),
|
477
|
+
("g", "ARRAY"),
|
478
|
+
("h", "FUNCTION_CALL"),
|
479
|
+
("i", "IMAGE"),
|
480
|
+
("j", "AUDIO"),
|
481
|
+
("k", "DOCUMENT"),
|
482
|
+
("l", "NULL"),
|
483
|
+
]:
|
484
|
+
mock_input = VellumVariable(
|
485
|
+
id=f"input_{key}",
|
486
|
+
key=key,
|
487
|
+
type=vellum_type,
|
488
|
+
required=True,
|
489
|
+
default=None,
|
490
|
+
)
|
491
|
+
mock_inputs.append(mock_input)
|
492
|
+
|
493
|
+
mock_release.workflow_version.input_variables = mock_inputs
|
494
|
+
mock_release.description = "This is a test deployment"
|
495
|
+
mock_client.release_reviews.retrieve_workflow_deployment_release.return_value = mock_release
|
496
|
+
|
497
|
+
deployment_config = {"deployment": "my_deployment", "release_tag": "latest"}
|
498
|
+
|
499
|
+
# WHEN compiling the deployment workflow function
|
500
|
+
compiled_function = compile_deployment_workflow_function_definition(deployment_config, mock_client)
|
501
|
+
|
502
|
+
# THEN it should return the compiled function definition
|
503
|
+
assert compiled_function == FunctionDefinition(
|
504
|
+
name="my_deployment",
|
505
|
+
description="This is a test deployment",
|
506
|
+
parameters={
|
507
|
+
"type": "object",
|
508
|
+
"properties": {
|
509
|
+
"a": {"type": "string"},
|
510
|
+
"b": {"type": "number"},
|
511
|
+
"c": {"type": "object"},
|
512
|
+
"d": {"type": "array"},
|
513
|
+
"e": {"type": "array"},
|
514
|
+
"f": {"type": "object"},
|
515
|
+
"g": {"type": "array"},
|
516
|
+
"h": {"type": "object"},
|
517
|
+
"i": {"type": "object"},
|
518
|
+
"j": {"type": "object"},
|
519
|
+
"k": {"type": "object"},
|
520
|
+
"l": {"type": "null"},
|
521
|
+
},
|
522
|
+
"required": ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"],
|
523
|
+
},
|
524
|
+
)
|
525
|
+
|
526
|
+
|
527
|
+
def test_compile_deployment_workflow_function_definition__defaults():
|
528
|
+
# GIVEN a mock Vellum client and deployment
|
529
|
+
mock_client = Mock()
|
530
|
+
mock_release = Mock()
|
531
|
+
|
532
|
+
mock_inputs = []
|
533
|
+
|
534
|
+
mock_input_no_default = VellumVariable(
|
535
|
+
id="no_default",
|
536
|
+
key="no_default",
|
537
|
+
type="STRING",
|
538
|
+
required=True,
|
539
|
+
default=None,
|
540
|
+
)
|
541
|
+
mock_inputs.append(mock_input_no_default)
|
542
|
+
|
543
|
+
mock_input_null_default = VellumVariable(
|
544
|
+
id="null_default",
|
545
|
+
key="null_default",
|
546
|
+
type="STRING",
|
547
|
+
required=False,
|
548
|
+
default=StringVellumValue(value=None),
|
549
|
+
)
|
550
|
+
mock_inputs.append(mock_input_null_default)
|
551
|
+
|
552
|
+
mock_input_actual_default = VellumVariable(
|
553
|
+
id="actual_default",
|
554
|
+
key="actual_default",
|
555
|
+
type="STRING",
|
556
|
+
required=False,
|
557
|
+
default=StringVellumValue(value="hello world"),
|
558
|
+
)
|
559
|
+
mock_inputs.append(mock_input_actual_default)
|
560
|
+
|
561
|
+
mock_release.workflow_version.input_variables = mock_inputs
|
562
|
+
mock_release.description = "This is a test deployment"
|
563
|
+
mock_client.release_reviews.retrieve_workflow_deployment_release.return_value = mock_release
|
564
|
+
|
565
|
+
deployment_config = {"deployment": "my_deployment", "release_tag": "latest"}
|
566
|
+
|
567
|
+
# WHEN compiling the deployment workflow function
|
568
|
+
compiled_function = compile_deployment_workflow_function_definition(deployment_config, mock_client)
|
569
|
+
|
570
|
+
# THEN it should return the compiled function definition with proper default handling
|
571
|
+
assert compiled_function == FunctionDefinition(
|
572
|
+
name="my_deployment",
|
573
|
+
description="This is a test deployment",
|
574
|
+
parameters={
|
575
|
+
"type": "object",
|
576
|
+
"properties": {
|
577
|
+
"no_default": {"type": "string"},
|
578
|
+
"null_default": {"type": "string", "default": None},
|
579
|
+
"actual_default": {"type": "string", "default": "hello world"},
|
580
|
+
},
|
581
|
+
"required": ["no_default"],
|
582
|
+
},
|
583
|
+
)
|
@@ -3,7 +3,10 @@ from typing import List, Optional
|
|
3
3
|
|
4
4
|
from vellum import ChatMessage, SearchResult, VellumAudio, VellumDocument, VellumImage
|
5
5
|
from vellum.workflows.types.core import Json
|
6
|
-
from vellum.workflows.utils.vellum_variables import
|
6
|
+
from vellum.workflows.utils.vellum_variables import (
|
7
|
+
primitive_type_to_vellum_variable_type,
|
8
|
+
vellum_variable_type_to_openapi_type,
|
9
|
+
)
|
7
10
|
|
8
11
|
|
9
12
|
@pytest.mark.parametrize(
|
@@ -31,3 +34,24 @@ from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_var
|
|
31
34
|
)
|
32
35
|
def test_primitive_type_to_vellum_variable_type(type_, expected):
|
33
36
|
assert primitive_type_to_vellum_variable_type(type_) == expected
|
37
|
+
|
38
|
+
|
39
|
+
@pytest.mark.parametrize(
|
40
|
+
"vellum_type, expected",
|
41
|
+
[
|
42
|
+
("STRING", "string"),
|
43
|
+
("NUMBER", "number"),
|
44
|
+
("JSON", "object"),
|
45
|
+
("CHAT_HISTORY", "array"),
|
46
|
+
("SEARCH_RESULTS", "array"),
|
47
|
+
("ERROR", "object"),
|
48
|
+
("ARRAY", "array"),
|
49
|
+
("FUNCTION_CALL", "object"),
|
50
|
+
("IMAGE", "object"),
|
51
|
+
("AUDIO", "object"),
|
52
|
+
("DOCUMENT", "object"),
|
53
|
+
("NULL", "null"),
|
54
|
+
],
|
55
|
+
)
|
56
|
+
def test_vellum_variable_type_to_openapi_type(vellum_type, expected):
|
57
|
+
assert vellum_variable_type_to_openapi_type(vellum_type) == expected
|
@@ -78,6 +78,36 @@ def primitive_type_to_vellum_variable_type(type_: Union[Type, BaseDescriptor]) -
|
|
78
78
|
return "JSON"
|
79
79
|
|
80
80
|
|
81
|
+
def vellum_variable_type_to_openapi_type(vellum_type: VellumVariableType) -> str:
|
82
|
+
"""Converts a VellumVariableType to a JSON schema primitive type string"""
|
83
|
+
if vellum_type == "STRING":
|
84
|
+
return "string"
|
85
|
+
elif vellum_type == "NUMBER":
|
86
|
+
return "number"
|
87
|
+
elif vellum_type == "JSON":
|
88
|
+
return "object"
|
89
|
+
elif vellum_type == "CHAT_HISTORY":
|
90
|
+
return "array"
|
91
|
+
elif vellum_type == "SEARCH_RESULTS":
|
92
|
+
return "array"
|
93
|
+
elif vellum_type == "ERROR":
|
94
|
+
return "object"
|
95
|
+
elif vellum_type == "ARRAY":
|
96
|
+
return "array"
|
97
|
+
elif vellum_type == "FUNCTION_CALL":
|
98
|
+
return "object"
|
99
|
+
elif vellum_type == "IMAGE":
|
100
|
+
return "object"
|
101
|
+
elif vellum_type == "AUDIO":
|
102
|
+
return "object"
|
103
|
+
elif vellum_type == "DOCUMENT":
|
104
|
+
return "object"
|
105
|
+
elif vellum_type == "NULL":
|
106
|
+
return "null"
|
107
|
+
else:
|
108
|
+
return "object"
|
109
|
+
|
110
|
+
|
81
111
|
def _is_type_optionally_equal(type_: Type, target_type: Type) -> bool:
|
82
112
|
if type_ == target_type:
|
83
113
|
return True
|
@@ -42,6 +42,7 @@ from vellum.workflows.events.node import (
|
|
42
42
|
NodeExecutionStreamingBody,
|
43
43
|
NodeExecutionStreamingEvent,
|
44
44
|
)
|
45
|
+
from vellum.workflows.events.stream import WorkflowEventGenerator
|
45
46
|
from vellum.workflows.events.workflow import (
|
46
47
|
GenericWorkflowEvent,
|
47
48
|
WorkflowExecutionFulfilledBody,
|
@@ -167,7 +168,7 @@ class BaseWorkflow(Generic[InputsType, StateType], metaclass=_BaseWorkflowMeta):
|
|
167
168
|
WorkflowExecutionPausedEvent,
|
168
169
|
]
|
169
170
|
|
170
|
-
WorkflowEventStream =
|
171
|
+
WorkflowEventStream = WorkflowEventGenerator[WorkflowEvent]
|
171
172
|
|
172
173
|
def __init__(
|
173
174
|
self,
|
@@ -444,7 +445,7 @@ class BaseWorkflow(Generic[InputsType, StateType], metaclass=_BaseWorkflowMeta):
|
|
444
445
|
"""
|
445
446
|
|
446
447
|
should_yield = event_filter or workflow_event_filter
|
447
|
-
|
448
|
+
runner_stream = WorkflowRunner(
|
448
449
|
self,
|
449
450
|
inputs=inputs,
|
450
451
|
state=state,
|
@@ -454,9 +455,14 @@ class BaseWorkflow(Generic[InputsType, StateType], metaclass=_BaseWorkflowMeta):
|
|
454
455
|
node_output_mocks=node_output_mocks,
|
455
456
|
max_concurrency=max_concurrency,
|
456
457
|
init_execution_context=self._execution_context,
|
457
|
-
).stream()
|
458
|
-
|
459
|
-
|
458
|
+
).stream()
|
459
|
+
|
460
|
+
def _generate_filtered_events() -> Generator[BaseWorkflow.WorkflowEvent, None, None]:
|
461
|
+
for event in runner_stream:
|
462
|
+
if should_yield(self.__class__, event):
|
463
|
+
yield event
|
464
|
+
|
465
|
+
return WorkflowEventGenerator(_generate_filtered_events(), runner_stream.span_id)
|
460
466
|
|
461
467
|
def validate(self) -> None:
|
462
468
|
"""
|