File size: 3,768 Bytes
447ebeb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# duplicate -> https://github.com/confident-ai/deepeval/blob/main/deepeval/confident/api.py
import logging
import httpx
from enum import Enum
from litellm._logging import verbose_logger

DEEPEVAL_BASE_URL = "https://deepeval.confident-ai.com"
DEEPEVAL_BASE_URL_EU = "https://eu.deepeval.confident-ai.com"
API_BASE_URL = "https://api.confident-ai.com"
API_BASE_URL_EU = "https://eu.api.confident-ai.com"
retryable_exceptions = httpx.HTTPError

from litellm.llms.custom_httpx.http_handler import (
    HTTPHandler,
    get_async_httpx_client,
    httpxSpecialProvider,
)


def log_retry_error(details):
    exception = details.get("exception")
    tries = details.get("tries")
    if exception:
        logging.error(f"Confident AI Error: {exception}. Retrying: {tries} time(s)...")
    else:
        logging.error(f"Retrying: {tries} time(s)...")


class HttpMethods(Enum):
    GET = "GET"
    POST = "POST"
    DELETE = "DELETE"
    PUT = "PUT"


class Endpoints(Enum):
    DATASET_ENDPOINT = "/v1/dataset"
    TEST_RUN_ENDPOINT = "/v1/test-run"
    TRACING_ENDPOINT = "/v1/tracing"
    EVENT_ENDPOINT = "/v1/event"
    FEEDBACK_ENDPOINT = "/v1/feedback"
    PROMPT_ENDPOINT = "/v1/prompt"
    RECOMMEND_ENDPOINT = "/v1/recommend-metrics"
    EVALUATE_ENDPOINT = "/evaluate"
    GUARD_ENDPOINT = "/guard"
    GUARDRAILS_ENDPOINT = "/guardrails"
    BASELINE_ATTACKS_ENDPOINT = "/generate-baseline-attacks"


class Api:
    def __init__(self, api_key: str, base_url=None):
        self.api_key = api_key
        self._headers = {
            "Content-Type": "application/json",
            # "User-Agent": "Python/Requests",
            "CONFIDENT_API_KEY": api_key,
        }
        # using the global non-eu variable for base url
        self.base_api_url = base_url or API_BASE_URL
        self.sync_http_handler = HTTPHandler()
        self.async_http_handler = get_async_httpx_client(
            llm_provider=httpxSpecialProvider.LoggingCallback
        )

    def _http_request(
        self, method: str, url: str, headers=None, json=None, params=None
    ):
        if method != "POST":
            raise Exception("Only POST requests are supported")
        try:
            self.sync_http_handler.post(
                url=url,
                headers=headers,
                json=json,
                params=params,
            )
        except httpx.HTTPStatusError as e:
            raise Exception(f"DeepEval logging error: {e.response.text}")
        except Exception as e:
            raise e

    def send_request(
        self, method: HttpMethods, endpoint: Endpoints, body=None, params=None
    ):
        url = f"{self.base_api_url}{endpoint.value}"
        res = self._http_request(
            method=method.value,
            url=url,
            headers=self._headers,
            json=body,
            params=params,
        )

        if res.status_code == 200:
            try:
                return res.json()
            except ValueError:
                return res.text
        else:
            verbose_logger.debug(res.json())
            raise Exception(res.json().get("error", res.text))

    async def a_send_request(
        self, method: HttpMethods, endpoint: Endpoints, body=None, params=None
    ):
        if method != HttpMethods.POST:
            raise Exception("Only POST requests are supported")

        url = f"{self.base_api_url}{endpoint.value}"
        try:
            await self.async_http_handler.post(
                url=url,
                headers=self._headers,
                json=body,
                params=params,
            )
        except httpx.HTTPStatusError as e:
            raise Exception(f"DeepEval logging error: {e.response.text}")
        except Exception as e:
            raise e