vellum-ai 0.14.68__py3-none-any.whl → 0.14.69__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 +4 -0
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/types/__init__.py +4 -0
- vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py +23 -0
- vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py +23 -0
- vellum/client/types/folder_entity_document_index_data.py +2 -0
- vellum/client/types/indexing_config_vectorizer.py +2 -0
- vellum/client/types/indexing_config_vectorizer_request.py +2 -0
- vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py +3 -0
- vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py +3 -0
- vellum/workflows/nodes/displayable/bases/search_node.py +15 -3
- vellum/workflows/nodes/displayable/tests/test_search_node_error_handling.py +215 -0
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.69.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.69.dist-info}/RECORD +19 -14
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +3 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +81 -0
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.69.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.69.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.69.dist-info}/entry_points.txt +0 -0
vellum/__init__.py
CHANGED
@@ -123,6 +123,8 @@ from .types import (
|
|
123
123
|
ExternalInputDescriptor,
|
124
124
|
ExternalTestCaseExecution,
|
125
125
|
ExternalTestCaseExecutionRequest,
|
126
|
+
FastEmbedVectorizerBaaiBgeSmallEnV15,
|
127
|
+
FastEmbedVectorizerBaaiBgeSmallEnV15Request,
|
126
128
|
FinishReasonEnum,
|
127
129
|
FolderEntity,
|
128
130
|
FolderEntityDocumentIndex,
|
@@ -750,6 +752,8 @@ __all__ = [
|
|
750
752
|
"ExternalInputDescriptor",
|
751
753
|
"ExternalTestCaseExecution",
|
752
754
|
"ExternalTestCaseExecutionRequest",
|
755
|
+
"FastEmbedVectorizerBaaiBgeSmallEnV15",
|
756
|
+
"FastEmbedVectorizerBaaiBgeSmallEnV15Request",
|
753
757
|
"FinishReasonEnum",
|
754
758
|
"FolderEntitiesListRequestEntityStatus",
|
755
759
|
"FolderEntity",
|
@@ -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.69",
|
22
22
|
}
|
23
23
|
headers["X-API-KEY"] = self.api_key
|
24
24
|
return headers
|
vellum/client/types/__init__.py
CHANGED
@@ -127,6 +127,8 @@ from .execution_vellum_value import ExecutionVellumValue
|
|
127
127
|
from .external_input_descriptor import ExternalInputDescriptor
|
128
128
|
from .external_test_case_execution import ExternalTestCaseExecution
|
129
129
|
from .external_test_case_execution_request import ExternalTestCaseExecutionRequest
|
130
|
+
from .fast_embed_vectorizer_baai_bge_small_en_v_15 import FastEmbedVectorizerBaaiBgeSmallEnV15
|
131
|
+
from .fast_embed_vectorizer_baai_bge_small_en_v_15_request import FastEmbedVectorizerBaaiBgeSmallEnV15Request
|
130
132
|
from .finish_reason_enum import FinishReasonEnum
|
131
133
|
from .folder_entity import FolderEntity
|
132
134
|
from .folder_entity_document_index import FolderEntityDocumentIndex
|
@@ -737,6 +739,8 @@ __all__ = [
|
|
737
739
|
"ExternalInputDescriptor",
|
738
740
|
"ExternalTestCaseExecution",
|
739
741
|
"ExternalTestCaseExecutionRequest",
|
742
|
+
"FastEmbedVectorizerBaaiBgeSmallEnV15",
|
743
|
+
"FastEmbedVectorizerBaaiBgeSmallEnV15Request",
|
740
744
|
"FinishReasonEnum",
|
741
745
|
"FolderEntity",
|
742
746
|
"FolderEntityDocumentIndex",
|
@@ -0,0 +1,23 @@
|
|
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 FastEmbedVectorizerBaaiBgeSmallEnV15(UniversalBaseModel):
|
10
|
+
"""
|
11
|
+
FastEmbed vectorizer for BAAI/bge-small-en-v1.5.
|
12
|
+
"""
|
13
|
+
|
14
|
+
model_name: typing.Literal["BAAI/bge-small-en-v1.5"] = "BAAI/bge-small-en-v1.5"
|
15
|
+
|
16
|
+
if IS_PYDANTIC_V2:
|
17
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
|
18
|
+
else:
|
19
|
+
|
20
|
+
class Config:
|
21
|
+
frozen = True
|
22
|
+
smart_union = True
|
23
|
+
extra = pydantic.Extra.allow
|
@@ -0,0 +1,23 @@
|
|
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 FastEmbedVectorizerBaaiBgeSmallEnV15Request(UniversalBaseModel):
|
10
|
+
"""
|
11
|
+
FastEmbed vectorizer for BAAI/bge-small-en-v1.5.
|
12
|
+
"""
|
13
|
+
|
14
|
+
model_name: typing.Literal["BAAI/bge-small-en-v1.5"] = "BAAI/bge-small-en-v1.5"
|
15
|
+
|
16
|
+
if IS_PYDANTIC_V2:
|
17
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
|
18
|
+
else:
|
19
|
+
|
20
|
+
class Config:
|
21
|
+
frozen = True
|
22
|
+
smart_union = True
|
23
|
+
extra = pydantic.Extra.allow
|
@@ -3,6 +3,7 @@
|
|
3
3
|
from ..core.pydantic_utilities import UniversalBaseModel
|
4
4
|
import datetime as dt
|
5
5
|
from .entity_status import EntityStatus
|
6
|
+
from .document_index_indexing_config import DocumentIndexIndexingConfig
|
6
7
|
from ..core.pydantic_utilities import IS_PYDANTIC_V2
|
7
8
|
import typing
|
8
9
|
import pydantic
|
@@ -14,6 +15,7 @@ class FolderEntityDocumentIndexData(UniversalBaseModel):
|
|
14
15
|
created: dt.datetime
|
15
16
|
modified: dt.datetime
|
16
17
|
status: EntityStatus
|
18
|
+
indexing_config: DocumentIndexIndexingConfig
|
17
19
|
|
18
20
|
if IS_PYDANTIC_V2:
|
19
21
|
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
|
@@ -16,6 +16,7 @@ from .google_vertex_ai_vectorizer_text_embedding_004 import GoogleVertexAiVector
|
|
16
16
|
from .google_vertex_ai_vectorizer_text_multilingual_embedding_002 import (
|
17
17
|
GoogleVertexAiVectorizerTextMultilingualEmbedding002,
|
18
18
|
)
|
19
|
+
from .fast_embed_vectorizer_baai_bge_small_en_v_15 import FastEmbedVectorizerBaaiBgeSmallEnV15
|
19
20
|
|
20
21
|
IndexingConfigVectorizer = typing.Union[
|
21
22
|
OpenAiVectorizerTextEmbedding3Small,
|
@@ -27,4 +28,5 @@ IndexingConfigVectorizer = typing.Union[
|
|
27
28
|
HkunlpInstructorXlVectorizer,
|
28
29
|
GoogleVertexAiVectorizerTextEmbedding004,
|
29
30
|
GoogleVertexAiVectorizerTextMultilingualEmbedding002,
|
31
|
+
FastEmbedVectorizerBaaiBgeSmallEnV15,
|
30
32
|
]
|
@@ -16,6 +16,7 @@ from .google_vertex_ai_vectorizer_text_embedding_004_request import GoogleVertex
|
|
16
16
|
from .google_vertex_ai_vectorizer_text_multilingual_embedding_002_request import (
|
17
17
|
GoogleVertexAiVectorizerTextMultilingualEmbedding002Request,
|
18
18
|
)
|
19
|
+
from .fast_embed_vectorizer_baai_bge_small_en_v_15_request import FastEmbedVectorizerBaaiBgeSmallEnV15Request
|
19
20
|
|
20
21
|
IndexingConfigVectorizerRequest = typing.Union[
|
21
22
|
OpenAiVectorizerTextEmbedding3SmallRequest,
|
@@ -27,4 +28,5 @@ IndexingConfigVectorizerRequest = typing.Union[
|
|
27
28
|
HkunlpInstructorXlVectorizerRequest,
|
28
29
|
GoogleVertexAiVectorizerTextEmbedding004Request,
|
29
30
|
GoogleVertexAiVectorizerTextMultilingualEmbedding002Request,
|
31
|
+
FastEmbedVectorizerBaaiBgeSmallEnV15Request,
|
30
32
|
]
|
@@ -106,11 +106,23 @@ class BaseSearchNode(BaseNode[StateType], Generic[StateType]):
|
|
106
106
|
message=f"Document Index '{self.document_index}' not found",
|
107
107
|
code=WorkflowErrorCode.INVALID_INPUTS,
|
108
108
|
)
|
109
|
-
except ApiError:
|
109
|
+
except ApiError as e:
|
110
|
+
if e.status_code and e.status_code == 403 and isinstance(e.body, dict):
|
111
|
+
raise NodeException(
|
112
|
+
message=e.body.get("detail", "Provider credentials is missing or unavailable"),
|
113
|
+
code=WorkflowErrorCode.PROVIDER_CREDENTIALS_UNAVAILABLE,
|
114
|
+
)
|
115
|
+
elif e.status_code and e.status_code >= 400 and e.status_code < 500 and isinstance(e.body, dict):
|
116
|
+
raise NodeException(
|
117
|
+
message=e.body.get(
|
118
|
+
"detail", f"An error occurred while searching against Document Index '{self.document_index}'"
|
119
|
+
),
|
120
|
+
code=WorkflowErrorCode.INVALID_INPUTS,
|
121
|
+
) from e
|
110
122
|
raise NodeException(
|
111
|
-
message=f"An error occurred while searching against Document Index '{self.document_index}'",
|
123
|
+
message=f"An error occurred while searching against Document Index '{self.document_index}'",
|
112
124
|
code=WorkflowErrorCode.INTERNAL_ERROR,
|
113
|
-
)
|
125
|
+
) from e
|
114
126
|
|
115
127
|
def _get_options_request(self) -> SearchRequestOptionsRequest:
|
116
128
|
return SearchRequestOptionsRequest(
|
@@ -0,0 +1,215 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from vellum.client.core.api_error import ApiError
|
4
|
+
from vellum.workflows.errors.types import WorkflowErrorCode
|
5
|
+
from vellum.workflows.exceptions import NodeException
|
6
|
+
from vellum.workflows.inputs import BaseInputs
|
7
|
+
from vellum.workflows.nodes.displayable.search_node import SearchNode as BaseSearchNode
|
8
|
+
from vellum.workflows.state import BaseState
|
9
|
+
from vellum.workflows.state.base import StateMeta
|
10
|
+
|
11
|
+
|
12
|
+
def test_search_node_handles_403_error(vellum_client):
|
13
|
+
"""Test that SearchNode properly handles 403 API errors with user-facing messages."""
|
14
|
+
|
15
|
+
class Inputs(BaseInputs):
|
16
|
+
query: str
|
17
|
+
document_index: str
|
18
|
+
|
19
|
+
class State(BaseState):
|
20
|
+
pass
|
21
|
+
|
22
|
+
class SearchNode(BaseSearchNode):
|
23
|
+
query = Inputs.query
|
24
|
+
document_index = Inputs.document_index
|
25
|
+
|
26
|
+
vellum_client.search.side_effect = ApiError(
|
27
|
+
status_code=403, body={"detail": "Provider credentials is missing or unavailable"}
|
28
|
+
)
|
29
|
+
|
30
|
+
node = SearchNode(
|
31
|
+
state=State(
|
32
|
+
meta=StateMeta(
|
33
|
+
workflow_inputs=Inputs(
|
34
|
+
query="test query",
|
35
|
+
document_index="test-index",
|
36
|
+
)
|
37
|
+
),
|
38
|
+
)
|
39
|
+
)
|
40
|
+
|
41
|
+
with pytest.raises(NodeException) as exc_info:
|
42
|
+
node.run()
|
43
|
+
|
44
|
+
assert exc_info.value.code == WorkflowErrorCode.PROVIDER_CREDENTIALS_UNAVAILABLE
|
45
|
+
assert exc_info.value.message == "Provider credentials is missing or unavailable"
|
46
|
+
|
47
|
+
|
48
|
+
def test_search_node_handles_403_error_with_custom_detail(vellum_client):
|
49
|
+
"""Test that SearchNode properly handles 403 API errors with custom detail message."""
|
50
|
+
|
51
|
+
class Inputs(BaseInputs):
|
52
|
+
query: str
|
53
|
+
document_index: str
|
54
|
+
|
55
|
+
class State(BaseState):
|
56
|
+
pass
|
57
|
+
|
58
|
+
class SearchNode(BaseSearchNode):
|
59
|
+
query = Inputs.query
|
60
|
+
document_index = Inputs.document_index
|
61
|
+
|
62
|
+
vellum_client.search.side_effect = ApiError(status_code=403, body={"detail": "Access denied to document index"})
|
63
|
+
|
64
|
+
node = SearchNode(
|
65
|
+
state=State(
|
66
|
+
meta=StateMeta(
|
67
|
+
workflow_inputs=Inputs(
|
68
|
+
query="test query",
|
69
|
+
document_index="test-index",
|
70
|
+
)
|
71
|
+
),
|
72
|
+
)
|
73
|
+
)
|
74
|
+
|
75
|
+
with pytest.raises(NodeException) as exc_info:
|
76
|
+
node.run()
|
77
|
+
|
78
|
+
assert exc_info.value.code == WorkflowErrorCode.PROVIDER_CREDENTIALS_UNAVAILABLE
|
79
|
+
assert exc_info.value.message == "Access denied to document index"
|
80
|
+
|
81
|
+
|
82
|
+
def test_search_node_handles_403_error_without_detail(vellum_client):
|
83
|
+
"""Test that SearchNode properly handles 403 API errors without detail in body."""
|
84
|
+
|
85
|
+
class Inputs(BaseInputs):
|
86
|
+
query: str
|
87
|
+
document_index: str
|
88
|
+
|
89
|
+
class State(BaseState):
|
90
|
+
pass
|
91
|
+
|
92
|
+
class SearchNode(BaseSearchNode):
|
93
|
+
query = Inputs.query
|
94
|
+
document_index = Inputs.document_index
|
95
|
+
|
96
|
+
vellum_client.search.side_effect = ApiError(status_code=403, body={})
|
97
|
+
|
98
|
+
node = SearchNode(
|
99
|
+
state=State(
|
100
|
+
meta=StateMeta(
|
101
|
+
workflow_inputs=Inputs(
|
102
|
+
query="test query",
|
103
|
+
document_index="test-index",
|
104
|
+
)
|
105
|
+
),
|
106
|
+
)
|
107
|
+
)
|
108
|
+
|
109
|
+
with pytest.raises(NodeException) as exc_info:
|
110
|
+
node.run()
|
111
|
+
|
112
|
+
assert exc_info.value.code == WorkflowErrorCode.PROVIDER_CREDENTIALS_UNAVAILABLE
|
113
|
+
assert exc_info.value.message == "Provider credentials is missing or unavailable"
|
114
|
+
|
115
|
+
|
116
|
+
def test_search_node_handles_other_4xx_errors(vellum_client):
|
117
|
+
"""Test that SearchNode properly handles other 4xx API errors."""
|
118
|
+
|
119
|
+
class Inputs(BaseInputs):
|
120
|
+
query: str
|
121
|
+
document_index: str
|
122
|
+
|
123
|
+
class State(BaseState):
|
124
|
+
pass
|
125
|
+
|
126
|
+
class SearchNode(BaseSearchNode):
|
127
|
+
query = Inputs.query
|
128
|
+
document_index = Inputs.document_index
|
129
|
+
|
130
|
+
vellum_client.search.side_effect = ApiError(status_code=400, body={"detail": "Invalid request parameters"})
|
131
|
+
|
132
|
+
node = SearchNode(
|
133
|
+
state=State(
|
134
|
+
meta=StateMeta(
|
135
|
+
workflow_inputs=Inputs(
|
136
|
+
query="test query",
|
137
|
+
document_index="test-index",
|
138
|
+
)
|
139
|
+
),
|
140
|
+
)
|
141
|
+
)
|
142
|
+
|
143
|
+
with pytest.raises(NodeException) as exc_info:
|
144
|
+
node.run()
|
145
|
+
|
146
|
+
assert exc_info.value.code == WorkflowErrorCode.INVALID_INPUTS
|
147
|
+
assert "Invalid request parameters" in exc_info.value.message
|
148
|
+
|
149
|
+
|
150
|
+
def test_search_node_handles_5xx_errors(vellum_client):
|
151
|
+
"""Test that SearchNode properly handles 5xx API errors as internal errors."""
|
152
|
+
|
153
|
+
class Inputs(BaseInputs):
|
154
|
+
query: str
|
155
|
+
document_index: str
|
156
|
+
|
157
|
+
class State(BaseState):
|
158
|
+
pass
|
159
|
+
|
160
|
+
class SearchNode(BaseSearchNode):
|
161
|
+
query = Inputs.query
|
162
|
+
document_index = Inputs.document_index
|
163
|
+
|
164
|
+
vellum_client.search.side_effect = ApiError(status_code=500, body={"detail": "Internal server error"})
|
165
|
+
|
166
|
+
node = SearchNode(
|
167
|
+
state=State(
|
168
|
+
meta=StateMeta(
|
169
|
+
workflow_inputs=Inputs(
|
170
|
+
query="test query",
|
171
|
+
document_index="test-index",
|
172
|
+
)
|
173
|
+
),
|
174
|
+
)
|
175
|
+
)
|
176
|
+
|
177
|
+
with pytest.raises(NodeException) as exc_info:
|
178
|
+
node.run()
|
179
|
+
|
180
|
+
assert exc_info.value.code == WorkflowErrorCode.INTERNAL_ERROR
|
181
|
+
assert "An error occurred while searching against Document Index 'test-index'" in exc_info.value.message
|
182
|
+
|
183
|
+
|
184
|
+
def test_search_node_handles_api_error_without_status_code(vellum_client):
|
185
|
+
"""Test that SearchNode properly handles API errors without status code."""
|
186
|
+
|
187
|
+
class Inputs(BaseInputs):
|
188
|
+
query: str
|
189
|
+
document_index: str
|
190
|
+
|
191
|
+
class State(BaseState):
|
192
|
+
pass
|
193
|
+
|
194
|
+
class SearchNode(BaseSearchNode):
|
195
|
+
query = Inputs.query
|
196
|
+
document_index = Inputs.document_index
|
197
|
+
|
198
|
+
vellum_client.search.side_effect = ApiError(status_code=None, body={"detail": "Unknown error"})
|
199
|
+
|
200
|
+
node = SearchNode(
|
201
|
+
state=State(
|
202
|
+
meta=StateMeta(
|
203
|
+
workflow_inputs=Inputs(
|
204
|
+
query="test query",
|
205
|
+
document_index="test-index",
|
206
|
+
)
|
207
|
+
),
|
208
|
+
)
|
209
|
+
)
|
210
|
+
|
211
|
+
with pytest.raises(NodeException) as exc_info:
|
212
|
+
node.run()
|
213
|
+
|
214
|
+
assert exc_info.value.code == WorkflowErrorCode.INTERNAL_ERROR
|
215
|
+
assert "An error occurred while searching against Document Index 'test-index'" in exc_info.value.message
|
@@ -41,7 +41,7 @@ vellum_ee/workflows/display/nodes/vellum/conditional_node.py,sha256=MrvyiYD0qgQf
|
|
41
41
|
vellum_ee/workflows/display/nodes/vellum/error_node.py,sha256=m2DmOXm9-jiiIl6zwkXHNfsYp5PTpBHEdt5xaIsabWo,2363
|
42
42
|
vellum_ee/workflows/display/nodes/vellum/final_output_node.py,sha256=jUDI2FwVaw0Or4zJL58J_g0S--i59Hzik60s_Es_M-8,3098
|
43
43
|
vellum_ee/workflows/display/nodes/vellum/guardrail_node.py,sha256=5_5D5PMzBOeUdVtRlANbfEsu7Gv3r37dLvpfjGAqYac,2330
|
44
|
-
vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256
|
44
|
+
vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=2qp3J1nZ4R4szTynakwT9gL51SZEjIiLLdTvA_wIQu0,10954
|
45
45
|
vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py,sha256=fQV5o83BPTwGX6o-ThN4r7BcIhySyqwpW1JGYWpvSJI,5625
|
46
46
|
vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=2teCYQSX8g-b8aaC_MY4XSC4GRMTJigPFWNTQEkC_gk,3907
|
47
47
|
vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=yBWeN4T_lOsDVnNOKWRiT7JYKu0IR5Fx2z99iq6QKSA,3273
|
@@ -82,7 +82,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_stat
|
|
82
82
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=MNnQ51ZWOQGVfBdpIqvr4OZF0tWdfrh2bsHP3xkTwQw,5841
|
83
83
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=kLOnUNn-r1w1JXNQcVKe-Vp-fKhSfuDBuDqrjGkFZ3U,5544
|
84
84
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py,sha256=v07cILUzS5iFYDrSOAXK93yz50-FtxLaMYMwoaPOv20,7374
|
85
|
-
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py,sha256=
|
85
|
+
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py,sha256=Jcuzu_zjS4ATrPg-pKvrU9WeUFAWMmPQVIcYltG6NfA,14930
|
86
86
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=u2nquKoO3o2xIkU_uFPOb_s5YoLmULiq09vb6Ee0Cqw,21415
|
87
87
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=3gZuNM8sT6ovVaeoAvd2JoyKwuxokvowlhH8kwDUoZ8,16559
|
88
88
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=IIJt7YZBzkhNtbmaMwCX4ENs58QtSIIoBHlMR6OwGU8,8342
|
@@ -131,12 +131,12 @@ vellum_ee/workflows/tests/local_workflow/workflow.py,sha256=A4qOzOPNwePYxWbcAgIP
|
|
131
131
|
vellum_ee/workflows/tests/test_display_meta.py,sha256=DIzjNbwK1-4mlttPML6NskQ4rPVMXhj5zeOmBEyPqKI,3728
|
132
132
|
vellum_ee/workflows/tests/test_server.py,sha256=SsOkS6sGO7uGC4mxvk4iv8AtcXs058P9hgFHzTWmpII,14519
|
133
133
|
vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
|
134
|
-
vellum/__init__.py,sha256=
|
134
|
+
vellum/__init__.py,sha256=IYGBqJ8OLfaIyX3UJcfQeRdF-qKVepOPdi6M0O3Vgq4,42290
|
135
135
|
vellum/client/README.md,sha256=CuGUYnaE0Imt0KqQ4sIPaUghCjLHkF3DdEvZWu14-8s,4807
|
136
136
|
vellum/client/__init__.py,sha256=AYopGv2ZRVn3zsU8_km6KOvEHDbXiTPCVuYVI7bWvdA,120166
|
137
137
|
vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
|
138
138
|
vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
|
139
|
-
vellum/client/core/client_wrapper.py,sha256=
|
139
|
+
vellum/client/core/client_wrapper.py,sha256=dnusvY6O2THB1zDdl_1dPfH3fL9UKVhqz1Gp1UtaEck,1869
|
140
140
|
vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
141
141
|
vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
|
142
142
|
vellum/client/core/http_client.py,sha256=Z77OIxIbL4OAB2IDqjRq_sYa5yNYAWfmdhdCSSvh6Y4,19552
|
@@ -204,7 +204,7 @@ vellum/client/resources/workspace_secrets/__init__.py,sha256=FTtvy8EDg9nNNg9WCat
|
|
204
204
|
vellum/client/resources/workspace_secrets/client.py,sha256=zlBdbeTP6sqvtyl_DlrpfG-W5hSP7tJ1NYLSygi4CLU,8205
|
205
205
|
vellum/client/resources/workspaces/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
|
206
206
|
vellum/client/resources/workspaces/client.py,sha256=RthwzN1o-Jxwg5yyNNodavFyNUSxfLoTv26w3mRR5g8,3595
|
207
|
-
vellum/client/types/__init__.py,sha256=
|
207
|
+
vellum/client/types/__init__.py,sha256=4IDszjF4RsdBrwOSkZ21ZJ1I90jyRwCkZpmXC8n7kpI,64067
|
208
208
|
vellum/client/types/ad_hoc_execute_prompt_event.py,sha256=bCjujA2XsOgyF3bRZbcEqV2rOIymRgsLoIRtZpB14xg,607
|
209
209
|
vellum/client/types/ad_hoc_expand_meta.py,sha256=1gv-NCsy_6xBYupLvZH979yf2VMdxAU-l0y0ynMKZaw,1331
|
210
210
|
vellum/client/types/ad_hoc_fulfilled_prompt_execution_meta.py,sha256=oDG60TpwK1YNSKhRsBbiP2O3ZF9PKR-M9chGIfKw4R4,1004
|
@@ -324,10 +324,12 @@ vellum/client/types/execution_vellum_value.py,sha256=PpbrbJdSioqaqT2gZ6mx2Ht0Oy8
|
|
324
324
|
vellum/client/types/external_input_descriptor.py,sha256=ErOW2OfFMz1FDGmVY6NgiUBPsleaWhdJBekwFp4ru7o,805
|
325
325
|
vellum/client/types/external_test_case_execution.py,sha256=TkO1CQcEI8LA7sdYJfAqhbdkj27sXEkF8VL7zBeDBM4,877
|
326
326
|
vellum/client/types/external_test_case_execution_request.py,sha256=xd80GZg4FbZP6FZRIhZL9V1uFetI3bcCj-wzanco5tQ,921
|
327
|
+
vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py,sha256=XhNEBWd5qzFiXTestFPTusjxYfqW8j_kHBebCMfa58M,719
|
328
|
+
vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py,sha256=xC0-zak2HonnyyiooqXSWiQQyrQK6yf6BFogt_TzSCo,726
|
327
329
|
vellum/client/types/finish_reason_enum.py,sha256=KoNjzvXMHDCT0AUhhwGoZ1_7bi4h3fZEFvvHyGyoTP8,169
|
328
330
|
vellum/client/types/folder_entity.py,sha256=v8zNprIbxktOzmncbNXTOJlLTBV5bZqD1Z_AGGHG1_8,578
|
329
331
|
vellum/client/types/folder_entity_document_index.py,sha256=-Tg2qnzGhp2FLnvGrgoVr0ZBEKFmm2TjgYvlII8tkog,839
|
330
|
-
vellum/client/types/folder_entity_document_index_data.py,sha256=
|
332
|
+
vellum/client/types/folder_entity_document_index_data.py,sha256=1mQxkj4TlbKyGpqMY_aPgWyDFTN6YW9VfszROU1cmM4,844
|
331
333
|
vellum/client/types/folder_entity_folder.py,sha256=1GWfyHdenyAI2GXiouIbnFhPK4ADqZGFh-6fpp_C6-U,792
|
332
334
|
vellum/client/types/folder_entity_folder_data.py,sha256=JLYkhvRY63-ojNY84lfRTaUg25KjslSE-iNAC2NYCTI,674
|
333
335
|
vellum/client/types/folder_entity_prompt_sandbox.py,sha256=7CGVcK5maoqO7CC7sFfi6F5X0QWdHVbEygqLyci_VDY,839
|
@@ -375,8 +377,8 @@ vellum/client/types/image_chat_message_content_request.py,sha256=b0K1NnY-NneG_V3
|
|
375
377
|
vellum/client/types/image_prompt_block.py,sha256=JIcfWZAWYcOm04Y6XjmxPG58SaoXwIjuZwnVypEVahU,1008
|
376
378
|
vellum/client/types/image_vellum_value.py,sha256=69XnqE9m-bd3dOdMD73WtfDm_kDrVg-y3fi35akuqsk,748
|
377
379
|
vellum/client/types/image_vellum_value_request.py,sha256=-Q66T8M6fAf9K_v0LeRwZjB_6pkBUSyMUQc6plRRK5E,777
|
378
|
-
vellum/client/types/indexing_config_vectorizer.py,sha256=
|
379
|
-
vellum/client/types/indexing_config_vectorizer_request.py,sha256=
|
380
|
+
vellum/client/types/indexing_config_vectorizer.py,sha256=pVZ5mCY75LQD15r83IMmPmt8tK__kSFlBd62szI_ZYw,1673
|
381
|
+
vellum/client/types/indexing_config_vectorizer_request.py,sha256=q2pC4oIEy74xCgsl4hOnHtNA4BRYhQsbiHOn_IdT3V8,1900
|
380
382
|
vellum/client/types/indexing_state_enum.py,sha256=KWYMz5DwJnVhu3ZlSDdqiC5MtiTIdrxE4EvwFYiel1U,213
|
381
383
|
vellum/client/types/initiated_ad_hoc_execute_prompt_event.py,sha256=B34Q2aU2vj9qpjpWXIieN839iB7t4EWCD9mmCfbkwpo,915
|
382
384
|
vellum/client/types/initiated_execute_prompt_event.py,sha256=tHt80ZIuKk6B85IQqSF3MQqiSSiBsSP2Aw3XuD5xk6E,893
|
@@ -1002,6 +1004,8 @@ vellum/types/execution_vellum_value.py,sha256=VRe64r540rkdVWjWijd7Y5JsYM_9zw09QU
|
|
1002
1004
|
vellum/types/external_input_descriptor.py,sha256=-r6xPo7-1Ioq4XZ2nwcrg8OBoyVItKr-BeXspJwDWDQ,163
|
1003
1005
|
vellum/types/external_test_case_execution.py,sha256=Av4H59SBBCZ9CZtT-eKD3n05lgljTqdtSZSjtsDpbc4,166
|
1004
1006
|
vellum/types/external_test_case_execution_request.py,sha256=oJx3JSLU9aponZ53dY78ymcSZbQbHpAwnch9aq0F7ws,174
|
1007
|
+
vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py,sha256=NG9MjraDr4m6gdIo-tuD9Rtc9qGAWBuwk8duZxjoIg0,182
|
1008
|
+
vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py,sha256=_5CERkmrTW-Pie0V9QC5IR_WFS5YRB4yNfndaUv6rJQ,190
|
1005
1009
|
vellum/types/finish_reason_enum.py,sha256=CIomSWB4DFcwnO92nIjQsI_TWMtJTxBFwnFSWVoATsY,156
|
1006
1010
|
vellum/types/folder_entity.py,sha256=zY6js2gTkiJtpUqa73fKd8niwxwsxF-woj_QiyTFXos,151
|
1007
1011
|
vellum/types/folder_entity_document_index.py,sha256=WWj08Jkv9NyoPwWtvhQmdoEMnSJJ42HIFgOHJiFsm4o,166
|
@@ -1594,7 +1598,7 @@ vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=cD2Rz
|
|
1594
1598
|
vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1595
1599
|
vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py,sha256=terQtPqLGiKKGtU7zbkM3XkbVddLQI87bBj31M0zaRE,21356
|
1596
1600
|
vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=0a40fkkZkFMmZN0CsWf6EP_y1H6x36EGa3WcfVNyOsM,9797
|
1597
|
-
vellum/workflows/nodes/displayable/bases/search_node.py,sha256
|
1601
|
+
vellum/workflows/nodes/displayable/bases/search_node.py,sha256=-BxQtuPgq8NZfUf5XJgHNQTni5kGbvAHq7WFqd0Euck,6107
|
1598
1602
|
vellum/workflows/nodes/displayable/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1599
1603
|
vellum/workflows/nodes/displayable/bases/tests/test_utils.py,sha256=eqdqbKNRWVMDPevgwLg1i6YK0g4L4bCy-7xCBN5yYZI,3156
|
1600
1604
|
vellum/workflows/nodes/displayable/bases/types.py,sha256=C37B2Qh2YP7s7pUjd-EYKc2Zl1TbnCgI_mENuUSb8bo,1706
|
@@ -1640,6 +1644,7 @@ vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/__init__.py
|
|
1640
1644
|
vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.py,sha256=c98nMPogZ6iN_pTvVUMTB3J72Hj--H-XVgvvRXhdSQE,19085
|
1641
1645
|
vellum/workflows/nodes/displayable/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1642
1646
|
vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py,sha256=MHuIolSsrY9ziwoXWsye3XOODncL9DLZOkNYzQMLhRw,4696
|
1647
|
+
vellum/workflows/nodes/displayable/tests/test_search_node_error_handling.py,sha256=8aw8hDFL0ZXThvAa7yxrJN026EYGD4-Q1si3Phu9-_0,6307
|
1643
1648
|
vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py,sha256=VepO5z1277c1y5N6LLIC31nnWD1aak2m5oPFplfJHHs,6935
|
1644
1649
|
vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py,sha256=dc3EEn1sOICpr3GdS8eyeFtExaGwWWcw9eHSdkRhQJU,2584
|
1645
1650
|
vellum/workflows/nodes/experimental/README.md,sha256=eF6DfIL8t-HbF9-mcofOMymKrraiBHDLKTlnBa51ZiE,284
|
@@ -1715,8 +1720,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
|
|
1715
1720
|
vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1716
1721
|
vellum/workflows/workflows/tests/test_base_workflow.py,sha256=fROqff6AZpCIzaSwOKSdtYy4XR0UZQ6ejxL3RJOSJVs,20447
|
1717
1722
|
vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
|
1718
|
-
vellum_ai-0.14.
|
1719
|
-
vellum_ai-0.14.
|
1720
|
-
vellum_ai-0.14.
|
1721
|
-
vellum_ai-0.14.
|
1722
|
-
vellum_ai-0.14.
|
1723
|
+
vellum_ai-0.14.69.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
1724
|
+
vellum_ai-0.14.69.dist-info/METADATA,sha256=kD1Yw09evk1wBzHUC1nBcnmpRGuK1v5ccyY_woFDV38,5556
|
1725
|
+
vellum_ai-0.14.69.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
1726
|
+
vellum_ai-0.14.69.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
|
1727
|
+
vellum_ai-0.14.69.dist-info/RECORD,,
|
@@ -18,10 +18,9 @@ _InlinePromptNodeType = TypeVar("_InlinePromptNodeType", bound=InlinePromptNode)
|
|
18
18
|
|
19
19
|
|
20
20
|
class BaseInlinePromptNodeDisplay(BaseNodeDisplay[_InlinePromptNodeType], Generic[_InlinePromptNodeType]):
|
21
|
-
__serializable_inputs__ = {InlinePromptNode.prompt_inputs}
|
21
|
+
__serializable_inputs__ = {InlinePromptNode.prompt_inputs, InlinePromptNode.functions}
|
22
22
|
__unserializable_attributes__ = {
|
23
23
|
InlinePromptNode.blocks,
|
24
|
-
InlinePromptNode.functions,
|
25
24
|
InlinePromptNode.parameters,
|
26
25
|
InlinePromptNode.settings,
|
27
26
|
InlinePromptNode.expand_meta,
|
@@ -48,9 +47,10 @@ class BaseInlinePromptNodeDisplay(BaseNodeDisplay[_InlinePromptNodeType], Generi
|
|
48
47
|
blocks: list = [
|
49
48
|
self._generate_prompt_block(block, input_variable_id_by_name, [i]) for i, block in enumerate(node_blocks)
|
50
49
|
]
|
50
|
+
|
51
51
|
functions = (
|
52
52
|
[self._generate_function_tools(function, i) for i, function in enumerate(function_definitions)]
|
53
|
-
if function_definitions
|
53
|
+
if isinstance(function_definitions, list)
|
54
54
|
else []
|
55
55
|
)
|
56
56
|
blocks.extend(functions)
|
@@ -1,5 +1,11 @@
|
|
1
1
|
from deepdiff import DeepDiff
|
2
2
|
|
3
|
+
from vellum import ChatMessagePromptBlock, FunctionDefinition, JinjaPromptBlock
|
4
|
+
from vellum.workflows import BaseWorkflow
|
5
|
+
from vellum.workflows.inputs import BaseInputs
|
6
|
+
from vellum.workflows.nodes import InlinePromptNode
|
7
|
+
from vellum.workflows.nodes.bases.base import BaseNode
|
8
|
+
from vellum.workflows.state import BaseState
|
3
9
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
4
10
|
|
5
11
|
from tests.workflows.basic_inline_prompt_node_with_functions.workflow import BasicInlinePromptWithFunctionsWorkflow
|
@@ -185,6 +191,27 @@ def test_serialize_workflow():
|
|
185
191
|
],
|
186
192
|
},
|
187
193
|
},
|
194
|
+
{
|
195
|
+
"id": "8107682b-2ca0-4967-88f9-284455936575",
|
196
|
+
"name": "functions",
|
197
|
+
"value": {
|
198
|
+
"type": "CONSTANT_VALUE",
|
199
|
+
"value": {
|
200
|
+
"type": "JSON",
|
201
|
+
"value": [
|
202
|
+
{
|
203
|
+
"state": None,
|
204
|
+
"cache_config": None,
|
205
|
+
"name": "favorite_noun",
|
206
|
+
"description": "Returns the favorite noun of the user",
|
207
|
+
"parameters": {},
|
208
|
+
"forced": None,
|
209
|
+
"strict": None,
|
210
|
+
}
|
211
|
+
],
|
212
|
+
},
|
213
|
+
},
|
214
|
+
},
|
188
215
|
],
|
189
216
|
},
|
190
217
|
prompt_node,
|
@@ -274,3 +301,57 @@ def test_serialize_workflow():
|
|
274
301
|
"name": "BasicInlinePromptWithFunctionsWorkflow",
|
275
302
|
"module": ["tests", "workflows", "basic_inline_prompt_node_with_functions", "workflow"],
|
276
303
|
}
|
304
|
+
|
305
|
+
|
306
|
+
def test_serialize_workflow_with_descriptor_functions():
|
307
|
+
"""Test that serialization handles BaseDescriptor instances in functions list."""
|
308
|
+
|
309
|
+
class TestInputs(BaseInputs):
|
310
|
+
noun: str
|
311
|
+
|
312
|
+
class MockMCPClientNode(BaseNode):
|
313
|
+
class Outputs(BaseNode.Outputs):
|
314
|
+
tools: list[FunctionDefinition]
|
315
|
+
|
316
|
+
class TestInlinePromptNodeWithDescriptorFunctions(InlinePromptNode):
|
317
|
+
ml_model = "gpt-4o"
|
318
|
+
blocks = [
|
319
|
+
ChatMessagePromptBlock(
|
320
|
+
chat_role="SYSTEM",
|
321
|
+
blocks=[JinjaPromptBlock(template="Test {{noun}}")],
|
322
|
+
),
|
323
|
+
]
|
324
|
+
prompt_inputs = {"noun": TestInputs.noun}
|
325
|
+
functions = MockMCPClientNode.Outputs.tools # type: ignore
|
326
|
+
|
327
|
+
class TestWorkflow(BaseWorkflow[TestInputs, BaseState]):
|
328
|
+
graph = MockMCPClientNode >> TestInlinePromptNodeWithDescriptorFunctions
|
329
|
+
|
330
|
+
workflow_display = get_workflow_display(workflow_class=TestWorkflow)
|
331
|
+
serialized: dict = workflow_display.serialize()
|
332
|
+
|
333
|
+
prompt_nodes = [node for node in serialized["workflow_raw_data"]["nodes"] if node["type"] == "PROMPT"]
|
334
|
+
assert len(prompt_nodes) == 1
|
335
|
+
|
336
|
+
prompt_node = prompt_nodes[0]
|
337
|
+
assert isinstance(prompt_node, dict)
|
338
|
+
blocks = prompt_node["data"]["exec_config"]["prompt_template_block_data"]["blocks"]
|
339
|
+
assert isinstance(blocks, list)
|
340
|
+
|
341
|
+
function_blocks = [
|
342
|
+
block for block in blocks if isinstance(block, dict) and block.get("block_type") == "FUNCTION_DEFINITION"
|
343
|
+
]
|
344
|
+
assert len(function_blocks) == 0 # We don't serialize the legacy function blocks when dynamic
|
345
|
+
|
346
|
+
assert "attributes" in prompt_node
|
347
|
+
assert isinstance(prompt_node["attributes"], list)
|
348
|
+
functions_attr = next(
|
349
|
+
(attr for attr in prompt_node["attributes"] if isinstance(attr, dict) and attr["name"] == "functions"), None
|
350
|
+
)
|
351
|
+
assert isinstance(functions_attr, dict), "functions attribute should be present in serialized attributes"
|
352
|
+
|
353
|
+
assert functions_attr["value"] == {
|
354
|
+
"node_id": "cb1186e0-8ff1-4145-823e-96b3fc05a39a",
|
355
|
+
"node_output_id": "470fadb9-b8b5-477e-a502-5209d398bcf9",
|
356
|
+
"type": "NODE_OUTPUT",
|
357
|
+
}
|
File without changes
|
File without changes
|
File without changes
|