vellum-ai 0.12.8__py3-none-any.whl → 0.12.11__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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)