View Source Anthropix (Anthropix v0.1.0)

Anthropix

License

Anthropix is an open-source Elixir client for the Anthropic API, providing a simple and convenient way to integrate Claude, Anthropic's powerful language model, into your applications.

  • ✅ API client fully implementing the Anthropic API
  • 🛜 Streaming API requests
    • Stream to an Enumerable
    • Or stream messages to any Elixir process
  • 😎 Powerful yet painless function calling with Agents

Installation

The package can be installed by adding anthropix to your list of dependencies in mix.exs.

def deps do
  [
    {:anthropix, "~> 0.1.0"}
  ]
end

Quickstart

For more examples, refer to the Anthropix documentation.

Initiate a client.

See Anthropix.init/2.

iex> client = Anthropix.init(api_key)

Chat with Claude

See Anthropix.chat/2.

iex> messages = [
...>   %{role: "system", content: "You are a helpful assistant."},
...>   %{role: "user", content: "Why is the sky blue?"},
...>   %{role: "assistant", content: "Due to rayleigh scattering."},
...>   %{role: "user", content: "How is that different than mie scattering?"},
...> ]

iex> Anthropix.chat(client, [
...>   model: "claude-3-opus-20240229",
...>   messages: messages,
...> ])
{:ok, %{"content" => [%{
  "type" => "text",
  "text" => "Mie scattering affects all wavelengths similarly, while Rayleigh favors shorter ones."
}], ...}}

Streaming

A streaming request can be initiated by setting the :stream option.

When :stream is true a lazy Enumerable.t/0 is returned which can be used with any Stream functions.

