vellum-ai 0.0.18__py3-none-any.whl → 0.0.25__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. vellum/__init__.py +119 -16
  2. vellum/client.py +341 -77
  3. vellum/core/__init__.py +11 -2
  4. vellum/core/client_wrapper.py +27 -0
  5. vellum/core/remove_none_from_dict.py +11 -0
  6. vellum/errors/__init__.py +2 -1
  7. vellum/errors/forbidden_error.py +9 -0
  8. vellum/resources/deployments/client.py +35 -15
  9. vellum/resources/document_indexes/client.py +64 -16
  10. vellum/resources/documents/client.py +110 -35
  11. vellum/resources/model_versions/client.py +67 -25
  12. vellum/resources/registered_prompts/client.py +80 -16
  13. vellum/resources/sandboxes/client.py +90 -25
  14. vellum/resources/test_suites/client.py +90 -25
  15. vellum/types/__init__.py +108 -0
  16. vellum/types/conditional_node_result.py +25 -0
  17. vellum/types/conditional_node_result_data.py +24 -0
  18. vellum/types/deployment_node_result.py +25 -0
  19. vellum/types/deployment_node_result_data.py +26 -0
  20. vellum/types/deployment_read.py +2 -6
  21. vellum/types/document.py +3 -7
  22. vellum/types/document_document_to_document_index.py +2 -2
  23. vellum/types/document_index_read.py +3 -7
  24. vellum/types/enriched_normalized_completion.py +5 -9
  25. vellum/types/evaluation_params.py +1 -3
  26. vellum/types/evaluation_params_request.py +1 -3
  27. vellum/types/execute_workflow_stream_error_response.py +24 -0
  28. vellum/types/generate_error_response.py +1 -1
  29. vellum/types/generate_request.py +3 -7
  30. vellum/types/generate_result.py +2 -6
  31. vellum/types/generate_result_data.py +1 -1
  32. vellum/types/generate_result_error.py +1 -1
  33. vellum/types/model_version_build_config.py +2 -6
  34. vellum/types/model_version_compile_prompt_response.py +1 -1
  35. vellum/types/model_version_compiled_prompt.py +2 -4
  36. vellum/types/model_version_exec_config.py +3 -3
  37. vellum/types/model_version_read.py +7 -10
  38. vellum/types/model_version_sandbox_snapshot.py +3 -5
  39. vellum/types/prompt_node_result.py +25 -0
  40. vellum/types/prompt_node_result_data.py +26 -0
  41. vellum/types/prompt_template_block_properties.py +1 -0
  42. vellum/types/prompt_template_block_properties_request.py +3 -2
  43. vellum/types/prompt_template_block_request.py +1 -1
  44. vellum/types/prompt_template_input_variable.py +1 -1
  45. vellum/types/prompt_template_input_variable_request.py +1 -1
  46. vellum/types/provider_enum.py +5 -0
  47. vellum/types/register_prompt_error_response.py +1 -1
  48. vellum/types/register_prompt_prompt.py +2 -2
  49. vellum/types/register_prompt_prompt_info_request.py +1 -1
  50. vellum/types/register_prompt_response.py +5 -7
  51. vellum/types/registered_prompt_deployment.py +3 -3
  52. vellum/types/registered_prompt_model_version.py +2 -2
  53. vellum/types/registered_prompt_sandbox.py +2 -2
  54. vellum/types/registered_prompt_sandbox_snapshot.py +1 -1
  55. vellum/types/sandbox_node_result.py +25 -0
  56. vellum/types/sandbox_node_result_data.py +26 -0
  57. vellum/types/sandbox_scenario.py +2 -2
  58. vellum/types/scenario_input_request.py +1 -1
  59. vellum/types/search_error_response.py +1 -1
  60. vellum/types/search_filters_request.py +1 -1
  61. vellum/types/search_node_result.py +25 -0
  62. vellum/types/search_node_result_data.py +27 -0
  63. vellum/types/search_request_options_request.py +4 -6
  64. vellum/types/search_response.py +1 -1
  65. vellum/types/search_result.py +3 -3
  66. vellum/types/search_result_merging_request.py +1 -1
  67. vellum/types/search_weights_request.py +2 -2
  68. vellum/types/slim_document.py +5 -9
  69. vellum/types/submit_completion_actual_request.py +5 -15
  70. vellum/types/terminal_node_chat_history_result.py +26 -0
  71. vellum/types/terminal_node_json_result.py +25 -0
  72. vellum/types/terminal_node_result.py +25 -0
  73. vellum/types/terminal_node_result_data.py +25 -0
  74. vellum/types/terminal_node_result_output.py +40 -0
  75. vellum/types/terminal_node_string_result.py +25 -0
  76. vellum/types/test_suite_test_case.py +4 -8
  77. vellum/types/upload_document_response.py +1 -1
  78. vellum/types/workflow_event_error.py +26 -0
  79. vellum/types/workflow_execution_event_error_code.py +31 -0
  80. vellum/types/workflow_execution_node_result_event.py +27 -0
  81. vellum/types/workflow_execution_workflow_result_event.py +27 -0
  82. vellum/types/workflow_node_result_data.py +72 -0
  83. vellum/types/workflow_node_result_event.py +33 -0
  84. vellum/types/workflow_node_result_event_state.py +36 -0
  85. vellum/types/workflow_request_chat_history_input_request.py +28 -0
  86. vellum/types/workflow_request_input_request.py +40 -0
  87. vellum/types/workflow_request_json_input_request.py +27 -0
  88. vellum/types/workflow_request_string_input_request.py +27 -0
  89. vellum/types/workflow_result_event.py +31 -0
  90. vellum/types/workflow_result_event_output_data.py +40 -0
  91. vellum/types/workflow_result_event_output_data_chat_history.py +32 -0
  92. vellum/types/workflow_result_event_output_data_json.py +31 -0
  93. vellum/types/workflow_result_event_output_data_string.py +33 -0
  94. vellum/types/workflow_stream_event.py +29 -0
  95. {vellum_ai-0.0.18.dist-info → vellum_ai-0.0.25.dist-info}/METADATA +1 -1
  96. vellum_ai-0.0.25.dist-info/RECORD +149 -0
  97. vellum/core/remove_none_from_headers.py +0 -11
  98. vellum_ai-0.0.18.dist-info/RECORD +0 -113
  99. {vellum_ai-0.0.18.dist-info → vellum_ai-0.0.25.dist-info}/WHEEL +0 -0
