vellum-ai 0.14.6__py3-none-any.whl → 0.14.7__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 (54) hide show
  1. vellum/__init__.py +12 -0
  2. vellum/client/core/client_wrapper.py +1 -1
  3. vellum/client/types/__init__.py +12 -0
  4. vellum/client/types/array_chat_message_content_item.py +6 -1
  5. vellum/client/types/array_chat_message_content_item_request.py +2 -0
  6. vellum/client/types/chat_message_content.py +2 -0
  7. vellum/client/types/chat_message_content_request.py +2 -0
  8. vellum/client/types/document_chat_message_content.py +25 -0
  9. vellum/client/types/document_chat_message_content_request.py +25 -0
  10. vellum/client/types/document_vellum_value.py +25 -0
  11. vellum/client/types/document_vellum_value_request.py +25 -0
  12. vellum/client/types/vellum_document.py +20 -0
  13. vellum/client/types/vellum_document_request.py +20 -0
  14. vellum/client/types/vellum_value.py +2 -0
  15. vellum/client/types/vellum_value_request.py +2 -0
  16. vellum/client/types/vellum_variable_type.py +1 -0
  17. vellum/types/document_chat_message_content.py +3 -0
  18. vellum/types/document_chat_message_content_request.py +3 -0
  19. vellum/types/document_vellum_value.py +3 -0
  20. vellum/types/document_vellum_value_request.py +3 -0
  21. vellum/types/vellum_document.py +3 -0
  22. vellum/types/vellum_document_request.py +3 -0
  23. vellum/workflows/exceptions.py +18 -0
  24. vellum/workflows/inputs/base.py +27 -1
  25. vellum/workflows/inputs/tests/__init__.py +0 -0
  26. vellum/workflows/inputs/tests/test_inputs.py +49 -0
  27. vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -1
  28. vellum/workflows/nodes/core/map_node/node.py +7 -7
  29. vellum/workflows/nodes/core/try_node/node.py +1 -1
  30. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +2 -2
  31. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +5 -3
  32. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +5 -4
  33. vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +4 -4
  34. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +39 -15
  35. vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.py +142 -0
  36. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +3 -1
  37. vellum/workflows/outputs/base.py +1 -1
  38. vellum/workflows/runner/runner.py +16 -10
  39. vellum/workflows/state/context.py +7 -7
  40. vellum/workflows/workflows/base.py +16 -5
  41. vellum/workflows/workflows/tests/test_base_workflow.py +131 -40
  42. {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/METADATA +1 -1
  43. {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/RECORD +54 -38
  44. vellum_cli/__init__.py +36 -0
  45. vellum_cli/init.py +128 -0
  46. vellum_cli/pull.py +6 -3
  47. vellum_cli/tests/test_init.py +355 -0
  48. vellum_cli/tests/test_pull.py +127 -0
  49. vellum_ee/workflows/display/nodes/base_node_display.py +4 -4
  50. vellum_ee/workflows/display/vellum.py +0 -4
  51. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +29 -0
  52. {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/LICENSE +0 -0
  53. {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/WHEEL +0 -0
  54. {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/entry_points.txt +0 -0
vellum/__init__.py CHANGED
@@ -74,6 +74,8 @@ from .types import (
74
74
  DeploymentReleaseTagDeploymentHistoryItem,
75
75
  DeploymentReleaseTagRead,
76
76
  DockerServiceToken,
77
+ DocumentChatMessageContent,
78
+ DocumentChatMessageContentRequest,
77
79
  DocumentDocumentToDocumentIndex,
78
80
  DocumentIndexChunking,
79
81
  DocumentIndexChunkingRequest,
@@ -83,6 +85,8 @@ from .types import (
83
85
  DocumentProcessingState,
84
86
  DocumentRead,
85
87
  DocumentStatus,
88
+ DocumentVellumValue,
89
+ DocumentVellumValueRequest,
86
90
  EnrichedNormalizedCompletion,
87
91
  EntityStatus,
88
92
  EntityVisibility,
@@ -438,6 +442,8 @@ from .types import (
438
442
  VariablePromptBlock,
439
443
  VellumAudio,
440
444
  VellumAudioRequest,
445
+ VellumDocument,
446
+ VellumDocumentRequest,
441
447
  VellumError,
442
448
  VellumErrorCodeEnum,
443
449
  VellumErrorRequest,
@@ -607,6 +613,8 @@ __all__ = [
607
613
  "DeploymentReleaseTagRead",
608
614
  "DeploymentsListRequestStatus",
609
615
  "DockerServiceToken",
616
+ "DocumentChatMessageContent",
617
+ "DocumentChatMessageContentRequest",
610
618
  "DocumentDocumentToDocumentIndex",
611
619
  "DocumentIndexChunking",
612
620
  "DocumentIndexChunkingRequest",
@@ -617,6 +625,8 @@ __all__ = [
617
625
  "DocumentProcessingState",
618
626
  "DocumentRead",
619
627
  "DocumentStatus",
628
+ "DocumentVellumValue",
629
+ "DocumentVellumValueRequest",
620
630
  "EnrichedNormalizedCompletion",
621
631
  "EntityStatus",
622
632
  "EntityVisibility",
@@ -980,6 +990,8 @@ __all__ = [
980
990
  "Vellum",
981
991
  "VellumAudio",
982
992
  "VellumAudioRequest",
993
+ "VellumDocument",
994
+ "VellumDocumentRequest",
983
995
  "VellumEnvironment",
984
996
  "VellumError",
985
997
  "VellumErrorCodeEnum",
@@ -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.14.6",
21
+ "X-Fern-SDK-Version": "0.14.7",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -78,6 +78,8 @@ from .deployment_read import DeploymentRead
78
78
  from .deployment_release_tag_deployment_history_item import DeploymentReleaseTagDeploymentHistoryItem
79
79
  from .deployment_release_tag_read import DeploymentReleaseTagRead
80
80
  from .docker_service_token import DockerServiceToken
81
+ from .document_chat_message_content import DocumentChatMessageContent
82
+ from .document_chat_message_content_request import DocumentChatMessageContentRequest
81
83
  from .document_document_to_document_index import DocumentDocumentToDocumentIndex
82
84
  from .document_index_chunking import DocumentIndexChunking
83
85
  from .document_index_chunking_request import DocumentIndexChunkingRequest
@@ -87,6 +89,8 @@ from .document_index_read import DocumentIndexRead
87
89
  from .document_processing_state import DocumentProcessingState
88
90
  from .document_read import DocumentRead
89
91
  from .document_status import DocumentStatus
92
+ from .document_vellum_value import DocumentVellumValue
93
+ from .document_vellum_value_request import DocumentVellumValueRequest
90
94
  from .enriched_normalized_completion import EnrichedNormalizedCompletion
91
95
  from .entity_status import EntityStatus
92
96
  from .entity_visibility import EntityVisibility
@@ -462,6 +466,8 @@ from .upsert_test_suite_test_case_request import UpsertTestSuiteTestCaseRequest
462
466
  from .variable_prompt_block import VariablePromptBlock
463
467
  from .vellum_audio import VellumAudio
464
468
  from .vellum_audio_request import VellumAudioRequest
469
+ from .vellum_document import VellumDocument
470
+ from .vellum_document_request import VellumDocumentRequest
465
471
  from .vellum_error import VellumError
466
472
  from .vellum_error_code_enum import VellumErrorCodeEnum
467
473
  from .vellum_error_request import VellumErrorRequest
@@ -596,6 +602,8 @@ __all__ = [
596
602
  "DeploymentReleaseTagDeploymentHistoryItem",
597
603
  "DeploymentReleaseTagRead",
598
604
  "DockerServiceToken",
605
+ "DocumentChatMessageContent",
606
+ "DocumentChatMessageContentRequest",
599
607
  "DocumentDocumentToDocumentIndex",
600
608
  "DocumentIndexChunking",
601
609
  "DocumentIndexChunkingRequest",
@@ -605,6 +613,8 @@ __all__ = [
605
613
  "DocumentProcessingState",
606
614
  "DocumentRead",
607
615
  "DocumentStatus",
616
+ "DocumentVellumValue",
617
+ "DocumentVellumValueRequest",
608
618
  "EnrichedNormalizedCompletion",
609
619
  "EntityStatus",
610
620
  "EntityVisibility",
@@ -960,6 +970,8 @@ __all__ = [
960
970
  "VariablePromptBlock",
961
971
  "VellumAudio",
962
972
  "VellumAudioRequest",
973
+ "VellumDocument",
974
+ "VellumDocumentRequest",
963
975
  "VellumError",
964
976
  "VellumErrorCodeEnum",
965
977
  "VellumErrorRequest",
@@ -5,7 +5,12 @@ from .string_chat_message_content import StringChatMessageContent
5
5
  from .function_call_chat_message_content import FunctionCallChatMessageContent
6
6
  from .image_chat_message_content import ImageChatMessageContent
7
7
  from .audio_chat_message_content import AudioChatMessageContent
8
+ from .document_chat_message_content import DocumentChatMessageContent
8
9
 
9
10
  ArrayChatMessageContentItem = typing.Union[
10
- StringChatMessageContent, FunctionCallChatMessageContent, ImageChatMessageContent, AudioChatMessageContent
11
+ StringChatMessageContent,
12
+ FunctionCallChatMessageContent,
13
+ ImageChatMessageContent,
14
+ AudioChatMessageContent,
15
+ DocumentChatMessageContent,
11
16
  ]
@@ -5,10 +5,12 @@ from .string_chat_message_content_request import StringChatMessageContentRequest
5
5
  from .function_call_chat_message_content_request import FunctionCallChatMessageContentRequest
6
6
  from .image_chat_message_content_request import ImageChatMessageContentRequest
7
7
  from .audio_chat_message_content_request import AudioChatMessageContentRequest
8
+ from .document_chat_message_content_request import DocumentChatMessageContentRequest
8
9
 
9
10
  ArrayChatMessageContentItemRequest = typing.Union[
10
11
  StringChatMessageContentRequest,
11
12
  FunctionCallChatMessageContentRequest,
12
13
  ImageChatMessageContentRequest,
13
14
  AudioChatMessageContentRequest,
15
+ DocumentChatMessageContentRequest,
14
16
  ]
@@ -6,6 +6,7 @@ from .function_call_chat_message_content import FunctionCallChatMessageContent
6
6
  from .array_chat_message_content import ArrayChatMessageContent
7
7
  from .image_chat_message_content import ImageChatMessageContent
8
8
  from .audio_chat_message_content import AudioChatMessageContent
9
+ from .document_chat_message_content import DocumentChatMessageContent
9
10
 
10
11
  ChatMessageContent = typing.Union[
11
12
  StringChatMessageContent,
@@ -13,4 +14,5 @@ ChatMessageContent = typing.Union[
13
14
  ArrayChatMessageContent,
14
15
  ImageChatMessageContent,
15
16
  AudioChatMessageContent,
17
+ DocumentChatMessageContent,
16
18
  ]
@@ -6,6 +6,7 @@ from .function_call_chat_message_content_request import FunctionCallChatMessageC
6
6
  from .array_chat_message_content_request import ArrayChatMessageContentRequest
7
7
  from .image_chat_message_content_request import ImageChatMessageContentRequest
8
8
  from .audio_chat_message_content_request import AudioChatMessageContentRequest
9
+ from .document_chat_message_content_request import DocumentChatMessageContentRequest
9
10
 
10
11
  ChatMessageContentRequest = typing.Union[
11
12
  StringChatMessageContentRequest,
@@ -13,4 +14,5 @@ ChatMessageContentRequest = typing.Union[
13
14
  ArrayChatMessageContentRequest,
14
15
  ImageChatMessageContentRequest,
15
16
  AudioChatMessageContentRequest,
17
+ DocumentChatMessageContentRequest,
16
18
  ]
@@ -0,0 +1,25 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from .vellum_document import VellumDocument
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
+ import pydantic
8
+
9
+
10
+ class DocumentChatMessageContent(UniversalBaseModel):
11
+ """
12
+ A document value that is used in a chat message.
13
+ """
14
+
15
+ type: typing.Literal["DOCUMENT"] = "DOCUMENT"
16
+ value: VellumDocument
17
+
18
+ if IS_PYDANTIC_V2:
19
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
20
+ else:
21
+
22
+ class Config:
23
+ frozen = True
24
+ smart_union = True
25
+ extra = pydantic.Extra.allow
@@ -0,0 +1,25 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from .vellum_document_request import VellumDocumentRequest
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
+ import pydantic
8
+
9
+
10
+ class DocumentChatMessageContentRequest(UniversalBaseModel):
11
+ """
12
+ A document value that is used in a chat message.
13
+ """
14
+
15
+ type: typing.Literal["DOCUMENT"] = "DOCUMENT"
16
+ value: VellumDocumentRequest
17
+
18
+ if IS_PYDANTIC_V2:
19
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
20
+ else:
21
+
22
+ class Config:
23
+ frozen = True
24
+ smart_union = True
25
+ extra = pydantic.Extra.allow
@@ -0,0 +1,25 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from .vellum_document import VellumDocument
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
+ import pydantic
8
+
9
+
10
+ class DocumentVellumValue(UniversalBaseModel):
11
+ """
12
+ A base Vellum primitive value representing a document.
13
+ """
14
+
15
+ type: typing.Literal["DOCUMENT"] = "DOCUMENT"
16
+ value: typing.Optional[VellumDocument] = None
17
+
18
+ if IS_PYDANTIC_V2:
19
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
20
+ else:
21
+
22
+ class Config:
23
+ frozen = True
24
+ smart_union = True
25
+ extra = pydantic.Extra.allow
@@ -0,0 +1,25 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from .vellum_document_request import VellumDocumentRequest
6
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
7
+ import pydantic
8
+
9
+
10
+ class DocumentVellumValueRequest(UniversalBaseModel):
11
+ """
12
+ A base Vellum primitive value representing a document.
13
+ """
14
+
15
+ type: typing.Literal["DOCUMENT"] = "DOCUMENT"
16
+ value: typing.Optional[VellumDocumentRequest] = None
17
+
18
+ if IS_PYDANTIC_V2:
19
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
20
+ else:
21
+
22
+ class Config:
23
+ frozen = True
24
+ smart_union = True
25
+ extra = pydantic.Extra.allow
@@ -0,0 +1,20 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
6
+ import pydantic
7
+
8
+
9
+ class VellumDocument(UniversalBaseModel):
10
+ src: str
11
+ metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
12
+
13
+ if IS_PYDANTIC_V2:
14
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
15
+ else:
16
+
17
+ class Config:
18
+ frozen = True
19
+ smart_union = True
20
+ extra = pydantic.Extra.allow
@@ -0,0 +1,20 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import typing
5
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
6
+ import pydantic
7
+
8
+
9
+ class VellumDocumentRequest(UniversalBaseModel):
10
+ src: str
11
+ metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
12
+
13
+ if IS_PYDANTIC_V2:
14
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
15
+ else:
16
+
17
+ class Config:
18
+ frozen = True
19
+ smart_union = True
20
+ extra = pydantic.Extra.allow
@@ -7,6 +7,7 @@ from .number_vellum_value import NumberVellumValue
7
7
  from .json_vellum_value import JsonVellumValue
8
8
  from .image_vellum_value import ImageVellumValue
9
9
  from .audio_vellum_value import AudioVellumValue
10
+ from .document_vellum_value import DocumentVellumValue
10
11
  from .function_call_vellum_value import FunctionCallVellumValue
11
12
  from .error_vellum_value import ErrorVellumValue
12
13
  from .chat_history_vellum_value import ChatHistoryVellumValue
@@ -21,6 +22,7 @@ VellumValue = typing.Union[
21
22
  JsonVellumValue,
22
23
  ImageVellumValue,
23
24
  AudioVellumValue,
25
+ DocumentVellumValue,
24
26
  FunctionCallVellumValue,
25
27
  ErrorVellumValue,
26
28
  "ArrayVellumValue",
@@ -7,6 +7,7 @@ from .number_vellum_value_request import NumberVellumValueRequest
7
7
  from .json_vellum_value_request import JsonVellumValueRequest
8
8
  from .image_vellum_value_request import ImageVellumValueRequest
9
9
  from .audio_vellum_value_request import AudioVellumValueRequest
10
+ from .document_vellum_value_request import DocumentVellumValueRequest
10
11
  from .function_call_vellum_value_request import FunctionCallVellumValueRequest
11
12
  from .error_vellum_value_request import ErrorVellumValueRequest
12
13
  from .chat_history_vellum_value_request import ChatHistoryVellumValueRequest
@@ -21,6 +22,7 @@ VellumValueRequest = typing.Union[
21
22
  JsonVellumValueRequest,
22
23
  ImageVellumValueRequest,
23
24
  AudioVellumValueRequest,
25
+ DocumentVellumValueRequest,
24
26
  FunctionCallVellumValueRequest,
25
27
  ErrorVellumValueRequest,
26
28
  "ArrayVellumValueRequest",
@@ -14,6 +14,7 @@ VellumVariableType = typing.Union[
14
14
  "FUNCTION_CALL",
15
15
  "IMAGE",
16
16
  "AUDIO",
17
+ "DOCUMENT",
17
18
  "NULL",
18
19
  ],
19
20
  typing.Any,
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.document_chat_message_content import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.document_chat_message_content_request import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.document_vellum_value import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.document_vellum_value_request import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.vellum_document import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.vellum_document_request import *
@@ -17,3 +17,21 @@ class NodeException(Exception):
17
17
  @staticmethod
18
18
  def of(workflow_error: WorkflowError) -> "NodeException":
19
19
  return NodeException(message=workflow_error.message, code=workflow_error.code)
20
+
21
+
22
+ class WorkflowInitializationException(Exception):
23
+ def __init__(self, message: str, code: WorkflowErrorCode = WorkflowErrorCode.INVALID_INPUTS):
24
+ self.message = message
25
+ self.code = code
26
+ super().__init__(message)
27
+
28
+ @property
29
+ def error(self) -> WorkflowError:
30
+ return WorkflowError(
31
+ message=self.message,
32
+ code=self.code,
33
+ )
34
+
35
+ @staticmethod
36
+ def of(workflow_error: WorkflowError) -> "WorkflowInitializationException":
37
+ return WorkflowInitializationException(message=workflow_error.message, code=workflow_error.code)
@@ -1,9 +1,11 @@
1
- from typing import Any, Iterator, Tuple, Type
1
+ from typing import Any, Iterator, Tuple, Type, Union, get_args, get_origin
2
2
  from typing_extensions import dataclass_transform
3
3
 
4
4
  from pydantic import GetCoreSchemaHandler
5
5
  from pydantic_core import core_schema
6
6
 
7
+ from vellum.workflows.errors.types import WorkflowErrorCode
8
+ from vellum.workflows.exceptions import WorkflowInitializationException
7
9
  from vellum.workflows.references import ExternalInputReference, WorkflowInputReference
8
10
  from vellum.workflows.references.input import InputReference
9
11
  from vellum.workflows.types.utils import get_class_attr_names, infer_types
@@ -40,7 +42,20 @@ class BaseInputs(metaclass=_BaseInputsMeta):
40
42
  __parent_class__: Type = type(None)
41
43
 
42
44
  def __init__(self, **kwargs: Any) -> None:
45
+ for name, field_type in self.__class__.__annotations__.items():
46
+ if name not in kwargs and name not in vars(self.__class__):
47
+ origin = get_origin(field_type)
48
+ args = get_args(field_type)
49
+ if not (origin is Union and type(None) in args):
50
+ raise WorkflowInitializationException(
51
+ message="Required input variables should have defined value",
52
+ code=WorkflowErrorCode.INVALID_INPUTS,
53
+ )
54
+
43
55
  for name, value in kwargs.items():
56
+ field_type = self.__class__.__annotations__.get(name)
57
+ if field_type:
58
+ self._validate_input(value, field_type)
44
59
  setattr(self, name, value)
45
60
 
46
61
  def __iter__(self) -> Iterator[Tuple[InputReference, Any]]:
@@ -48,6 +63,17 @@ class BaseInputs(metaclass=_BaseInputsMeta):
48
63
  if hasattr(self, input_descriptor.name):
49
64
  yield (input_descriptor, getattr(self, input_descriptor.name))
50
65
 
66
+ def _validate_input(self, value: Any, field_type: Any) -> None:
67
+ if value is None:
68
+ # Check if field_type is Optional
69
+ origin = get_origin(field_type)
70
+ args = get_args(field_type)
71
+ if not (origin is Union and type(None) in args):
72
+ raise WorkflowInitializationException(
73
+ message="Required input variables should have defined value",
74
+ code=WorkflowErrorCode.INVALID_INPUTS,
75
+ )
76
+
51
77
  @classmethod
52
78
  def __get_pydantic_core_schema__(
53
79
  cls, source_type: Type[Any], handler: GetCoreSchemaHandler
File without changes
@@ -0,0 +1,49 @@
1
+ import pytest
2
+ from typing import Optional
3
+
4
+ from vellum.workflows.errors import WorkflowErrorCode
5
+ from vellum.workflows.exceptions import WorkflowInitializationException
6
+ from vellum.workflows.inputs import BaseInputs
7
+
8
+
9
+ def test_base_inputs_happy_path():
10
+ # GIVEN some input class with required and optional fields
11
+ class TestInputs(BaseInputs):
12
+ required_string: str
13
+ required_int: int
14
+ optional_string: Optional[str]
15
+
16
+ # WHEN we assign the inputs some valid values
17
+ inputs = TestInputs(required_string="hello", required_int=42, optional_string=None)
18
+
19
+ # THEN the inputs should have the correct values
20
+ assert inputs.required_string == "hello"
21
+ assert inputs.required_int == 42
22
+ assert inputs.optional_string is None
23
+
24
+
25
+ def test_base_inputs_empty_value():
26
+ # GIVEN some input class with required and optional string fields
27
+ class TestInputs(BaseInputs):
28
+ required_string: str
29
+ optional_string: Optional[str]
30
+
31
+ # WHEN we try to omit a required field
32
+ with pytest.raises(WorkflowInitializationException) as exc_info:
33
+ TestInputs(optional_string="ok") # type: ignore
34
+
35
+ # THEN it should raise a NodeException with the correct error message and code
36
+ assert exc_info.value.code == WorkflowErrorCode.INVALID_INPUTS
37
+ assert "Required input variables should have defined value" in str(exc_info.value)
38
+
39
+
40
+ def test_base_inputs_with_default():
41
+ # GIVEN some input class with a field that has a default value
42
+ class TestInputs(BaseInputs):
43
+ string_with_default: str = "default_value"
44
+
45
+ # WHEN we create an instance without providing the field
46
+ inputs = TestInputs()
47
+
48
+ # THEN it should use the default value
49
+ assert inputs.string_with_default == "default_value"
@@ -70,7 +70,7 @@ class InlineSubworkflowNode(
70
70
  subworkflow_inputs: ClassVar[Union[EntityInputsInterface, BaseInputs, Type[undefined]]] = undefined
71
71
 
72
72
  def run(self) -> Iterator[BaseOutput]:
73
- with execution_context(parent_context=get_parent_context() or self._context.parent_context):
73
+ with execution_context(parent_context=get_parent_context()):
74
74
  subworkflow = self.subworkflow(
75
75
  parent_state=self.state,
76
76
  context=WorkflowContext(vellum_client=self._context.vellum_client),
@@ -16,10 +16,9 @@ from typing import (
16
16
  overload,
17
17
  )
18
18
 
19
- from vellum.workflows.context import execution_context, get_parent_context
19
+ from vellum.workflows.context import ExecutionContext, execution_context, get_execution_context
20
20
  from vellum.workflows.descriptors.base import BaseDescriptor
21
21
  from vellum.workflows.errors.types import WorkflowErrorCode
22
- from vellum.workflows.events.types import ParentContext
23
22
  from vellum.workflows.exceptions import NodeException
24
23
  from vellum.workflows.inputs.base import BaseInputs
25
24
  from vellum.workflows.nodes.bases.base_adornment_node import BaseAdornmentNode
@@ -76,13 +75,13 @@ class MapNode(BaseAdornmentNode[StateType], Generic[StateType, MapNodeItemType])
76
75
  fulfilled_iterations: List[bool] = []
77
76
  for index, item in enumerate(self.items):
78
77
  fulfilled_iterations.append(False)
79
- parent_context = get_parent_context() or self._context.parent_context
78
+ current_execution_context = get_execution_context()
80
79
  thread = Thread(
81
80
  target=self._context_run_subworkflow,
82
81
  kwargs={
83
82
  "item": item,
84
83
  "index": index,
85
- "parent_context": parent_context,
84
+ "current_execution_context": current_execution_context,
86
85
  },
87
86
  )
88
87
  if self.max_concurrency is None:
@@ -143,10 +142,11 @@ class MapNode(BaseAdornmentNode[StateType], Generic[StateType, MapNodeItemType])
143
142
  yield BaseOutput(name=output_name, value=output_list)
144
143
 
145
144
  def _context_run_subworkflow(
146
- self, *, item: MapNodeItemType, index: int, parent_context: Optional[ParentContext] = None
145
+ self, *, item: MapNodeItemType, index: int, current_execution_context: ExecutionContext
147
146
  ) -> None:
148
- parent_context = parent_context or self._context.parent_context
149
- with execution_context(parent_context=parent_context):
147
+ parent_context = current_execution_context.parent_context
148
+ trace_id = current_execution_context.trace_id
149
+ with execution_context(parent_context=parent_context, trace_id=trace_id):
150
150
  self._run_subworkflow(item=item, index=index)
151
151
 
152
152
  def _run_subworkflow(self, *, item: MapNodeItemType, index: int) -> None:
@@ -27,7 +27,7 @@ class TryNode(BaseAdornmentNode[StateType], Generic[StateType]):
27
27
  error: Optional[WorkflowError] = None
28
28
 
29
29
  def run(self) -> Iterator[BaseOutput]:
30
- parent_context = get_parent_context() or self._context.parent_context
30
+ parent_context = get_parent_context()
31
31
  with execution_context(parent_context=parent_context):
32
32
  subworkflow = self.subworkflow(
33
33
  parent_state=self.state,
@@ -67,11 +67,11 @@ class BasePromptNode(BaseNode, Generic[StateType]):
67
67
  def _handle_api_error(self, e: ApiError):
68
68
  if e.status_code and e.status_code >= 400 and e.status_code < 500 and isinstance(e.body, dict):
69
69
  raise NodeException(
70
- message=e.body.get("detail", "Failed to execute prompt"),
70
+ message=e.body.get("detail", "Failed to execute Prompt"),
71
71
  code=WorkflowErrorCode.INVALID_INPUTS,
72
72
  ) from e
73
73
 
74
74
  raise NodeException(
75
- message="Failed to execute prompt",
75
+ message="Failed to execute Prompt",
76
76
  code=WorkflowErrorCode.INTERNAL_ERROR,
77
77
  ) from e
@@ -19,7 +19,7 @@ from vellum.client import RequestOptions
19
19
  from vellum.client.types.chat_message_request import ChatMessageRequest
20
20
  from vellum.client.types.prompt_settings import PromptSettings
21
21
  from vellum.workflows.constants import OMIT
22
- from vellum.workflows.context import get_parent_context
22
+ from vellum.workflows.context import get_execution_context
23
23
  from vellum.workflows.errors import WorkflowErrorCode
24
24
  from vellum.workflows.events.types import default_serializer
25
25
  from vellum.workflows.exceptions import NodeException
@@ -61,11 +61,13 @@ class BaseInlinePromptNode(BasePromptNode[StateType], Generic[StateType]):
61
61
 
62
62
  def _get_prompt_event_stream(self) -> Iterator[AdHocExecutePromptEvent]:
63
63
  input_variables, input_values = self._compile_prompt_inputs()
64
- parent_context = get_parent_context()
64
+ current_context = get_execution_context()
65
+ parent_context = current_context.parent_context
66
+ trace_id = current_context.trace_id
65
67
  request_options = self.request_options or RequestOptions()
66
68
 
67
69
  request_options["additional_body_parameters"] = {
68
- "execution_context": {"parent_context": parent_context},
70
+ "execution_context": {"parent_context": parent_context, "trace_id": trace_id},
69
71
  **request_options.get("additional_body_parameters", {}),
70
72
  }
71
73
  normalized_functions = (
@@ -15,7 +15,7 @@ from vellum import (
15
15
  from vellum.client import RequestOptions
16
16
  from vellum.client.types.chat_message_request import ChatMessageRequest
17
17
  from vellum.workflows.constants import LATEST_RELEASE_TAG, OMIT
18
- from vellum.workflows.context import get_parent_context
18
+ from vellum.workflows.context import get_execution_context
19
19
  from vellum.workflows.errors import WorkflowErrorCode
20
20
  from vellum.workflows.events.types import default_serializer
21
21
  from vellum.workflows.exceptions import NodeException
@@ -55,11 +55,12 @@ class BasePromptDeploymentNode(BasePromptNode, Generic[StateType]):
55
55
  merge_behavior = MergeBehavior.AWAIT_ANY
56
56
 
57
57
  def _get_prompt_event_stream(self) -> Iterator[ExecutePromptEvent]:
58
- current_parent_context = get_parent_context()
59
- parent_context = current_parent_context.model_dump() if current_parent_context else None
58
+ current_context = get_execution_context()
59
+ trace_id = current_context.trace_id
60
+ parent_context = current_context.parent_context.model_dump() if current_context.parent_context else None
60
61
  request_options = self.request_options or RequestOptions()
61
62
  request_options["additional_body_parameters"] = {
62
- "execution_context": {"parent_context": parent_context},
63
+ "execution_context": {"parent_context": parent_context, "trace_id": trace_id},
63
64
  **request_options.get("additional_body_parameters", {}),
64
65
  }
65
66
  return self._context.vellum_client.execute_prompt_stream(