iex> {:ok, stream} = Anthropix.chat(client, [
...>   model: "claude-3-opus-20240229",
...>   messages: messages,
...>   stream: true,
...> ])
{:ok, #Function<52.53678557/2 in Stream.resource/3>}

iex> stream
...> |> Stream.each(&update_ui_with_chunk/1)
...> |> Stream.run()
:ok

Because the above approach builds the Enumerable.t/0 by calling receive, using this approach inside GenServer callbacks may cause the GenServer to misbehave. Setting the :stream option to a pid/0 returns a Task.t/0 which will send messages to the specified process.

Function calling

Chatting with Claude is nice and all, but when it comes to function calling, Anthropix has a trick up its sleeve. Meet Anthropix.Agent.

The Agent module abstracts away all the rough bits of implementing Anthropic style function calling, leaving a delightfully simple API that opens the doors to powerful and advanced agent workflows.

iex> ticker_tool = %Anthropix.Tool.new([
...>   name: "get_ticker_symbol",
...>   description: "Gets the stock ticker symbol for a company searched by name. Returns str: The ticker symbol for the company stock. Raises TickerNotFound: if no matching ticker symbol is found.",
...>   params: [
...>     %{name: "company_name", description: "The name of the company.", type: "string"}
...>   ],
...>   function: &MyStocks.get_ticker/1
...> ])

iex> price_tool = %Anthropix.Tool.new([
...>   name: "get_current_stock_price",
...>   description: "Gets the current stock price for a company. Returns float: The current stock price. Raises ValueError: if the input symbol is invalid/unknown.",
...>   params: [
...>     %{name: "symbol", description: "The stock symbol of the company to get the price for.", type: "string"}
...>   ],
...>   function: &MyStocks.get_price/1
...> ])

iex> agent = Anthropix.Agent.init(
...>   Anthropix.init(api_key),
...>   [ticker_tool, price_tool]
...> )

iex> Anthropix.Agent.chat(agent, [
...>   model: "claude-3-sonnet-20240229",
...>   system: "Answer like Snoop Dogg.",
...>   messages: [
...>     %{role: "user", content: "What is the current stock price of General Motors?"}
...>   ]
...> ])
%{
  result: %{
    "content" => [%{
      "type" => "text",
      "text" => "*snaps fingers* Damn shawty, General Motors' stock is sittin' pretty at $39.21 per share right now. Dat's a fly price for them big ballers investin' in one of Detroit's finest auto makers, ya heard? *puts hands up like car doors* If ya askin' Snoop, dat stock could be rollin' on some dubs fo' sho'. Just don't get caught slippin' when them prices dippin', ya dig?"
    }]
  }
}

For a more detailed walkthrough, refer to the Anthropix.Agent documentation.

Summary

Types

Client struct

Message content block.

Chat message

Client response

Functions

Chat with Claude. Send a list of structured input messages with text and/or image content, and Claude will generate the next message in the conversation.

Calling init/1 without passing an API key, creates a new Anthropix API client using the API key set in your application's config.

Calling init/2 with an API key creates a new Anthropix API client, using the given API key. Optionally, a keyword list of options can be passed through to Req.new/1.

Types

@type client() :: %Anthropix{req: Req.Request.t()}

Client struct

@type content_block() :: %{
  :type => String.t(),
  optional(:text) => String.t(),
  optional(:source) => %{
    type: String.t(),
    media_type: String.t(),
    data: String.t()
  }
}

Message content block.

@type message() :: %{role: String.t(), content: String.t() | [content_block()]}

Chat message

A chat message is a map/0 with the following fields:

  • :role (String.t/0) - Required. The role of the message, either user or assistant.
  • :content - Required. Message content, either a single string or an array of content blocks.
@type response() :: {:ok, map() | Enumerable.t() | Task.t()} | {:error, term()}

Client response

Functions

Link to this function

chat(client, params \\ [])

View Source
@spec chat(
  client(),
  keyword()
) :: response()

Chat with Claude. Send a list of structured input messages with text and/or image content, and Claude will generate the next message in the conversation.

Options

  • :model (String.t/0) - Required. The model that will complete your prompt.
  • :messages (list of map/0) - Required. Input messages.
  • :system (String.t/0) - System prompt.
  • :max_tokens (integer/0) - The maximum number of tokens to generate before stopping. The default value is 4096.
  • :metadata (map/0) - A map describing metadata about the request.
  • :stop_sequences (list of String.t/0) - Custom text sequences that will cause the model to stop generating.
  • :stream - Whether to incrementally stream the response using server-sent events. The default value is false.
  • :tools (list of struct of type Anthropix.Tool) - A list of tools the model may call.
  • :temperature (float/0) - Amount of randomness injected into the response.
  • :top_k (integer/0) - Only sample from the top K options for each subsequent token.
  • :top_p (float/0) - Amount of randomness injected into the response.

Message structure

Each message is a map with the following fields:

  • :role (String.t/0) - Required. The role of the message, either user or assistant.
  • :content - Required. Message content, either a single string or an array of content blocks.

Examples

iex> messages = [
...>   %{role: "system", content: "You are a helpful assistant."},
...>   %{role: "user", content: "Why is the sky blue?"},
...>   %{role: "assistant", content: "Due to rayleigh scattering."},
...>   %{role: "user", content: "How is that different than mie scattering?"},
...> ]

iex> Anthropix.chat(client, [
...>   model: "claude-3-opus-20240229",
...>   messages: messages,
...> ])
{:ok, %{"content" => [%{
  "type" => "text",
  "text" => "Mie scattering affects all wavelengths similarly, while Rayleigh favors shorter ones."
}], ...}}

# Passing true to the :stream option initiates an async streaming request.
iex> Anthropix.chat(client, [
...>   model: "claude-3-opus-20240229",
...>   messages: messages,
...>   stream: true,
...> ])
{:ok, #Function<52.53678557/2 in Stream.resource/3>}
@spec init() :: client()

Calling init/1 without passing an API key, creates a new Anthropix API client using the API key set in your application's config.

config :anthropix, :api_key, "sk-ant-your-key"

If given, a keyword list of options will be passed to Req.new/1.

Examples

iex> client = Anthropix.init()
%Anthropix{}
@spec init(keyword()) :: client()
Link to this function

init(api_key, opts \\ [])

View Source
@spec init(
  String.t(),
  keyword()
) :: client()

Calling init/2 with an API key creates a new Anthropix API client, using the given API key. Optionally, a keyword list of options can be passed through to Req.new/1.

Examples

iex> client = Anthropix.init("sk-ant-your-key", receive_timeout: :infinity)
%Anthropix{}