Skip to content

Commit

Permalink
Add RunFailed event
Browse files Browse the repository at this point in the history
The agent will now publish a RunFailed event when it detects that the
status of an ongoing run has transitioned to "failed". The event
includes OpenAI's code and message values verbatim.
  • Loading branch information
jwilger committed Feb 22, 2024
1 parent c1ad069 commit c31231f
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 2 deletions.
15 changes: 14 additions & 1 deletion lib/gpt_agent.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defmodule GptAgent do
alias GptAgent.Events.{
AssistantMessageAdded,
RunCompleted,
RunFailed,
RunStarted,
ToolCallOutputRecorded,
ToolCallRequested,
Expand Down Expand Up @@ -429,7 +430,19 @@ defmodule GptAgent do
log("Run ID #{inspect(id)} failed with status #{inspect(status)}", :warning)
log("Response: #{inspect(response)}")
log("State: #{inspect(state)}")
noreply(%{state | running?: false, run_id: nil})

state
|> Map.put(:running?, false)
|> publish_event(
RunFailed.new!(
id: id,
thread_id: state.thread_id,
assistant_id: state.assistant_id,
code: response |> Map.get("last_error", %{}) |> Map.get("code") || "unknown",
message: response |> Map.get("last_error", %{}) |> Map.get("message") || "unknown"
)
)
|> noreply()
end

defmodule Impl do
Expand Down
16 changes: 16 additions & 0 deletions lib/gpt_agent/events/run_failed.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule GptAgent.Events.RunFailed do
@moduledoc """
An OpenAI Assistants run was completed
"""

use GptAgent.Types
alias GptAgent.Types

typedstruct enforce: true do
field :id, Types.run_id()
field :thread_id, Types.thread_id()
field :assistant_id, Types.assistant_id()
field :code, Types.run_error_code()
field :message, Types.run_error_message()
end
end
3 changes: 3 additions & 0 deletions lib/gpt_agent/types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ defmodule GptAgent.Types do
@type thread_id() :: nonblank_string()
@type file_id() :: nonblank_string()

@type run_error_code() :: nonblank_string()
@type run_error_message() :: nonblank_string()

@type message_metadata() :: %{optional(String.t()) => Jason.Encoder.t()}
precond message_metadata: &validate_message_metadata/1

Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule GptAgent.MixProject do
def project do
[
app: :gpt_agent,
version: "9.0.1",
version: "9.1.0",
elixir: "~> 1.16",
start_permanent: Mix.env() == :prod,
aliases: aliases(),
Expand Down
56 changes: 56 additions & 0 deletions test/gpt_agent_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule GptAgentTest do
alias GptAgent.Events.{
AssistantMessageAdded,
RunCompleted,
RunFailed,
RunStarted,
ToolCallOutputRecorded,
ToolCallRequested,
Expand Down Expand Up @@ -1106,6 +1107,61 @@ defmodule GptAgentTest do
assert :ok = GptAgent.add_user_message(pid, Faker.Lorem.sentence())
assert_receive {^pid, %UserMessageAdded{}}, 5_000
end

@tag capture_log: true
test "when the run is fails, sends the RunFailed event to the callback handler", %{
bypass: bypass,
assistant_id: assistant_id,
thread_id: thread_id,
run_id: run_id
} do
{:ok, pid} =
GptAgent.connect(thread_id: thread_id, last_message_id: nil, assistant_id: assistant_id)

Bypass.expect_once(bypass, "GET", "/v1/threads/#{thread_id}/runs/#{run_id}", fn conn ->
conn
|> Plug.Conn.put_resp_content_type("application/json")
|> Plug.Conn.resp(
200,
Jason.encode!(%{
"id" => run_id,
"object" => "thread.run",
"created_at" => 1_699_075_072,
"assistant_id" => assistant_id,
"thread_id" => thread_id,
"status" => "failed",
"started_at" => 1_699_075_072,
"expires_at" => nil,
"cancelled_at" => nil,
"completed_at" => nil,
"failed_at" => 1_699_075_073,
"last_error" => %{
"code" => "rate_limit_exceeded",
"message" =>
"You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors."
},
"model" => "gpt-4-1106-preview",
"instructions" => nil,
"tools" => [],
"file_ids" => [],
"metadata" => %{}
})
)
end)

:ok = GptAgent.add_user_message(pid, "Hello")

assert_receive {^pid,
%RunFailed{
id: ^run_id,
thread_id: ^thread_id,
assistant_id: ^assistant_id,
code: "rate_limit_exceeded",
message:
"You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors."
}},
5_000
end
end

describe "submit_tool_output/3" do
Expand Down

0 comments on commit c31231f

Please sign in to comment.