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.
- vellum/__init__.py +12 -0
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/types/__init__.py +12 -0
- vellum/client/types/array_chat_message_content_item.py +6 -1
- vellum/client/types/array_chat_message_content_item_request.py +2 -0
- vellum/client/types/chat_message_content.py +2 -0
- vellum/client/types/chat_message_content_request.py +2 -0
- vellum/client/types/document_chat_message_content.py +25 -0
- vellum/client/types/document_chat_message_content_request.py +25 -0
- vellum/client/types/document_vellum_value.py +25 -0
- vellum/client/types/document_vellum_value_request.py +25 -0
- vellum/client/types/vellum_document.py +20 -0
- vellum/client/types/vellum_document_request.py +20 -0
- vellum/client/types/vellum_value.py +2 -0
- vellum/client/types/vellum_value_request.py +2 -0
- vellum/client/types/vellum_variable_type.py +1 -0
- vellum/types/document_chat_message_content.py +3 -0
- vellum/types/document_chat_message_content_request.py +3 -0
- vellum/types/document_vellum_value.py +3 -0
- vellum/types/document_vellum_value_request.py +3 -0
- vellum/types/vellum_document.py +3 -0
- vellum/types/vellum_document_request.py +3 -0
- vellum/workflows/exceptions.py +18 -0
- vellum/workflows/inputs/base.py +27 -1
- vellum/workflows/inputs/tests/__init__.py +0 -0
- vellum/workflows/inputs/tests/test_inputs.py +49 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -1
- vellum/workflows/nodes/core/map_node/node.py +7 -7
- vellum/workflows/nodes/core/try_node/node.py +1 -1
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +2 -2
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +5 -3
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +5 -4
- vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +4 -4
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +39 -15
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.py +142 -0
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +3 -1
- vellum/workflows/outputs/base.py +1 -1
- vellum/workflows/runner/runner.py +16 -10
- vellum/workflows/state/context.py +7 -7
- vellum/workflows/workflows/base.py +16 -5
- vellum/workflows/workflows/tests/test_base_workflow.py +131 -40
- {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/RECORD +54 -38
- vellum_cli/__init__.py +36 -0
- vellum_cli/init.py +128 -0
- vellum_cli/pull.py +6 -3
- vellum_cli/tests/test_init.py +355 -0
- vellum_cli/tests/test_pull.py +127 -0
- vellum_ee/workflows/display/nodes/base_node_display.py +4 -4
- vellum_ee/workflows/display/vellum.py +0 -4
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +29 -0
- {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.6.dist-info → vellum_ai-0.14.7.dist-info}/WHEEL +0 -0
- {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.
|
21
|
+
"X-Fern-SDK-Version": "0.14.7",
|
22
22
|
}
|
23
23
|
headers["X_API_KEY"] = self.api_key
|
24
24
|
return headers
|
vellum/client/types/__init__.py
CHANGED
@@ -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,
|
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",
|
vellum/workflows/exceptions.py
CHANGED
@@ -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)
|
vellum/workflows/inputs/base.py
CHANGED
@@ -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()
|
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,
|
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
|
-
|
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
|
-
"
|
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,
|
145
|
+
self, *, item: MapNodeItemType, index: int, current_execution_context: ExecutionContext
|
147
146
|
) -> None:
|
148
|
-
parent_context =
|
149
|
-
|
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()
|
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
|
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
|
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
|
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
|
-
|
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
|
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
|
-
|
59
|
-
|
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(
|