Packages

A well-typed, idiomatic Gleam client for Anthropic's Claude API with streaming support and tool use

Current section

Files

Jump to
anthropic_gleam src examples@tool_use_integration_test.erl
Raw

src/examples@tool_use_integration_test.erl

-module(examples@tool_use_integration_test).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/examples/tool_use_integration_test.gleam").
-export([main/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Tool Use Integration Test for Anthropic API\n"
"\n"
" This script tests the complete tool use workflow with the Claude API\n"
" Run with: gleam run -m examples/tool_use_integration_test\n"
).
-file("src/examples/tool_use_integration_test.gleam", 735).
-spec stop_reason_to_string(
gleam@option:option(anthropic@types@request:stop_reason())
) -> binary().
stop_reason_to_string(Reason) ->
case Reason of
none ->
<<"none"/utf8>>;
{some, R} ->
anthropic@types@request:stop_reason_to_string(R)
end.
-file("src/examples/tool_use_integration_test.gleam", 128).
-spec test_tool_definition_auto(binary()) -> boolean().
test_tool_definition_auto(Api_key) ->
gleam_stdlib:println(<<"Testing tool definition with Auto choice..."/utf8>>),
Config_result = begin
_pipe = anthropic@config:config_options(),
_pipe@1 = anthropic@config:with_api_key(_pipe, Api_key),
anthropic@config:load_config(_pipe@1)
end,
case Config_result of
{error, Err} ->
gleam_stdlib:println(
<<"Config error: "/utf8,
(anthropic@types@error:error_to_string(Err))/binary>>
),
false;
{ok, Cfg} ->
Api_client = anthropic@client:new(Cfg),
Calculator_tool = begin
_pipe@2 = anthropic@tools@builder:tool_builder(
<<"calculator"/utf8>>
),
_pipe@3 = anthropic@tools@builder:with_description(
_pipe@2,
<<"Perform basic arithmetic operations"/utf8>>
),
_pipe@4 = anthropic@tools@builder:add_string_param(
_pipe@3,
<<"operation"/utf8>>,
<<"The operation: add, subtract, multiply, divide"/utf8>>,
true
),
_pipe@5 = anthropic@tools@builder:add_string_param(
_pipe@4,
<<"a"/utf8>>,
<<"First number as a string"/utf8>>,
true
),
_pipe@6 = anthropic@tools@builder:add_string_param(
_pipe@5,
<<"b"/utf8>>,
<<"Second number as a string"/utf8>>,
true
),
anthropic@tools@builder:build(_pipe@6)
end,
Req = begin
_pipe@7 = anthropic@types@request:create_request(
<<"claude-3-5-haiku-20241022"/utf8>>,
[anthropic@types@message:user_message(
<<"What is 15 + 27? Use the calculator tool."/utf8>>
)],
200
),
_pipe@8 = anthropic@types@request:with_tools(
_pipe@7,
[Calculator_tool]
),
anthropic@types@request:with_tool_choice(_pipe@8, auto)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"REQUEST:"/utf8>>),
gleam_stdlib:println(<<" Model: claude-3-5-haiku-20241022"/utf8>>),
gleam_stdlib:println(
<<" Tool: calculator (add, subtract, multiply, divide)"/utf8>>
),
gleam_stdlib:println(<<" Tool Choice: Auto"/utf8>>),
gleam_stdlib:println(
<<" Message: What is 15 + 27? Use the calculator tool."/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Sending request to API..."/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
case anthropic@api:create_message(Api_client, Req) of
{ok, Response} ->
gleam_stdlib:println(<<"RESPONSE:"/utf8>>),
gleam_stdlib:println(
<<" ID: "/utf8, (erlang:element(2, Response))/binary>>
),
gleam_stdlib:println(
<<" Model: "/utf8,
(erlang:element(6, Response))/binary>>
),
gleam_stdlib:println(
<<" Stop reason: "/utf8,
(stop_reason_to_string(erlang:element(7, Response)))/binary>>
),
gleam_stdlib:println(
<<" Input tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(2, erlang:element(9, Response))
))/binary>>
),
gleam_stdlib:println(
<<" Output tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(3, erlang:element(9, Response))
))/binary>>
),
Is_tool_use = anthropic@tools:needs_tool_execution(Response),
gleam_stdlib:println(
<<" Needs tool execution: "/utf8,
(gleam@string:inspect(Is_tool_use))/binary>>
),
case Is_tool_use of
true ->
Tool_calls = anthropic@tools:extract_tool_calls(
Response
),
gleam_stdlib:println(
<<" Tool calls count: "/utf8,
(erlang:integer_to_binary(
erlang:length(Tool_calls)
))/binary>>
),
gleam@list:each(
Tool_calls,
fun(Call) ->
gleam_stdlib:println(
<<" Tool call:"/utf8>>
),
gleam_stdlib:println(
<<" ID: "/utf8,
(erlang:element(2, Call))/binary>>
),
gleam_stdlib:println(
<<" Name: "/utf8,
(erlang:element(3, Call))/binary>>
),
gleam_stdlib:println(
<<" Input: "/utf8,
(erlang:element(4, Call))/binary>>
)
end
),
true;
false ->
gleam_stdlib:println(
<<" Text response: "/utf8,
(anthropic@types@request:response_text(
Response
))/binary>>
),
true
end;
{error, Err@1} ->
gleam_stdlib:println(
<<"ERROR: "/utf8,
(anthropic@types@error:error_to_string(Err@1))/binary>>
),
false
end
end.
-file("src/examples/tool_use_integration_test.gleam", 225).
-spec test_forced_tool_use(binary()) -> boolean().
test_forced_tool_use(Api_key) ->
gleam_stdlib:println(
<<"Testing forced tool use with ToolName choice..."/utf8>>
),
Config_result = begin
_pipe = anthropic@config:config_options(),
_pipe@1 = anthropic@config:with_api_key(_pipe, Api_key),
anthropic@config:load_config(_pipe@1)
end,
case Config_result of
{error, Err} ->
gleam_stdlib:println(
<<"Config error: "/utf8,
(anthropic@types@error:error_to_string(Err))/binary>>
),
false;
{ok, Cfg} ->
Api_client = anthropic@client:new(Cfg),
Weather_tool = begin
_pipe@2 = anthropic@tools@builder:tool_builder(
<<"get_weather"/utf8>>
),
_pipe@3 = anthropic@tools@builder:with_description(
_pipe@2,
<<"Get the current weather for a location"/utf8>>
),
_pipe@4 = anthropic@tools@builder:add_string_param(
_pipe@3,
<<"location"/utf8>>,
<<"City and state, e.g. 'San Francisco, CA'"/utf8>>,
true
),
_pipe@5 = anthropic@tools@builder:add_enum_param(
_pipe@4,
<<"unit"/utf8>>,
<<"Temperature unit"/utf8>>,
[<<"celsius"/utf8>>, <<"fahrenheit"/utf8>>],
false
),
anthropic@tools@builder:build(_pipe@5)
end,
Req = begin
_pipe@6 = anthropic@types@request:create_request(
<<"claude-3-5-haiku-20241022"/utf8>>,
[anthropic@types@message:user_message(
<<"Tell me about the weather in Tokyo."/utf8>>
)],
200
),
_pipe@7 = anthropic@types@request:with_tools(
_pipe@6,
[Weather_tool]
),
anthropic@types@request:with_tool_choice(
_pipe@7,
{tool_name, <<"get_weather"/utf8>>}
)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"REQUEST:"/utf8>>),
gleam_stdlib:println(<<" Model: claude-3-5-haiku-20241022"/utf8>>),
gleam_stdlib:println(<<" Tool: get_weather"/utf8>>),
gleam_stdlib:println(
<<" Tool Choice: ToolName(\"get_weather\") - FORCED"/utf8>>
),
gleam_stdlib:println(
<<" Message: Tell me about the weather in Tokyo."/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Sending request to API..."/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
case anthropic@api:create_message(Api_client, Req) of
{ok, Response} ->
gleam_stdlib:println(<<"RESPONSE:"/utf8>>),
gleam_stdlib:println(
<<" ID: "/utf8, (erlang:element(2, Response))/binary>>
),
gleam_stdlib:println(
<<" Stop reason: "/utf8,
(stop_reason_to_string(erlang:element(7, Response)))/binary>>
),
gleam_stdlib:println(
<<" Input tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(2, erlang:element(9, Response))
))/binary>>
),
gleam_stdlib:println(
<<" Output tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(3, erlang:element(9, Response))
))/binary>>
),
Is_tool_use = anthropic@tools:needs_tool_execution(Response),
gleam_stdlib:println(
<<" Needs tool execution: "/utf8,
(gleam@string:inspect(Is_tool_use))/binary>>
),
case Is_tool_use of
true ->
Tool_calls = anthropic@tools:extract_tool_calls(
Response
),
gleam_stdlib:println(
<<" Tool calls count: "/utf8,
(erlang:integer_to_binary(
erlang:length(Tool_calls)
))/binary>>
),
gleam@list:each(
Tool_calls,
fun(Call) ->
gleam_stdlib:println(
<<" Tool call:"/utf8>>
),
gleam_stdlib:println(
<<" ID: "/utf8,
(erlang:element(2, Call))/binary>>
),
gleam_stdlib:println(
<<" Name: "/utf8,
(erlang:element(3, Call))/binary>>
),
gleam_stdlib:println(
<<" Input: "/utf8,
(erlang:element(4, Call))/binary>>
)
end
),
case gleam@list:first(Tool_calls) of
{ok, Call@1} ->
erlang:element(3, Call@1) =:= <<"get_weather"/utf8>>;
{error, _} ->
false
end;
false ->
gleam_stdlib:println(
<<"ERROR: Expected tool_use but got text response"/utf8>>
),
false
end;
{error, Err@1} ->
gleam_stdlib:println(
<<"ERROR: "/utf8,
(anthropic@types@error:error_to_string(Err@1))/binary>>
),
false
end
end.
-file("src/examples/tool_use_integration_test.gleam", 327).
-spec test_complete_workflow(binary()) -> boolean().
test_complete_workflow(Api_key) ->
gleam_stdlib:println(<<"Testing complete tool use workflow..."/utf8>>),
gleam_stdlib:println(
<<"(tool_use -> execute -> tool_result -> final response)"/utf8>>
),
Config_result = begin
_pipe = anthropic@config:config_options(),
_pipe@1 = anthropic@config:with_api_key(_pipe, Api_key),
anthropic@config:load_config(_pipe@1)
end,
case Config_result of
{error, Err} ->
gleam_stdlib:println(
<<"Config error: "/utf8,
(anthropic@types@error:error_to_string(Err))/binary>>
),
false;
{ok, Cfg} ->
Api_client = anthropic@client:new(Cfg),
Lookup_tool = begin
_pipe@2 = anthropic@tools@builder:tool_builder(
<<"lookup_capital"/utf8>>
),
_pipe@3 = anthropic@tools@builder:with_description(
_pipe@2,
<<"Look up the capital city of a country"/utf8>>
),
_pipe@4 = anthropic@tools@builder:add_string_param(
_pipe@3,
<<"country"/utf8>>,
<<"The country name"/utf8>>,
true
),
anthropic@tools@builder:build(_pipe@4)
end,
Original_messages = [anthropic@types@message:user_message(
<<"What is the capital of France? Use the lookup tool."/utf8>>
)],
Req = begin
_pipe@5 = anthropic@types@request:create_request(
<<"claude-3-5-haiku-20241022"/utf8>>,
Original_messages,
200
),
_pipe@6 = anthropic@types@request:with_tools(
_pipe@5,
[Lookup_tool]
),
anthropic@types@request:with_tool_choice(
_pipe@6,
{tool_name, <<"lookup_capital"/utf8>>}
)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"STEP 1: Initial request with tool"/utf8>>),
gleam_stdlib:println(
<<" Message: What is the capital of France? Use the lookup tool."/utf8>>
),
gleam_stdlib:println(
<<" Tool Choice: ToolName(\"lookup_capital\") - FORCED"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Sending request to API..."/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
case anthropic@api:create_message(Api_client, Req) of
{ok, Response} ->
gleam_stdlib:println(<<"STEP 1 RESPONSE:"/utf8>>),
gleam_stdlib:println(
<<" ID: "/utf8, (erlang:element(2, Response))/binary>>
),
gleam_stdlib:println(
<<" Stop reason: "/utf8,
(stop_reason_to_string(erlang:element(7, Response)))/binary>>
),
case anthropic@tools:needs_tool_execution(Response) of
true ->
Tool_calls = anthropic@tools:extract_tool_calls(
Response
),
gleam_stdlib:println(
<<" Tool calls: "/utf8,
(erlang:integer_to_binary(
erlang:length(Tool_calls)
))/binary>>
),
Handlers = [{<<"lookup_capital"/utf8>>,
fun(_) ->
{ok,
<<"{\"capital\": \"Paris\", \"country\": \"France\"}"/utf8>>}
end}],
Results = anthropic@tools:dispatch_tool_calls(
Tool_calls,
Handlers
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<"STEP 2: Tool execution"/utf8>>
),
gleam@list:each(
Results,
fun(Result) -> case Result of
{tool_success, Id, Content} ->
gleam_stdlib:println(
<<" Tool result (success):"/utf8>>
),
gleam_stdlib:println(
<<" ID: "/utf8, Id/binary>>
),
gleam_stdlib:println(
<<" Content: "/utf8,
Content/binary>>
);
{tool_failure, Id@1, Err@1} ->
gleam_stdlib:println(
<<" Tool result (failure):"/utf8>>
),
gleam_stdlib:println(
<<" ID: "/utf8, Id@1/binary>>
),
gleam_stdlib:println(
<<" Error: "/utf8,
Err@1/binary>>
)
end end
),
Continuation_messages = anthropic@tools:build_tool_result_messages(
Original_messages,
Response,
Results
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<"STEP 3: Sending tool results back"/utf8>>
),
gleam_stdlib:println(
<<" Messages count: "/utf8,
(erlang:integer_to_binary(
erlang:length(Continuation_messages)
))/binary>>
),
Continuation_req = begin
_pipe@7 = anthropic@types@request:create_request(
<<"claude-3-5-haiku-20241022"/utf8>>,
Continuation_messages,
200
),
anthropic@types@request:with_tools(
_pipe@7,
[Lookup_tool]
)
end,
case anthropic@api:create_message(
Api_client,
Continuation_req
) of
{ok, Final_response} ->
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<"STEP 3 RESPONSE (Final):"/utf8>>
),
gleam_stdlib:println(
<<" ID: "/utf8,
(erlang:element(2, Final_response))/binary>>
),
gleam_stdlib:println(
<<" Stop reason: "/utf8,
(stop_reason_to_string(
erlang:element(
7,
Final_response
)
))/binary>>
),
gleam_stdlib:println(
<<" Content: "/utf8,
(anthropic@types@request:response_text(
Final_response
))/binary>>
),
gleam_stdlib:println(
<<" Input tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(
2,
erlang:element(
9,
Final_response
)
)
))/binary>>
),
gleam_stdlib:println(
<<" Output tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(
3,
erlang:element(
9,
Final_response
)
)
))/binary>>
),
case erlang:element(7, Final_response) of
{some, end_turn} ->
true;
{some, max_tokens} ->
true;
_ ->
gleam_stdlib:println(
<<" Warning: Unexpected stop reason"/utf8>>
),
true
end;
{error, Err@2} ->
gleam_stdlib:println(
<<"ERROR in continuation: "/utf8,
(anthropic@types@error:error_to_string(
Err@2
))/binary>>
),
false
end;
false ->
gleam_stdlib:println(
<<"ERROR: Expected tool_use but got text response"/utf8>>
),
false
end;
{error, Err@3} ->
gleam_stdlib:println(
<<"ERROR: "/utf8,
(anthropic@types@error:error_to_string(Err@3))/binary>>
),
false
end
end.
-file("src/examples/tool_use_integration_test.gleam", 490).
-spec test_multiple_tools(binary()) -> boolean().
test_multiple_tools(Api_key) ->
gleam_stdlib:println(<<"Testing multiple tools with Any choice..."/utf8>>),
Config_result = begin
_pipe = anthropic@config:config_options(),
_pipe@1 = anthropic@config:with_api_key(_pipe, Api_key),
anthropic@config:load_config(_pipe@1)
end,
case Config_result of
{error, Err} ->
gleam_stdlib:println(
<<"Config error: "/utf8,
(anthropic@types@error:error_to_string(Err))/binary>>
),
false;
{ok, Cfg} ->
Api_client = anthropic@client:new(Cfg),
Weather_tool = begin
_pipe@2 = anthropic@tools@builder:tool_builder(
<<"get_weather"/utf8>>
),
_pipe@3 = anthropic@tools@builder:with_description(
_pipe@2,
<<"Get weather for a location"/utf8>>
),
_pipe@4 = anthropic@tools@builder:add_string_param(
_pipe@3,
<<"location"/utf8>>,
<<"City name"/utf8>>,
true
),
anthropic@tools@builder:build(_pipe@4)
end,
Time_tool = begin
_pipe@5 = anthropic@tools@builder:tool_builder(
<<"get_time"/utf8>>
),
_pipe@6 = anthropic@tools@builder:with_description(
_pipe@5,
<<"Get current time in a timezone"/utf8>>
),
_pipe@7 = anthropic@tools@builder:add_string_param(
_pipe@6,
<<"timezone"/utf8>>,
<<"Timezone name like 'America/New_York'"/utf8>>,
true
),
anthropic@tools@builder:build(_pipe@7)
end,
Stock_tool = begin
_pipe@8 = anthropic@tools@builder:tool_builder(
<<"get_stock_price"/utf8>>
),
_pipe@9 = anthropic@tools@builder:with_description(
_pipe@8,
<<"Get stock price for a ticker symbol"/utf8>>
),
_pipe@10 = anthropic@tools@builder:add_string_param(
_pipe@9,
<<"symbol"/utf8>>,
<<"Stock ticker symbol like 'AAPL'"/utf8>>,
true
),
anthropic@tools@builder:build(_pipe@10)
end,
Req = begin
_pipe@11 = anthropic@types@request:create_request(
<<"claude-3-5-haiku-20241022"/utf8>>,
[anthropic@types@message:user_message(
<<"I need to know the current time in New York."/utf8>>
)],
200
),
_pipe@12 = anthropic@types@request:with_tools(
_pipe@11,
[Weather_tool, Time_tool, Stock_tool]
),
anthropic@types@request:with_tool_choice(_pipe@12, any)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"REQUEST:"/utf8>>),
gleam_stdlib:println(<<" Model: claude-3-5-haiku-20241022"/utf8>>),
gleam_stdlib:println(
<<" Tools: get_weather, get_time, get_stock_price"/utf8>>
),
gleam_stdlib:println(
<<" Tool Choice: Any - must use one of the tools"/utf8>>
),
gleam_stdlib:println(
<<" Message: I need to know the current time in New York."/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Sending request to API..."/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
case anthropic@api:create_message(Api_client, Req) of
{ok, Response} ->
gleam_stdlib:println(<<"RESPONSE:"/utf8>>),
gleam_stdlib:println(
<<" ID: "/utf8, (erlang:element(2, Response))/binary>>
),
gleam_stdlib:println(
<<" Stop reason: "/utf8,
(stop_reason_to_string(erlang:element(7, Response)))/binary>>
),
gleam_stdlib:println(
<<" Input tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(2, erlang:element(9, Response))
))/binary>>
),
gleam_stdlib:println(
<<" Output tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(3, erlang:element(9, Response))
))/binary>>
),
Is_tool_use = anthropic@tools:needs_tool_execution(Response),
gleam_stdlib:println(
<<" Needs tool execution: "/utf8,
(gleam@string:inspect(Is_tool_use))/binary>>
),
case Is_tool_use of
true ->
Tool_calls = anthropic@tools:extract_tool_calls(
Response
),
gleam_stdlib:println(
<<" Tool calls: "/utf8,
(erlang:integer_to_binary(
erlang:length(Tool_calls)
))/binary>>
),
gleam@list:each(
Tool_calls,
fun(Call) ->
gleam_stdlib:println(
<<" Tool call:"/utf8>>
),
gleam_stdlib:println(
<<" ID: "/utf8,
(erlang:element(2, Call))/binary>>
),
gleam_stdlib:println(
<<" Name: "/utf8,
(erlang:element(3, Call))/binary>>
),
gleam_stdlib:println(
<<" Input: "/utf8,
(erlang:element(4, Call))/binary>>
)
end
),
case gleam@list:first(Tool_calls) of
{ok, Call@1} ->
gleam_stdlib:println(
<<<<" Selected tool: "/utf8,
(erlang:element(3, Call@1))/binary>>/binary,
" (expected: get_time)"/utf8>>
),
erlang:element(3, Call@1) =:= <<"get_time"/utf8>>;
{error, _} ->
false
end;
false ->
gleam_stdlib:println(
<<"ERROR: Any choice should force tool use"/utf8>>
),
false
end;
{error, Err@1} ->
gleam_stdlib:println(
<<"ERROR: "/utf8,
(anthropic@types@error:error_to_string(Err@1))/binary>>
),
false
end
end.
-file("src/examples/tool_use_integration_test.gleam", 604).
-spec test_tool_builder(binary()) -> boolean().
test_tool_builder(Api_key) ->
gleam_stdlib:println(
<<"Testing tool builder API with complex tool..."/utf8>>
),
Config_result = begin
_pipe = anthropic@config:config_options(),
_pipe@1 = anthropic@config:with_api_key(_pipe, Api_key),
anthropic@config:load_config(_pipe@1)
end,
case Config_result of
{error, Err} ->
gleam_stdlib:println(
<<"Config error: "/utf8,
(anthropic@types@error:error_to_string(Err))/binary>>
),
false;
{ok, Cfg} ->
Api_client = anthropic@client:new(Cfg),
Search_tool = begin
_pipe@2 = anthropic@tools@builder:tool_builder(
<<"search_database"/utf8>>
),
_pipe@3 = anthropic@tools@builder:with_description(
_pipe@2,
<<"Search a database with various filters"/utf8>>
),
_pipe@4 = anthropic@tools@builder:add_string_param(
_pipe@3,
<<"query"/utf8>>,
<<"The search query string"/utf8>>,
true
),
_pipe@5 = anthropic@tools@builder:add_enum_param(
_pipe@4,
<<"category"/utf8>>,
<<"Category to search in"/utf8>>,
[<<"products"/utf8>>, <<"users"/utf8>>, <<"orders"/utf8>>],
false
),
_pipe@6 = anthropic@tools@builder:add_enum_param(
_pipe@5,
<<"sort_order"/utf8>>,
<<"Sort order for results"/utf8>>,
[<<"asc"/utf8>>, <<"desc"/utf8>>],
false
),
anthropic@tools@builder:build(_pipe@6)
end,
Req = begin
_pipe@7 = anthropic@types@request:create_request(
<<"claude-3-5-haiku-20241022"/utf8>>,
[anthropic@types@message:user_message(
<<"Search for 'laptop' in the products category, sorted descending."/utf8>>
)],
200
),
_pipe@8 = anthropic@types@request:with_tools(
_pipe@7,
[Search_tool]
),
anthropic@types@request:with_tool_choice(
_pipe@8,
{tool_name, <<"search_database"/utf8>>}
)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"REQUEST:"/utf8>>),
gleam_stdlib:println(<<" Model: claude-3-5-haiku-20241022"/utf8>>),
gleam_stdlib:println(
<<" Tool: search_database (built with builder API)"/utf8>>
),
gleam_stdlib:println(<<" Parameters:"/utf8>>),
gleam_stdlib:println(<<" - query (string, required)"/utf8>>),
gleam_stdlib:println(
<<" - category (enum: products/users/orders, optional)"/utf8>>
),
gleam_stdlib:println(
<<" - sort_order (enum: asc/desc, optional)"/utf8>>
),
gleam_stdlib:println(
<<" Tool Choice: ToolName(\"search_database\") - FORCED"/utf8>>
),
gleam_stdlib:println(
<<" Message: Search for 'laptop' in the products category, sorted descending."/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"Sending request to API..."/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
case anthropic@api:create_message(Api_client, Req) of
{ok, Response} ->
gleam_stdlib:println(<<"RESPONSE:"/utf8>>),
gleam_stdlib:println(
<<" ID: "/utf8, (erlang:element(2, Response))/binary>>
),
gleam_stdlib:println(
<<" Stop reason: "/utf8,
(stop_reason_to_string(erlang:element(7, Response)))/binary>>
),
gleam_stdlib:println(
<<" Input tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(2, erlang:element(9, Response))
))/binary>>
),
gleam_stdlib:println(
<<" Output tokens: "/utf8,
(erlang:integer_to_binary(
erlang:element(3, erlang:element(9, Response))
))/binary>>
),
Is_tool_use = anthropic@tools:needs_tool_execution(Response),
gleam_stdlib:println(
<<" Needs tool execution: "/utf8,
(gleam@string:inspect(Is_tool_use))/binary>>
),
case Is_tool_use of
true ->
Tool_calls = anthropic@tools:extract_tool_calls(
Response
),
gleam@list:each(
Tool_calls,
fun(Call) ->
gleam_stdlib:println(
<<" Tool call:"/utf8>>
),
gleam_stdlib:println(
<<" ID: "/utf8,
(erlang:element(2, Call))/binary>>
),
gleam_stdlib:println(
<<" Name: "/utf8,
(erlang:element(3, Call))/binary>>
),
gleam_stdlib:println(
<<" Input: "/utf8,
(erlang:element(4, Call))/binary>>
)
end
),
case gleam@list:first(Tool_calls) of
{ok, Call@1} ->
Has_query = gleam_stdlib:contains_string(
erlang:element(4, Call@1),
<<"laptop"/utf8>>
),
Has_category = gleam_stdlib:contains_string(
erlang:element(4, Call@1),
<<"products"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(
<<" Validation:"/utf8>>
),
gleam_stdlib:println(
<<" Contains 'laptop': "/utf8,
(gleam@string:inspect(Has_query))/binary>>
),
gleam_stdlib:println(
<<" Contains 'products': "/utf8,
(gleam@string:inspect(Has_category))/binary>>
),
(erlang:element(3, Call@1) =:= <<"search_database"/utf8>>)
andalso Has_query;
{error, _} ->
false
end;
false ->
gleam_stdlib:println(
<<"ERROR: Expected tool_use response"/utf8>>
),
false
end;
{error, Err@1} ->
gleam_stdlib:println(
<<"ERROR: "/utf8,
(anthropic@types@error:error_to_string(Err@1))/binary>>
),
false
end
end.
-file("src/examples/tool_use_integration_test.gleam", 51).
-spec run_tests(binary()) -> nil.
run_tests(Api_key) ->
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
gleam_stdlib:println(<<"TEST 1: Tool Definition with Auto Choice"/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
R1 = test_tool_definition_auto(Api_key),
case R1 of
true ->
gleam_stdlib:println(<<"TEST 1: PASSED"/utf8>>);
false ->
gleam_stdlib:println(<<"TEST 1: FAILED"/utf8>>)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
gleam_stdlib:println(<<"TEST 2: Forced Tool Use (ToolName Choice)"/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
R2 = test_forced_tool_use(Api_key),
case R2 of
true ->
gleam_stdlib:println(<<"TEST 2: PASSED"/utf8>>);
false ->
gleam_stdlib:println(<<"TEST 2: FAILED"/utf8>>)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
gleam_stdlib:println(<<"TEST 3: Complete Tool Use Workflow"/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
R3 = test_complete_workflow(Api_key),
case R3 of
true ->
gleam_stdlib:println(<<"TEST 3: PASSED"/utf8>>);
false ->
gleam_stdlib:println(<<"TEST 3: FAILED"/utf8>>)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
gleam_stdlib:println(<<"TEST 4: Multiple Tools with Any Choice"/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
R4 = test_multiple_tools(Api_key),
case R4 of
true ->
gleam_stdlib:println(<<"TEST 4: PASSED"/utf8>>);
false ->
gleam_stdlib:println(<<"TEST 4: FAILED"/utf8>>)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
gleam_stdlib:println(<<"TEST 5: Tool Builder API"/utf8>>),
gleam_stdlib:println(<<"-------------------------------------------"/utf8>>),
R5 = test_tool_builder(Api_key),
case R5 of
true ->
gleam_stdlib:println(<<"TEST 5: PASSED"/utf8>>);
false ->
gleam_stdlib:println(<<"TEST 5: FAILED"/utf8>>)
end,
Results = [R1, R2, R3, R4, R5],
Passed = begin
_pipe = gleam@list:filter(Results, fun(R) -> R end),
erlang:length(_pipe)
end,
Failed = begin
_pipe@1 = gleam@list:filter(Results, fun(R@1) -> not R@1 end),
erlang:length(_pipe@1)
end,
gleam_stdlib:println(<<""/utf8>>),
gleam_stdlib:println(<<"==========================================="/utf8>>),
gleam_stdlib:println(<<"Tool Use Integration Tests Complete"/utf8>>),
gleam_stdlib:println(<<"==========================================="/utf8>>),
gleam_stdlib:println(
<<<<<<<<"Results: "/utf8, (erlang:integer_to_binary(Passed))/binary>>/binary,
" passed, "/utf8>>/binary,
(erlang:integer_to_binary(Failed))/binary>>/binary,
" failed"/utf8>>
).
-file("src/examples/tool_use_integration_test.gleam", 749).
-spec get_api_key() -> {ok, binary()} | {error, nil}.
get_api_key() ->
Value = begin
_pipe = os:getenv(
unicode:characters_to_list(<<"ANTHROPIC_API_KEY"/utf8>>),
unicode:characters_to_list(<<""/utf8>>)
),
unicode:characters_to_binary(_pipe)
end,
case Value of
<<""/utf8>> ->
{error, nil};
V ->
{ok, V}
end.
-file("src/examples/tool_use_integration_test.gleam", 28).
?DOC(" Main entry point\n").
-spec main() -> nil.
main() ->
gleam_stdlib:println(<<"==========================================="/utf8>>),
gleam_stdlib:println(<<"Anthropic Tool Use Integration Test"/utf8>>),
gleam_stdlib:println(<<"==========================================="/utf8>>),
gleam_stdlib:println(<<""/utf8>>),
case get_api_key() of
{error, nil} ->
gleam_stdlib:println(
<<"ERROR: ANTHROPIC_API_KEY environment variable not set"/utf8>>
),
gleam_stdlib:println(<<"Please set it and try again:"/utf8>>),
gleam_stdlib:println(
<<" export ANTHROPIC_API_KEY=your-api-key"/utf8>>
);
{ok, Api_key} ->
gleam_stdlib:println(
<<<<"API Key: [REDACTED - "/utf8,
(gleam@string:slice(Api_key, 0, 8))/binary>>/binary,
"...]"/utf8>>
),
gleam_stdlib:println(<<""/utf8>>),
run_tests(Api_key)
end.