# This file was auto-generated by Fern from our API Definition.

import json
import typing
import urllib.parse
from json.decoder import JSONDecodeError

import httpx

from .core.api_error import ApiError
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .core.jsonable_encoder import jsonable_encoder
from .core.pydantic_utilities import pydantic_v1
from .core.remove_none_from_dict import remove_none_from_dict
from .core.request_options import RequestOptions
from .environment import VellumEnvironment
from .errors.bad_request_error import BadRequestError
from .errors.forbidden_error import ForbiddenError
from .errors.internal_server_error import InternalServerError
from .errors.not_found_error import NotFoundError
from .resources.deployments.client import AsyncDeploymentsClient, DeploymentsClient
from .resources.document_indexes.client import AsyncDocumentIndexesClient, DocumentIndexesClient
from .resources.documents.client import AsyncDocumentsClient, DocumentsClient
from .resources.folder_entities.client import AsyncFolderEntitiesClient, FolderEntitiesClient
from .resources.sandboxes.client import AsyncSandboxesClient, SandboxesClient
from .resources.test_suite_runs.client import AsyncTestSuiteRunsClient, TestSuiteRunsClient
from .resources.test_suites.client import AsyncTestSuitesClient, TestSuitesClient
from .resources.workflow_deployments.client import AsyncWorkflowDeploymentsClient, WorkflowDeploymentsClient
from .types.execute_prompt_event import ExecutePromptEvent
from .types.execute_prompt_response import ExecutePromptResponse
from .types.execute_workflow_response import ExecuteWorkflowResponse
from .types.generate_options_request import GenerateOptionsRequest
from .types.generate_request import GenerateRequest
from .types.generate_response import GenerateResponse
from .types.generate_stream_response import GenerateStreamResponse
from .types.prompt_deployment_expand_meta_request_request import PromptDeploymentExpandMetaRequestRequest
from .types.prompt_deployment_input_request import PromptDeploymentInputRequest
from .types.raw_prompt_execution_overrides_request import RawPromptExecutionOverridesRequest
from .types.search_request_options_request import SearchRequestOptionsRequest
from .types.search_response import SearchResponse
from .types.submit_completion_actual_request import SubmitCompletionActualRequest
from .types.submit_workflow_execution_actual_request import SubmitWorkflowExecutionActualRequest
from .types.workflow_execution_event_type import WorkflowExecutionEventType
from .types.workflow_request_input_request import WorkflowRequestInputRequest
from .types.workflow_stream_event import WorkflowStreamEvent

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class Vellum:
    """
    Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions.

    Parameters:
        - environment: VellumEnvironment. The environment to use for requests from the client. from .environment import VellumEnvironment

                                          Defaults to VellumEnvironment.PRODUCTION

        - api_key: str.

        - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds, unless a custom httpx client is used, in which case a default is not set.

        - follow_redirects: typing.Optional[bool]. Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

        - httpx_client: typing.Optional[httpx.Client]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
    ---
    from vellum.client import Vellum

    client = Vellum(
        api_key="YOUR_API_KEY",
    )
    """

    def __init__(
        self,
        *,
        environment: VellumEnvironment = VellumEnvironment.PRODUCTION,
        api_key: str,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.Client] = None,
    ):
        _defaulted_timeout = timeout if timeout is not None else None if httpx_client is None else None
        self._client_wrapper = SyncClientWrapper(
            environment=environment,
            api_key=api_key,
            httpx_client=httpx_client
            if httpx_client is not None
            else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
            if follow_redirects is not None
            else httpx.Client(timeout=_defaulted_timeout),
            timeout=_defaulted_timeout,
        )
        self.deployments = DeploymentsClient(client_wrapper=self._client_wrapper)
        self.document_indexes = DocumentIndexesClient(client_wrapper=self._client_wrapper)
        self.documents = DocumentsClient(client_wrapper=self._client_wrapper)
        self.folder_entities = FolderEntitiesClient(client_wrapper=self._client_wrapper)
        self.sandboxes = SandboxesClient(client_wrapper=self._client_wrapper)
        self.test_suite_runs = TestSuiteRunsClient(client_wrapper=self._client_wrapper)
        self.test_suites = TestSuitesClient(client_wrapper=self._client_wrapper)
        self.workflow_deployments = WorkflowDeploymentsClient(client_wrapper=self._client_wrapper)

    def execute_prompt(
        self,
        *,
        inputs: typing.Sequence[PromptDeploymentInputRequest],
        prompt_deployment_id: typing.Optional[str] = OMIT,
        prompt_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest] = OMIT,
        raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest] = OMIT,
        expand_raw: typing.Optional[typing.Sequence[str]] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExecutePromptResponse:
        """
        Executes a deployed Prompt and returns the result.

        Parameters:
            - inputs: typing.Sequence[PromptDeploymentInputRequest]. The list of inputs defined in the Prompt's deployment with their corresponding values.

            - prompt_deployment_id: typing.Optional[str]. The ID of the Prompt Deployment. Must provide either this or prompt_deployment_name.

            - prompt_deployment_name: typing.Optional[str]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment

            - external_id: typing.Optional[str]. "Optionally include a unique identifier for tracking purposes. Must be unique for a given prompt deployment.

            - expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest].

            - expand_raw: typing.Optional[typing.Sequence[str]]. Returns the raw API response data sent from the model host. Combined with `raw_overrides`, it can be used to access new features from models.

            - metadata: typing.Optional[typing.Dict[str, typing.Any]].

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import (
            PromptDeploymentExpandMetaRequestRequest,
            PromptDeploymentInputRequest_String,
            RawPromptExecutionOverridesRequest,
        )
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.execute_prompt(
            inputs=[
                PromptDeploymentInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            prompt_deployment_id="string",
            prompt_deployment_name="string",
            release_tag="string",
            external_id="string",
            expand_meta=PromptDeploymentExpandMetaRequestRequest(
                model_name=True,
                latency=True,
                deployment_release_tag=True,
                prompt_version_id=True,
                finish_reason=True,
                usage=True,
            ),
            raw_overrides=RawPromptExecutionOverridesRequest(
                body={"string": {"key": "value"}},
                headers={"string": {"key": "value"}},
                url="string",
            ),
            expand_raw=["string"],
            metadata={"string": {"key": "value"}},
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if prompt_deployment_id is not OMIT:
            _request["prompt_deployment_id"] = prompt_deployment_id
        if prompt_deployment_name is not OMIT:
            _request["prompt_deployment_name"] = prompt_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if expand_meta is not OMIT:
            _request["expand_meta"] = expand_meta
        if raw_overrides is not OMIT:
            _request["raw_overrides"] = raw_overrides
        if expand_raw is not OMIT:
            _request["expand_raw"] = expand_raw
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/execute-prompt"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ExecutePromptResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 403:
            raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def execute_prompt_stream(
        self,
        *,
        inputs: typing.Sequence[PromptDeploymentInputRequest],
        prompt_deployment_id: typing.Optional[str] = OMIT,
        prompt_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest] = OMIT,
        raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest] = OMIT,
        expand_raw: typing.Optional[typing.Sequence[str]] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[ExecutePromptEvent]:
        """
        Executes a deployed Prompt and streams back the results.

        Parameters:
            - inputs: typing.Sequence[PromptDeploymentInputRequest]. The list of inputs defined in the Prompt's deployment with their corresponding values.

            - prompt_deployment_id: typing.Optional[str]. The ID of the Prompt Deployment. Must provide either this or prompt_deployment_name.

            - prompt_deployment_name: typing.Optional[str]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment

            - external_id: typing.Optional[str]. "Optionally include a unique identifier for tracking purposes. Must be unique for a given prompt deployment.

            - expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest].

            - expand_raw: typing.Optional[typing.Sequence[str]]. Returns the raw API response data sent from the model host. Combined with `raw_overrides`, it can be used to access new features from models.

            - metadata: typing.Optional[typing.Dict[str, typing.Any]].

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import (
            PromptDeploymentExpandMetaRequestRequest,
            PromptDeploymentInputRequest_String,
            RawPromptExecutionOverridesRequest,
        )
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.execute_prompt_stream(
            inputs=[
                PromptDeploymentInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            prompt_deployment_id="string",
            prompt_deployment_name="string",
            release_tag="string",
            external_id="string",
            expand_meta=PromptDeploymentExpandMetaRequestRequest(
                model_name=True,
                latency=True,
                deployment_release_tag=True,
                prompt_version_id=True,
                finish_reason=True,
                usage=True,
            ),
            raw_overrides=RawPromptExecutionOverridesRequest(
                body={"string": {"key": "value"}},
                headers={"string": {"key": "value"}},
                url="string",
            ),
            expand_raw=["string"],
            metadata={"string": {"key": "value"}},
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if prompt_deployment_id is not OMIT:
            _request["prompt_deployment_id"] = prompt_deployment_id
        if prompt_deployment_name is not OMIT:
            _request["prompt_deployment_name"] = prompt_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if expand_meta is not OMIT:
            _request["expand_meta"] = expand_meta
        if raw_overrides is not OMIT:
            _request["raw_overrides"] = raw_overrides
        if expand_raw is not OMIT:
            _request["expand_raw"] = expand_raw
        if metadata is not OMIT:
            _request["metadata"] = metadata
        with self._client_wrapper.httpx_client.stream(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/execute-prompt-stream"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        ) as _response:
            if 200 <= _response.status_code < 300:
                for _text in _response.iter_lines():
                    if len(_text) == 0:
                        continue
                    yield pydantic_v1.parse_obj_as(ExecutePromptEvent, json.loads(_text))  # type: ignore
                return
            _response.read()
            if _response.status_code == 400:
                raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 403:
                raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 404:
                raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 500:
                raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            try:
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    def execute_workflow(
        self,
        *,
        inputs: typing.Sequence[WorkflowRequestInputRequest],
        workflow_deployment_id: typing.Optional[str] = OMIT,
        workflow_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExecuteWorkflowResponse:
        """
        Executes a deployed Workflow and returns its outputs.

        Parameters:
            - inputs: typing.Sequence[WorkflowRequestInputRequest]. The list of inputs defined in the Workflow's Deployment with their corresponding values.

            - workflow_deployment_id: typing.Optional[str]. The ID of the Workflow Deployment. Must provide either this or workflow_deployment_name.

            - workflow_deployment_name: typing.Optional[str]. The name of the Workflow Deployment. Must provide either this or workflow_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment

            - external_id: typing.Optional[str]. Optionally include a unique identifier for tracking purposes. Must be unique for a given workflow deployment.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import WorkflowRequestInputRequest_String
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.execute_workflow(
            inputs=[
                WorkflowRequestInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            workflow_deployment_id="string",
            workflow_deployment_name="string",
            release_tag="string",
            external_id="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if workflow_deployment_id is not OMIT:
            _request["workflow_deployment_id"] = workflow_deployment_id
        if workflow_deployment_name is not OMIT:
            _request["workflow_deployment_name"] = workflow_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/execute-workflow"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ExecuteWorkflowResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def execute_workflow_stream(
        self,
        *,
        inputs: typing.Sequence[WorkflowRequestInputRequest],
        workflow_deployment_id: typing.Optional[str] = OMIT,
        workflow_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        event_types: typing.Optional[typing.Sequence[WorkflowExecutionEventType]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[WorkflowStreamEvent]:
        """
        Executes a deployed Workflow and streams back its results.

        Parameters:
            - inputs: typing.Sequence[WorkflowRequestInputRequest]. The list of inputs defined in the Workflow's Deployment with their corresponding values.

            - workflow_deployment_id: typing.Optional[str]. The ID of the Workflow Deployment. Must provide either this or workflow_deployment_name.

            - workflow_deployment_name: typing.Optional[str]. The name of the Workflow Deployment. Must provide either this or workflow_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment

            - external_id: typing.Optional[str]. Optionally include a unique identifier for tracking purposes. Must be unique for a given workflow deployment.

            - event_types: typing.Optional[typing.Sequence[WorkflowExecutionEventType]]. Optionally specify which events you want to receive. Defaults to only WORKFLOW events. Note that the schema of non-WORKFLOW events is unstable and should be used with caution.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import WorkflowRequestInputRequest_String
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.execute_workflow_stream(
            inputs=[
                WorkflowRequestInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            workflow_deployment_id="string",
            workflow_deployment_name="string",
            release_tag="string",
            external_id="string",
            event_types=["NODE"],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if workflow_deployment_id is not OMIT:
            _request["workflow_deployment_id"] = workflow_deployment_id
        if workflow_deployment_name is not OMIT:
            _request["workflow_deployment_name"] = workflow_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if event_types is not OMIT:
            _request["event_types"] = event_types
        with self._client_wrapper.httpx_client.stream(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_environment().predict}/", "v1/execute-workflow-stream"
            ),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        ) as _response:
            if 200 <= _response.status_code < 300:
                for _text in _response.iter_lines():
                    if len(_text) == 0:
                        continue
                    yield pydantic_v1.parse_obj_as(WorkflowStreamEvent, json.loads(_text))  # type: ignore
                return
            _response.read()
            if _response.status_code == 400:
                raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 404:
                raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 500:
                raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            try:
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    def generate(
        self,
        *,
        deployment_id: typing.Optional[str] = OMIT,
        deployment_name: typing.Optional[str] = OMIT,
        requests: typing.Sequence[GenerateRequest],
        options: typing.Optional[GenerateOptionsRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GenerateResponse:
        """
        Generate a completion using a previously defined deployment.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.

            - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.

            - requests: typing.Sequence[GenerateRequest]. The generation request to make. Bulk requests are no longer supported, this field must be an array of length 1.

            - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import GenerateRequest
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.generate(
            requests=[
                GenerateRequest(
                    input_values={},
                )
            ],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"requests": requests}
        if deployment_id is not OMIT:
            _request["deployment_id"] = deployment_id
        if deployment_name is not OMIT:
            _request["deployment_name"] = deployment_name
        if options is not OMIT:
            _request["options"] = options
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/generate"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(GenerateResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 403:
            raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def generate_stream(
        self,
        *,
        deployment_id: typing.Optional[str] = OMIT,
        deployment_name: typing.Optional[str] = OMIT,
        requests: typing.Sequence[GenerateRequest],
        options: typing.Optional[GenerateOptionsRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[GenerateStreamResponse]:
        """
        Generate a stream of completions using a previously defined deployment.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.

            - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.

            - requests: typing.Sequence[GenerateRequest]. The generation request to make. Bulk requests are no longer supported, this field must be an array of length 1.

            - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import (
            ChatMessageContentRequest_String,
            ChatMessageRequest,
            GenerateOptionsRequest,
            GenerateRequest,
        )
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.generate_stream(
            deployment_id="string",
            deployment_name="string",
            requests=[
                GenerateRequest(
                    input_values={"string": {"key": "value"}},
                    chat_history=[
                        ChatMessageRequest(
                            text="string",
                            role="SYSTEM",
                            content=ChatMessageContentRequest_String(),
                            source="string",
                        )
                    ],
                    external_ids=["string"],
                )
            ],
            options=GenerateOptionsRequest(
                logprobs="ALL",
            ),
        )
        """
        _request: typing.Dict[str, typing.Any] = {"requests": requests}
        if deployment_id is not OMIT:
            _request["deployment_id"] = deployment_id
        if deployment_name is not OMIT:
            _request["deployment_name"] = deployment_name
        if options is not OMIT:
            _request["options"] = options
        with self._client_wrapper.httpx_client.stream(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/generate-stream"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        ) as _response:
            if 200 <= _response.status_code < 300:
                for _text in _response.iter_lines():
                    if len(_text) == 0:
                        continue
                    yield pydantic_v1.parse_obj_as(GenerateStreamResponse, json.loads(_text))  # type: ignore
                return
            _response.read()
            if _response.status_code == 400:
                raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 403:
                raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 404:
                raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 500:
                raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            try:
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    def search(
        self,
        *,
        index_id: typing.Optional[str] = OMIT,
        index_name: typing.Optional[str] = OMIT,
        query: str,
        options: typing.Optional[SearchRequestOptionsRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SearchResponse:
        """
        Perform a search against a document index.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - index_id: typing.Optional[str]. The ID of the index to search against. Must provide either this or index_name.

            - index_name: typing.Optional[str]. The name of the index to search against. Must provide either this or index_id.

            - query: str. The query to search for.

            - options: typing.Optional[SearchRequestOptionsRequest]. Configuration options for the search.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.search(
            query="query",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"query": query}
        if index_id is not OMIT:
            _request["index_id"] = index_id
        if index_name is not OMIT:
            _request["index_name"] = index_name
        if options is not OMIT:
            _request["options"] = options
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/search"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(SearchResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def submit_completion_actuals(
        self,
        *,
        deployment_id: typing.Optional[str] = OMIT,
        deployment_name: typing.Optional[str] = OMIT,
        actuals: typing.Sequence[SubmitCompletionActualRequest],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Used to submit feedback regarding the quality of previously generated completions.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.

            - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.

            - actuals: typing.Sequence[SubmitCompletionActualRequest]. Feedback regarding the quality of previously generated completions

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import SubmitCompletionActualRequest
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.submit_completion_actuals(
            actuals=[SubmitCompletionActualRequest()],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"actuals": actuals}
        if deployment_id is not OMIT:
            _request["deployment_id"] = deployment_id
        if deployment_name is not OMIT:
            _request["deployment_name"] = deployment_name
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_environment().predict}/", "v1/submit-completion-actuals"
            ),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def submit_workflow_execution_actuals(
        self,
        *,
        actuals: typing.Sequence[SubmitWorkflowExecutionActualRequest],
        execution_id: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
            Used to submit feedback regarding the quality of previous workflow execution and its outputs.

            **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - actuals: typing.Sequence[SubmitWorkflowExecutionActualRequest]. Feedback regarding the quality of an output on a previously executed workflow.

            - execution_id: typing.Optional[str]. The Vellum-generated ID of a previously executed workflow. Must provide either this or external_id.

            - external_id: typing.Optional[str]. The external ID that was originally provided by when executing the workflow, if applicable, that you'd now like to submit actuals for. Must provide either this or execution_id.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum.client import Vellum

        client = Vellum(
            api_key="YOUR_API_KEY",
        )
        client.submit_workflow_execution_actuals(
            actuals=[],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"actuals": actuals}
        if execution_id is not OMIT:
            _request["execution_id"] = execution_id
        if external_id is not OMIT:
            _request["external_id"] = external_id
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_environment().predict}/", "v1/submit-workflow-execution-actuals"
            ),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


class AsyncVellum:
    """
    Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions.

    Parameters:
        - environment: VellumEnvironment. The environment to use for requests from the client. from .environment import VellumEnvironment

                                          Defaults to VellumEnvironment.PRODUCTION

        - api_key: str.

        - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds, unless a custom httpx client is used, in which case a default is not set.

        - follow_redirects: typing.Optional[bool]. Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.

        - httpx_client: typing.Optional[httpx.AsyncClient]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
    ---
    from vellum.client import AsyncVellum

    client = AsyncVellum(
        api_key="YOUR_API_KEY",
    )
    """

    def __init__(
        self,
        *,
        environment: VellumEnvironment = VellumEnvironment.PRODUCTION,
        api_key: str,
        timeout: typing.Optional[float] = None,
        follow_redirects: typing.Optional[bool] = True,
        httpx_client: typing.Optional[httpx.AsyncClient] = None,
    ):
        _defaulted_timeout = timeout if timeout is not None else None if httpx_client is None else None
        self._client_wrapper = AsyncClientWrapper(
            environment=environment,
            api_key=api_key,
            httpx_client=httpx_client
            if httpx_client is not None
            else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
            if follow_redirects is not None
            else httpx.AsyncClient(timeout=_defaulted_timeout),
            timeout=_defaulted_timeout,
        )
        self.deployments = AsyncDeploymentsClient(client_wrapper=self._client_wrapper)
        self.document_indexes = AsyncDocumentIndexesClient(client_wrapper=self._client_wrapper)
        self.documents = AsyncDocumentsClient(client_wrapper=self._client_wrapper)
        self.folder_entities = AsyncFolderEntitiesClient(client_wrapper=self._client_wrapper)
        self.sandboxes = AsyncSandboxesClient(client_wrapper=self._client_wrapper)
        self.test_suite_runs = AsyncTestSuiteRunsClient(client_wrapper=self._client_wrapper)
        self.test_suites = AsyncTestSuitesClient(client_wrapper=self._client_wrapper)
        self.workflow_deployments = AsyncWorkflowDeploymentsClient(client_wrapper=self._client_wrapper)

    async def execute_prompt(
        self,
        *,
        inputs: typing.Sequence[PromptDeploymentInputRequest],
        prompt_deployment_id: typing.Optional[str] = OMIT,
        prompt_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest] = OMIT,
        raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest] = OMIT,
        expand_raw: typing.Optional[typing.Sequence[str]] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExecutePromptResponse:
        """
        Executes a deployed Prompt and returns the result.

        Parameters:
            - inputs: typing.Sequence[PromptDeploymentInputRequest]. The list of inputs defined in the Prompt's deployment with their corresponding values.

            - prompt_deployment_id: typing.Optional[str]. The ID of the Prompt Deployment. Must provide either this or prompt_deployment_name.

            - prompt_deployment_name: typing.Optional[str]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment

            - external_id: typing.Optional[str]. "Optionally include a unique identifier for tracking purposes. Must be unique for a given prompt deployment.

            - expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest].

            - expand_raw: typing.Optional[typing.Sequence[str]]. Returns the raw API response data sent from the model host. Combined with `raw_overrides`, it can be used to access new features from models.

            - metadata: typing.Optional[typing.Dict[str, typing.Any]].

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import (
            PromptDeploymentExpandMetaRequestRequest,
            PromptDeploymentInputRequest_String,
            RawPromptExecutionOverridesRequest,
        )
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.execute_prompt(
            inputs=[
                PromptDeploymentInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            prompt_deployment_id="string",
            prompt_deployment_name="string",
            release_tag="string",
            external_id="string",
            expand_meta=PromptDeploymentExpandMetaRequestRequest(
                model_name=True,
                latency=True,
                deployment_release_tag=True,
                prompt_version_id=True,
                finish_reason=True,
                usage=True,
            ),
            raw_overrides=RawPromptExecutionOverridesRequest(
                body={"string": {"key": "value"}},
                headers={"string": {"key": "value"}},
                url="string",
            ),
            expand_raw=["string"],
            metadata={"string": {"key": "value"}},
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if prompt_deployment_id is not OMIT:
            _request["prompt_deployment_id"] = prompt_deployment_id
        if prompt_deployment_name is not OMIT:
            _request["prompt_deployment_name"] = prompt_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if expand_meta is not OMIT:
            _request["expand_meta"] = expand_meta
        if raw_overrides is not OMIT:
            _request["raw_overrides"] = raw_overrides
        if expand_raw is not OMIT:
            _request["expand_raw"] = expand_raw
        if metadata is not OMIT:
            _request["metadata"] = metadata
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/execute-prompt"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ExecutePromptResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 403:
            raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def execute_prompt_stream(
        self,
        *,
        inputs: typing.Sequence[PromptDeploymentInputRequest],
        prompt_deployment_id: typing.Optional[str] = OMIT,
        prompt_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest] = OMIT,
        raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest] = OMIT,
        expand_raw: typing.Optional[typing.Sequence[str]] = OMIT,
        metadata: typing.Optional[typing.Dict[str, typing.Any]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[ExecutePromptEvent]:
        """
        Executes a deployed Prompt and streams back the results.

        Parameters:
            - inputs: typing.Sequence[PromptDeploymentInputRequest]. The list of inputs defined in the Prompt's deployment with their corresponding values.

            - prompt_deployment_id: typing.Optional[str]. The ID of the Prompt Deployment. Must provide either this or prompt_deployment_name.

            - prompt_deployment_name: typing.Optional[str]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment

            - external_id: typing.Optional[str]. "Optionally include a unique identifier for tracking purposes. Must be unique for a given prompt deployment.

            - expand_meta: typing.Optional[PromptDeploymentExpandMetaRequestRequest]. The name of the Prompt Deployment. Must provide either this or prompt_deployment_id.

            - raw_overrides: typing.Optional[RawPromptExecutionOverridesRequest].

            - expand_raw: typing.Optional[typing.Sequence[str]]. Returns the raw API response data sent from the model host. Combined with `raw_overrides`, it can be used to access new features from models.

            - metadata: typing.Optional[typing.Dict[str, typing.Any]].

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import (
            PromptDeploymentExpandMetaRequestRequest,
            PromptDeploymentInputRequest_String,
            RawPromptExecutionOverridesRequest,
        )
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.execute_prompt_stream(
            inputs=[
                PromptDeploymentInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            prompt_deployment_id="string",
            prompt_deployment_name="string",
            release_tag="string",
            external_id="string",
            expand_meta=PromptDeploymentExpandMetaRequestRequest(
                model_name=True,
                latency=True,
                deployment_release_tag=True,
                prompt_version_id=True,
                finish_reason=True,
                usage=True,
            ),
            raw_overrides=RawPromptExecutionOverridesRequest(
                body={"string": {"key": "value"}},
                headers={"string": {"key": "value"}},
                url="string",
            ),
            expand_raw=["string"],
            metadata={"string": {"key": "value"}},
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if prompt_deployment_id is not OMIT:
            _request["prompt_deployment_id"] = prompt_deployment_id
        if prompt_deployment_name is not OMIT:
            _request["prompt_deployment_name"] = prompt_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if expand_meta is not OMIT:
            _request["expand_meta"] = expand_meta
        if raw_overrides is not OMIT:
            _request["raw_overrides"] = raw_overrides
        if expand_raw is not OMIT:
            _request["expand_raw"] = expand_raw
        if metadata is not OMIT:
            _request["metadata"] = metadata
        async with self._client_wrapper.httpx_client.stream(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/execute-prompt-stream"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        ) as _response:
            if 200 <= _response.status_code < 300:
                async for _text in _response.aiter_lines():
                    if len(_text) == 0:
                        continue
                    yield pydantic_v1.parse_obj_as(ExecutePromptEvent, json.loads(_text))  # type: ignore
                return
            await _response.aread()
            if _response.status_code == 400:
                raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 403:
                raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 404:
                raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 500:
                raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            try:
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    async def execute_workflow(
        self,
        *,
        inputs: typing.Sequence[WorkflowRequestInputRequest],
        workflow_deployment_id: typing.Optional[str] = OMIT,
        workflow_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ExecuteWorkflowResponse:
        """
        Executes a deployed Workflow and returns its outputs.

        Parameters:
            - inputs: typing.Sequence[WorkflowRequestInputRequest]. The list of inputs defined in the Workflow's Deployment with their corresponding values.

            - workflow_deployment_id: typing.Optional[str]. The ID of the Workflow Deployment. Must provide either this or workflow_deployment_name.

            - workflow_deployment_name: typing.Optional[str]. The name of the Workflow Deployment. Must provide either this or workflow_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment

            - external_id: typing.Optional[str]. Optionally include a unique identifier for tracking purposes. Must be unique for a given workflow deployment.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import WorkflowRequestInputRequest_String
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.execute_workflow(
            inputs=[
                WorkflowRequestInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            workflow_deployment_id="string",
            workflow_deployment_name="string",
            release_tag="string",
            external_id="string",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if workflow_deployment_id is not OMIT:
            _request["workflow_deployment_id"] = workflow_deployment_id
        if workflow_deployment_name is not OMIT:
            _request["workflow_deployment_name"] = workflow_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/execute-workflow"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ExecuteWorkflowResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def execute_workflow_stream(
        self,
        *,
        inputs: typing.Sequence[WorkflowRequestInputRequest],
        workflow_deployment_id: typing.Optional[str] = OMIT,
        workflow_deployment_name: typing.Optional[str] = OMIT,
        release_tag: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        event_types: typing.Optional[typing.Sequence[WorkflowExecutionEventType]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[WorkflowStreamEvent]:
        """
        Executes a deployed Workflow and streams back its results.

        Parameters:
            - inputs: typing.Sequence[WorkflowRequestInputRequest]. The list of inputs defined in the Workflow's Deployment with their corresponding values.

            - workflow_deployment_id: typing.Optional[str]. The ID of the Workflow Deployment. Must provide either this or workflow_deployment_name.

            - workflow_deployment_name: typing.Optional[str]. The name of the Workflow Deployment. Must provide either this or workflow_deployment_id.

            - release_tag: typing.Optional[str]. Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment

            - external_id: typing.Optional[str]. Optionally include a unique identifier for tracking purposes. Must be unique for a given workflow deployment.

            - event_types: typing.Optional[typing.Sequence[WorkflowExecutionEventType]]. Optionally specify which events you want to receive. Defaults to only WORKFLOW events. Note that the schema of non-WORKFLOW events is unstable and should be used with caution.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import WorkflowRequestInputRequest_String
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.execute_workflow_stream(
            inputs=[
                WorkflowRequestInputRequest_String(
                    name="string",
                    value="string",
                )
            ],
            workflow_deployment_id="string",
            workflow_deployment_name="string",
            release_tag="string",
            external_id="string",
            event_types=["NODE"],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"inputs": inputs}
        if workflow_deployment_id is not OMIT:
            _request["workflow_deployment_id"] = workflow_deployment_id
        if workflow_deployment_name is not OMIT:
            _request["workflow_deployment_name"] = workflow_deployment_name
        if release_tag is not OMIT:
            _request["release_tag"] = release_tag
        if external_id is not OMIT:
            _request["external_id"] = external_id
        if event_types is not OMIT:
            _request["event_types"] = event_types
        async with self._client_wrapper.httpx_client.stream(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_environment().predict}/", "v1/execute-workflow-stream"
            ),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        ) as _response:
            if 200 <= _response.status_code < 300:
                async for _text in _response.aiter_lines():
                    if len(_text) == 0:
                        continue
                    yield pydantic_v1.parse_obj_as(WorkflowStreamEvent, json.loads(_text))  # type: ignore
                return
            await _response.aread()
            if _response.status_code == 400:
                raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 404:
                raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 500:
                raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            try:
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    async def generate(
        self,
        *,
        deployment_id: typing.Optional[str] = OMIT,
        deployment_name: typing.Optional[str] = OMIT,
        requests: typing.Sequence[GenerateRequest],
        options: typing.Optional[GenerateOptionsRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> GenerateResponse:
        """
        Generate a completion using a previously defined deployment.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.

            - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.

            - requests: typing.Sequence[GenerateRequest]. The generation request to make. Bulk requests are no longer supported, this field must be an array of length 1.

            - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import GenerateRequest
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.generate(
            requests=[
                GenerateRequest(
                    input_values={},
                )
            ],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"requests": requests}
        if deployment_id is not OMIT:
            _request["deployment_id"] = deployment_id
        if deployment_name is not OMIT:
            _request["deployment_name"] = deployment_name
        if options is not OMIT:
            _request["options"] = options
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/generate"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(GenerateResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 403:
            raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def generate_stream(
        self,
        *,
        deployment_id: typing.Optional[str] = OMIT,
        deployment_name: typing.Optional[str] = OMIT,
        requests: typing.Sequence[GenerateRequest],
        options: typing.Optional[GenerateOptionsRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[GenerateStreamResponse]:
        """
        Generate a stream of completions using a previously defined deployment.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.

            - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.

            - requests: typing.Sequence[GenerateRequest]. The generation request to make. Bulk requests are no longer supported, this field must be an array of length 1.

            - options: typing.Optional[GenerateOptionsRequest]. Additional configuration that can be used to control what's included in the response.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import (
            ChatMessageContentRequest_String,
            ChatMessageRequest,
            GenerateOptionsRequest,
            GenerateRequest,
        )
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.generate_stream(
            deployment_id="string",
            deployment_name="string",
            requests=[
                GenerateRequest(
                    input_values={"string": {"key": "value"}},
                    chat_history=[
                        ChatMessageRequest(
                            text="string",
                            role="SYSTEM",
                            content=ChatMessageContentRequest_String(),
                            source="string",
                        )
                    ],
                    external_ids=["string"],
                )
            ],
            options=GenerateOptionsRequest(
                logprobs="ALL",
            ),
        )
        """
        _request: typing.Dict[str, typing.Any] = {"requests": requests}
        if deployment_id is not OMIT:
            _request["deployment_id"] = deployment_id
        if deployment_name is not OMIT:
            _request["deployment_name"] = deployment_name
        if options is not OMIT:
            _request["options"] = options
        async with self._client_wrapper.httpx_client.stream(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/generate-stream"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        ) as _response:
            if 200 <= _response.status_code < 300:
                async for _text in _response.aiter_lines():
                    if len(_text) == 0:
                        continue
                    yield pydantic_v1.parse_obj_as(GenerateStreamResponse, json.loads(_text))  # type: ignore
                return
            await _response.aread()
            if _response.status_code == 400:
                raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 403:
                raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 404:
                raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            if _response.status_code == 500:
                raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
            try:
                _response_json = _response.json()
            except JSONDecodeError:
                raise ApiError(status_code=_response.status_code, body=_response.text)
            raise ApiError(status_code=_response.status_code, body=_response_json)

    async def search(
        self,
        *,
        index_id: typing.Optional[str] = OMIT,
        index_name: typing.Optional[str] = OMIT,
        query: str,
        options: typing.Optional[SearchRequestOptionsRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SearchResponse:
        """
        Perform a search against a document index.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - index_id: typing.Optional[str]. The ID of the index to search against. Must provide either this or index_name.

            - index_name: typing.Optional[str]. The name of the index to search against. Must provide either this or index_id.

            - query: str. The query to search for.

            - options: typing.Optional[SearchRequestOptionsRequest]. Configuration options for the search.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.search(
            query="query",
        )
        """
        _request: typing.Dict[str, typing.Any] = {"query": query}
        if index_id is not OMIT:
            _request["index_id"] = index_id
        if index_name is not OMIT:
            _request["index_name"] = index_name
        if options is not OMIT:
            _request["options"] = options
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(f"{self._client_wrapper.get_environment().predict}/", "v1/search"),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(SearchResponse, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def submit_completion_actuals(
        self,
        *,
        deployment_id: typing.Optional[str] = OMIT,
        deployment_name: typing.Optional[str] = OMIT,
        actuals: typing.Sequence[SubmitCompletionActualRequest],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Used to submit feedback regarding the quality of previously generated completions.

        **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - deployment_id: typing.Optional[str]. The ID of the deployment. Must provide either this or deployment_name.

            - deployment_name: typing.Optional[str]. The name of the deployment. Must provide either this or deployment_id.

            - actuals: typing.Sequence[SubmitCompletionActualRequest]. Feedback regarding the quality of previously generated completions

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum import SubmitCompletionActualRequest
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.submit_completion_actuals(
            actuals=[SubmitCompletionActualRequest()],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"actuals": actuals}
        if deployment_id is not OMIT:
            _request["deployment_id"] = deployment_id
        if deployment_name is not OMIT:
            _request["deployment_name"] = deployment_name
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_environment().predict}/", "v1/submit-completion-actuals"
            ),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return
        if _response.status_code == 400:
            raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 500:
            raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def submit_workflow_execution_actuals(
        self,
        *,
        actuals: typing.Sequence[SubmitWorkflowExecutionActualRequest],
        execution_id: typing.Optional[str] = OMIT,
        external_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
            Used to submit feedback regarding the quality of previous workflow execution and its outputs.

            **Note:** Uses a base url of `https://predict.vellum.ai`.

        Parameters:
            - actuals: typing.Sequence[SubmitWorkflowExecutionActualRequest]. Feedback regarding the quality of an output on a previously executed workflow.

            - execution_id: typing.Optional[str]. The Vellum-generated ID of a previously executed workflow. Must provide either this or external_id.

            - external_id: typing.Optional[str]. The external ID that was originally provided by when executing the workflow, if applicable, that you'd now like to submit actuals for. Must provide either this or execution_id.

            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        ---
        from vellum.client import AsyncVellum

        client = AsyncVellum(
            api_key="YOUR_API_KEY",
        )
        await client.submit_workflow_execution_actuals(
            actuals=[],
        )
        """
        _request: typing.Dict[str, typing.Any] = {"actuals": actuals}
        if execution_id is not OMIT:
            _request["execution_id"] = execution_id
        if external_id is not OMIT:
            _request["external_id"] = external_id
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_environment().predict}/", "v1/submit-workflow-execution-actuals"
            ),
            params=jsonable_encoder(
                request_options.get("additional_query_parameters") if request_options is not None else None
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
