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

import typing
from json.decoder import JSONDecodeError

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.request_options import RequestOptions
from .errors.unprocessable_entity_error import UnprocessableEntityError
from .types.details import Details
from .types.http_validation_error import HttpValidationError
from .types.list_tunes_response import ListTunesResponse
from .types.tune import Tune
from .types.tune_type import TuneType

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


class FineTuningClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def create(
        self,
        *,
        details: Details,
        name: str,
        continue_on_rejection: typing.Optional[bool] = OMIT,
        description: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Tune:
        """
        Spawn a tune.

        Parameters
        ----------
        details : Details
            Details of the tune.

        name : str
            The name of the tune.

        continue_on_rejection : typing.Optional[bool]
            Continue fine-tuning if any asset was rejected.

        description : typing.Optional[str]
            Description for the tune.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import OctoAI
        from octoai.fine_tuning import (
            Details_LoraTune,
            LoraTuneCheckpoint,
            LoraTuneFile,
        )

        client = OctoAI(
            api_key="YOUR_API_KEY",
        )
        client.fine_tuning.create(
            continue_on_rejection=True,
            description="string",
            details=Details_LoraTune(
                base_checkpoint=LoraTuneCheckpoint(),
                files=[LoraTuneFile()],
                resize_images=True,
                seed=1,
                steps=1,
                trigger_words=["string"],
            ),
            name="string",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/tune",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "continue_on_rejection": continue_on_rejection,
                "description": description,
                "details": details,
                "name": name,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 get(self, tune_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tune:
        """
        Retrieve a specific tune.

        Parameters
        ----------
        tune_id : str
            The ID of the tune to retrieve.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import OctoAI

        client = OctoAI(
            api_key="YOUR_API_KEY",
        )
        client.fine_tuning.get(
            tune_id="string",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/tune/{jsonable_encoder(tune_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 delete(self, tune_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tune:
        """
        Delete the specified tune.

        Parameters
        ----------
        tune_id : str
            The ID of the tune to delete.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import OctoAI

        client = OctoAI(
            api_key="YOUR_API_KEY",
        )
        client.fine_tuning.delete(
            tune_id="string",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/tune/{jsonable_encoder(tune_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 cancel(self, tune_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tune:
        """
        Cancel the specified tune.

        Parameters
        ----------
        tune_id : str
            The ID of the tune to cancel.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import OctoAI

        client = OctoAI(
            api_key="YOUR_API_KEY",
        )
        client.fine_tuning.cancel(
            tune_id="string",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/tune/{jsonable_encoder(tune_id)}/cancel",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 list(
        self,
        *,
        offset: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        name: typing.Optional[str] = None,
        tune_type: typing.Optional[TuneType] = None,
        base_checkpoint_id: typing.Optional[str] = None,
        trigger_words: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        engine: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListTunesResponse:
        """
        List all tunes owned by the current user.

        Parameters
        ----------
        offset : typing.Optional[int]
            Offset into the results.

        limit : typing.Optional[int]
            The max number of results to be shown (limit 100).

        name : typing.Optional[str]
            The name of the tune to filter on.

        tune_type : typing.Optional[TuneType]
            The type of the tune to filter on.

        base_checkpoint_id : typing.Optional[str]
            The base checkpoint ID for the LoRA tune.

        trigger_words : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            The trigger words to filter on.

        engine : typing.Optional[str]
            The engine type for listing tunes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListTunesResponse
            Successful Response

        Examples
        --------
        from octoai.client import OctoAI

        client = OctoAI(
            api_key="YOUR_API_KEY",
        )
        client.fine_tuning.list()
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/tunes",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "offset": offset,
                "limit": limit,
                "name": name,
                "tune_type": tune_type,
                "base_checkpoint_id": base_checkpoint_id,
                "trigger_words": trigger_words,
                "engine": engine,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(ListTunesResponse, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 AsyncFineTuningClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def create(
        self,
        *,
        details: Details,
        name: str,
        continue_on_rejection: typing.Optional[bool] = OMIT,
        description: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Tune:
        """
        Spawn a tune.

        Parameters
        ----------
        details : Details
            Details of the tune.

        name : str
            The name of the tune.

        continue_on_rejection : typing.Optional[bool]
            Continue fine-tuning if any asset was rejected.

        description : typing.Optional[str]
            Description for the tune.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import AsyncOctoAI
        from octoai.fine_tuning import (
            Details_LoraTune,
            LoraTuneCheckpoint,
            LoraTuneFile,
        )

        client = AsyncOctoAI(
            api_key="YOUR_API_KEY",
        )
        await client.fine_tuning.create(
            continue_on_rejection=True,
            description="string",
            details=Details_LoraTune(
                base_checkpoint=LoraTuneCheckpoint(),
                files=[LoraTuneFile()],
                resize_images=True,
                seed=1,
                steps=1,
                trigger_words=["string"],
            ),
            name="string",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/tune",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "continue_on_rejection": continue_on_rejection,
                "description": description,
                "details": details,
                "name": name,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 get(self, tune_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tune:
        """
        Retrieve a specific tune.

        Parameters
        ----------
        tune_id : str
            The ID of the tune to retrieve.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import AsyncOctoAI

        client = AsyncOctoAI(
            api_key="YOUR_API_KEY",
        )
        await client.fine_tuning.get(
            tune_id="string",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/tune/{jsonable_encoder(tune_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 delete(self, tune_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tune:
        """
        Delete the specified tune.

        Parameters
        ----------
        tune_id : str
            The ID of the tune to delete.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import AsyncOctoAI

        client = AsyncOctoAI(
            api_key="YOUR_API_KEY",
        )
        await client.fine_tuning.delete(
            tune_id="string",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/tune/{jsonable_encoder(tune_id)}",
            base_url=self._client_wrapper.get_environment().default,
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 cancel(self, tune_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tune:
        """
        Cancel the specified tune.

        Parameters
        ----------
        tune_id : str
            The ID of the tune to cancel.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Tune
            Successful Response

        Examples
        --------
        from octoai.client import AsyncOctoAI

        client = AsyncOctoAI(
            api_key="YOUR_API_KEY",
        )
        await client.fine_tuning.cancel(
            tune_id="string",
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/tune/{jsonable_encoder(tune_id)}/cancel",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(Tune, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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 list(
        self,
        *,
        offset: typing.Optional[int] = None,
        limit: typing.Optional[int] = None,
        name: typing.Optional[str] = None,
        tune_type: typing.Optional[TuneType] = None,
        base_checkpoint_id: typing.Optional[str] = None,
        trigger_words: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        engine: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ListTunesResponse:
        """
        List all tunes owned by the current user.

        Parameters
        ----------
        offset : typing.Optional[int]
            Offset into the results.

        limit : typing.Optional[int]
            The max number of results to be shown (limit 100).

        name : typing.Optional[str]
            The name of the tune to filter on.

        tune_type : typing.Optional[TuneType]
            The type of the tune to filter on.

        base_checkpoint_id : typing.Optional[str]
            The base checkpoint ID for the LoRA tune.

        trigger_words : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            The trigger words to filter on.

        engine : typing.Optional[str]
            The engine type for listing tunes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ListTunesResponse
            Successful Response

        Examples
        --------
        from octoai.client import AsyncOctoAI

        client = AsyncOctoAI(
            api_key="YOUR_API_KEY",
        )
        await client.fine_tuning.list()
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/tunes",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "offset": offset,
                "limit": limit,
                "name": name,
                "tune_type": tune_type,
                "base_checkpoint_id": base_checkpoint_id,
                "trigger_words": trigger_words,
                "engine": engine,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return pydantic_v1.parse_obj_as(ListTunesResponse, _response.json())  # type: ignore
            if _response.status_code == 422:
                raise UnprocessableEntityError(
                    pydantic_v1.parse_obj_as(HttpValidationError, _response.json())  # type: ignore
                )
            _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)