vellum/client.py CHANGED
@@ -9,10 +9,11 @@ import httpx
9
9
  import pydantic
10
10
 
11
11
  from .core.api_error import ApiError
12
+ from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
12
13
  from .core.jsonable_encoder import jsonable_encoder
13
- from .core.remove_none_from_headers import remove_none_from_headers
14
14
  from .environment import VellumEnvironment
15
15
  from .errors.bad_request_error import BadRequestError
16
+ from .errors.forbidden_error import ForbiddenError
16
17
  from .errors.internal_server_error import InternalServerError
17
18
  from .errors.not_found_error import NotFoundError
18
19
  from .resources.deployments.client import AsyncDeploymentsClient, DeploymentsClient
@@ -22,6 +23,7 @@ from .resources.model_versions.client import AsyncModelVersionsClient, ModelVers
22
23
  from .resources.registered_prompts.client import AsyncRegisteredPromptsClient, RegisteredPromptsClient
23
24
  from .resources.sandboxes.client import AsyncSandboxesClient, SandboxesClient
24
25
  from .resources.test_suites.client import AsyncTestSuitesClient, TestSuitesClient
26
+ from .types.generate_error_response import GenerateErrorResponse
25
27
  from .types.generate_options_request import GenerateOptionsRequest
26
28
  from .types.generate_request import GenerateRequest
27
29
  from .types.generate_response import GenerateResponse
@@ -29,22 +31,88 @@ from .types.generate_stream_response import GenerateStreamResponse
29
31
  from .types.search_request_options_request import SearchRequestOptionsRequest
30
32
  from .types.search_response import SearchResponse
31
33
  from .types.submit_completion_actual_request import SubmitCompletionActualRequest
34
+ from .types.workflow_request_input_request import WorkflowRequestInputRequest
35
+ from .types.workflow_stream_event import WorkflowStreamEvent
32
36
 
33
37
  # this is used as the default value for optional parameters
34
38
  OMIT = typing.cast(typing.Any, ...)
35
39
 
36
40
 
37
41
  class Vellum:
38
- def __init__(self, *, environment: VellumEnvironment = VellumEnvironment.PRODUCTION, api_key: str):
42
+ def __init__(
43
+ self,
44
+ *,
45
+ environment: VellumEnvironment = VellumEnvironment.PRODUCTION,
46
+ api_key: str,
47
+ timeout: typing.Optional[float] = None,
48
+ ):
39
49
  self._environment = environment
