Skip to content

Commit

Permalink
adds tests for handling responses with tool use. Supports #8 and #9
Browse files Browse the repository at this point in the history
  • Loading branch information
lebrunel committed Nov 15, 2024
1 parent 6a504fc commit c86c709
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 8 deletions.
57 changes: 57 additions & 0 deletions test/anthropix_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,63 @@ defmodule AnthropixTest do
assert get_in(last, ["usage", "output_tokens"]) == 34
end

test "generates a response with tool use" do
client = Mock.client(& Mock.respond(&1, :messages_tools))
assert {:ok, res} = Anthropix.chat(client, [
model: "claude-3-haiku-20240307",
messages: [
%{role: "user", content: "What is the weather in London?"}
],
tools: [
%{
name: "get_weather",
description: "Fetches the weather for the given location.",
input_schema: %{
type: "object",
properties: %{
location: %{type: "string", description: "Location name - town, city or area."}
},
required: ["location"]
}
}
]
])

block = Enum.find(res["content"], & &1["type"] == "tool_use")
assert is_map(block)
assert get_in(block, ["name"]) == "get_weather"
assert get_in(block, ["input", "location"]) == "London"
end

test "streams a response with tool use" do
client = Mock.client(& Mock.stream(&1, :messages_tools))
assert {:ok, stream} = Anthropix.chat(client, [
model: "claude-3-haiku-20240307",
messages: [
%{role: "user", content: "What is the weather in London?"}
],
tools: [
%{
name: "get_weather",
description: "Fetches the weather for the given location.",
input_schema: %{
type: "object",
properties: %{
location: %{type: "string", description: "Location name - town, city or area."}
},
required: ["location"]
}
}
],
stream: true
])
res = Enum.to_list(stream)
last = Enum.find(res, & &1["type"] == "message_delta")
assert is_list(res)
assert get_in(last, ["delta", "stop_reason"]) == "tool_use"
assert get_in(last, ["usage", "output_tokens"]) == 61
end

test "returns error when model not found" do
client = Mock.client(& Mock.respond(&1, 404))
assert {:error, %APIError{type: "not_found"}} = Anthropix.chat(client, [
Expand Down
70 changes: 62 additions & 8 deletions test/support/mock.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,30 @@ defmodule Anthropix.Mock do
"usage" => %{"input_tokens" => 18, "output_tokens" => 36}
},

:messages_tools => %{
"content" => [
%{"text" => "Okay, let me check the weather for London:", "type" => "text"},
%{
"id" => "toolu_01C8aPF8bZPusgu3LvVAf4Mo",
"input" => %{"location" => "London"},
"name" => "get_weather",
"type" => "tool_use"
}
],
"id" => "msg_01THGxy3R57vpDPKmqPmcALZ",
"model" => "claude-3-haiku-20240307",
"role" => "assistant",
"stop_reason" => "tool_use",
"stop_sequence" => nil,
"type" => "message",
"usage" => %{
"cache_creation_input_tokens" => 0,
"cache_read_input_tokens" => 0,
"input_tokens" => 348,
"output_tokens" => 65
}
},

:batch_list => %{
"data" => [
%{
Expand Down Expand Up @@ -86,14 +110,14 @@ defmodule Anthropix.Mock do
@stream_mocks %{
messages: [
%{"type" => "message_start", "message" => %{
"content" => [],
"id" => "msg_01AgC6AM5riFWbgj1ZoSgD1b",
"model" => "claude-3-sonnet-20240229",
"role" => "assistant",
"stop_reason" => nil,
"stop_sequence" => nil,
"type" => "message",
"usage" => %{"input_tokens" => 18, "output_tokens" => 1}
"content" => [],
"id" => "msg_01AgC6AM5riFWbgj1ZoSgD1b",
"model" => "claude-3-sonnet-20240229",
"role" => "assistant",
"stop_reason" => nil,
"stop_sequence" => nil,
"type" => "message",
"usage" => %{"input_tokens" => 18, "output_tokens" => 1}
}},
%{"type" => "content_block_start", "index" => 0, "content_block" => %{"text" => "", "type" => "text"}},
%{"type" => "content_block_delta", "index" => 0, "delta" => %{"text" => "Here", "type" => "text_delta"}},
Expand Down Expand Up @@ -125,6 +149,36 @@ defmodule Anthropix.Mock do
%{"type" => "content_block_stop", "index" => 0},
%{"type" => "message_delta", "delta" => %{"stop_reason" => "end_turn", "stop_sequence" => nil}, "usage" => %{"output_tokens" => 34}},
%{"type" => "message_stop"}
],

messages_tools: [
%{"type" => "message_start", "message" => %{
"content" => [],
"id" => "msg_017cEgug4oBcJZ9BBpB4iFuS",
"model" => "claude-3-haiku-20240307",
"role" => "assistant",
"stop_reason" => nil,
"stop_sequence" => nil,
"type" => "message",
"usage" => %{"cache_creation_input_tokens" => 0, "cache_read_input_tokens" => 0, "input_tokens" => 348, "output_tokens" => 4}
}},
%{"type" => "content_block_start", "index" => 0, "content_block" => %{"text" => "", "type" => "text"}},
%{"type" => "content_block_delta", "index" => 0, "delta" => %{"text" => "Here is the weather", "type" => "text_delta"}},
%{"type" => "content_block_delta", "index" => 0, "delta" => %{"text" => " for London:", "type" => "text_delta"}},
%{"type" => "content_block_stop", "index" => 0},
%{"type" => "content_block_start", "index" => 1, "content_block" => %{
"id" => "toolu_01HkwGv3jQLx1fGJV8qfskQZ",
"input" => %{},
"name" => "get_weather",
"type" => "tool_use"
}},
%{"type" => "content_block_delta", "index" => 1, "delta" => %{"partial_json" => "", "type" => "input_json_delta"}},
%{"type" => "content_block_delta", "index" => 1, "delta" => %{"partial_json" => "{\"location\"", "type" => "input_json_delta"}},
%{"type" => "content_block_delta", "index" => 1, "delta" => %{"partial_json" => ": \"Lond", "type" => "input_json_delta"}},
%{"type" => "content_block_delta", "index" => 1, "delta" => %{"partial_json" => "on\"}", "type" => "input_json_delta"}},
%{"type" => "content_block_stop", "index" => 1},
%{"type" => "message_delta", "delta" => %{"stop_reason" => "tool_use", "stop_sequence" => nil}, "usage" => %{"output_tokens" => 61}},
%{"type" => "message_stop"}
]
}

Expand Down

0 comments on commit c86c709

Please sign in to comment.