vellum-ai 0.12.8__py3-none-any.whl → 0.12.11__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 (49) hide show
  1. vellum/__init__.py +2 -2
  2. vellum/client/__init__.py +14 -4
  3. vellum/client/core/client_wrapper.py +1 -1
  4. vellum/client/types/__init__.py +2 -2
  5. vellum/client/types/function_call.py +0 -2
  6. vellum/client/types/function_call_request.py +0 -2
  7. vellum/client/types/metric_definition_execution.py +6 -0
  8. vellum/client/types/test_suite_run_execution_metric_result.py +6 -0
  9. vellum/client/types/test_suite_run_metric_array_output.py +32 -0
  10. vellum/client/types/test_suite_run_metric_output.py +2 -0
  11. vellum/evaluations/resources.py +1 -1
  12. vellum/prompts/blocks/compilation.py +4 -4
  13. vellum/types/{fulfilled_enum.py → test_suite_run_metric_array_output.py} +1 -1
  14. vellum/workflows/nodes/bases/__init__.py +0 -2
  15. vellum/workflows/nodes/bases/base.py +2 -6
  16. vellum/workflows/nodes/core/inline_subworkflow_node/node.py +13 -7
  17. vellum/workflows/nodes/core/inline_subworkflow_node/tests/__init__.py +0 -0
  18. vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py +41 -0
  19. vellum/workflows/nodes/core/map_node/node.py +1 -1
  20. vellum/workflows/nodes/core/templating_node/node.py +8 -1
  21. vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +66 -0
  22. vellum/workflows/nodes/core/try_node/node.py +1 -3
  23. vellum/workflows/nodes/core/try_node/tests/test_node.py +1 -1
  24. vellum/workflows/nodes/displayable/bases/api_node/node.py +2 -2
  25. vellum/workflows/nodes/displayable/bases/search_node.py +1 -2
  26. vellum/workflows/nodes/displayable/inline_prompt_node/node.py +17 -10
  27. vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +13 -3
  28. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +4 -2
  29. vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py +1 -2
  30. vellum/workflows/sandbox.py +4 -5
  31. vellum/workflows/state/context.py +5 -4
  32. vellum/workflows/state/encoder.py +4 -0
  33. vellum/workflows/state/tests/test_state.py +19 -0
  34. vellum/workflows/tests/test_sandbox.py +2 -2
  35. vellum/workflows/utils/tests/test_vellum_variables.py +3 -0
  36. vellum/workflows/utils/vellum_variables.py +5 -4
  37. vellum/workflows/workflows/base.py +5 -2
  38. {vellum_ai-0.12.8.dist-info → vellum_ai-0.12.11.dist-info}/METADATA +1 -1
  39. {vellum_ai-0.12.8.dist-info → vellum_ai-0.12.11.dist-info}/RECORD +46 -45
  40. vellum_cli/tests/test_push.py +1 -1
  41. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +6 -1
  42. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +207 -0
  43. vellum/client/types/fulfilled_enum.py +0 -5
  44. vellum/workflows/nodes/bases/base_subworkflow_node/__init__.py +0 -5
  45. vellum/workflows/nodes/bases/base_subworkflow_node/node.py +0 -10
  46. /vellum/{evaluations/utils → utils}/uuid.py +0 -0
  47. {vellum_ai-0.12.8.dist-info → vellum_ai-0.12.11.dist-info}/LICENSE +0 -0
  48. {vellum_ai-0.12.8.dist-info → vellum_ai-0.12.11.dist-info}/WHEEL +0 -0
  49. {vellum_ai-0.12.8.dist-info → vellum_ai-0.12.11.dist-info}/entry_points.txt +0 -0