40
- self.api_key = api_key
41
- self.deployments = DeploymentsClient(environment=self._environment, api_key=self.api_key)
42
- self.document_indexes = DocumentIndexesClient(environment=self._environment, api_key=self.api_key)
43
- self.documents = DocumentsClient(environment=self._environment, api_key=self.api_key)
44
- self.model_versions = ModelVersionsClient(environment=self._environment, api_key=self.api_key)
45
- self.registered_prompts = RegisteredPromptsClient(environment=self._environment, api_key=self.api_key)
46
- self.sandboxes = SandboxesClient(environment=self._environment, api_key=self.api_key)
47
- self.test_suites = TestSuitesClient(environment=self._environment, api_key=self.api_key)
50
+ self._client_wrapper = SyncClientWrapper(api_key=api_key, httpx_client=httpx.Client(timeout=timeout))
51
+ self.deployments = DeploymentsClient(environment=environment, client_wrapper=self._client_wrapper)
52
+ self.document_indexes = DocumentIndexesClient(environment=environment, client_wrapper=self._client_wrapper)
53
+ self.documents = DocumentsClient(environment=environment, client_wrapper=self._client_wrapper)
54
+ self.model_versions = ModelVersionsClient(environment=environment, client_wrapper=self._client_wrapper)
55
+ self.registered_prompts = RegisteredPromptsClient(environment=environment, client_wrapper=self._client_wrapper)
56
+ self.sandboxes = SandboxesClient(environment=environment, client_wrapper=self._client_wrapper)
57
+ self.test_suites = TestSuitesClient(environment=environment, client_wrapper=self._client_wrapper)
58
+
59
+ def execute_workflow_stream(
60
+ self,
61
+ *,
62
+ workflow_deployment_id: typing.Optional[str] = OMIT,
63
+ workflow_deployment_name: typing.Optional[str] = OMIT,
64
+ release_tag: typing.Optional[str] = OMIT,
65
+ inputs: typing.List[WorkflowRequestInputRequest],
66
+ external_id: typing.Optional[str] = OMIT,
67
+ ) -> typing.Iterator[WorkflowStreamEvent]:
68
+ """
69
+ <strong style="background-color:#ffc107; color:white; padding:4px; border-radius:4px">Unstable</strong>
70
+
71
+ Executes a deployed Workflow and streams back its results.
72
+
73
+ Parameters:
74
+ - workflow_deployment_id: typing.Optional[str]. The ID of the Workflow Deployment. Must provide either this or workflow_deployment_name.
75
+
76
+ - workflow_deployment_name: typing.Optional[str]. The name of the Workflow Deployment. Must provide either this or workflow_deployment_id.
77
+
78
+ - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment
79
+
80
+ - inputs: typing.List[WorkflowRequestInputRequest].
81
+
82
+ - external_id: typing.Optional[str]. Optionally include a unique identifier for tracking purposes.
83
+ """
84
+ _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
85
+ if workflow_deployment_id is not OMIT:
86
+ _request["workflow_deployment_id"] = workflow_deployment_id
87
+ if workflow_deployment_name is not OMIT:
88
+ _request["workflow_deployment_name"] = workflow_deployment_name
89
+ if release_tag is not OMIT:
90
+ _request["release_tag"] = release_tag
91
+ if external_id is not OMIT:
92
+ _request["external_id"] = external_id
93
+ with self._client_wrapper.httpx_client.stream(
94
+ "POST",
95
+ urllib.parse.urljoin(f"{self._environment.predict}/", "v1/execute-workflow-stream"),
96
+ json=jsonable_encoder(_request),
97
+ headers=self._client_wrapper.get_headers(),
98
+ timeout=None,
99
+ ) as _response:
100
+ if 200 <= _response.status_code < 300:
101
+ for _text in _response.iter_lines():
102
+ if len(_text) == 0:
103
+ continue
104
+ yield pydantic.parse_obj_as(WorkflowStreamEvent, json.loads(_text)) # type: ignore
105
+ return
106
+ if _response.status_code == 404:
107
+ raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
108
+ if _response.status_code == 500:
109
+ raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
110
+ try:
111
+ _response.read()
112
+ _response_json = _response.json()
113
+ except JSONDecodeError:
114
+ raise ApiError(status_code=_response.status_code, body=_response.text)
115
+ raise ApiError(status_code=_response.status_code, body=_response_json)
48
116
 
49
117
  def generate(
50
118
  self,
@@ -54,6 +122,22 @@ class Vellum:
54
122
  requests: typing.List[GenerateRequest],
55
123
  options: typing.Optional[GenerateOptionsRequest] = OMIT,
56
124
  ) -> GenerateResponse:
125
+ """
126
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
127
+
128
+ Generate a completion using a previously defined deployment.
129
+
130
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
131
+
132
+ Parameters:
133
+ - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.
134
+
135
+ - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.
136
+
137
+ - requests: typing.List[GenerateRequest]. The generation requests to make. Supplying multiple will perform a bulk request to the LLM provided when possible.
138
+
139
+ - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.
140
+ """
57
141
  _request: typing.Dict[str, typing.Any] = {"requests": requests}
