# 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.http_response import AsyncHttpResponse, HttpResponse
from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.bad_request_error import BadRequestError
from ..errors.forbidden_error import ForbiddenError
from ..types.bad_request_error_body import BadRequestErrorBody
from ..types.error import Error
from ..types.hallucination_correction_response import HallucinationCorrectionResponse
from ..types.hallucination_corrector import HallucinationCorrector
from ..types.hcm_source_document import HcmSourceDocument
from ..types.list_hallucination_correctors_response import ListHallucinationCorrectorsResponse

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


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

    def list(
        self,
        *,
        filter: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        page_key: typing.Optional[str] = None,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[HallucinationCorrector]:
        """
        Retrieves a list of available hallucination correctors used for detecting and correcting hallucinations in AI-generated content. This endpoint supports filtering by name or description, pagination, and metadata for navigating large result sets.

        Parameters
        ----------
        filter : typing.Optional[str]
            A regular expression applied to the name and description fields. Use this to return only hallucination correctors that match specific keywords or naming conventions.

        limit : typing.Optional[int]
            The maximum number of hallucination correctors to return in the list. Defaults to 10. Range is between 1 and 100.

        page_key : typing.Optional[str]
            Retrieves the next page of hallucination correctors after reaching the limit.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

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

        Returns
        -------
        SyncPager[HallucinationCorrector]
            List of hallucination correctors.
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/hallucination_correctors",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "filter": filter,
                "limit": limit,
                "page_key": page_key,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListHallucinationCorrectorsResponse,
                    parse_obj_as(
                        type_=ListHallucinationCorrectorsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.hallucination_correctors
                _has_next = False
                _get_next = None
                if _parsed_response.metadata is not None:
                    _parsed_next = _parsed_response.metadata.page_key
                    _has_next = _parsed_next is not None and _parsed_next != ""
                    _get_next = lambda: self.list(
                        filter=filter,
                        limit=limit,
                        page_key=_parsed_next,
                        request_timeout=request_timeout,
                        request_timeout_millis=request_timeout_millis,
                        request_options=request_options,
                    )
                return SyncPager(
                    has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def hallucination_correction(
        self,
        *,
        generated_text: str,
        documents: typing.Sequence[HcmSourceDocument],
        model_name: str,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        query: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[HallucinationCorrectionResponse]:
        """
        This endpoint identifies information in generated text that is not supported by the provided source documents and offers corrections with minimal changes. This can be used standalone or as part of a RAG workflow where the HHEM score indicates potential hallucinations.

        Parameters
        ----------
        generated_text : str
            The generated text to be evaluated. The hallucination corrector reviews this text and applies corrections based on the provided source documents.

        documents : typing.Sequence[HcmSourceDocument]
            The source documents that were used to generate the text.

        model_name : str
            The name of the LLM model to use for hallucination correction.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        query : typing.Optional[str]
            Optional query that provides context for the expected response format and factual information. When provided, enables query-aware hallucination correction that considers the specific response format and factual context expected for the query.

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

        Returns
        -------
        HttpResponse[HallucinationCorrectionResponse]
            Successfully analyzed the text for hallucinations
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/hallucination_correctors/correct_hallucinations",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "generated_text": generated_text,
                "documents": convert_and_respect_annotation_metadata(
                    object_=documents, annotation=typing.Sequence[HcmSourceDocument], direction="write"
                ),
                "model_name": model_name,
                "query": query,
            },
            headers={
                "content-type": "application/json",
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    HallucinationCorrectionResponse,
                    parse_obj_as(
                        type_=HallucinationCorrectionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        BadRequestErrorBody,
                        parse_obj_as(
                            type_=BadRequestErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawHallucinationCorrectorsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list(
        self,
        *,
        filter: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        page_key: typing.Optional[str] = None,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[HallucinationCorrector]:
        """
        Retrieves a list of available hallucination correctors used for detecting and correcting hallucinations in AI-generated content. This endpoint supports filtering by name or description, pagination, and metadata for navigating large result sets.

        Parameters
        ----------
        filter : typing.Optional[str]
            A regular expression applied to the name and description fields. Use this to return only hallucination correctors that match specific keywords or naming conventions.

        limit : typing.Optional[int]
            The maximum number of hallucination correctors to return in the list. Defaults to 10. Range is between 1 and 100.

        page_key : typing.Optional[str]
            Retrieves the next page of hallucination correctors after reaching the limit.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

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

        Returns
        -------
        AsyncPager[HallucinationCorrector]
            List of hallucination correctors.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/hallucination_correctors",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "filter": filter,
                "limit": limit,
                "page_key": page_key,
            },
            headers={
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListHallucinationCorrectorsResponse,
                    parse_obj_as(
                        type_=ListHallucinationCorrectorsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.hallucination_correctors
                _has_next = False
                _get_next = None
                if _parsed_response.metadata is not None:
                    _parsed_next = _parsed_response.metadata.page_key
                    _has_next = _parsed_next is not None and _parsed_next != ""

                    async def _get_next():
                        return await self.list(
                            filter=filter,
                            limit=limit,
                            page_key=_parsed_next,
                            request_timeout=request_timeout,
                            request_timeout_millis=request_timeout_millis,
                            request_options=request_options,
                        )

                return AsyncPager(
                    has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def hallucination_correction(
        self,
        *,
        generated_text: str,
        documents: typing.Sequence[HcmSourceDocument],
        model_name: str,
        request_timeout: typing.Optional[int] = None,
        request_timeout_millis: typing.Optional[int] = None,
        query: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[HallucinationCorrectionResponse]:
        """
        This endpoint identifies information in generated text that is not supported by the provided source documents and offers corrections with minimal changes. This can be used standalone or as part of a RAG workflow where the HHEM score indicates potential hallucinations.

        Parameters
        ----------
        generated_text : str
            The generated text to be evaluated. The hallucination corrector reviews this text and applies corrections based on the provided source documents.

        documents : typing.Sequence[HcmSourceDocument]
            The source documents that were used to generate the text.

        model_name : str
            The name of the LLM model to use for hallucination correction.

        request_timeout : typing.Optional[int]
            The API will make a best effort to complete the request in the specified seconds or time out.

        request_timeout_millis : typing.Optional[int]
            The API will make a best effort to complete the request in the specified milliseconds or time out.

        query : typing.Optional[str]
            Optional query that provides context for the expected response format and factual information. When provided, enables query-aware hallucination correction that considers the specific response format and factual context expected for the query.

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

        Returns
        -------
        AsyncHttpResponse[HallucinationCorrectionResponse]
            Successfully analyzed the text for hallucinations
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/hallucination_correctors/correct_hallucinations",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "generated_text": generated_text,
                "documents": convert_and_respect_annotation_metadata(
                    object_=documents, annotation=typing.Sequence[HcmSourceDocument], direction="write"
                ),
                "model_name": model_name,
                "query": query,
            },
            headers={
                "content-type": "application/json",
                "Request-Timeout": str(request_timeout) if request_timeout is not None else None,
                "Request-Timeout-Millis": str(request_timeout_millis) if request_timeout_millis is not None else None,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    HallucinationCorrectionResponse,
                    parse_obj_as(
                        type_=HallucinationCorrectionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        BadRequestErrorBody,
                        parse_obj_as(
                            type_=BadRequestErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