vellum/__init__.py CHANGED
@@ -120,7 +120,6 @@ from .types import (
120
120
  FolderEntityWorkflowSandbox,
121
121
  FolderEntityWorkflowSandboxData,
122
122
  FulfilledAdHocExecutePromptEvent,
123
- FulfilledEnum,
124
123
  FulfilledExecutePromptEvent,
125
124
  FulfilledExecutePromptResponse,
126
125
  FulfilledExecuteWorkflowWorkflowResultEvent,
@@ -389,6 +388,7 @@ from .types import (
389
388
  TestSuiteRunExternalExecConfigData,
390
389
  TestSuiteRunExternalExecConfigDataRequest,
391
390
  TestSuiteRunExternalExecConfigRequest,
391
+ TestSuiteRunMetricArrayOutput,
392
392
  TestSuiteRunMetricErrorOutput,
393
393
  TestSuiteRunMetricJsonOutput,
394
394
  TestSuiteRunMetricNumberOutput,
@@ -649,7 +649,6 @@ __all__ = [
649
649
  "FolderEntityWorkflowSandboxData",
650
650
  "ForbiddenError",
651
651
  "FulfilledAdHocExecutePromptEvent",
652
- "FulfilledEnum",
653
652
  "FulfilledExecutePromptEvent",
654
653
  "FulfilledExecutePromptResponse",
655
654
  "FulfilledExecuteWorkflowWorkflowResultEvent",
@@ -922,6 +921,7 @@ __all__ = [
922
921
  "TestSuiteRunExternalExecConfigData",
923
922
  "TestSuiteRunExternalExecConfigDataRequest",
924
923
  "TestSuiteRunExternalExecConfigRequest",
924
+ "TestSuiteRunMetricArrayOutput",
925
925
  "TestSuiteRunMetricErrorOutput",
926
926
  "TestSuiteRunMetricJsonOutput",
927
927
  "TestSuiteRunMetricNumberOutput",
vellum/client/__init__.py CHANGED
@@ -1079,6 +1079,7 @@ class Vellum:
1079
1079
  index_id: typing.Optional[str] = OMIT,
1080
1080
  index_name: typing.Optional[str] = OMIT,
1081
1081
  options: typing.Optional[SearchRequestOptionsRequest] = OMIT,
1082
+ document_index: typing.Optional[str] = OMIT,
1082
1083
  request_options: typing.Optional[RequestOptions] = None,
1083
1084
  ) -> SearchResponse:
1084
1085
  """
@@ -1090,14 +1091,17 @@ class Vellum:
1090
1091
  The query to search for.
1091
1092
 
1092
1093
  index_id : typing.Optional[str]
1093
- The ID of the index to search against. Must provide either this or index_name.
1094
+ The ID of the index to search against. Must provide either this, index_name or document_index.
1094
1095
 
1095
1096
  index_name : typing.Optional[str]
1096
- The name of the index to search against. Must provide either this or index_id.
1097
+ The name of the index to search against. Must provide either this, index_id or document_index.
1097
1098
 
1098
1099
  options : typing.Optional[SearchRequestOptionsRequest]
1099
1100
  Configuration options for the search.
1100
1101
 
1102
+ document_index : typing.Optional[str]
1103
+ Either the index name or index ID to search against. Must provide either this, index_id or index_name.
1104
+
1101
1105
  request_options : typing.Optional[RequestOptions]
1102
1106
  Request-specific configuration.
1103
1107
 
@@ -1128,6 +1132,7 @@ class Vellum:
1128
1132
  "options": convert_and_respect_annotation_metadata(
1129
1133
  object_=options, annotation=SearchRequestOptionsRequest, direction="write"
1130
1134
  ),
1135
+ "document_index": document_index,
1131
1136
  },
1132
1137
  request_options=request_options,
1133
1138
  omit=OMIT,
@@ -2395,6 +2400,7 @@ class AsyncVellum:
2395
2400
  index_id: typing.Optional[str] = OMIT,
2396
2401
  index_name: typing.Optional[str] = OMIT,
2397
2402
  options: typing.Optional[SearchRequestOptionsRequest] = OMIT,
2403
+ document_index: typing.Optional[str] = OMIT,
2398
2404
  request_options: typing.Optional[RequestOptions] = None,
2399
2405
  ) -> SearchResponse:
2400
2406
  """
@@ -2406,14 +2412,17 @@ class AsyncVellum:
2406
2412
  The query to search for.
2407
2413
 
2408
2414
  index_id : typing.Optional[str]
2409
- The ID of the index to search against. Must provide either this or index_name.
2415
+ The ID of the index to search against. Must provide either this, index_name or document_index.
2410
2416
 
2411
2417
  index_name : typing.Optional[str]
2412
- The name of the index to search against. Must provide either this or index_id.
2418
+ The name of the index to search against. Must provide either this, index_id or document_index.
2413
2419
 
2414
2420
  options : typing.Optional[SearchRequestOptionsRequest]
2415
2421
  Configuration options for the search.
2416
2422
 
2423
+ document_index : typing.Optional[str]
2424
+ Either the index name or index ID to search against. Must provide either this, index_id or index_name.
2425
+
2417
2426
  request_options : typing.Optional[RequestOptions]
2418
2427
  Request-specific configuration.
2419
2428
 
@@ -2452,6 +2461,7 @@ class AsyncVellum:
2452
2461
  "options": convert_and_respect_annotation_metadata(
2453
2462
  object_=options, annotation=SearchRequestOptionsRequest, direction="write"
2454
2463
  ),
2464
+ "document_index": document_index,
2455
2465
  },
2456
2466
  request_options=request_options,
2457
2467
  omit=OMIT,
@@ -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.12.8",
21
+ "X-Fern-SDK-Version": "0.12.11",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -127,7 +127,6 @@ from .folder_entity_test_suite_data import FolderEntityTestSuiteData
127
127
  from .folder_entity_workflow_sandbox import FolderEntityWorkflowSandbox
128
128
  from .folder_entity_workflow_sandbox_data import FolderEntityWorkflowSandboxData
129
129
  from .fulfilled_ad_hoc_execute_prompt_event import FulfilledAdHocExecutePromptEvent
130
- from .fulfilled_enum import FulfilledEnum
131
130
  from .fulfilled_execute_prompt_event import FulfilledExecutePromptEvent
132
131
  from .fulfilled_execute_prompt_response import FulfilledExecutePromptResponse
133
132
  from .fulfilled_execute_workflow_workflow_result_event import FulfilledExecuteWorkflowWorkflowResultEvent
@@ -402,6 +401,7 @@ from .test_suite_run_external_exec_config import TestSuiteRunExternalExecConfig
402
401
  from .test_suite_run_external_exec_config_data import TestSuiteRunExternalExecConfigData
403
402
  from .test_suite_run_external_exec_config_data_request import TestSuiteRunExternalExecConfigDataRequest
404
403
  from .test_suite_run_external_exec_config_request import TestSuiteRunExternalExecConfigRequest
404
+ from .test_suite_run_metric_array_output import TestSuiteRunMetricArrayOutput
405
405
  from .test_suite_run_metric_error_output import TestSuiteRunMetricErrorOutput
406
406
  from .test_suite_run_metric_json_output import TestSuiteRunMetricJsonOutput
407
407
  from .test_suite_run_metric_number_output import TestSuiteRunMetricNumberOutput
@@ -641,7 +641,6 @@ __all__ = [
641
641
  "FolderEntityWorkflowSandbox",
642
642
  "FolderEntityWorkflowSandboxData",
643
643
  "FulfilledAdHocExecutePromptEvent",
644
- "FulfilledEnum",
645
644
  "FulfilledExecutePromptEvent",
646
645
  "FulfilledExecutePromptResponse",
647
646
  "FulfilledExecuteWorkflowWorkflowResultEvent",
@@ -910,6 +909,7 @@ __all__ = [
910
909
  "TestSuiteRunExternalExecConfigData",
911
910
  "TestSuiteRunExternalExecConfigDataRequest",
912
911
  "TestSuiteRunExternalExecConfigRequest",
912
+ "TestSuiteRunMetricArrayOutput",
913
913
  "TestSuiteRunMetricErrorOutput",
914
914
  "TestSuiteRunMetricJsonOutput",
915
915
  "TestSuiteRunMetricNumberOutput",
@@ -2,7 +2,6 @@
2
2
 
3
3
  from ..core.pydantic_utilities import UniversalBaseModel
4
4
  import typing
5
- from .fulfilled_enum import FulfilledEnum
6
5
  from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
6
  import pydantic
8
7
 
@@ -15,7 +14,6 @@ class FunctionCall(UniversalBaseModel):
15
14
  arguments: typing.Dict[str, typing.Optional[typing.Any]]
16
15
  id: typing.Optional[str] = None
17
16
  name: str
18
- state: typing.Optional[FulfilledEnum] = None
19
17
 
20
18
  if IS_PYDANTIC_V2:
21
19
  model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
@@ -2,7 +2,6 @@
2
2
 
3
3
  from ..core.pydantic_utilities import UniversalBaseModel
4
4
  import typing
5
- from .fulfilled_enum import FulfilledEnum
6
5
  from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
6
  import pydantic
8
7
 
@@ -15,7 +14,6 @@ class FunctionCallRequest(UniversalBaseModel):
15
14
  arguments: typing.Dict[str, typing.Optional[typing.Any]]
16
15
  id: typing.Optional[str] = None
17
16
  name: str
18
- state: typing.Optional[FulfilledEnum] = None
19
17
 
20
18
  if IS_PYDANTIC_V2:
21
19
  model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
@@ -1,10 +1,13 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
+ from __future__ import annotations
3
4
  from ..core.pydantic_utilities import UniversalBaseModel
5
+ from .array_vellum_value import ArrayVellumValue
4
6
  import typing
5
7
  from .test_suite_run_metric_output import TestSuiteRunMetricOutput
6
8
  from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
9
  import pydantic
10
+ from ..core.pydantic_utilities import update_forward_refs
8
11
 
9
12
 
10
13
  class MetricDefinitionExecution(UniversalBaseModel):
@@ -18,3 +21,6 @@ class MetricDefinitionExecution(UniversalBaseModel):
18
21
  frozen = True
19
22
  smart_union = True
20
23
  extra = pydantic.Extra.allow
24
+
25
+
26
+ update_forward_refs(ArrayVellumValue, MetricDefinitionExecution=MetricDefinitionExecution)
@@ -1,11 +1,14 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
+ from __future__ import annotations
3
4
  from ..core.pydantic_utilities import UniversalBaseModel
5
+ from .array_vellum_value import ArrayVellumValue
4
6
  import typing
5
7
  from .test_suite_run_metric_output import TestSuiteRunMetricOutput
6
8
  from .test_suite_run_execution_metric_definition import TestSuiteRunExecutionMetricDefinition
7
9
  from ..core.pydantic_utilities import IS_PYDANTIC_V2
8
10
  import pydantic
11
+ from ..core.pydantic_utilities import update_forward_refs
9
12
 
10
13
 
11
14
  class TestSuiteRunExecutionMetricResult(UniversalBaseModel):
@@ -22,3 +25,6 @@ class TestSuiteRunExecutionMetricResult(UniversalBaseModel):
22
25
  frozen = True
23
26
  smart_union = True
24
27
  extra = pydantic.Extra.allow
28
+
29
+
30
+ update_forward_refs(ArrayVellumValue, TestSuiteRunExecutionMetricResult=TestSuiteRunExecutionMetricResult)
@@ -0,0 +1,32 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from __future__ import annotations
4
+ from ..core.pydantic_utilities import UniversalBaseModel
5
+ from .array_vellum_value import ArrayVellumValue
6
+ import typing
7
+ from .vellum_value import VellumValue
8
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
9
+ import pydantic
10
+ from ..core.pydantic_utilities import update_forward_refs
11
+
12
+
13
+ class TestSuiteRunMetricArrayOutput(UniversalBaseModel):
14
+ """
15
+ Output for a test suite run metric that is of type ARRAY
16
+ """
17
+
18
+ value: typing.Optional[typing.List[VellumValue]] = None
19
+ type: typing.Literal["ARRAY"] = "ARRAY"
20
+ name: str
21
+
22
+ if IS_PYDANTIC_V2:
23
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
24
+ else:
25
+
26
+ class Config:
27
+ frozen = True
28
+ smart_union = True
29
+ extra = pydantic.Extra.allow
30
+
31
+
32
+ update_forward_refs(ArrayVellumValue, TestSuiteRunMetricArrayOutput=TestSuiteRunMetricArrayOutput)
@@ -5,10 +5,12 @@ from .test_suite_run_metric_string_output import TestSuiteRunMetricStringOutput
5
5
  from .test_suite_run_metric_number_output import TestSuiteRunMetricNumberOutput
6
6
  from .test_suite_run_metric_json_output import TestSuiteRunMetricJsonOutput
7
7
  from .test_suite_run_metric_error_output import TestSuiteRunMetricErrorOutput
8
+ from .test_suite_run_metric_array_output import TestSuiteRunMetricArrayOutput
8
9
 
9
10
  TestSuiteRunMetricOutput = typing.Union[
10
11
  TestSuiteRunMetricStringOutput,
11
12
  TestSuiteRunMetricNumberOutput,
12
13
  TestSuiteRunMetricJsonOutput,
13
14
  TestSuiteRunMetricErrorOutput,
15
+ TestSuiteRunMetricArrayOutput,
14
16
  ]
@@ -12,7 +12,6 @@ from vellum.evaluations.constants import DEFAULT_MAX_POLLING_DURATION_MS, DEFAUL
12
12
  from vellum.evaluations.exceptions import TestSuiteRunResultsException
13
13
  from vellum.evaluations.utils.env import get_api_key
14
14
  from vellum.evaluations.utils.paginator import PaginatedResults, get_all_results
15
- from vellum.evaluations.utils.uuid import is_valid_uuid
16
15
  from vellum.types import (
17
16
  ExternalTestCaseExecutionRequest,
18
17
  NamedTestCaseVariableValueRequest,
@@ -24,6 +23,7 @@ from vellum.types import (
24
23
  TestSuiteRunState,
25
24
  )
26
25
  from vellum.utils.typing import cast_not_optional
26
+ from vellum.utils.uuid import is_valid_uuid
27
27
 
28
28
  logger = logging.getLogger(__name__)
29
29
 
@@ -104,16 +104,16 @@ def compile_prompt_blocks(
104
104
  chat_message_blocks = _compile_chat_messages_as_prompt_blocks(compiled_input.value)
105
105
  compiled_blocks.extend(chat_message_blocks)
106
106
  else:
107
- raise ValueError(f"Invalid input type for variable block: {compiled_input.type}")
107
+ raise PromptCompilationError(f"Invalid input type for variable block: {compiled_input.type}")
108
108
 
109
109
  elif block.block_type == "RICH_TEXT":
110
110
  value_block = _compile_rich_text_block_as_value_block(block=block, inputs=sanitized_inputs)
111
111
  compiled_blocks.append(value_block)
112
112
 
113
113
  elif block.block_type == "FUNCTION_DEFINITION":
114
- raise ValueError("Function definitions shouldn't go through compilation process")
114
+ raise PromptCompilationError("Function definitions shouldn't go through compilation process")
115
115
  else:
116
- raise ValueError(f"Unknown block_type: {block.block_type}")
116
+ raise PromptCompilationError(f"Unknown block_type: {block.block_type}")
117
117
 
118
118
  return compiled_blocks
119
119
 
@@ -172,7 +172,7 @@ def _compile_rich_text_block_as_value_block(
172
172
  f"Input variable '{child_block.input_variable}' must be of type STRING or JSON"
173
173
  )
174
174
  else:
175
- raise ValueError(f"Invalid child block_type for RICH_TEXT: {child_block.block_type}")
175
+ raise PromptCompilationError(f"Invalid child block_type for RICH_TEXT: {child_block.block_type}")
176
176
 
177
177
  return CompiledValuePromptBlock(content=StringVellumValue(value=value), cache_config=block.cache_config)
178
178
 
@@ -1,3 +1,3 @@
1
1
  # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
2
 
3
- from vellum.client.types.fulfilled_enum import *
3
+ from vellum.client.types.test_suite_run_metric_array_output import *
@@ -1,7 +1,5 @@
1
1
  from .base import BaseNode
2
- from .base_subworkflow_node import BaseSubworkflowNode
3
2
 
4
3
  __all__ = [
5
4
  "BaseNode",
6
- "BaseSubworkflowNode",
7
5
  ]
@@ -344,8 +344,8 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
344
344
  all_inputs = {}
345
345
  for key, value in inputs.items():
346
346
  path_parts = key.split(".")
347
- node_attribute_discriptor = getattr(self.__class__, path_parts[0])
348
- inputs_key = reduce(lambda acc, part: acc[part], path_parts[1:], node_attribute_discriptor)
347
+ node_attribute_descriptor = getattr(self.__class__, path_parts[0])
348
+ inputs_key = reduce(lambda acc, part: acc[part], path_parts[1:], node_attribute_descriptor)
349
349
  all_inputs[inputs_key] = value
350
350
 
351
351
  self._inputs = MappingProxyType(all_inputs)
@@ -355,7 +355,3 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
355
355
 
356
356
  def __repr__(self) -> str:
357
357
  return str(self.__class__)
358
-
359
-
360
- class MyNode2(BaseNode):
361
- pass
@@ -1,12 +1,14 @@
1
- from typing import TYPE_CHECKING, Generic, Iterator, Optional, Set, Type, TypeVar
1
+ from typing import TYPE_CHECKING, ClassVar, Generic, Iterator, Optional, Set, Type, TypeVar, Union
2
2
 
3
3
  from vellum.workflows.context import execution_context, get_parent_context
4
4
  from vellum.workflows.errors.types import WorkflowErrorCode
5
5
  from vellum.workflows.exceptions import NodeException
6
- from vellum.workflows.nodes.bases.base_subworkflow_node import BaseSubworkflowNode
6
+ from vellum.workflows.inputs.base import BaseInputs
7
+ from vellum.workflows.nodes.bases.base import BaseNode
7
8
  from vellum.workflows.outputs.base import BaseOutput, BaseOutputs
8
9
  from vellum.workflows.state.base import BaseState
9
10
  from vellum.workflows.state.context import WorkflowContext
11
+ from vellum.workflows.types.core import EntityInputsInterface
10
12
  from vellum.workflows.types.generics import StateType, WorkflowInputsType
11
13
 
12
14
  if TYPE_CHECKING:
@@ -15,7 +17,7 @@ if TYPE_CHECKING:
15
17
  InnerStateType = TypeVar("InnerStateType", bound=BaseState)
16
18
 
17
19
 
18
- class InlineSubworkflowNode(BaseSubworkflowNode[StateType], Generic[StateType, WorkflowInputsType, InnerStateType]):
20
+ class InlineSubworkflowNode(BaseNode[StateType], Generic[StateType, WorkflowInputsType, InnerStateType]):
19
21
  """
20
22
  Used to execute a Subworkflow defined inline.
21
23
 
@@ -24,14 +26,13 @@ class InlineSubworkflowNode(BaseSubworkflowNode[StateType], Generic[StateType, W
24
26
  """
25
27
 
26
28
  subworkflow: Type["BaseWorkflow[WorkflowInputsType, InnerStateType]"]
29
+ subworkflow_inputs: ClassVar[Union[EntityInputsInterface, BaseInputs]] = {}
27
30
 
28
31
  def run(self) -> Iterator[BaseOutput]:
29
32
  with execution_context(parent_context=get_parent_context() or self._context.parent_context):
30
33
  subworkflow = self.subworkflow(
31
34
  parent_state=self.state,
32
- context=WorkflowContext(
33
- _vellum_client=self._context._vellum_client,
34
- ),
35
+ context=WorkflowContext(vellum_client=self._context.vellum_client),
35
36
  )
36
37
  subworkflow_stream = subworkflow.stream(
37
38
  inputs=self._compile_subworkflow_inputs(),
@@ -68,4 +69,9 @@ class InlineSubworkflowNode(BaseSubworkflowNode[StateType], Generic[StateType, W
68
69
 
69
70
  def _compile_subworkflow_inputs(self) -> WorkflowInputsType:
70
71
  inputs_class = self.subworkflow.get_inputs_class()
71
- return inputs_class(**self.subworkflow_inputs)
72
+ if isinstance(self.subworkflow_inputs, dict):
73
+ return inputs_class(**self.subworkflow_inputs)
74
+ elif isinstance(self.subworkflow_inputs, inputs_class):
75
+ return self.subworkflow_inputs
76
+ else:
77
+ raise ValueError(f"Invalid subworkflow inputs type: {type(self.subworkflow_inputs)}")
@@ -0,0 +1,41 @@
1
+ import pytest
2
+
3
+ from vellum.workflows.inputs.base import BaseInputs
4
+ from vellum.workflows.nodes.bases.base import BaseNode
5
+ from vellum.workflows.nodes.core.inline_subworkflow_node.node import InlineSubworkflowNode
6
+ from vellum.workflows.outputs.base import BaseOutput
7
+ from vellum.workflows.state.base import BaseState
8
+ from vellum.workflows.workflows.base import BaseWorkflow
9
+
10
+
11
+ class Inputs(BaseInputs):
12
+ foo: str
13
+
14
+
15
+ class MyInnerNode(BaseNode):
16
+ class Outputs(BaseNode.Outputs):
17
+ out = Inputs.foo
18
+
19
+
20
+ class MySubworkflow(BaseWorkflow[Inputs, BaseState]):
21
+ graph = MyInnerNode
22
+
23
+ class Outputs(BaseWorkflow.Outputs):
24
+ out = MyInnerNode.Outputs.out
25
+
26
+
27
+ @pytest.mark.parametrize("inputs", [{"foo": "bar"}, Inputs(foo="bar")])
28
+ def test_inline_subworkflow_node__inputs(inputs):
29
+ # GIVEN a node setup with subworkflow inputs
30
+ class MyNode(InlineSubworkflowNode):
31
+ subworkflow = MySubworkflow
32
+ subworkflow_inputs = inputs
33
+
34
+ # WHEN the node is run
35
+ node = MyNode()
36
+ events = list(node.run())
37
+
38
+ # THEN the output is as expected
39
+ assert events == [
40
+ BaseOutput(name="out", value="bar"),
41
+ ]
@@ -108,7 +108,7 @@ class MapNode(BaseNode, Generic[StateType, MapNodeItemType]):
108
108
  self._run_subworkflow(item=item, index=index)
109
109
 
110
110
  def _run_subworkflow(self, *, item: MapNodeItemType, index: int) -> None:
111
- context = WorkflowContext(_vellum_client=self._context._vellum_client)
111
+ context = WorkflowContext(vellum_client=self._context.vellum_client)
112
112
  subworkflow = self.subworkflow(parent_state=self.state, context=context)
113
113
  events = subworkflow.stream(
114
114
  inputs=self.SubworkflowInputs(index=index, item=item, all_items=self.items),
@@ -1,3 +1,4 @@
1
+ import json
1
2
  from typing import Any, Callable, ClassVar, Dict, Generic, Mapping, Tuple, Type, TypeVar, Union, get_args
2
3
 
3
4
  from vellum.utils.templating.constants import DEFAULT_JINJA_CUSTOM_FILTERS, DEFAULT_JINJA_GLOBALS
@@ -7,7 +8,7 @@ from vellum.workflows.errors import WorkflowErrorCode
7
8
  from vellum.workflows.exceptions import NodeException
8
9
  from vellum.workflows.nodes.bases import BaseNode
9
10
  from vellum.workflows.nodes.bases.base import BaseNodeMeta
10
- from vellum.workflows.types.core import EntityInputsInterface
11
+ from vellum.workflows.types.core import EntityInputsInterface, Json
11
12
  from vellum.workflows.types.generics import StateType
12
13
  from vellum.workflows.types.utils import get_original_base
13
14
 
@@ -87,6 +88,12 @@ class TemplatingNode(BaseNode[StateType], Generic[StateType, _OutputType], metac
87
88
  if output_type is bool:
88
89
  return bool(rendered_template)
89
90
 
91
+ if output_type is Json:
92
+ try:
93
+ return json.loads(rendered_template)
94
+ except json.JSONDecodeError:
95
+ raise ValueError("Invalid JSON format for rendered_template")
96
+
90
97
  raise ValueError(f"Unsupported output type: {output_type}")
91
98
 
92
99
  def run(self) -> Outputs:
@@ -2,6 +2,8 @@ import json
2
2
 
3
3
  from vellum.workflows.nodes.bases.base import BaseNode
4
4
  from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
5
+ from vellum.workflows.state import BaseState
6
+ from vellum.workflows.types.core import Json
5
7
 
6
8
 
7
9
  def test_templating_node__dict_output():
@@ -22,6 +24,70 @@ def test_templating_node__dict_output():
22
24
  assert json.loads(outputs.result) == {"key": "value"}
23
25
 
24
26
 
27
+ def test_templating_node__int_output():
28
+ # GIVEN a templating node that outputs an integer
29
+ class IntTemplateNode(TemplatingNode[BaseState, int]):
30
+ template = "{{ data }}"
31
+ inputs = {
32
+ "data": 42,
33
+ }
34
+
35
+ # WHEN the node is run
36
+ node = IntTemplateNode()
37
+ outputs = node.run()
38
+
39
+ # THEN the output is the expected integer
40
+ assert outputs.result == 42
41
+
42
+
43
+ def test_templating_node__float_output():
44
+ # GIVEN a templating node that outputs a float
45
+ class FloatTemplateNode(TemplatingNode[BaseState, float]):
46
+ template = "{{ data }}"
47
+ inputs = {
48
+ "data": 42.5,
49
+ }
50
+
51
+ # WHEN the node is run
52
+ node = FloatTemplateNode()
53
+ outputs = node.run()
54
+
55
+ # THEN the output is the expected float
56
+ assert outputs.result == 42.5
57
+
58
+
59
+ def test_templating_node__bool_output():
60
+ # GIVEN a templating node that outputs a bool
61
+ class BoolTemplateNode(TemplatingNode[BaseState, bool]):
62
+ template = "{{ data }}"
63
+ inputs = {
64
+ "data": True,
65
+ }
66
+
67
+ # WHEN the node is run
68
+ node = BoolTemplateNode()
69
+ outputs = node.run()
70
+
71
+ # THEN the output is the expected bool
72
+ assert outputs.result is True
73
+
74
+
75
+ def test_templating_node__json_output():
76
+ # GIVEN a templating node that outputs JSON
77
+ class JSONTemplateNode(TemplatingNode[BaseState, Json]):
78
+ template = "{{ data }}"
79
+ inputs = {
80
+ "data": {"key": "value"},
81
+ }
82
+
83
+ # WHEN the node is run
84
+ node = JSONTemplateNode()
85
+ outputs = node.run()
86
+
87
+ # THEN the output is the expected JSON
88
+ assert outputs.result == {"key": "value"}
89
+
90
+
25
91
  def test_templating_node__execution_count_reference():
26
92
  # GIVEN a random node
27
93
  class OtherNode(BaseNode):
@@ -73,9 +73,7 @@ class TryNode(BaseNode[StateType], Generic[StateType], metaclass=_TryNodeMeta):
73
73
  def run(self) -> Iterator[BaseOutput]:
74
74
  subworkflow = self.subworkflow(
75
75
  parent_state=self.state,
76
- context=WorkflowContext(
77
- _vellum_client=self._context._vellum_client,
78
- ),
76
+ context=WorkflowContext(vellum_client=self._context.vellum_client),
79
77
  )
80
78
  subworkflow_stream = subworkflow.stream(
81
79
  event_filter=all_workflow_event_filter,
@@ -103,7 +103,7 @@ def test_try_node__use_parent_execution_context():
103
103
  # WHEN the node is run with a custom vellum client
104
104
  node = TestNode(
105
105
  context=WorkflowContext(
106
- _vellum_client=Vellum(api_key="test-key"),
106
+ vellum_client=Vellum(api_key="test-key"),
107
107
  )
108
108
  )
109
109
  outputs = list(node.run())
@@ -26,11 +26,11 @@ class BaseAPINode(BaseNode, Generic[StateType]):
26
26
  url: str
27
27
  method: APIRequestMethod
28
28
  data: Optional[str] = None
29
- json: Optional["Json"] = None
29
+ json: Optional[Json] = None
30
30
  headers: Optional[Dict[str, Union[str, VellumSecret]]] = None
31
31
 
32
32
  class Outputs(BaseOutputs):
33
- json: Optional["Json"]
33
+ json: Optional[Json]
34
34
  headers: Dict[str, str]
35
35
  status_code: int
36
36
  text: str
@@ -76,8 +76,7 @@ class BaseSearchNode(BaseNode[StateType], Generic[StateType]):
76
76
  try:
77
77
  return self._context.vellum_client.search(
78
78
  query=self.query,
79
- index_id=str(self.document_index) if isinstance(self.document_index, UUID) else None,
80
- index_name=self.document_index if isinstance(self.document_index, str) else None,
79
+ document_index=str(self.document_index),
81
80
  options=self.options,
82
81
  )
83
82
  except NotFoundError:
@@ -1,3 +1,4 @@
1
+ import json
1
2
  from typing import Iterator
2
3
 
3
4
  from vellum.workflows.errors import WorkflowErrorCode
@@ -37,13 +38,19 @@ class InlinePromptNode(BaseInlinePromptNode[StateType]):
37
38
  code=WorkflowErrorCode.INTERNAL_ERROR,
38
39
  )
39
40
 
40
- string_output = next((output for output in outputs if output.type == "STRING"), None)
41
- if not string_output or string_output.value is None:
42
- output_types = {output.type for output in outputs}
43
- is_plural = len(output_types) > 1
44
- raise NodeException(
45
- message=f"Expected to receive a non-null string output from Prompt. Only found outputs of type{'s' if is_plural else ''}: {', '.join(output_types)}", # noqa: E501
46
- code=WorkflowErrorCode.INTERNAL_ERROR,
47
- )
48
-
49
- yield BaseOutput(name="text", value=string_output.value)
41
+ string_outputs = []
42
+ for output in outputs:
43
+ if output.value is None:
44
+ continue
45
+
46
+ if output.type == "STRING":
47
+ string_outputs.append(output.value)
48
+ elif output.type == "JSON":
49
+ string_outputs.append(json.dumps(output.value, indent=4))
50
+ elif output.type == "FUNCTION_CALL":
51
+ string_outputs.append(output.value.model_dump_json(indent=4))
52
+ else:
53
+ string_outputs.append(output.value.message)
54
+
55
+ value = "\n".join(string_outputs)
56
+ yield BaseOutput(name="text", value=value)