clust
An unofficial Rust client for the Anthropic/Claude API.
Installation
Run the following Cargo command in your project directory:
cargo add clust
or add the following line to your Cargo.toml:
[]
= "0.8.0"
Supported APIs
- Messages
Feature flags
macros: Enable theclust::attributse::clust_toolattribute macro for generatingclust::messages::Toolorclust::messages::AsyncToolfrom a Rust function.
Usages
API key and client
First you need to create a new API client: clust::Client with your Anthropic API key from environment variable: "
ANTHROPIC_API_KEY"
use Client;
let client = from_env.unwrap;
or specify the API key directly:
use Client;
use ApiKey;
let client = from_api_key;
If you want to customize the client, you can use builder pattern by clust::ClientBuilder:
use ClientBuilder;
use ApiKey;
use Version;
let client = new
.version
.client
.build;
Models and max tokens
You can specify the model by clust::messages::ClaudeModel.
use ClaudeModel;
use MessagesRequestBody;
let model = Claude3Sonnet20240229;
let request_body = MessagesRequestBody ;
Because max number of tokens of text generation: clust::messages::MaxTokens depends on the model,
you need to create clust::messages::MaxTokens with the model.
use ClaudeModel;
use MaxTokens;
use MessagesRequestBody;
let model = Claude3Sonnet20240229;
let max_tokens = new.unwrap;
let request_body = MessagesRequestBody ;
Prompt
You can specify the system prompt by clust::messages::SystemPrompt and there is no "system" role in the message.
use SystemPrompt;
use MessagesRequestBody;
let system_prompt = new;
let request_body = MessagesRequestBody ;
Messages and contents
Build messages by a vector of clust::messages::Message:
use Role;
use Content;
/// The message.
You can create each role message as follows:
use Message;
let message = user;
let message = assistant;
and a content: clust::messages::Content.
use ContentBlock;
/// The content of the message.
Multiple blocks is a vector of content block: clust::messages::ContentBlock:
use TextContentBlock;
use ImageContentBlock;
/// The content block of the message.
You can create a content as follows:
use Content;
use ContentBlock;
use TextContentBlock;
use ImageContentBlock;
use ImageContentSource;
use ImageMediaType;
// Single text content
let content = SingleText;
// or use `From` trait
let content = from;
// Multiple content blocks
let content = MultipleBlocks;
// or use `From` trait for `String` or `ImageContentSource`
let content = from;
Request body
The request body is defined by clust::messages::MessagesRequestBody.
See also MessagesRequestBody for other options.
use MessagesRequestBody;
use ClaudeModel;
use Message;
use MaxTokens;
use SystemPrompt;
let request_body = MessagesRequestBody ;
You can also use the builder pattern with clust::messages::MessagesRequestBuilder:
use MessagesRequestBuilder;
use ClaudeModel;
use Message;
use SystemPrompt;
let request_body = new_with_max_tokens.unwrap
.messages
.system
.build;
API calling
Call the API by clust::Client::create_a_message with the request body.
use Client;
use MessagesRequestBody;
async
Streaming
When you want to stream the response incrementally,
you can use clust::Client::create_a_message_stream with the stream option: StreamOption::ReturnStream.
use Client;
use MessagesRequestBody;
use StreamOption;
use StreamExt;
async
Function calling
Overview
Function calling is not formally supported as the official guide.
- Define a tool (or tools) by
clust::messages::ToolDescription. - Embed tool description(s) in your system prompt.
- Call the API with tools.
- Extract the XML of the function calls by
clust::messages::FunctionCallsfrom the response. - Call the function with
clust::messages::FunctionCallsand get the result asclust::messages::FunctionResults. - Embed the function results in message as a user message.
- Call the API again with the function results.
- Continue the conversation.
Structures for function calling are (de)serialized as XML string.
clust::messages::ToolDescriptionclust::messages::FunctionCallsclust::messages::FunctionResultsclust::messages::ToolList- etc...
This crate provides two methods to define function calling:
- Add the
clust::attributes::clust_toolattribute macro to your Rust function and use generatedclust::messages::Toolorclust::messages::AsyncToolwith themacrosfeature flag. - Manually create
clust::messages::ToolDescription.
How to define and call a tool by the attribute macro
Let's see how to define and call a tool by the attribute macro.
By adding #[clust_tool] to your function with documentation for function description and arguments (parameters),
a structure ClustTool_{function_name} that implements a trait: clust::messages::Tool or clust::messages::AsyncTool
is automatically generated by macro.
You can get clust::messages::ToolDescription by ClustTool_{function_name}.description()
and call the function by ClustTool_{function_name}.call() method with clust::messages::FunctionCalls generated by
the assistant.
use clust_tool;
use Tool;
use FunctionCalls;
use Invoke;
use BTreeMap;
// Define a tool by attribute macro for your function.
// NOTE: Documentation for description and arguments is required.
/// Gets the current stock price for a company. Returns float: The current stock price. Raises ValueError: if the input symbol is invalid/unknown.
///
/// ## Arguments
/// - `symbol` - The stock symbol of the company to get the price for.
// Create a tool instance of generated struct.
let tool = ClustTool_get_current_stock_price ;
// Get the tool description.
let tool_description = tool.description;
// ToolDescription is displayed as XML string.
// e.g.
// <tool_description>
// <tool_name>get_current_stock_price</tool_name>
// <description>Gets the current stock price for a company. Returns float: The current stock price. Raises ValueError: if the input symbol is invalid/unknown.</description>
// <parameters>
// <parameter>
// <name>symbol</name>
// <type>String</type>
// <description>The stock symbol of the company to get the price for.</description>
// </parameter>
// </parameters>
// </tool_description>
let prompt = format!;
// NOTE: Actually you can get the function calls from the response.
// MessagesResponseBody.content.extract_function_calls().unwrap();
// e.g.
// <function_calls>
// <invoke>
// <tool_name>get_current_stock_price</tool_name>
// <parameters>
// <symbol>GM</symbol>
// </parameters>
// </invoke>
// </function_calls>
let function_calls = FunctionCalls ;
// Call the function and get the function results.
// e.g.
// <function_results>
// <result>
// <tool_name>get_current_stock_price</tool_name>
// <stdout>38.50</stdout>
// </result>
// </function_results>
let function_results = tool.call.unwrap;
When you have some tools, you can create a tool list by clust::messages::ToolList,
embed the tool list in your system prompt
and call the function with clust::messages::FunctionCalls via tool list.
For more details, see a function calling example.
Examples
Create a message
An example of creating a message with the API key loaded from the environment variable: ANTHROPIC_API_KEY
ANTHROPIC_API_KEY={your-api-key}
is as follows:
use ClaudeModel;
use MaxTokens;
use Message;
use MessagesRequestBody;
use SystemPrompt;
use Client;
async
Streaming messages with tokio backend
An example of creating a message stream with the API key loaded from the environment variable: ANTHROPIC_API_KEY
ANTHROPIC_API_KEY={your-api-key}
with tokio-stream is as follows:
use ClaudeModel;
use MaxTokens;
use Message;
use MessagesRequestBody;
use SystemPrompt;
use StreamOption;
use StreamChunk;
use Client;
use StreamExt;
async
}
println!;
Ok
}
Create a message with vision
Conversation
Function calling
See a function calling example.
Other examples
See also the examples directory for more examples.
Changelog
See CHANGELOG.
License
Licensed under either of the Apache License, Version 2.0 or the MIT license at your option.