58
142
  if deployment_id is not OMIT:
59
143
  _request["deployment_id"] = deployment_id
@@ -61,17 +145,19 @@ class Vellum:
61
145
  _request["deployment_name"] = deployment_name
62
146
  if options is not OMIT:
63
147
  _request["options"] = options
64
- _response = httpx.request(
148
+ _response = self._client_wrapper.httpx_client.request(
65
149
  "POST",
66
150
  urllib.parse.urljoin(f"{self._environment.predict}/", "v1/generate"),
67
151
  json=jsonable_encoder(_request),
68
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
152
+ headers=self._client_wrapper.get_headers(),
69
153
  timeout=None,
70
154
  )
71
155
  if 200 <= _response.status_code < 300:
72
156
  return pydantic.parse_obj_as(GenerateResponse, _response.json()) # type: ignore
73
157
  if _response.status_code == 400:
74
158
  raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
159
+ if _response.status_code == 403:
160
+ raise ForbiddenError(pydantic.parse_obj_as(GenerateErrorResponse, _response.json())) # type: ignore
75
161
  if _response.status_code == 404:
76
162
  raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
77
163
  if _response.status_code == 500:
@@ -90,6 +176,22 @@ class Vellum:
90
176
  requests: typing.List[GenerateRequest],
91
177
  options: typing.Optional[GenerateOptionsRequest] = OMIT,
92
178
  ) -> typing.Iterator[GenerateStreamResponse]:
179
+ """
180
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
181
+
182
+ Generate a stream of completions using a previously defined deployment.
183
+
184
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
185
+
186
+ Parameters:
187
+ - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.
188
+
189
+ - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.
190
+
191
+ - requests: typing.List[GenerateRequest]. The generation requests to make. Supplying multiple will perform a bulk request to the LLM provided when possible.
192
+
193
+ - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.
194
+ """
93
195
  _request: typing.Dict[str, typing.Any] = {"requests": requests}
94
196
  if deployment_id is not OMIT:
95
197
  _request["deployment_id"] = deployment_id
@@ -97,26 +199,29 @@ class Vellum:
97
199
  _request["deployment_name"] = deployment_name
98
200
  if options is not OMIT:
99
201
  _request["options"] = options
100
- with httpx.stream(
202
+ with self._client_wrapper.httpx_client.stream(
101
203
  "POST",
102
204
  urllib.parse.urljoin(f"{self._environment.predict}/", "v1/generate-stream"),
103
205
  json=jsonable_encoder(_request),
104
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
206
+ headers=self._client_wrapper.get_headers(),
105
207
  timeout=None,
106
208
  ) as _response:
107
209
  if 200 <= _response.status_code < 300:
108
- for _text in _response.iter_text():
210
+ for _text in _response.iter_lines():
109
211
  if len(_text) == 0:
110
212
  continue
111
213
  yield pydantic.parse_obj_as(GenerateStreamResponse, json.loads(_text)) # type: ignore
112
214
  return
113
215
  if _response.status_code == 400:
114
216
  raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
217
+ if _response.status_code == 403:
218
+ raise ForbiddenError(pydantic.parse_obj_as(GenerateErrorResponse, _response.json())) # type: ignore
115
219
  if _response.status_code == 404:
116
220
  raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
117
221
  if _response.status_code == 500:
118
222
  raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
119
223
  try:
224
+ _response.read()
120
225
  _response_json = _response.json()
121
226
  except JSONDecodeError:
122
227
  raise ApiError(status_code=_response.status_code, body=_response.text)
@@ -130,6 +235,22 @@ class Vellum:
130
235
  query: str,
131
236
  options: typing.Optional[SearchRequestOptionsRequest] = OMIT,
132
237
  ) -> SearchResponse:
238
+ """
239
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
240
+
241
+ Perform a search against a document index.
242
+
243
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
244
+
245
+ Parameters:
246
+ - index_id: typing.Optional[str]. The ID of the index to search against. Must provide either this or index_name.
247
+
248
+ - index_name: typing.Optional[str]. The name of the index to search against. Must provide either this or index_id.
249
+
250
+ - query: str. The query to search for. <span style="white-space: nowrap">`non-empty`</span>
251
+
252
+ - options: typing.Optional[SearchRequestOptionsRequest]. Configuration options for the search.
253
+ """
133
254
  _request: typing.Dict[str, typing.Any] = {"query": query}
134
255
  if index_id is not OMIT:
135
256
  _request["index_id"] = index_id
