import os
# os.environ['ANTHROPIC_LOG'] = 'debug'
claudette
NB: If you are reading this in GitHub’s readme, we recommend you instead read the much more nicely formatted documentation format of this tutorial.
Claudette is a wrapper for Anthropic’s Python SDK.
The SDK works well, but it is quite low level – it leaves the developer to do a lot of stuff manually. That’s a lot of extra work and boilerplate! Claudette automates pretty much everything that can be automated, whilst providing full control. Amongst the features provided:
- A
Chat
class that creates stateful dialogs - Support for prefill, which tells Claude what to use as the first few words of its response
- Convenient image support
- Simple and convenient support for Claude’s new Tool Use API.
You’ll need to set the ANTHROPIC_API_KEY
environment variable to the key provided to you by Anthropic in order to use this library.
Note that this library is the first ever “literate nbdev” project. That means that the actual source code for the library is a rendered Jupyter Notebook which includes callout notes and tips, HTML tables and images, detailed explanations, and teaches how and why the code is written the way it is. Even if you’ve never used the Anthropic Python SDK or Claude API before, you should be able to read the source code. Click Claudette’s Source to read it, or clone the git repo and execute the notebook yourself to see every step of the creation process in action. The tutorial below includes links to API details which will take you to relevant parts of the source. The reason this project is a new kind of literal program is because we take seriously Knuth’s call to action, that we have a “moral commitment” to never write an “illiterate program” – and so we have a commitment to making literate programming and easy and pleasant experience. (For more on this, see this talk from Hamel Husain.)
“Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.” Donald E. Knuth, Literate Programming (1984)
Install
pip install claudette
Getting started
Anthropic’s Python SDK will automatically be installed with Claudette, if you don’t already have it.
To print every HTTP request and response in full, uncomment the above line.
from claudette import *
Claudette only exports the symbols that are needed to use the library, so you can use import *
to import them. Alternatively, just use:
import claudette
…and then add the prefix claudette.
to any usages of the module.
Claudette provides models
, which is a list of models currently available from the SDK.
models
['claude-3-opus-20240229',
'claude-3-5-sonnet-20240620',
'claude-3-haiku-20240307']
For these examples, we’ll use Sonnet 3.5, since it’s awesome!
= models[1] model
Chat
The main interface to Claudette is the Chat
class, which provides a stateful interface to Claude:
= Chat(model, sp="""You are a helpful and concise assistant.""")
chat "I'm Jeremy") chat(
Hello Jeremy, it’s nice to meet you. How can I assist you today?
- id:
msg_01XCDYdAigXPV3tr4Gk1jgHa
- content:
[{'text': "Hello Jeremy, it's nice to meet you. How can I assist you today?", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 19, 'output_tokens': 20, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
= chat("What's my name?")
r r
Your name is Jeremy, as you just told me.
- id:
msg_011MfA5LVyBsZLLChaTTJDBk
- content:
[{'text': 'Your name is Jeremy, as you just told me.', 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 47, 'output_tokens': 14, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
= chat("What's my name?")
r r
Your name is Jeremy.
- id:
msg_01Qosij9Tbc9u82bTFmdoXpU
- content:
[{'text': 'Your name is Jeremy.', 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 69, 'output_tokens': 8, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
As you see above, displaying the results of a call in a notebook shows just the message contents, with the other details hidden behind a collapsible section. Alternatively you can print
the details:
print(r)
Message(id='msg_01Qosij9Tbc9u82bTFmdoXpU', content=[TextBlock(text='Your name is Jeremy.', type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 69; Out: 8; Cache create: 0; Cache read: 0; Total: 77)
Claude supports adding an extra assistant
message at the end, which contains the prefill – i.e. the text we want Claude to assume the response starts with. Let’s try it out:
"Concisely, what is the meaning of life?",
chat(='According to Douglas Adams,') prefill
According to Douglas Adams, the meaning of life is 42. Philosophically, it’s often considered to be finding purpose, happiness, and fulfillment in one’s existence.
- id:
msg_01MvA934wD5Ssyr3jhWTmV1G
- content:
[{'text': "According to Douglas Adams, the meaning of life is 42. Philosophically, it's often considered to be finding purpose, happiness, and fulfillment in one's existence.", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 97, 'output_tokens': 36, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
You can add stream=True
to stream the results as soon as they arrive (although you will only see the gradual generation if you execute the notebook yourself, of course!)
for o in chat("Concisely, what book was that in?", prefill='It was in', stream=True):
print(o, end='')
It was in "The Hitchhiker's Guide to the Galaxy" by Douglas Adams.
Async
Alternatively, you can use AsyncChat
(or AsyncClient
) for the async versions, e.g:
= AsyncChat(model)
chat await chat("I'm Jeremy")
Hello Jeremy! It’s nice to meet you. How can I assist you today? Is there anything specific you’d like to talk about or any questions you have?
- id:
msg_018i1EFCqB2vHmNBvspg9eUZ
- content:
[{'text': "Hello Jeremy! It's nice to meet you. How can I assist you today? Is there anything specific you'd like to talk about or any questions you have?", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 10, 'output_tokens': 36, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
Remember to use async for
when streaming in this case:
async for o in await chat("Concisely, what is the meaning of life?",
='According to Douglas Adams,', stream=True):
prefillprint(o, end='')
According to Douglas Adams, the meaning of life is 42. More seriously, philosophers have debated this for millennia. Common answers include:
1. Finding personal happiness
2. Serving others
3. Pursuing knowledge
4. Creating meaning through our choices
5. Fulfilling our potential
6. Connecting with others
7. Experiencing love and beauty
Ultimately, many believe we must each find our own meaning.
Prompt caching
If you use mk_msg(msg, cache=True)
, then the message is cached using Claude’s prompt caching feature. For instance, here we use caching when asking about Claudette’s readme file:
= Chat(model, sp="""You are a helpful and concise assistant.""") chat
= Path('README.txt').read_text()
nbtxt = f'''<README>
msg {nbtxt}
</README>
In brief, what is the purpose of this project based on the readme?'''
= chat(mk_msg(msg, cache=True))
r r
Based on the readme, the main purpose of the Claudette project is to provide a high-level wrapper around Anthropic’s Python SDK for interacting with Claude AI models. Key features and goals include:
Automating and simplifying interactions with Claude, reducing boilerplate code.
Providing a stateful dialog interface through the
Chat
class.Supporting features like prefill (specifying the start of Claude’s response) and image handling.
Offering convenient support for Claude’s Tool Use API.
Serving as an example of “literate programming”, with the source code designed to be readable and educational, including explanations of how and why the code is written.
Supporting multiple model providers, including direct Anthropic API access as well as Claude models available through Amazon Bedrock and Google Vertex AI.
The project aims to make working with Claude models more convenient and accessible for developers while also serving as an educational resource on how to effectively use and interact with these AI models.
- id:
msg_015khP4yqW57tH4qK6tGTkQr
- content:
[{'text': 'Based on the readme, the main purpose of the Claudette project is to provide a high-level wrapper around Anthropic\'s Python SDK for interacting with Claude AI models. Key features and goals include:\n\n1. Automating and simplifying interactions with Claude, reducing boilerplate code.\n\n2. Providing a stateful dialog interface through the [
Chat](https://claudette.answer.ai/core.html#chat) class.\n\n3. Supporting features like prefill (specifying the start of Claude\'s response) and image handling.\n\n4. Offering convenient support for Claude\'s Tool Use API.\n\n5. Serving as an example of "literate programming", with the source code designed to be readable and educational, including explanations of how and why the code is written.\n\n6. Supporting multiple model providers, including direct Anthropic API access as well as Claude models available through Amazon Bedrock and Google Vertex AI.\n\nThe project aims to make working with Claude models more convenient and accessible for developers while also serving as an educational resource on how to effectively use and interact with these AI models.', 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 4, 'output_tokens': 220, 'cache_creation_input_tokens': 7171, 'cache_read_input_tokens': 0}
The response records the a cache has been created using these input tokens:
print(r.usage)
Usage(input_tokens=4, output_tokens=220, cache_creation_input_tokens=7171, cache_read_input_tokens=0)
We can now ask a followup question in this chat:
= chat('How does it make tool use more ergonomic?')
r r
Claudette makes tool use more ergonomic in several ways:
Simplified function definition: It uses docments to make defining Python functions for tools as simple as possible. Each parameter and the return value should have a type and a description.
Automatic handling: The
Chat
class can be initialized with a list of tools, and Claudette handles the back-and-forth between Claude and the tools automatically.Single-step execution: The
Chat.toolloop
method allows for executing a series of tool calls in a single step, even if multiple tools are needed to solve a problem.Forced tool use: You can set
tool_choice
to force Claude to always answer using a specific tool.Tracing: The
toolloop
method supports atrace_func
parameter, allowing you to see each response from Claude during the process.Automatic parameter passing: When Claude decides to use a tool, Claudette automatically calls the tool with the provided parameters.
System prompt integration: It allows setting a system prompt to guide Claude’s behavior when using tools, such as instructing it not to mention the tools it’s using.
These features significantly reduce the amount of code and manual handling required to use Claude’s tool use capabilities, making the process more streamlined and developer-friendly.
- id:
msg_01B4KHLHzM6MUnRgiB3tZ1m5
- content:
[{'text': "Claudette makes tool use more ergonomic in several ways:\n\n1. Simplified function definition: It uses docments to make defining Python functions for tools as simple as possible. Each parameter and the return value should have a type and a description.\n\n2. Automatic handling: The [
Chat](https://claudette.answer.ai/core.html#chat) class can be initialized with a list of tools, and Claudette handles the back-and-forth between Claude and the tools automatically.\n\n3. Single-step execution: The [
Chat.toolloop](https://claudette.answer.ai/toolloop.html#chat.toolloop) method allows for executing a series of tool calls in a single step, even if multiple tools are needed to solve a problem.\n\n4. Forced tool use: You can set
tool_choiceto force Claude to always answer using a specific tool.\n\n5. Tracing: The
toolloopmethod supports a
trace_funcparameter, allowing you to see each response from Claude during the process.\n\n6. Automatic parameter passing: When Claude decides to use a tool, Claudette automatically calls the tool with the provided parameters.\n\n7. System prompt integration: It allows setting a system prompt to guide Claude's behavior when using tools, such as instructing it not to mention the tools it's using.\n\nThese features significantly reduce the amount of code and manual handling required to use Claude's tool use capabilities, making the process more streamlined and developer-friendly.", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 240, 'output_tokens': 289, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 7171}
We can see that this only used ~200 regular input tokens – the 7000+ context tokens have been read from cache.
print(r.usage)
Usage(input_tokens=240, output_tokens=289, cache_creation_input_tokens=0, cache_read_input_tokens=7171)
chat.use
In: 244; Out: 509; Cache create: 7171; Cache read: 7171; Total: 15095
Tool use
Tool use lets Claude use external tools.
We use docments to make defining Python functions as ergonomic as possible. Each parameter (and the return value) should have a type, and a docments comment with the description of what it is. As an example we’ll write a simple function that adds numbers together, and will tell us when it’s being called:
def sums(
int, # First thing to sum
a:int=1 # Second thing to sum
b:-> int: # The sum of the inputs
) "Adds a + b."
print(f"Finding the sum of {a} and {b}")
return a + b
Sometimes Claude will say something like “according to the sums
tool the answer is” – generally we’d rather it just tells the user the answer, so we can use a system prompt to help with this:
= "Never mention what tools you use." sp
We’ll get Claude to add up some long numbers:
= 604542,6458932
a,b = f"What is {a}+{b}?"
pr pr
'What is 604542+6458932?'
To use tools, pass a list of them to Chat
, and to force it to always answer using a tool, set tool_choice
to that function name:
= Chat(model, sp=sp, tools=[sums], tool_choice='sums') chat
Now when we call that with our prompt, Claude doesn’t return the answer, but instead returns a tool_use
message, which means we have to call the named tool with the provided parameters:
= chat(pr)
r r
Finding the sum of 604542 and 6458932
ToolUseBlock(id=‘toolu_01SCB8X3NpcucTBQcHCtRxuZ’, input={‘a’: 604542, ‘b’: 6458932}, name=‘sums’, type=‘tool_use’)
- id:
msg_01J1fmKt3wwMVrbBxoZANA9X
- content:
[{'id': 'toolu_01SCB8X3NpcucTBQcHCtRxuZ', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
tool_use
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 414, 'output_tokens': 53, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
Claudette handles all that for us – we just call it again, and it all happens automatically:
chat()
The sum of 604542 and 6458932 is 7063474.
- id:
msg_01R4SGHWELZeSYkGyrK2A2Cn
- content:
[{'text': 'The sum of 604542 and 6458932 is 7063474.', 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 515, 'output_tokens': 23, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
You can see how many tokens have been used at any time by checking the use
property. Note that (as of May 2024) tool use in Claude uses a lot of tokens, since it automatically adds a large system prompt.
chat.use
In: 929; Out: 76; Cache create: 0; Cache read: 0; Total: 1005
We can do everything needed to use tools in a single step, by using Chat.toolloop
. This can even call multiple tools as needed solve a problem. For example, let’s define a tool to handle multiplication:
def mults(
int, # First thing to multiply
a:int=1 # Second thing to multiply
b:-> int: # The product of the inputs
) "Multiplies a * b."
print(f"Finding the product of {a} and {b}")
return a * b
Now with a single call we can calculate (a+b)*2
– by passing show_trace
we can see each response from Claude in the process:
= Chat(model, sp=sp, tools=[sums,mults])
chat = f'Calculate ({a}+{b})*2'
pr pr
'Calculate (604542+6458932)*2'
=print) chat.toolloop(pr, trace_func
Finding the sum of 604542 and 6458932
Message(id='msg_01BidPp2g3FuMLzFJd7jHDeb', content=[TextBlock(text='Certainly! To calculate (604542+6458932)*2, we\'ll need to use the available tools to perform the addition and multiplication operations. Let\'s break it down step by step:\n\n1. First, we\'ll add 604542 and 6458932 using the "sums" function.\n2. Then, we\'ll multiply the result by 2 using the "mults" function.\n\nLet\'s start with the addition:', type='text'), ToolUseBlock(id='toolu_017v8XraNE8sEaErP3SqwWw2', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 538; Out: 168; Cache create: 0; Cache read: 0; Total: 706)
Finding the product of 7063474 and 2
Message(id='msg_01XpkGk396hzw5zS8qfC6zb5', content=[TextBlock(text="Great! The sum of 604542 and 6458932 is 7063474.\n\nNow, let's multiply this result by 2:", type='text'), ToolUseBlock(id='toolu_012R3kQMdwT75GtbzWjfXL3k', input={'a': 7063474, 'b': 2}, name='mults', type='tool_use')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 721; Out: 106; Cache create: 0; Cache read: 0; Total: 827)
Message(id='msg_018bqP3PhfdcP5N7KKyTSLzF', content=[TextBlock(text='Now we have our final result. \n\nThe calculation (604542+6458932)*2 equals 14126948.\n\nTo break it down:\n1. 604542 + 6458932 = 7063474\n2. 7063474 * 2 = 14126948\n\nSo, the final answer to (604542+6458932)*2 is 14126948.', type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 841; Out: 95; Cache create: 0; Cache read: 0; Total: 936)
Now we have our final result.
The calculation (604542+6458932)*2 equals 14126948.
To break it down: 1. 604542 + 6458932 = 7063474 2. 7063474 * 2 = 14126948
So, the final answer to (604542+6458932)*2 is 14126948.
- id:
msg_018bqP3PhfdcP5N7KKyTSLzF
- content:
[{'text': 'Now we have our final result. \n\nThe calculation (604542+6458932)*2 equals 14126948.\n\nTo break it down:\n1. 604542 + 6458932 = 7063474\n2. 7063474 * 2 = 14126948\n\nSo, the final answer to (604542+6458932)*2 is 14126948.', 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 841, 'output_tokens': 95, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
Structured data
If you just want the immediate result from a single tool, use Client.structured
.
= Client(model) cli
def sums(
int, # First thing to sum
a:int=1 # Second thing to sum
b:-> int: # The sum of the inputs
) "Adds a + b."
print(f"Finding the sum of {a} and {b}")
return a + b
"What is 604542+6458932", sums) cli.structured(
Finding the sum of 604542 and 6458932
[7063474]
This is particularly useful for getting back structured information, e.g:
class President:
"Information about a president of the United States"
def __init__(self,
str, # first name
first:str, # last name
last:str, # name of spouse
spouse:str, # format: "{start_year}-{end_year}"
years_in_office:str, # name of city
birthplace:int # year of birth, `0` if unknown
birth_year:
):assert re.match(r'\d{4}-\d{4}', years_in_office), "Invalid format: `years_in_office`"
store_attr()
__repr__ = basic_repr('first, last, spouse, years_in_office, birthplace, birth_year')
"Provide key information about the 3rd President of the United States", President) cli.structured(
[__main__.President(first='Thomas', last='Jefferson', spouse='Martha Wayles Skelton', years_in_office='1801-1809', birthplace='Shadwell, Virginia', birth_year=1743)]
Images
Claude can handle image data as well. As everyone knows, when testing image APIs you have to use a cute puppy.
= Path('samples/puppy.jpg')
fn =fn, width=200) display.Image(filename
We create a Chat
object as before:
= Chat(model) chat
Claudette expects images as a list of bytes, so we read in the file:
= fn.read_bytes() img
Prompts to Claudette can be lists, containing text, images, or both, eg:
"In brief, what color flowers are in this image?"]) chat([img,
The flowers in this image are purple. They appear to be small, daisy-like flowers, possibly asters or some type of purple daisy, blooming in the background behind the adorable puppy in the foreground.
- id:
msg_01Wq2UqWLrQhWmmcuS7Dd8aL
- content:
[{'text': 'The flowers in this image are purple. They appear to be small, daisy-like flowers, possibly asters or some type of purple daisy, blooming in the background behind the adorable puppy in the foreground.', 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 110, 'output_tokens': 50, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
The image is included as input tokens.
chat.use
In: 110; Out: 50; Cache create: 0; Cache read: 0; Total: 160
Alternatively, Claudette supports creating a multi-stage chat with separate image and text prompts. For instance, you can pass just the image as the initial prompt (in which case Claude will make some general comments about what it sees), and then follow up with questions in additional prompts:
= Chat(model)
chat chat(img)
This image shows an adorable puppy lying in the grass. The puppy appears to be a Cavalier King Charles Spaniel or a similar breed, with distinctive white and reddish-brown fur coloring. Its face is predominantly white with large, expressive dark eyes and a small black nose.
The puppy is resting on a grassy surface, and behind it, you can see some purple flowers, which look like asters or michaelmas daisies. These flowers add a lovely splash of color to the background. There’s also what seems to be a wooden structure or fence visible behind the puppy, giving the scene a rustic, garden-like feel.
The composition of the image is quite charming, with the puppy as the main focus in the foreground and the natural elements providing a beautiful, colorful backdrop. The lighting appears soft, highlighting the puppy’s fur and giving the whole image a warm, inviting atmosphere.
This kind of image would be perfect for a greeting card, calendar, or as a heartwarming pet portrait. It captures the innocence and cuteness of a young dog in a picturesque outdoor setting.
- id:
msg_015NoQzCLM5ofbZTCxDPmWAT
- content:
[{'text': "This image shows an adorable puppy lying in the grass. The puppy appears to be a Cavalier King Charles Spaniel or a similar breed, with distinctive white and reddish-brown fur coloring. Its face is predominantly white with large, expressive dark eyes and a small black nose.\n\nThe puppy is resting on a grassy surface, and behind it, you can see some purple flowers, which look like asters or michaelmas daisies. These flowers add a lovely splash of color to the background. There's also what seems to be a wooden structure or fence visible behind the puppy, giving the scene a rustic, garden-like feel.\n\nThe composition of the image is quite charming, with the puppy as the main focus in the foreground and the natural elements providing a beautiful, colorful backdrop. The lighting appears soft, highlighting the puppy's fur and giving the whole image a warm, inviting atmosphere.\n\nThis kind of image would be perfect for a greeting card, calendar, or as a heartwarming pet portrait. It captures the innocence and cuteness of a young dog in a picturesque outdoor setting.", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 98, 'output_tokens': 248, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
'What direction is the puppy facing?') chat(
The puppy in the image is facing towards the left side of the frame. Its head is turned slightly, allowing us to see most of its face, including both eyes, which are looking directly at the camera. The puppy’s body is angled diagonally, with its front paws and chest visible as it rests on the grass. This positioning gives a good view of the puppy’s facial features and part of its body, creating an engaging and endearing portrait of the young dog.
- id:
msg_018bjcun7oQyBLtn3eMi1nHU
- content:
[{'text': "The puppy in the image is facing towards the left side of the frame. Its head is turned slightly, allowing us to see most of its face, including both eyes, which are looking directly at the camera. The puppy's body is angled diagonally, with its front paws and chest visible as it rests on the grass. This positioning gives a good view of the puppy's facial features and part of its body, creating an engaging and endearing portrait of the young dog.", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 357, 'output_tokens': 105, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
'What color is it?') chat(
The puppy in the image has a combination of two main colors:
White: The majority of its face, including the area around its eyes, muzzle, and part of its chest, is white.
Reddish-brown (often called “ruby” or “chestnut” in dog breed descriptions): This color appears on its ears and patches on its body.
This color combination is typical of Cavalier King Charles Spaniels, particularly the Blenheim variety, though without being able to see the full body, it’s hard to confirm the exact breed. The contrast between the white and reddish-brown fur creates a striking and adorable appearance for the puppy.
- id:
msg_01T4JvKPNT9a9iWXachmszAU
- content:
[{'text': 'The puppy in the image has a combination of two main colors:\n\n1. White: The majority of its face, including the area around its eyes, muzzle, and part of its chest, is white.\n\n2. Reddish-brown (often called "ruby" or "chestnut" in dog breed descriptions): This color appears on its ears and patches on its body.\n\nThis color combination is typical of Cavalier King Charles Spaniels, particularly the Blenheim variety, though without being able to see the full body, it\'s hard to confirm the exact breed. The contrast between the white and reddish-brown fur creates a striking and adorable appearance for the puppy.', 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 470, 'output_tokens': 154, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}
Note that the image is passed in again for every input in the dialog, so that number of input tokens increases quickly with this kind of chat. (For large images, using prompt caching might be a good idea.)
chat.use
In: 925; Out: 507; Cache create: 0; Cache read: 0; Total: 1432
Other model providers
You can also use 3rd party providers of Anthropic models, as shown here.
Amazon Bedrock
These are the models available through Bedrock:
models_aws
('anthropic.claude-3-haiku-20240307-v1:0',
'anthropic.claude-3-sonnet-20240229-v1:0',
'anthropic.claude-3-opus-20240229-v1:0',
'anthropic.claude-3-5-sonnet-20240620-v1:0')
To use them, call AnthropicBedrock
with your access details, and pass that to Client
:
from anthropic import AnthropicBedrock
= AnthropicBedrock(
ab =os.environ['AWS_ACCESS_KEY'],
aws_access_key=os.environ['AWS_SECRET_KEY'],
aws_secret_key
)= Client(models_aws[-1], ab) client
Now create your Chat
object passing this client to the cli
parameter – and from then on, everything is identical to the previous examples.
= Chat(cli=client)
chat "I'm Jeremy") chat(
Hello Jeremy! It’s nice to meet you. How can I assist you today? Is there anything specific you’d like to talk about or any questions you have?
- id:
msg_bdrk_01VFVE1Pe5LNubaWYKC1sz8f
- content:
[{'text': "Hello Jeremy! It's nice to meet you. How can I assist you today? Is there anything specific you'd like to talk about or any questions you have?", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 10, 'output_tokens': 36}
Google Vertex
These are the models available through Vertex:
models_goog
('claude-3-haiku@20240307',
'claude-3-sonnet@20240229',
'claude-3-opus@20240229',
'claude-3-5-sonnet@20240620')
To use them, call AnthropicVertex
with your access details, and pass that to Client
:
from anthropic import AnthropicVertex
import google.auth
= google.auth.default()[1]
project_id = AnthropicVertex(project_id=project_id, region="us-east5")
gv = Client(models_goog[-1], gv) client
= Chat(cli=client)
chat "I'm Jeremy") chat(
Hello Jeremy! It’s nice to meet you. How can I assist you today? Is there anything specific you’d like to talk about or any questions you have?
- id:
msg_vrtx_01P251BUJXBBvihsvb3VVgZ3
- content:
[{'text': "Hello Jeremy! It's nice to meet you. How can I assist you today? Is there anything specific you'd like to talk about or any questions you have?", 'type': 'text'}]
- model:
claude-3-5-sonnet-20240620
- role:
assistant
- stop_reason:
end_turn
- stop_sequence:
None
- type:
message
- usage:
{'input_tokens': 10, 'output_tokens': 36}