diff --git a/00_core.ipynb b/00_core.ipynb index 88a8690..0f17898 100644 --- a/00_core.ipynb +++ b/00_core.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "efe78920", "metadata": {}, "outputs": [], @@ -31,20 +31,16 @@ { "cell_type": "markdown", "id": "ff6f6471-8061-4fdd-85a1-25fdc27c5cf3", - "metadata": { - "heading_collapsed": true - }, + "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "f1ad998e-4bb1-4bed-abf4-6e8606cb2453", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "import os\n", @@ -54,20 +50,16 @@ { "cell_type": "markdown", "id": "5b16f396", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "To print every HTTP request and response in full, uncomment the above line. This functionality is provided by Anthropic's SDK." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "033c76fd", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| export\n", @@ -90,11 +82,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "13866a72", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| hide\n", @@ -103,11 +93,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "f5fa6b92", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| export\n", @@ -117,9 +105,7 @@ { "cell_type": "markdown", "id": "9c3c2197", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ ":::{.callout-tip}\n", "\n", @@ -132,11 +118,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "0fff8869", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -146,20 +130,16 @@ { "cell_type": "markdown", "id": "ba6c7f48", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "These are the current versions of Anthropic's model at the time of writing." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "dacf2bd2", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "model = models[-1]" @@ -168,9 +148,7 @@ { "cell_type": "markdown", "id": "71985a9c", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "For examples, we'll use Haiku, since it's fast and cheap (and surprisingly good!)" ] @@ -178,20 +156,16 @@ { "cell_type": "markdown", "id": "863d4d81", - "metadata": { - "heading_collapsed": true - }, + "metadata": {}, "source": [ "## Antropic SDK" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "70b53a51", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "cli = Anthropic()" @@ -200,9 +174,7 @@ { "cell_type": "markdown", "id": "23055b40", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "This is what Anthropic's SDK provides for interacting with Python. To use it, pass it a list of *messages*, with *content* and a *role*. The roles should alternate between *user* and *assistant*." ] @@ -210,9 +182,7 @@ { "cell_type": "markdown", "id": "b2db9466", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ ":::{.callout-tip}\n", "\n", @@ -223,19 +193,17 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "6ec40731", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Message(id='msg_01KGbtHuA2PXPBFtjLBngVSb', content=[TextBlock(text=\"It's nice to meet you Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=Usage(input_tokens=10, output_tokens=31))" + "Message(id='msg_015cyLkDadtiL5ynbiMzDtb4', content=[TextBlock(text=\"Nice to meet you, Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=Usage(input_tokens=10, output_tokens=30))" ] }, - "execution_count": 9, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -249,10 +217,7 @@ { "cell_type": "markdown", "id": "d6359e1a", - "metadata": { - "heading_collapsed": true, - "hidden": true - }, + "metadata": {}, "source": [ "### Formatting output" ] @@ -260,9 +225,7 @@ { "cell_type": "markdown", "id": "865c40a9", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "That output is pretty long and hard to read, so let's clean it up. We'll start by pulling out the `Content` part of the message.\n", "To do that, we're going to write our first function which will be included to the `claudia/core.py` module." @@ -271,9 +234,7 @@ { "cell_type": "markdown", "id": "e42e5d44", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ ":::{.callout-tip}\n", "\n", @@ -291,11 +252,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "eba620ce", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -309,28 +268,24 @@ { "cell_type": "markdown", "id": "1fa93ca1", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "This makes it easier to grab the needed parts of Claude's responses, which can include multiple pieces of content. By default, we look for the first text block. That will generally have the content we want to display." ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "10af0e65", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "TextBlock(text=\"It's nice to meet you Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')" + "TextBlock(text=\"Nice to meet you, Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')" ] }, - "execution_count": 11, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -341,11 +296,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "ae99799d", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -359,28 +312,24 @@ { "cell_type": "markdown", "id": "ffb59427", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "For display purposes, we often just want to show the text itself." ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "6d5f2107", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "\"It's nice to meet you Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\"" + "\"Nice to meet you, Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\"" ] }, - "execution_count": 13, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -391,11 +340,9 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "17924d0c", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -414,44 +361,40 @@ { "cell_type": "markdown", "id": "3764d112", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Jupyter looks for a `_repr_markdown_` method in displayed objects; we add this in order to display just the content text, and collapse full details into a hideable section. Note that `patch` is from [fastcore](https://fastcore.fast.ai/), and is used to add (or replace) functionality in an existing class. We pass the class(es) that we want to patch as type annotations to `self`. In this case, `_repr_markdown_` is being added to Anthropic's `ToolsBetaMessage` and `Message` classes, so when we display the message now we just see the contents, and the details are hidden away in a collapsible details block." ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "cfd85eeb", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "It's nice to meet you Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\n", + "Nice to meet you, Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\n", "\n", "
\n", "\n", - "- id: msg_01KGbtHuA2PXPBFtjLBngVSb\n", - "- content: [{'text': \"It's nice to meet you Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", 'type': 'text'}]\n", + "- id: msg_015cyLkDadtiL5ynbiMzDtb4\n", + "- content: [{'text': \"Nice to meet you, Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", "- stop_reason: end_turn\n", "- stop_sequence: None\n", "- type: message\n", - "- usage: {'input_tokens': 10, 'output_tokens': 31}\n", + "- usage: {'input_tokens': 10, 'output_tokens': 30}\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01KGbtHuA2PXPBFtjLBngVSb', content=[TextBlock(text=\"It's nice to meet you Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=Usage(input_tokens=10, output_tokens=31))" + "Message(id='msg_015cyLkDadtiL5ynbiMzDtb4', content=[TextBlock(text=\"Nice to meet you, Jeremy! I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=Usage(input_tokens=10, output_tokens=30))" ] }, - "execution_count": 15, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -463,9 +406,7 @@ { "cell_type": "markdown", "id": "8615447e", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "One key part of the response is the `usage` key, which tells us how many tokens we used by returning a `Usage` object.\n", "\n", @@ -474,19 +415,17 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "10c7466f", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Usage(input_tokens=10, output_tokens=31)" + "Usage(input_tokens=10, output_tokens=30)" ] }, - "execution_count": 16, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -497,11 +436,9 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "b1a24f68", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -515,20 +452,16 @@ { "cell_type": "markdown", "id": "2184ec7f", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "The constructor provided by Anthropic is rather verbose, so we clean it up a bit, using a lowercase version of the name." ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "a7e52afd", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -536,7 +469,7 @@ "Usage(input_tokens=5, output_tokens=0)" ] }, - "execution_count": 18, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -547,11 +480,9 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "id": "2db64da5", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -562,20 +493,16 @@ { "cell_type": "markdown", "id": "5363afa4", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Adding a `total` property to `Usage` makes it easier to see how many tokens we've used up altogether." ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "74553203", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -583,7 +510,7 @@ "6" ] }, - "execution_count": 20, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -594,11 +521,9 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "27468180", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -609,28 +534,24 @@ { "cell_type": "markdown", "id": "dbbf7024", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "In python, patching `__repr__` lets us change how an object is displayed. (More generally, methods starting and ending in `__` in Python are called `dunder` methods, and have some `magic` behavior -- such as, in this case, changing how an object is displayed.)" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "id": "765ca615", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "In: 10; Out: 31; Total: 41" + "In: 10; Out: 30; Total: 40" ] }, - "execution_count": 22, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -641,11 +562,9 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "id": "bec303ba", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -658,28 +577,24 @@ { "cell_type": "markdown", "id": "81d64102", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "And, patching `__add__` lets `+` work on a `Usage` object." ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "bffb0b2e", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "In: 20; Out: 62; Total: 82" + "In: 20; Out: 60; Total: 80" ] }, - "execution_count": 24, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -691,10 +606,7 @@ { "cell_type": "markdown", "id": "edd0a43f", - "metadata": { - "heading_collapsed": true, - "hidden": true - }, + "metadata": {}, "source": [ "### Creating messages" ] @@ -702,20 +614,16 @@ { "cell_type": "markdown", "id": "36c9755d", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Creating correctly formatted `dict`s from scratch every time isn't very handy, so next up we'll add helpers for this." ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "id": "4f3e4de9", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "def mk_msg(content, role='user', **kw):\n", @@ -725,9 +633,7 @@ { "cell_type": "markdown", "id": "1a76545a", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "We make things a bit more convenient by writing a function to create a message for us." ] @@ -735,9 +641,7 @@ { "cell_type": "markdown", "id": "bf331696", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ ":::{.callout-note}\n", "\n", @@ -748,11 +652,9 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "id": "28542783", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -760,7 +662,7 @@ "{'role': 'user', 'content': \"I'm Jeremy\"}" ] }, - "execution_count": 26, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -773,35 +675,33 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "id": "9ba165ff", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "It's nice to meet you, Jeremy! I'm Claude, an AI assistant. How can I help you today?\n", + "Hello Jeremy! It's nice to meet you. As an AI assistant, I'm here to help you with any questions or tasks you may have. Please let me know if there is anything I can assist you with.\n", "\n", "
\n", "\n", - "- id: msg_01HT1jWQaXwB7TSXfnfdBsvR\n", - "- content: [{'text': \"It's nice to meet you, Jeremy! I'm Claude, an AI assistant. How can I help you today?\", 'type': 'text'}]\n", + "- id: msg_01Acuq6N4soghJf7cR8MtzDk\n", + "- content: [{'text': \"Hello Jeremy! It's nice to meet you. As an AI assistant, I'm here to help you with any questions or tasks you may have. Please let me know if there is anything I can assist you with.\", 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", "- stop_reason: end_turn\n", "- stop_sequence: None\n", "- type: message\n", - "- usage: {'input_tokens': 10, 'output_tokens': 27}\n", + "- usage: {'input_tokens': 10, 'output_tokens': 47}\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01HT1jWQaXwB7TSXfnfdBsvR', content=[TextBlock(text=\"It's nice to meet you, Jeremy! I'm Claude, an AI assistant. How can I help you today?\", type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 27; Total: 37)" + "Message(id='msg_01Acuq6N4soghJf7cR8MtzDk', content=[TextBlock(text=\"Hello Jeremy! It's nice to meet you. As an AI assistant, I'm here to help you with any questions or tasks you may have. Please let me know if there is anything I can assist you with.\", type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 47; Total: 57)" ] }, - "execution_count": 27, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -813,11 +713,9 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "id": "8cfb240d", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -830,9 +728,7 @@ { "cell_type": "markdown", "id": "423b5739", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "LLMs, including Claude, don't actually have state, but instead dialogs are created by passing back all previous prompts and responses every time. With Claude, they always alternate *user* and *assistant*. Therefore we create a function to make it easier to build up these dialog lists.\n", "\n", @@ -841,11 +737,9 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "id": "8ab553a4", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "def mk_msg(content, role='user', **kw):\n", @@ -857,22 +751,20 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "id": "7eef3715", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[{'role': 'user', 'content': \"I'm Jeremy\"},\n", " {'role': 'assistant',\n", - " 'content': [TextBlock(text=\"It's nice to meet you, Jeremy! I'm Claude, an AI assistant. How can I help you today?\", type='text')]},\n", + " 'content': [TextBlock(text=\"Hello Jeremy! It's nice to meet you. As an AI assistant, I'm here to help you with any questions or tasks you may have. Please let me know if there is anything I can assist you with.\", type='text')]},\n", " {'role': 'user', 'content': 'I forgot my name. Can you remind me please?'}]" ] }, - "execution_count": 30, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -885,44 +777,40 @@ { "cell_type": "markdown", "id": "9ddf95e1", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Now, if we pass this list of messages to Claude, the model treats it as a conversation to respond to." ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "id": "6c464f8b", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "I'm afraid I don't actually know your name - I was just addressing you as \"Jeremy\" because that's the name you provided earlier in our conversation. As an AI, I don't have personal information about you or your identity. I'm happy to continue our conversation, but I can't remind you of a name that I don't have access to.\n", + "I'm sorry, but I don't actually know your name. I was just addressing you as \"Jeremy\" based on the introduction you provided earlier. As an AI, I don't have independent knowledge of your identity or personal details. I'm happy to continue our conversation, but I can't remind you of a name I don't have on record. Please feel free to reintroduce yourself if you'd like.\n", "\n", "
\n", "\n", - "- id: msg_014L2XW8mwVWstPp1xrusmQ1\n", - "- content: [{'text': 'I\\'m afraid I don\\'t actually know your name - I was just addressing you as \"Jeremy\" because that\\'s the name you provided earlier in our conversation. As an AI, I don\\'t have personal information about you or your identity. I\\'m happy to continue our conversation, but I can\\'t remind you of a name that I don\\'t have access to.', 'type': 'text'}]\n", + "- id: msg_01DDd9cnNVNbbmqUnRFi8TCN\n", + "- content: [{'text': 'I\\'m sorry, but I don\\'t actually know your name. I was just addressing you as \"Jeremy\" based on the introduction you provided earlier. As an AI, I don\\'t have independent knowledge of your identity or personal details. I\\'m happy to continue our conversation, but I can\\'t remind you of a name I don\\'t have on record. Please feel free to reintroduce yourself if you\\'d like.', 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", "- stop_reason: end_turn\n", "- stop_sequence: None\n", "- type: message\n", - "- usage: {'input_tokens': 51, 'output_tokens': 76}\n", + "- usage: {'input_tokens': 71, 'output_tokens': 88}\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_014L2XW8mwVWstPp1xrusmQ1', content=[TextBlock(text='I\\'m afraid I don\\'t actually know your name - I was just addressing you as \"Jeremy\" because that\\'s the name you provided earlier in our conversation. As an AI, I don\\'t have personal information about you or your identity. I\\'m happy to continue our conversation, but I can\\'t remind you of a name that I don\\'t have access to.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 51; Out: 76; Total: 127)" + "Message(id='msg_01DDd9cnNVNbbmqUnRFi8TCN', content=[TextBlock(text='I\\'m sorry, but I don\\'t actually know your name. I was just addressing you as \"Jeremy\" based on the introduction you provided earlier. As an AI, I don\\'t have independent knowledge of your identity or personal details. I\\'m happy to continue our conversation, but I can\\'t remind you of a name I don\\'t have on record. Please feel free to reintroduce yourself if you\\'d like.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 71; Out: 88; Total: 159)" ] }, - "execution_count": 31, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -934,20 +822,16 @@ { "cell_type": "markdown", "id": "281f8a4d", - "metadata": { - "heading_collapsed": true - }, + "metadata": {}, "source": [ "## Client" ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "id": "3b873aaf", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -961,20 +845,16 @@ { "cell_type": "markdown", "id": "146e39f0", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "We'll create a simple `Client` for `Anthropic` which tracks usage stores the model to use. We don't add any methods right away -- instead we'll use `patch` for that so we can add and document them incrementally." ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "id": "d01e9ccf", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -982,7 +862,7 @@ "In: 0; Out: 0; Total: 0" ] }, - "execution_count": 33, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -994,11 +874,9 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "id": "be54737f", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -1007,7 +885,7 @@ " \"Store the result of the message and accrue total usage.\"\n", " if prefill:\n", " blk = find_block(r)\n", - " blk.text = prefill + blk.text\n", + " blk.text = prefill + (blk.text or '')\n", " self.result = r\n", " self.use += r.usage\n", " return r" @@ -1016,9 +894,7 @@ { "cell_type": "markdown", "id": "68d2eb9b", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "We use a `_` prefix on private methods, but we document them here in the interests of literate source code.\n", "\n", @@ -1027,19 +903,17 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "id": "0181f7b3", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "In: 10; Out: 27; Total: 37" + "In: 10; Out: 47; Total: 57" ] }, - "execution_count": 35, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1052,20 +926,16 @@ { "cell_type": "markdown", "id": "7258fd6e", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Whereas OpenAI's models use a `stream` parameter for streaming, Anthropic's use a separate method. We implement Anthropic's approach in a private method, and then use a `stream` parameter in `__call__` for consistency:" ] }, { "cell_type": "code", - "execution_count": 36, + "execution_count": null, "id": "6520a355", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -1080,20 +950,16 @@ { "cell_type": "markdown", "id": "f2269e53", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "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. However Claude doesn't actually repeat that in the response, so for convenience we add it." ] }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "id": "5fb96c43", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -1121,20 +987,16 @@ { "cell_type": "markdown", "id": "3cee10c8", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Defining `__call__` let's us use an object like a function (i.e it's *callable*). We use it as a small wrapper over `messages.create`." ] }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "id": "881b5e78", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -1142,7 +1004,7 @@ "In: 0; Out: 0; Total: 0" ] }, - "execution_count": 38, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1154,11 +1016,9 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": null, "id": "338a38e5", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -1167,7 +1027,7 @@ "\n", "
\n", "\n", - "- id: msg_01B83nQnCXb5qZheimqKqGLD\n", + "- id: msg_015nHG72tsVoRAub81gSHBe6\n", "- content: [{'text': 'Hello! How can I assist you today?', 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", @@ -1179,10 +1039,10 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_01B83nQnCXb5qZheimqKqGLD', content=[TextBlock(text='Hello! How can I assist you today?', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 8; Out: 12; Total: 20)" + "ToolsBetaMessage(id='msg_015nHG72tsVoRAub81gSHBe6', content=[TextBlock(text='Hello! How can I assist you today?', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 8; Out: 12; Total: 20)" ] }, - "execution_count": 39, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1193,11 +1053,9 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "id": "ae9f7e06", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -1205,7 +1063,7 @@ "In: 8; Out: 12; Total: 20" ] }, - "execution_count": 40, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1217,20 +1075,16 @@ { "cell_type": "markdown", "id": "2d269ed8", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Let's try out *prefill*:" ] }, { "cell_type": "code", - "execution_count": 41, + "execution_count": null, "id": "7f479429", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "q = \"Concisely, what is the meaning of life?\"\n", @@ -1239,11 +1093,9 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": null, "id": "b831ca3d", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -1252,7 +1104,7 @@ "\n", "
\n", "\n", - "- id: msg_019aiRDVfzq6BYzvayPj9rJt\n", + "- id: msg_01JrwsHxcL5rowcaoUyNrita\n", "- content: [{'text': 'According to Douglas Adams, \"The answer to the ultimate question of life, the universe, and everything is 42.\"', 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", @@ -1264,10 +1116,10 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_019aiRDVfzq6BYzvayPj9rJt', content=[TextBlock(text='According to Douglas Adams, \"The answer to the ultimate question of life, the universe, and everything is 42.\"', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 24; Out: 23; Total: 47)" + "ToolsBetaMessage(id='msg_01JrwsHxcL5rowcaoUyNrita', content=[TextBlock(text='According to Douglas Adams, \"The answer to the ultimate question of life, the universe, and everything is 42.\"', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 24; Out: 23; Total: 47)" ] }, - "execution_count": 42, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1279,20 +1131,16 @@ { "cell_type": "markdown", "id": "216b2704", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "We can pass `stream=True` to stream the response back incrementally:" ] }, { "cell_type": "code", - "execution_count": 43, + "execution_count": null, "id": "c2c46d27", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1308,11 +1156,9 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": null, "id": "beb25f2a", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -1320,7 +1166,7 @@ "In: 40; Out: 47; Total: 87" ] }, - "execution_count": 44, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1331,11 +1177,9 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": null, "id": "db1c75ef", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1351,11 +1195,9 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": null, "id": "e36eddc9", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -1363,7 +1205,7 @@ "In: 64; Out: 70; Total: 134" ] }, - "execution_count": 46, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1390,7 +1232,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": null, "id": "046e8cc3", "metadata": {}, "outputs": [], @@ -1406,7 +1248,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": null, "id": "bff81d52", "metadata": {}, "outputs": [], @@ -1427,19 +1269,19 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": null, "id": "c2ceeb75", "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "ToolUseBlock(id='toolu_01RWao1KKoetRSppoY3FAsQv', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", + "ToolUseBlock(id='toolu_01Gyn1KdTZaLFe2VjNxdDcmT', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", "\n", "
\n", "\n", - "- id: msg_01CacgtjKjuUpXjKKdUi1H6p\n", - "- content: [{'id': 'toolu_01RWao1KKoetRSppoY3FAsQv', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]\n", + "- id: msg_01AtpJk38uznGZwksAPu3cVn\n", + "- content: [{'id': 'toolu_01Gyn1KdTZaLFe2VjNxdDcmT', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", "- stop_reason: tool_use\n", @@ -1450,10 +1292,10 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_01CacgtjKjuUpXjKKdUi1H6p', content=[ToolUseBlock(id='toolu_01RWao1KKoetRSppoY3FAsQv', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-haiku-20240307', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 414; Out: 72; Total: 486)" + "ToolsBetaMessage(id='msg_01AtpJk38uznGZwksAPu3cVn', content=[ToolUseBlock(id='toolu_01Gyn1KdTZaLFe2VjNxdDcmT', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-haiku-20240307', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 414; Out: 72; Total: 486)" ] }, - "execution_count": 49, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1476,7 +1318,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": null, "id": "5ce1b859", "metadata": {}, "outputs": [], @@ -1489,7 +1331,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "id": "4fb9826f", "metadata": {}, "outputs": [ @@ -1499,7 +1341,7 @@ "{'sums': int>}" ] }, - "execution_count": 51, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1511,7 +1353,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": null, "id": "ed48a299", "metadata": {}, "outputs": [], @@ -1540,7 +1382,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": null, "id": "893f81ca", "metadata": {}, "outputs": [ @@ -1555,11 +1397,11 @@ "data": { "text/plain": [ "{'type': 'tool_result',\n", - " 'tool_use_id': 'toolu_01RWao1KKoetRSppoY3FAsQv',\n", + " 'tool_use_id': 'toolu_01Gyn1KdTZaLFe2VjNxdDcmT',\n", " 'content': '7063474'}" ] }, - "execution_count": 53, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1572,7 +1414,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": null, "id": "d475922d", "metadata": {}, "outputs": [], @@ -1601,7 +1443,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": null, "id": "f13de1fc", "metadata": {}, "outputs": [ @@ -1616,14 +1458,14 @@ "data": { "text/plain": [ "[{'role': 'assistant',\n", - " 'content': [ToolUseBlock(id='toolu_01RWao1KKoetRSppoY3FAsQv', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')]},\n", + " 'content': [ToolUseBlock(id='toolu_01Gyn1KdTZaLFe2VjNxdDcmT', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')]},\n", " {'role': 'user',\n", " 'content': [{'type': 'tool_result',\n", - " 'tool_use_id': 'toolu_01RWao1KKoetRSppoY3FAsQv',\n", + " 'tool_use_id': 'toolu_01Gyn1KdTZaLFe2VjNxdDcmT',\n", " 'content': '7063474'}]}]" ] }, - "execution_count": 55, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1643,7 +1485,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": null, "id": "eed99502", "metadata": {}, "outputs": [ @@ -1653,7 +1495,7 @@ "'The sum of 604542 and 6458932 is 7063474.'" ] }, - "execution_count": 56, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1673,7 +1515,7 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": null, "id": "800a53a9", "metadata": {}, "outputs": [], @@ -1691,7 +1533,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": null, "id": "b21e6290", "metadata": {}, "outputs": [ @@ -1708,7 +1550,7 @@ "'The sum of 604542 and 6458932 is 7063474.'" ] }, - "execution_count": 58, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1742,7 +1584,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": null, "id": "a77d1edb", "metadata": {}, "outputs": [], @@ -1773,7 +1615,7 @@ }, { "cell_type": "code", - "execution_count": 84, + "execution_count": null, "id": "04b837c5", "metadata": {}, "outputs": [ @@ -1783,7 +1625,7 @@ "(In: 0; Out: 0; Total: 0, [])" ] }, - "execution_count": 84, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1796,7 +1638,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": null, "id": "42a05df9", "metadata": {}, "outputs": [], @@ -1810,7 +1652,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": null, "id": "bec85e37", "metadata": {}, "outputs": [], @@ -1844,7 +1686,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": null, "id": "40073f42", "metadata": {}, "outputs": [ @@ -1854,7 +1696,7 @@ "'Your name is Jeremy, as you mentioned earlier.'" ] }, - "execution_count": 87, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1874,7 +1716,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": null, "id": "20a32de0", "metadata": {}, "outputs": [], @@ -1885,7 +1727,7 @@ }, { "cell_type": "code", - "execution_count": 89, + "execution_count": null, "id": "9b28705d", "metadata": {}, "outputs": [ @@ -1896,7 +1738,7 @@ "\n", "
\n", "\n", - "- id: msg_017cJZXeKUwEvsauDMaBni37\n", + "- id: msg_01QtRi3Wy7dpJpE2sMc9yt7j\n", "- content: [{'text': 'According to Douglas Adams, \"The answer to the ultimate question of life, the universe, and everything is 42.\"', 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", @@ -1908,10 +1750,10 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_017cJZXeKUwEvsauDMaBni37', content=[TextBlock(text='According to Douglas Adams, \"The answer to the ultimate question of life, the universe, and everything is 42.\"', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 109; Out: 23; Total: 132)" + "ToolsBetaMessage(id='msg_01QtRi3Wy7dpJpE2sMc9yt7j', content=[TextBlock(text='According to Douglas Adams, \"The answer to the ultimate question of life, the universe, and everything is 42.\"', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 109; Out: 23; Total: 132)" ] }, - "execution_count": 89, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1922,7 +1764,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": null, "id": "529104ec", "metadata": {}, "outputs": [ @@ -1941,7 +1783,7 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": null, "id": "14abb3dc", "metadata": {}, "outputs": [ @@ -1975,7 +1817,7 @@ }, { "cell_type": "code", - "execution_count": 92, + "execution_count": null, "id": "ee6535cf", "metadata": {}, "outputs": [ @@ -1985,7 +1827,7 @@ "'What is 604542+6458932?'" ] }, - "execution_count": 92, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -1997,7 +1839,7 @@ }, { "cell_type": "code", - "execution_count": 93, + "execution_count": null, "id": "797741c5", "metadata": {}, "outputs": [ @@ -2011,12 +1853,12 @@ { "data": { "text/markdown": [ - "ToolUseBlock(id='toolu_01By8MztjzQAWi5JdS7sxrj4', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", + "ToolUseBlock(id='toolu_01UWnJcCiDQAgUuha3hFbK7w', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", "\n", "
\n", "\n", - "- id: msg_01XhnDAZM3pycNci6kKs53EN\n", - "- content: [{'id': 'toolu_01By8MztjzQAWi5JdS7sxrj4', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]\n", + "- id: msg_01EaeP4Axf5FFDfq9fVHmP54\n", + "- content: [{'id': 'toolu_01UWnJcCiDQAgUuha3hFbK7w', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", "- stop_reason: tool_use\n", @@ -2027,10 +1869,10 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_01XhnDAZM3pycNci6kKs53EN', content=[ToolUseBlock(id='toolu_01By8MztjzQAWi5JdS7sxrj4', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-haiku-20240307', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 398; Out: 72; Total: 470)" + "ToolsBetaMessage(id='msg_01EaeP4Axf5FFDfq9fVHmP54', content=[ToolUseBlock(id='toolu_01UWnJcCiDQAgUuha3hFbK7w', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-haiku-20240307', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 398; Out: 72; Total: 470)" ] }, - "execution_count": 93, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -2043,7 +1885,7 @@ }, { "cell_type": "code", - "execution_count": 94, + "execution_count": null, "id": "0979c832", "metadata": {}, "outputs": [ @@ -2054,7 +1896,7 @@ "\n", "
\n", "\n", - "- id: msg_01SAvMekJ4RPdUniFqrx67Th\n", + "- id: msg_01BTaqswRAufpQ2L7MDQmMEs\n", "- content: [{'text': 'The sum of 604,542 and 6,458,932 is 7,063,474.', 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", @@ -2066,10 +1908,10 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_01SAvMekJ4RPdUniFqrx67Th', content=[TextBlock(text='The sum of 604,542 and 6,458,932 is 7,063,474.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 485; Out: 28; Total: 513)" + "ToolsBetaMessage(id='msg_01BTaqswRAufpQ2L7MDQmMEs', content=[TextBlock(text='The sum of 604,542 and 6,458,932 is 7,063,474.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 485; Out: 28; Total: 513)" ] }, - "execution_count": 94, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -2088,7 +1930,7 @@ }, { "cell_type": "code", - "execution_count": 95, + "execution_count": null, "id": "b7ff0879", "metadata": {}, "outputs": [ @@ -2098,7 +1940,7 @@ "7063474" ] }, - "execution_count": 95, + "execution_count": null, "metadata": {}, "output_type": "execute_result" } @@ -2110,9 +1952,7 @@ { "cell_type": "markdown", "id": "df1dd4c3", - "metadata": { - "heading_collapsed": true - }, + "metadata": {}, "source": [ "## Images" ] @@ -2120,9 +1960,7 @@ { "cell_type": "markdown", "id": "cf741dbc", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Claude can handle image data as well. As everyone knows, when testing image APIs you have to use a cute puppy." ] @@ -2131,9 +1969,7 @@ "cell_type": "code", "execution_count": null, "id": "5d35d564", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -2161,9 +1997,7 @@ "cell_type": "code", "execution_count": null, "id": "d120d8fb", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "img = fn.read_bytes()" @@ -2173,9 +2007,7 @@ "cell_type": "code", "execution_count": null, "id": "af0c7392", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -2190,9 +2022,7 @@ { "cell_type": "markdown", "id": "5f3b6dee", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "Anthropic have documented the particular `dict` structure that expect image data to be in, so we have a little function to create that for us." ] @@ -2201,9 +2031,7 @@ "cell_type": "code", "execution_count": null, "id": "07b3340d", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -2215,9 +2043,7 @@ { "cell_type": "markdown", "id": "eeb468d9", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "A Claude message can be a list of image and text parts. So we've also created a helper for making the text parts." ] @@ -2226,9 +2052,7 @@ "cell_type": "code", "execution_count": null, "id": "0c0eed5d", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "q = \"In brief, what color flowers are in this image?\"\n", @@ -2239,9 +2063,7 @@ "cell_type": "code", "execution_count": null, "id": "2295c2d3", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -2250,7 +2072,7 @@ "\n", "
\n", "\n", - "- id: msg_01FWg2KXoCFR8Wg1h8QLbuRp\n", + "- id: msg_01DbzXZELSzz7b8JBqg3UXBu\n", "- content: [{'text': 'The image contains purple or lavender-colored flowers, which appear to be daisies or a similar type of flower.', 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", @@ -2262,7 +2084,7 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_01FWg2KXoCFR8Wg1h8QLbuRp', content=[TextBlock(text='The image contains purple or lavender-colored flowers, which appear to be daisies or a similar type of flower.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 28; Total: 138)" + "ToolsBetaMessage(id='msg_01DbzXZELSzz7b8JBqg3UXBu', content=[TextBlock(text='The image contains purple or lavender-colored flowers, which appear to be daisies or a similar type of flower.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 28; Total: 138)" ] }, "execution_count": null, @@ -2278,9 +2100,7 @@ "cell_type": "code", "execution_count": null, "id": "8764c605", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -2294,9 +2114,7 @@ { "cell_type": "markdown", "id": "a67923d1", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "There's not need to manually choose the type of message, since we figure that out from the data of the source data." ] @@ -2305,9 +2123,7 @@ "cell_type": "code", "execution_count": null, "id": "6ccff61c", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -2328,9 +2144,7 @@ "cell_type": "code", "execution_count": null, "id": "a33731ba", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#| exports\n", @@ -2348,9 +2162,7 @@ { "cell_type": "markdown", "id": "339cbd22", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ "When we construct a message, we now use `_mk_content` to create the appropriate parts. Since a dialog contains multiple messages, and a message can contain multiple content parts, to pass a single message with multiple parts we have to use a list containing a single list:" ] @@ -2359,9 +2171,7 @@ "cell_type": "code", "execution_count": null, "id": "4f2ea0d4", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [ { "data": { @@ -2370,7 +2180,7 @@ "\n", "
\n", "\n", - "- id: msg_01FeYnGPDLpbA2ai39iUAADo\n", + "- id: msg_0194Hq3hJ7L8JAhzHCntH54u\n", "- content: [{'text': 'The image contains purple or lavender-colored flowers, which appear to be daisies or a similar type of flower.', 'type': 'text'}]\n", "- model: claude-3-haiku-20240307\n", "- role: assistant\n", @@ -2382,7 +2192,7 @@ "
" ], "text/plain": [ - "ToolsBetaMessage(id='msg_01FeYnGPDLpbA2ai39iUAADo', content=[TextBlock(text='The image contains purple or lavender-colored flowers, which appear to be daisies or a similar type of flower.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 28; Total: 138)" + "ToolsBetaMessage(id='msg_0194Hq3hJ7L8JAhzHCntH54u', content=[TextBlock(text='The image contains purple or lavender-colored flowers, which appear to be daisies or a similar type of flower.', type='text')], model='claude-3-haiku-20240307', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 28; Total: 138)" ] }, "execution_count": null, @@ -2397,9 +2207,7 @@ { "cell_type": "markdown", "id": "4daa7f37", - "metadata": { - "hidden": true - }, + "metadata": {}, "source": [ ":::{.callout-note}\n", "\n", @@ -2411,9 +2219,7 @@ { "cell_type": "markdown", "id": "94ec4289", - "metadata": { - "heading_collapsed": true - }, + "metadata": {}, "source": [ "## Export -" ] @@ -2422,9 +2228,7 @@ "cell_type": "code", "execution_count": null, "id": "1e9ee5c1", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [ "#|hide\n", @@ -2437,30 +2241,16 @@ "cell_type": "code", "execution_count": null, "id": "207f9715", - "metadata": { - "hidden": true - }, + "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "python3", "language": "python", "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.8" } }, "nbformat": 4, diff --git a/claudette/core.py b/claudette/core.py index b8244b5..1e38a29 100644 --- a/claudette/core.py +++ b/claudette/core.py @@ -93,7 +93,7 @@ def _r(self:Client, r:ToolsBetaMessage, prefill=''): "Store the result of the message and accrue total usage." if prefill: blk = find_block(r) - blk.text = prefill + blk.text + blk.text = prefill + (blk.text or '') self.result = r self.use += r.usage return r