@@ -137,11 +258,11 @@ class Vellum:
137
258
  _request["index_name"] = index_name
138
259
  if options is not OMIT:
139
260
  _request["options"] = options
140
- _response = httpx.request(
261
+ _response = self._client_wrapper.httpx_client.request(
141
262
  "POST",
142
263
  urllib.parse.urljoin(f"{self._environment.predict}/", "v1/search"),
143
264
  json=jsonable_encoder(_request),
144
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
265
+ headers=self._client_wrapper.get_headers(),
145
266
  timeout=None,
146
267
  )
147
268
  if 200 <= _response.status_code < 300:
@@ -165,16 +286,30 @@ class Vellum:
165
286
  deployment_name: typing.Optional[str] = OMIT,
166
287
  actuals: typing.List[SubmitCompletionActualRequest],
167
288
  ) -> None:
289
+ """
290
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
291
+
292
+ Used to submit feedback regarding the quality of previously generated completions.
293
+
294
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
295
+
296
+ Parameters:
297
+ - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.
298
+
299
+ - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.
300
+
301
+ - actuals: typing.List[SubmitCompletionActualRequest]. Feedback regarding the quality of previously generated completions
302
+ """
168
303
  _request: typing.Dict[str, typing.Any] = {"actuals": actuals}
169
304
  if deployment_id is not OMIT:
170
305
  _request["deployment_id"] = deployment_id
171
306
  if deployment_name is not OMIT:
172
307
  _request["deployment_name"] = deployment_name
