Source file openai_error.ml

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
open Melange_json.Primitives

type openai_error_type =
  | Invalid_request_error
  | Authentication_error
  | Rate_limit_error
  | Not_found_error
  | Server_error
  | Unknown_error of string

type error_detail = {
  typ : string; [@json.key "type"] [@json.default "unknown"]
  message : string; [@json.default ""]
}
[@@json.allow_extra_fields] [@@deriving of_json]

type error_envelope = { error : error_detail } [@@json.allow_extra_fields] [@@deriving of_json]

let error_type_of_string = function
  | "invalid_request_error" -> Invalid_request_error
  | "authentication_error" -> Authentication_error
  | "rate_limit_error" -> Rate_limit_error
  | "not_found_error" -> Not_found_error
  | "server_error" -> Server_error
  | s -> Unknown_error s

let is_retryable = function
  | Rate_limit_error | Server_error -> true
  | Invalid_request_error | Authentication_error | Not_found_error | Unknown_error _ -> false

let of_response ~status ~body =
  let error_type, message =
    try
      let json = Yojson.Basic.from_string body in
      let { error = { typ; message } } = error_envelope_of_json json in
      Some (error_type_of_string typ), message
    with
    | Yojson.Json_error _ -> None, body
    | Melange_json.Of_json_error _ -> None, body
  in
  let error_body =
    match error_type with
    | Some t when is_retryable t -> "[retryable] " ^ message
    | Some _ | None -> message
  in
  { Ai_provider.Provider_error.provider = "openai"; kind = Api_error { status; body = error_body } }