Harden OpenAI api layer
- Support rate limiting - Add proper error handling (don't rely on exceptions) Closes #147
This commit is contained in:
+3
-1
@@ -72,7 +72,9 @@ config :music_library, BraveSearch,
|
|||||||
user_agent: user_agent,
|
user_agent: user_agent,
|
||||||
api_cooldown: 1000
|
api_cooldown: 1000
|
||||||
|
|
||||||
config :music_library, OpenAI, api_key: "change me"
|
config :music_library, OpenAI,
|
||||||
|
api_key: "change me",
|
||||||
|
api_cooldown: 250
|
||||||
|
|
||||||
# Configure esbuild (the version is required)
|
# Configure esbuild (the version is required)
|
||||||
config :esbuild,
|
config :esbuild,
|
||||||
|
|||||||
+2
-1
@@ -96,7 +96,8 @@ config :music_library, OpenAI,
|
|||||||
req_options: [
|
req_options: [
|
||||||
plug: {Req.Test, OpenAI.API},
|
plug: {Req.Test, OpenAI.API},
|
||||||
max_retries: 0
|
max_retries: 0
|
||||||
]
|
],
|
||||||
|
api_cooldown: 0
|
||||||
|
|
||||||
config :phoenix_test, :endpoint, MusicLibraryWeb.Endpoint
|
config :phoenix_test, :endpoint, MusicLibraryWeb.Endpoint
|
||||||
|
|
||||||
|
|||||||
+23
-20
@@ -3,27 +3,29 @@ defmodule OpenAI.API do
|
|||||||
|
|
||||||
@spec gpt(OpenAI.Completion.t(), OpenAI.Config.t()) :: {:ok, map()} | {:error, term()}
|
@spec gpt(OpenAI.Completion.t(), OpenAI.Config.t()) :: {:ok, map()} | {:error, term()}
|
||||||
def gpt(completion, config) do
|
def gpt(completion, config) do
|
||||||
resp =
|
case config
|
||||||
config
|
|> new_request()
|
||||||
|> new_request()
|
|> Req.merge(
|
||||||
|> Req.merge(
|
url: "/v1/chat/completions",
|
||||||
url: "/v1/chat/completions",
|
receive_timeout: 10_000,
|
||||||
receive_timeout: 10_000,
|
connect_options: [timeout: 2_500],
|
||||||
connect_options: [timeout: 2_500],
|
json: %{
|
||||||
json: %{
|
model: completion.model,
|
||||||
model: completion.model,
|
messages: [Map.take(completion, [:content, :role])],
|
||||||
messages: [Map.take(completion, [:content, :role])],
|
response_format: %{type: "json_object"},
|
||||||
response_format: %{type: "json_object"},
|
temperature: completion.temperature
|
||||||
temperature: completion.temperature
|
}
|
||||||
}
|
)
|
||||||
)
|
|> Req.post() do
|
||||||
|> Req.post!()
|
{:ok, %{status: status, body: body}} when status in 200..299 ->
|
||||||
|
content = get_in(body, ["choices", Access.at(0), "message", "content"])
|
||||||
|
JSON.decode(content)
|
||||||
|
|
||||||
if resp.status in 200..299 do
|
{:ok, %{body: body}} ->
|
||||||
content = get_in(resp.body, ["choices", Access.at(0), "message", "content"])
|
{:error, "OpenAI API error: #{inspect(body)}"}
|
||||||
{:ok, JSON.decode!(content)}
|
|
||||||
else
|
{:error, exception} ->
|
||||||
{:error, resp.body}
|
{:error, "Connection error: #{Exception.message(exception)}"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -92,6 +94,7 @@ defmodule OpenAI.API do
|
|||||||
auth: {:bearer, config.api_key}
|
auth: {:bearer, config.api_key}
|
||||||
)
|
)
|
||||||
|> Req.Request.merge_options(config.req_options)
|
|> Req.Request.merge_options(config.req_options)
|
||||||
|
|> Req.RateLimiter.attach(name: :open_ai, cooldown: config.api_cooldown)
|
||||||
|> Req.Request.append_request_steps(log_attempt: &log_attempt/1)
|
|> Req.Request.append_request_steps(log_attempt: &log_attempt/1)
|
||||||
|> Req.Request.append_response_steps(log_error: &log_error/1)
|
|> Req.Request.append_response_steps(log_error: &log_error/1)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
defmodule OpenAI.Config do
|
defmodule OpenAI.Config do
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
api_key: String.t(),
|
api_key: String.t(),
|
||||||
req_options: Keyword.t()
|
req_options: Keyword.t(),
|
||||||
|
api_cooldown: non_neg_integer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@enforce_keys [:api_key]
|
@enforce_keys [:api_key]
|
||||||
defstruct api_key: "",
|
defstruct api_key: "",
|
||||||
req_options: []
|
req_options: [],
|
||||||
|
api_cooldown: 500
|
||||||
|
|
||||||
@schema NimbleOptions.new!(
|
@schema NimbleOptions.new!(
|
||||||
api_key: [
|
api_key: [
|
||||||
@@ -17,6 +19,11 @@ defmodule OpenAI.Config do
|
|||||||
type: :keyword_list,
|
type: :keyword_list,
|
||||||
required: false,
|
required: false,
|
||||||
default: []
|
default: []
|
||||||
|
],
|
||||||
|
api_cooldown: [
|
||||||
|
type: :integer,
|
||||||
|
required: false,
|
||||||
|
default: 500
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user