173
- _response = httpx.request(
308
+ _response = self._client_wrapper.httpx_client.request(
174
309
  "POST",
175
310
  urllib.parse.urljoin(f"{self._environment.predict}/", "v1/submit-completion-actuals"),
176
311
  json=jsonable_encoder(_request),
177
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
312
+ headers=self._client_wrapper.get_headers(),
178
313
  timeout=None,
179
314
  )
180
315
  if 200 <= _response.status_code < 300:
@@ -193,16 +328,82 @@ class Vellum:
193
328
 
194
329
 
195
330
  class AsyncVellum:
196
- def __init__(self, *, environment: VellumEnvironment = VellumEnvironment.PRODUCTION, api_key: str):
331
+ def __init__(
332
+ self,
333
+ *,
334
+ environment: VellumEnvironment = VellumEnvironment.PRODUCTION,
335
+ api_key: str,
336
+ timeout: typing.Optional[float] = None,
337
+ ):
197
338
  self._environment = environment
198
- self.api_key = api_key
199
- self.deployments = AsyncDeploymentsClient(environment=self._environment, api_key=self.api_key)
200
- self.document_indexes = AsyncDocumentIndexesClient(environment=self._environment, api_key=self.api_key)
201
- self.documents = AsyncDocumentsClient(environment=self._environment, api_key=self.api_key)
202
- self.model_versions = AsyncModelVersionsClient(environment=self._environment, api_key=self.api_key)
203
- self.registered_prompts = AsyncRegisteredPromptsClient(environment=self._environment, api_key=self.api_key)
204
- self.sandboxes = AsyncSandboxesClient(environment=self._environment, api_key=self.api_key)
205
- self.test_suites = AsyncTestSuitesClient(environment=self._environment, api_key=self.api_key)
339
+ self._client_wrapper = AsyncClientWrapper(api_key=api_key, httpx_client=httpx.AsyncClient(timeout=timeout))
340
+ self.deployments = AsyncDeploymentsClient(environment=environment, client_wrapper=self._client_wrapper)
341
+ self.document_indexes = AsyncDocumentIndexesClient(environment=environment, client_wrapper=self._client_wrapper)
342
+ self.documents = AsyncDocumentsClient(environment=environment, client_wrapper=self._client_wrapper)
343
+ self.model_versions = AsyncModelVersionsClient(environment=environment, client_wrapper=self._client_wrapper)
344
+ self.registered_prompts = AsyncRegisteredPromptsClient(
345
+ environment=environment, client_wrapper=self._client_wrapper
346
+ )
347
+ self.sandboxes = AsyncSandboxesClient(environment=environment, client_wrapper=self._client_wrapper)
348
+ self.test_suites = AsyncTestSuitesClient(environment=environment, client_wrapper=self._client_wrapper)
349
+
350
+ async def execute_workflow_stream(
351
+ self,
352
+ *,
353
+ workflow_deployment_id: typing.Optional[str] = OMIT,
354
+ workflow_deployment_name: typing.Optional[str] = OMIT,
355
+ release_tag: typing.Optional[str] = OMIT,
356
+ inputs: typing.List[WorkflowRequestInputRequest],
357
+ external_id: typing.Optional[str] = OMIT,
358
+ ) -> typing.AsyncIterator[WorkflowStreamEvent]:
359
+ """
360
+ <strong style="background-color:#ffc107; color:white; padding:4px; border-radius:4px">Unstable</strong>
361
+
362
+ Executes a deployed Workflow and streams back its results.
363
+
364
+ Parameters:
365
+ - workflow_deployment_id: typing.Optional[str]. The ID of the Workflow Deployment. Must provide either this or workflow_deployment_name.
366
+
367
+ - workflow_deployment_name: typing.Optional[str]. The name of the Workflow Deployment. Must provide either this or workflow_deployment_id.
368
+
369
+ - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment
370
+
371
+ - inputs: typing.List[WorkflowRequestInputRequest].
372
+
373
+ - external_id: typing.Optional[str]. Optionally include a unique identifier for tracking purposes.
374
+ """
375
+ _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
376
+ if workflow_deployment_id is not OMIT:
377
+ _request["workflow_deployment_id"] = workflow_deployment_id
378
+ if workflow_deployment_name is not OMIT:
379
+ _request["workflow_deployment_name"] = workflow_deployment_name
380
+ if release_tag is not OMIT:
381
+ _request["release_tag"] = release_tag
382
+ if external_id is not OMIT:
383
+ _request["external_id"] = external_id
384
+ async with self._client_wrapper.httpx_client.stream(
385
+ "POST",
386
+ urllib.parse.urljoin(f"{self._environment.predict}/", "v1/execute-workflow-stream"),
387
+ json=jsonable_encoder(_request),
388
+ headers=self._client_wrapper.get_headers(),
389
+ timeout=None,
390
+ ) as _response:
391
+ if 200 <= _response.status_code < 300:
392
+ async for _text in _response.aiter_lines():
393
+ if len(_text) == 0:
394
+ continue
395
+ yield pydantic.parse_obj_as(WorkflowStreamEvent, json.loads(_text)) # type: ignore
396
+ return
397
+ if _response.status_code == 404:
398
+ raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
399
+ if _response.status_code == 500:
400
+ raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
401
+ try:
402
+ await _response.aread()
403
+ _response_json = _response.json()
404
+ except JSONDecodeError:
405
+ raise ApiError(status_code=_response.status_code, body=_response.text)
406
+ raise ApiError(status_code=_response.status_code, body=_response_json)
206
407
 
207
408
  async def generate(
208
409
  self,
@@ -212,6 +413,22 @@ class AsyncVellum:
212
413
  requests: typing.List[GenerateRequest],
213
414
  options: typing.Optional[GenerateOptionsRequest] = OMIT,
214
415
  ) -> GenerateResponse:
416
+ """
417
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
418
+
419
+ Generate a completion using a previously defined deployment.
420
+
421
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
422
+
423
+ Parameters:
424
+ - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.
425
+
426
+ - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.
427
+
428
+ - requests: typing.List[GenerateRequest]. The generation requests to make. Supplying multiple will perform a bulk request to the LLM provided when possible.
429
+
430
+ - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.
431
+ """
215
432
  _request: typing.Dict[str, typing.Any] = {"requests": requests}
216
433
  if deployment_id is not OMIT:
217
434
  _request["deployment_id"] = deployment_id
@@ -219,18 +436,19 @@ class AsyncVellum:
219
436
  _request["deployment_name"] = deployment_name
220
437
  if options is not OMIT:
221
438
  _request["options"] = options
222
- async with httpx.AsyncClient() as _client:
223
- _response = await _client.request(
224
- "POST",
225
- urllib.parse.urljoin(f"{self._environment.predict}/", "v1/generate"),
226
- json=jsonable_encoder(_request),
227
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
228
- timeout=None,
229
- )
439
+ _response = await self._client_wrapper.httpx_client.request(
440
+ "POST",
441
+ urllib.parse.urljoin(f"{self._environment.predict}/", "v1/generate"),
442
+ json=jsonable_encoder(_request),
443
+ headers=self._client_wrapper.get_headers(),
444
+ timeout=None,
445
+ )
230
446
  if 200 <= _response.status_code < 300:
231
447
  return pydantic.parse_obj_as(GenerateResponse, _response.json()) # type: ignore
232
448
  if _response.status_code == 400:
233
449
  raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
450
+ if _response.status_code == 403:
451
+ raise ForbiddenError(pydantic.parse_obj_as(GenerateErrorResponse, _response.json())) # type: ignore
234
452
  if _response.status_code == 404:
235
453
  raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
236
454
  if _response.status_code == 500:
@@ -249,6 +467,22 @@ class AsyncVellum:
249
467
  requests: typing.List[GenerateRequest],
250
468
  options: typing.Optional[GenerateOptionsRequest] = OMIT,
251
469
  ) -> typing.AsyncIterator[GenerateStreamResponse]:
470
+ """
471
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
472
+
473
+ Generate a stream of completions using a previously defined deployment.
474
+
475
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
476
+
477
+ Parameters:
478
+ - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.
479
+
480
+ - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.
481
+
482
+ - requests: typing.List[GenerateRequest]. The generation requests to make. Supplying multiple will perform a bulk request to the LLM provided when possible.
483
+
484
+ - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.
485
+ """
252
486
  _request: typing.Dict[str, typing.Any] = {"requests": requests}
253
487
  if deployment_id is not OMIT:
254
488
  _request["deployment_id"] = deployment_id
@@ -256,31 +490,33 @@ class AsyncVellum:
256
490
  _request["deployment_name"] = deployment_name
257
491
  if options is not OMIT:
258
492
  _request["options"] = options
259
- async with httpx.AsyncClient() as _client:
260
- async with _client.stream(
261
- "POST",
262
- urllib.parse.urljoin(f"{self._environment.predict}/", "v1/generate-stream"),
263
- json=jsonable_encoder(_request),
264
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
265
- timeout=None,
266
- ) as _response:
267
- if 200 <= _response.status_code < 300:
268
- async for _text in _response.aiter_text():
269
- if len(_text) == 0:
270
- continue
271
- yield pydantic.parse_obj_as(GenerateStreamResponse, json.loads(_text)) # type: ignore
272
- return
273
- if _response.status_code == 400:
274
- raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
275
- if _response.status_code == 404:
276
- raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
277
- if _response.status_code == 500:
278
- raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
279
- try:
280
- _response_json = _response.json()
281
- except JSONDecodeError:
282
- raise ApiError(status_code=_response.status_code, body=_response.text)
283
- raise ApiError(status_code=_response.status_code, body=_response_json)
493
+ async with self._client_wrapper.httpx_client.stream(
494
+ "POST",
495
+ urllib.parse.urljoin(f"{self._environment.predict}/", "v1/generate-stream"),
496
+ json=jsonable_encoder(_request),
497
+ headers=self._client_wrapper.get_headers(),
498
+ timeout=None,
499
+ ) as _response:
500
+ if 200 <= _response.status_code < 300:
501
+ async for _text in _response.aiter_lines():
502
+ if len(_text) == 0:
503
+ continue
504
+ yield pydantic.parse_obj_as(GenerateStreamResponse, json.loads(_text)) # type: ignore
505
+ return
506
+ if _response.status_code == 400:
507
+ raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
508
+ if _response.status_code == 403:
509
+ raise ForbiddenError(pydantic.parse_obj_as(GenerateErrorResponse, _response.json())) # type: ignore
510
+ if _response.status_code == 404:
511
+ raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
512
+ if _response.status_code == 500:
513
+ raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore
514
+ try:
515
+ await _response.aread()
516
+ _response_json = _response.json()
517
+ except JSONDecodeError:
518
+ raise ApiError(status_code=_response.status_code, body=_response.text)
519
+ raise ApiError(status_code=_response.status_code, body=_response_json)
284
520
 
285
521
  async def search(
286
522
  self,
@@ -290,6 +526,22 @@ class AsyncVellum:
290
526
  query: str,
291
527
  options: typing.Optional[SearchRequestOptionsRequest] = OMIT,
292
528
  ) -> SearchResponse:
529
+ """
530
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
531
+
532
+ Perform a search against a document index.
533
+
534
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
535
+
536
+ Parameters:
537
+ - index_id: typing.Optional[str]. The ID of the index to search against. Must provide either this or index_name.
538
+
539
+ - index_name: typing.Optional[str]. The name of the index to search against. Must provide either this or index_id.
540
+
541
+ - query: str. The query to search for. <span style="white-space: nowrap">`non-empty`</span>
542
+
543
+ - options: typing.Optional[SearchRequestOptionsRequest]. Configuration options for the search.
544
+ """
293
545
  _request: typing.Dict[str, typing.Any] = {"query": query}
294
546
  if index_id is not OMIT:
295
547
  _request["index_id"] = index_id
@@ -297,14 +549,13 @@ class AsyncVellum:
297
549
  _request["index_name"] = index_name
298
550
  if options is not OMIT:
299
551
  _request["options"] = options
300
- async with httpx.AsyncClient() as _client:
301
- _response = await _client.request(
302
- "POST",
303
- urllib.parse.urljoin(f"{self._environment.predict}/", "v1/search"),
304
- json=jsonable_encoder(_request),
305
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
306
- timeout=None,
307
- )
552
+ _response = await self._client_wrapper.httpx_client.request(
553
+ "POST",
554
+ urllib.parse.urljoin(f"{self._environment.predict}/", "v1/search"),
555
+ json=jsonable_encoder(_request),
556
+ headers=self._client_wrapper.get_headers(),
557
+ timeout=None,
558
+ )
308
559
  if 200 <= _response.status_code < 300:
309
560
  return pydantic.parse_obj_as(SearchResponse, _response.json()) # type: ignore
310
561
  if _response.status_code == 400:
@@ -326,19 +577,32 @@ class AsyncVellum:
326
577
  deployment_name: typing.Optional[str] = OMIT,
327
578
  actuals: typing.List[SubmitCompletionActualRequest],
328
579
  ) -> None:
580
+ """
581
+ <strong style="background-color:#4caf50; color:white; padding:4px; border-radius:4px">Stable</strong>
582
+
583
+ Used to submit feedback regarding the quality of previously generated completions.
584
+
585
+ **Note:** Uses a base url of `https://predict.vellum.ai`.
586
+
587
+ Parameters:
588
+ - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.
589
+
590
+ - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.
591
+
592
+ - actuals: typing.List[SubmitCompletionActualRequest]. Feedback regarding the quality of previously generated completions
593
+ """
329
594
  _request: typing.Dict[str, typing.Any] = {"actuals": actuals}
330
595
  if deployment_id is not OMIT:
331
596
  _request["deployment_id"] = deployment_id
332
597
  if deployment_name is not OMIT:
333
598
  _request["deployment_name"] = deployment_name
334
- async with httpx.AsyncClient() as _client:
335
- _response = await _client.request(
336
- "POST",
337
- urllib.parse.urljoin(f"{self._environment.predict}/", "v1/submit-completion-actuals"),
338
- json=jsonable_encoder(_request),
339
- headers=remove_none_from_headers({"X_API_KEY": self.api_key}),
340
- timeout=None,
341
- )
599
+ _response = await self._client_wrapper.httpx_client.request(
600
+ "POST",
601
+ urllib.parse.urljoin(f"{self._environment.predict}/", "v1/submit-completion-actuals"),
602
+ json=jsonable_encoder(_request),
603
+ headers=self._client_wrapper.get_headers(),
604
+ timeout=None,
605
+ )
342
606
  if 200 <= _response.status_code < 300:
343
607
  return
344
608
  if _response.status_code == 400:
vellum/core/__init__.py CHANGED
@@ -1,8 +1,17 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
3
  from .api_error import ApiError
4
+ from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
4
5
  from .datetime_utils import serialize_datetime
5
6
  from .jsonable_encoder import jsonable_encoder
6
- from .remove_none_from_headers import remove_none_from_headers
7
+ from .remove_none_from_dict import remove_none_from_dict
7
8
 
8
- __all__ = ["ApiError", "jsonable_encoder", "remove_none_from_headers", "serialize_datetime"]
9
+ __all__ = [
10
+ "ApiError",
11
+ "AsyncClientWrapper",
12
+ "BaseClientWrapper",
13
+ "SyncClientWrapper",
14
+ "jsonable_encoder",
15
+ "remove_none_from_dict",
16
+ "serialize_datetime",
17
+ ]
@@ -0,0 +1,27 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+
5
+ import httpx
6
+
7
+
8
+ class BaseClientWrapper:
9
+ def __init__(self, *, api_key: str):
10
+ self.api_key = api_key
11
+
12
+ def get_headers(self) -> typing.Dict[str, str]:
13
+ headers: typing.Dict[str, str] = {}
14
+ headers["X_API_KEY"] = self.api_key
15
+ return headers
16
+
17
+
18
+ class SyncClientWrapper(BaseClientWrapper):
19
+ def __init__(self, *, api_key: str, httpx_client: httpx.Client):
20
+ super().__init__(api_key=api_key)
21
+ self.httpx_client = httpx_client
22
+
23
+
24
+ class AsyncClientWrapper(BaseClientWrapper):
25
+ def __init__(self, *, api_key: str, httpx_client: httpx.AsyncClient):
26
+ super().__init__(api_key=api_key)
27
+ self.httpx_client = httpx_client
@@ -0,0 +1,11 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from typing import Any, Dict, Optional
4
+
5
+
6
+ def remove_none_from_dict(original: Dict[str, Optional[Any]]) -> Dict[str, Any]:
7
+ new: Dict[str, Any] = {}
8
+ for key, value in original.items():
9
+ if value is not None:
10
+ new[key] = value
11
+ return new