From c40a026c31354e6cd27c988d05ec5b12c7e6f08a Mon Sep 17 00:00:00 2001 From: Jay Suh Date: Tue, 4 Feb 2025 01:14:17 -0600 Subject: [PATCH 1/6] Add citations --- 00_core.ipynb | 185 +++++++++++++++++++++++++++++++++++++++++++++- claudette/core.py | 2 +- 2 files changed, 185 insertions(+), 2 deletions(-) diff --git a/00_core.ipynb b/00_core.ipynb index 4255867..60ab376 100644 --- a/00_core.ipynb +++ b/00_core.ipynb @@ -79,7 +79,7 @@ "\n", "from fastcore.meta import delegates\n", "from fastcore.utils import *\n", - "from msglm import mk_msg_anthropic as mk_msg, mk_msgs_anthropic as mk_msgs" + "from msglm import mk_msg_anthropic as mk_msg, mk_msgs_anthropic as mk_msgs, mk_ant_doc as mk_doc" ] }, { @@ -3856,6 +3856,189 @@ "chat(\"Oh thank you! Sorry, my lorem ipsum generator got out of control!\")" ] }, + { + "cell_type": "markdown", + "id": "c07e0589", + "metadata": {}, + "source": [ + "## Citations" + ] + }, + { + "cell_type": "markdown", + "id": "fa6796f3", + "metadata": {}, + "source": [ + "Claude is capable of providing detailed citations when answering questions about documents, helping you track and verify information sources in responses.\n", + "\n", + "Claude expects an documents to have the following structure\n", + "\n", + "``` python\n", + "{\n", + " \"role\": \"user\",\n", + " \"content\": [\n", + " {\n", + " \"type\": \"document\",\n", + " \"source\": {\n", + " \"type\": \"text\",\n", + " \"media_type\": \"text/plain\",\n", + " \"data\": \"The grass is green. The sky is blue.\"\n", + " },\n", + " \"title\": \"My Document\",\n", + " \"context\": \"This is a trustworthy document.\",\n", + " \"citations\": {\"enabled\": True}\n", + " },\n", + " {\n", + " \"type\": \"text\",\n", + " \"text\": \"What color is the grass and sky?\"\n", + " }\n", + " ]\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "82930a8b", + "metadata": {}, + "source": [ + "To create a document, we pass `citation=True` when calling `mk_doc` with any document. Claude supports plain text, PDF, and custom content." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0436c60f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'type': 'document',\n", + " 'source': {'type': 'text',\n", + " 'media_type': 'text/plain',\n", + " 'data': 'The grass is green. The sky is blue.'},\n", + " 'citations': {'enabled': True},\n", + " 'title': 'My Document',\n", + " 'context': 'This is a trustworthy document.'}" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "doc = mk_doc(\"The grass is green. The sky is blue.\", title=\"My Document\", context=\"This is a trustworthy document.\", citation=True)\n", + "doc" + ] + }, + { + "cell_type": "markdown", + "id": "1455effe", + "metadata": {}, + "source": [ + "Let's use the document with a message." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a77d714", + "metadata": {}, + "outputs": [], + "source": [ + "c = Chat(model)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eacea213", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```json\n", + "{ 'content': [ { 'citations': {'enabled': True},\n", + " 'context': 'This is a trustworthy document.',\n", + " 'source': { 'data': 'The grass is green. The sky is blue.',\n", + " 'media_type': 'text/plain',\n", + " 'type': 'text'},\n", + " 'title': 'My Document',\n", + " 'type': 'document'},\n", + " {'text': 'What color is the grass and sky?', 'type': 'text'}],\n", + " 'role': 'user'}\n", + "```" + ], + "text/plain": [ + "{'role': 'user',\n", + " 'content': [{'type': 'document',\n", + " 'source': {'type': 'text',\n", + " 'media_type': 'text/plain',\n", + " 'data': 'The grass is green. The sky is blue.'},\n", + " 'citations': {'enabled': True},\n", + " 'title': 'My Document',\n", + " 'context': 'This is a trustworthy document.'},\n", + " {'type': 'text', 'text': 'What color is the grass and sky?'}]}" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mk_msg([doc, \"What color is the grass and sky?\"])" + ] + }, + { + "cell_type": "markdown", + "id": "21a52343", + "metadata": {}, + "source": [ + "The response contains text and citations alternating back and forth." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31a575c4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "The grass is green and the sky is blue\n", + "\n", + "
\n", + "\n", + "- id: `msg_017wTFkMcBQehknSYmirqfX1`\n", + "- content: `[{'citations': [{'cited_text': 'The grass is green. The sky is blue.', 'document_index': 1, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'The grass is green and the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", + "- model: `claude-3-5-sonnet-20241022`\n", + "- role: `assistant`\n", + "- stop_reason: `end_turn`\n", + "- stop_sequence: `None`\n", + "- type: `message`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 785, 'output_tokens': 33}`\n", + "\n", + "
" + ], + "text/plain": [ + "Message(id='msg_017wTFkMcBQehknSYmirqfX1', content=[TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. The sky is blue.', document_index=1, document_title='My Document', end_char_index=36, start_char_index=0, type='char_location')], text='The grass is green and the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 785; Out: 33; Cache create: 0; Cache read: 0; Total: 818)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "q = \"What color is the grass and sky?\"\n", + "c([doc, q])" + ] + }, { "cell_type": "markdown", "id": "b1580f5c", diff --git a/claudette/core.py b/claudette/core.py index 073b6ef..2bdaff1 100644 --- a/claudette/core.py +++ b/claudette/core.py @@ -22,7 +22,7 @@ from fastcore.meta import delegates from fastcore.utils import * -from msglm import mk_msg_anthropic as mk_msg, mk_msgs_anthropic as mk_msgs +from msglm import mk_msg_anthropic as mk_msg, mk_msgs_anthropic as mk_msgs, mk_ant_doc as mk_doc # %% ../00_core.ipynb _all_ = ['mk_msg', 'mk_msgs'] From 971ba7d35d66b59c680cc3223ed1ab6f0e63fcef Mon Sep 17 00:00:00 2001 From: Jay Suh Date: Thu, 6 Feb 2025 18:59:24 -0600 Subject: [PATCH 2/6] display citations nicely --- 00_core.ipynb | 172 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 5 deletions(-) diff --git a/00_core.ipynb b/00_core.ipynb index 60ab376..37a9423 100644 --- a/00_core.ipynb +++ b/00_core.ipynb @@ -4010,23 +4010,133 @@ { "data": { "text/markdown": [ - "The grass is green and the sky is blue\n", + "Based on the provided document, \n", + "> The grass is green. \n", + "\n", + " and \n", + "> The sky is blue.\n", + "\n", + ".\n", + "\n", + "
\n", + "\n", + "- id: `msg_014yrYM7x1DH2PiYDApCjpA1`\n", + "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': 'The grass is green. ', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 20, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'the grass is green', 'type': 'text'}, {'citations': None, 'text': ' and ', 'type': 'text'}, {'citations': [{'cited_text': 'The sky is blue.', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 20, 'type': 'char_location'}], 'text': 'the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", + "- model: `claude-3-5-sonnet-20241022`\n", + "- role: `assistant`\n", + "- stop_reason: `end_turn`\n", + "- stop_sequence: `None`\n", + "- type: `message`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 610, 'output_tokens': 52}`\n", + "\n", + "
" + ], + "text/plain": [ + "Message(id='msg_014yrYM7x1DH2PiYDApCjpA1', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "q = \"What color is the grass and sky?\"\n", + "c([doc, q])" + ] + }, + { + "cell_type": "markdown", + "id": "fc52b9da", + "metadata": {}, + "source": [ + "Only the first text block is displayed, but let's display citations and the rest of the messages, too. When a message is displayed, each citation is inside of a block quote." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b144898", + "metadata": {}, + "outputs": [], + "source": [ + "#| exports\n", + "def cite_msgs(msg) -> str:\n", + " \"\"\"Render a Claude message with citations as markdown.\"\"\"\n", + " result = []\n", + " for block in msg.content:\n", + " if block.citations:\n", + " for c in block.citations:\n", + " result.append(f\"\\n> {c.cited_text}\\n\\n\")\n", + " else:\n", + " result.append(block.text)\n", + " return ''.join(result)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da3c7b60", + "metadata": {}, + "outputs": [], + "source": [ + "#| exports\n", + "def has_citations(r):\n", + " \"\"\"Check if a Claude response contains any citations\"\"\"\n", + " return any(getattr(block, 'citations', None) and isinstance(block.citations, list)\n", + " for block in r.content)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa168512", + "metadata": {}, + "outputs": [], + "source": [ + "#| exports\n", + "def contents(r):\n", + " \"Helper to get the contents from Claude response `r`.\"\n", + " blk = cite_msgs(r) if has_citations(r) else find_block(r)\n", + " if not blk and r.content: blk = r.content[0]\n", + " if hasattr(blk,'text'): return blk.text.strip()\n", + " elif hasattr(blk,'content'): return blk.content.strip()\n", + " elif hasattr(blk,'source'): return f'*Media Type - {blk.type}*'\n", + " return str(blk)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4cb7e85a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "Based on the provided document, \n", + "> The grass is green. \n", + "\n", + " and \n", + "> The sky is blue.\n", + "\n", + ".\n", "\n", "
\n", "\n", - "- id: `msg_017wTFkMcBQehknSYmirqfX1`\n", - "- content: `[{'citations': [{'cited_text': 'The grass is green. The sky is blue.', 'document_index': 1, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'The grass is green and the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", + "- id: `msg_01DuY7aVG4QdybigKq3rRbeK`\n", + "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': 'The grass is green. ', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 20, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'the grass is green', 'type': 'text'}, {'citations': None, 'text': ' and ', 'type': 'text'}, {'citations': [{'cited_text': 'The sky is blue.', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 20, 'type': 'char_location'}], 'text': 'the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 785, 'output_tokens': 33}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 610, 'output_tokens': 52}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_017wTFkMcBQehknSYmirqfX1', content=[TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. The sky is blue.', document_index=1, document_title='My Document', end_char_index=36, start_char_index=0, type='char_location')], text='The grass is green and the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 785; Out: 33; Cache create: 0; Cache read: 0; Total: 818)" + "Message(id='msg_01DuY7aVG4QdybigKq3rRbeK', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" ] }, "execution_count": null, @@ -4035,10 +4145,62 @@ } ], "source": [ + "c = Chat(model)\n", "q = \"What color is the grass and sky?\"\n", "c([doc, q])" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "c09e70ce", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "Based on the provided document, \n", + "> The grass is green. \n", + "\n", + " and \n", + "> The sky is blue.\n", + "\n", + ".\n", + "\n", + "
\n", + "History\n", + "\n", + "**user**: *Media Type - document*\n", + "\n", + "**assistant**: Based on the provided document, \n", + "> The grass is green. \n", + "\n", + " and \n", + "> The sky is blue.\n", + "\n", + ".\n", + "
\n", + "\n", + "| Metric | Count | Cost (USD) |\n", + "|--------|------:|-----:|\n", + "| Input tokens | 610 | 0.001830 |\n", + "| Output tokens | 52 | 0.000780 |\n", + "| Cache tokens | 0 | 0.000000 |\n", + "| **Total** | **662** | **$0.002610** |" + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "c" + ] + }, { "cell_type": "markdown", "id": "b1580f5c", From e788f577b947e7fa71c03419d166228db5e3c738 Mon Sep 17 00:00:00 2001 From: Jay Suh Date: Thu, 6 Feb 2025 19:13:40 -0600 Subject: [PATCH 3/6] Export citations --- 00_core.ipynb | 16 +++++----------- claudette/_modidx.py | 2 ++ claudette/core.py | 31 ++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/00_core.ipynb b/00_core.ipynb index 29936ae..4bdd161 100644 --- a/00_core.ipynb +++ b/00_core.ipynb @@ -4126,17 +4126,11 @@ { "data": { "text/markdown": [ - "Based on the provided document, \n", - "> The grass is green. \n", - "\n", - " and \n", - "> The sky is blue.\n", - "\n", - ".\n", + "Based on the provided document,\n", "\n", "
\n", "\n", - "- id: `msg_014yrYM7x1DH2PiYDApCjpA1`\n", + "- id: `msg_01W9SvULG3mdvoUProc7GEJo`\n", "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': 'The grass is green. ', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 20, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'the grass is green', 'type': 'text'}, {'citations': None, 'text': ' and ', 'type': 'text'}, {'citations': [{'cited_text': 'The sky is blue.', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 20, 'type': 'char_location'}], 'text': 'the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", @@ -4148,7 +4142,7 @@ "
" ], "text/plain": [ - "Message(id='msg_014yrYM7x1DH2PiYDApCjpA1', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" + "Message(id='msg_01W9SvULG3mdvoUProc7GEJo', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" ] }, "execution_count": null, @@ -4240,7 +4234,7 @@ "\n", "
\n", "\n", - "- id: `msg_01DuY7aVG4QdybigKq3rRbeK`\n", + "- id: `msg_01AQsSJf4Xd96ojvWVGQSx4C`\n", "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': 'The grass is green. ', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 20, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'the grass is green', 'type': 'text'}, {'citations': None, 'text': ' and ', 'type': 'text'}, {'citations': [{'cited_text': 'The sky is blue.', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 20, 'type': 'char_location'}], 'text': 'the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", @@ -4252,7 +4246,7 @@ "
" ], "text/plain": [ - "Message(id='msg_01DuY7aVG4QdybigKq3rRbeK', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" + "Message(id='msg_01AQsSJf4Xd96ojvWVGQSx4C', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" ] }, "execution_count": null, diff --git a/claudette/_modidx.py b/claudette/_modidx.py index b1cd76e..f94c55f 100644 --- a/claudette/_modidx.py +++ b/claudette/_modidx.py @@ -44,11 +44,13 @@ 'claudette.core.can_set_system_prompt': ('core.html#can_set_system_prompt', 'claudette/core.py'), 'claudette.core.can_set_temperature': ('core.html#can_set_temperature', 'claudette/core.py'), 'claudette.core.can_stream': ('core.html#can_stream', 'claudette/core.py'), + 'claudette.core.cite_msgs': ('core.html#cite_msgs', 'claudette/core.py'), 'claudette.core.contents': ('core.html#contents', 'claudette/core.py'), 'claudette.core.find_block': ('core.html#find_block', 'claudette/core.py'), 'claudette.core.get_costs': ('core.html#get_costs', 'claudette/core.py'), 'claudette.core.get_pricing': ('core.html#get_pricing', 'claudette/core.py'), 'claudette.core.get_types': ('core.html#get_types', 'claudette/core.py'), + 'claudette.core.has_citations': ('core.html#has_citations', 'claudette/core.py'), 'claudette.core.mk_funcres': ('core.html#mk_funcres', 'claudette/core.py'), 'claudette.core.mk_tool_choice': ('core.html#mk_tool_choice', 'claudette/core.py'), 'claudette.core.mk_toolres': ('core.html#mk_toolres', 'claudette/core.py'), diff --git a/claudette/core.py b/claudette/core.py index 039c26a..fadf6c4 100644 --- a/claudette/core.py +++ b/claudette/core.py @@ -4,7 +4,8 @@ __all__ = ['empty', 'model_types', 'all_models', 'models', 'models_aws', 'models_goog', 'text_only_models', 'has_streaming_models', 'has_system_prompt_models', 'has_temperature_models', 'pricing', 'can_stream', 'can_set_system_prompt', 'can_set_temperature', 'find_block', 'usage', 'Client', 'get_pricing', 'get_costs', - 'mk_tool_choice', 'mk_funcres', 'mk_toolres', 'get_types', 'tool', 'Chat', 'contents', 'mk_msg', 'mk_msgs'] + 'mk_tool_choice', 'mk_funcres', 'mk_toolres', 'get_types', 'tool', 'Chat', 'contents', 'cite_msgs', + 'has_citations', 'mk_msg', 'mk_msgs'] # %% ../00_core.ipynb import inspect, typing, json @@ -409,3 +410,31 @@ def contents(r): elif hasattr(blk,'content'): return blk.content.strip() elif hasattr(blk,'source'): return f'*Media Type - {blk.type}*' return str(blk) + +# %% ../00_core.ipynb +def cite_msgs(msg) -> str: + """Render a Claude message with citations as markdown.""" + result = [] + for block in msg.content: + if block.citations: + for c in block.citations: + result.append(f"\n> {c.cited_text}\n\n") + else: + result.append(block.text) + return ''.join(result) + +# %% ../00_core.ipynb +def has_citations(r): + """Check if a Claude response contains any citations""" + return any(getattr(block, 'citations', None) and isinstance(block.citations, list) + for block in r.content) + +# %% ../00_core.ipynb +def contents(r): + "Helper to get the contents from Claude response `r`." + blk = cite_msgs(r) if has_citations(r) else find_block(r) + if not blk and r.content: blk = r.content[0] + if hasattr(blk,'text'): return blk.text.strip() + elif hasattr(blk,'content'): return blk.content.strip() + elif hasattr(blk,'source'): return f'*Media Type - {blk.type}*' + return str(blk) From b0d9f482b9cc24741f9cdf266b2fe46316b61f62 Mon Sep 17 00:00:00 2001 From: ncoop57 Date: Sun, 23 Feb 2025 09:18:11 -0600 Subject: [PATCH 4/6] Enhance citation formatting and fix bug in contents function --- 00_core.ipynb | 525 +++++++++++++++++++++++++++------------------- claudette/core.py | 23 +- 2 files changed, 312 insertions(+), 236 deletions(-) diff --git a/00_core.ipynb b/00_core.ipynb index 4bdd161..86658dc 100644 --- a/00_core.ipynb +++ b/00_core.ipynb @@ -90,6 +90,7 @@ "outputs": [], "source": [ "#| hide\n", + "from httpx import get as xget\n", "from nbdev import show_doc" ] }, @@ -169,7 +170,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Available models as of 2025-02-06:\n", + "Available models as of 2025-02-23:\n", "\n" ] }, @@ -390,23 +391,23 @@ { "data": { "text/markdown": [ - "Hi Jeremy! I'm Claude. Nice to meet you.\n", + "Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\n", "\n", "
\n", "\n", - "- id: `msg_0158aovhxvr9sFq6zmrMzfAr`\n", - "- content: `[{'text': \"Hi Jeremy! I'm Claude. Nice to meet you.\", 'type': 'text'}]`\n", + "- id: `msg_01TbKY5AhCvCF8n5AfGajZmw`\n", + "- content: `[{'citations': None, 'text': \"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 15}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 22}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_0158aovhxvr9sFq6zmrMzfAr', content=[TextBlock(text=\"Hi Jeremy! I'm Claude. Nice to meet you.\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 15; Cache create: 0; Cache read: 0; Total: 25)" + "Message(id='msg_01TbKY5AhCvCF8n5AfGajZmw', content=[TextBlock(citations=None, text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32)" ] }, "execution_count": null, @@ -488,7 +489,7 @@ { "data": { "text/plain": [ - "TextBlock(text=\"Hi Jeremy! I'm Claude. Nice to meet you.\", type='text')" + "TextBlock(citations=None, text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')" ] }, "execution_count": null, @@ -531,7 +532,7 @@ { "data": { "text/plain": [ - "\"Hi Jeremy! I'm Claude. Nice to meet you.\"" + "\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\"" ] }, "execution_count": null, @@ -581,23 +582,23 @@ { "data": { "text/markdown": [ - "Hi Jeremy! I'm Claude. Nice to meet you.\n", + "Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\n", "\n", "
\n", "\n", - "- id: `msg_0158aovhxvr9sFq6zmrMzfAr`\n", - "- content: `[{'text': \"Hi Jeremy! I'm Claude. Nice to meet you.\", 'type': 'text'}]`\n", + "- id: `msg_01TbKY5AhCvCF8n5AfGajZmw`\n", + "- content: `[{'citations': None, 'text': \"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 15}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 22}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_0158aovhxvr9sFq6zmrMzfAr', content=[TextBlock(text=\"Hi Jeremy! I'm Claude. Nice to meet you.\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 15; Cache create: 0; Cache read: 0; Total: 25)" + "Message(id='msg_01TbKY5AhCvCF8n5AfGajZmw', content=[TextBlock(citations=None, text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32)" ] }, "execution_count": null, @@ -628,7 +629,7 @@ { "data": { "text/plain": [ - "In: 10; Out: 15; Cache create: 0; Cache read: 0; Total: 25" + "In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32" ] }, "execution_count": null, @@ -799,7 +800,7 @@ { "data": { "text/plain": [ - "In: 20; Out: 30; Cache create: 0; Cache read: 0; Total: 50" + "In: 20; Out: 44; Cache create: 0; Cache read: 0; Total: 64" ] }, "execution_count": null, @@ -838,23 +839,23 @@ { "data": { "text/markdown": [ - "Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant created by Anthropic. How can I help you today?\n", + "Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\n", "\n", "
\n", "\n", - "- id: `msg_01Absw9JQLUQgvYsmrX9yRog`\n", - "- content: `[{'text': \"Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", 'type': 'text'}]`\n", + "- id: `msg_015oTMXat2vJ7rwViLtezhrV`\n", + "- content: `[{'citations': None, 'text': \"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 31}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 22}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01Absw9JQLUQgvYsmrX9yRog', content=[TextBlock(text=\"Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 31; Cache create: 0; Cache read: 0; Total: 41)" + "Message(id='msg_015oTMXat2vJ7rwViLtezhrV', content=[TextBlock(citations=None, text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32)" ] }, "execution_count": null, @@ -915,7 +916,7 @@ "text/plain": [ "[{'role': 'user', 'content': \"I'm Jeremy\"},\n", " {'role': 'assistant',\n", - " 'content': [TextBlock(text=\"Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant created by Anthropic. How can I help you today?\", type='text')]},\n", + " 'content': [TextBlock(citations=None, text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')]},\n", " {'role': 'user', 'content': 'I forgot my name. Can you remind me please?'}]" ] }, @@ -942,19 +943,19 @@ "\n", "
\n", "\n", - "- id: `msg_01F7tpx559aabbj94DLcnqSh`\n", - "- content: `[{'text': 'You just told me your name is Jeremy.', 'type': 'text'}]`\n", + "- id: `msg_01KzyfFGrYpFDPVLwMocFSs8`\n", + "- content: `[{'citations': None, 'text': 'You just told me your name is Jeremy.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 55, 'output_tokens': 12}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 46, 'output_tokens': 12}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01F7tpx559aabbj94DLcnqSh', content=[TextBlock(text='You just told me your name is Jeremy.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 55; Out: 12; Cache create: 0; Cache read: 0; Total: 67)" + "Message(id='msg_01KzyfFGrYpFDPVLwMocFSs8', content=[TextBlock(citations=None, text='You just told me your name is Jeremy.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 46; Out: 12; Cache create: 0; Cache read: 0; Total: 58)" ] }, "execution_count": null, @@ -1062,7 +1063,7 @@ { "data": { "text/plain": [ - "In: 10; Out: 31; Cache create: 0; Cache read: 0; Total: 41" + "In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32" ] }, "execution_count": null, @@ -1214,8 +1215,8 @@ "\n", "
\n", "\n", - "- id: `msg_01E4ZBvp4rqb9RSiUvRi5jFR`\n", - "- content: `[{'text': 'Hello! How can I help you today?', 'type': 'text'}]`\n", + "- id: `msg_01U9k6CorxUKs12ukhwgMQwC`\n", + "- content: `[{'citations': None, 'text': 'Hello! How can I help you today?', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", @@ -1226,7 +1227,7 @@ "
" ], "text/plain": [ - "Message(id='msg_01E4ZBvp4rqb9RSiUvRi5jFR', content=[TextBlock(text='Hello! How can I help you today?', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 8; Out: 12; Cache create: 0; Cache read: 0; Total: 20)" + "Message(id='msg_01U9k6CorxUKs12ukhwgMQwC', content=[TextBlock(citations=None, text='Hello! How can I help you today?', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 8; Out: 12; Cache create: 0; Cache read: 0; Total: 20)" ] }, "execution_count": null, @@ -1287,23 +1288,23 @@ { "data": { "text/markdown": [ - "According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, creating meaning through relationships and achievements, pursuing knowledge, helping others, or fulfilling one's potential.\n", + "According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, making meaningful connections, pursuing purpose through work/creativity, helping others, or simply experiencing and appreciating existence.\n", "\n", "
\n", "\n", - "- id: `msg_012g4DVP6R774J4tASWNubMR`\n", - "- content: `[{'text': \"According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, creating meaning through relationships and achievements, pursuing knowledge, helping others, or fulfilling one's potential.\", 'type': 'text'}]`\n", + "- id: `msg_01C3hEX5R5zk8Ajr1yvzbhd9`\n", + "- content: `[{'citations': None, 'text': \"According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, making meaningful connections, pursuing purpose through work/creativity, helping others, or simply experiencing and appreciating existence.\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 24, 'output_tokens': 50}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 24, 'output_tokens': 52}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_012g4DVP6R774J4tASWNubMR', content=[TextBlock(text=\"According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, creating meaning through relationships and achievements, pursuing knowledge, helping others, or fulfilling one's potential.\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 24; Out: 50; Cache create: 0; Cache read: 0; Total: 74)" + "Message(id='msg_01C3hEX5R5zk8Ajr1yvzbhd9', content=[TextBlock(citations=None, text=\"According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, making meaningful connections, pursuing purpose through work/creativity, helping others, or simply experiencing and appreciating existence.\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 24; Out: 52; Cache create: 0; Cache read: 0; Total: 76)" ] }, "execution_count": null, @@ -1350,7 +1351,7 @@ { "data": { "text/plain": [ - "In: 40; Out: 74; Cache create: 0; Cache read: 0; Total: 114" + "In: 40; Out: 76; Cache create: 0; Cache read: 0; Total: 116" ] }, "execution_count": null, @@ -1372,7 +1373,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, creating meaning through relationships and achievements, pursuing knowledge, helping others, or fulfilling one's potential." + "According to Douglas Adams, it's 42. More seriously, there's no universal answer - it's deeply personal. Common perspectives include: finding happiness, making meaningful connections, pursuing purpose through work/creativity, helping others, or simply experiencing and appreciating existence." ] } ], @@ -1389,7 +1390,7 @@ { "data": { "text/plain": [ - "In: 64; Out: 124; Cache create: 0; Cache read: 0; Total: 188" + "In: 64; Out: 128; Cache create: 0; Cache read: 0; Total: 192" ] }, "execution_count": null, @@ -1425,8 +1426,8 @@ "\n", "
\n", "\n", - "- id: `msg_01Xf8kU7k91uymCpi5UpbvTa`\n", - "- content: `[{'text': '1\\n2\\n3\\n4\\n', 'type': 'text'}]`\n", + "- id: `msg_01Penda9QWGV5nQ4VfeyX7gh`\n", + "- content: `[{'citations': None, 'text': '1\\n2\\n3\\n4\\n', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `stop_sequence`\n", @@ -1437,7 +1438,7 @@ "
" ], "text/plain": [ - "Message(id='msg_01Xf8kU7k91uymCpi5UpbvTa', content=[TextBlock(text='1\\n2\\n3\\n4\\n', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='stop_sequence', stop_sequence='5', type='message', usage=In: 15; Out: 10; Cache create: 0; Cache read: 0; Total: 25)" + "Message(id='msg_01Penda9QWGV5nQ4VfeyX7gh', content=[TextBlock(citations=None, text='1\\n2\\n3\\n4\\n', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='stop_sequence', stop_sequence='5', type='message', usage=In: 15; Out: 10; Cache create: 0; Cache read: 0; Total: 25)" ] }, "execution_count": null, @@ -1505,8 +1506,8 @@ " 'temp': None,\n", " 'stream': None,\n", " 'stop': None,\n", - " 'result': Message(id='msg_01UQkPC3f5fcAmrAgxB9AeXK', content=[TextBlock(text='1\\n', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='stop_sequence', stop_sequence='2', type='message', usage=In: 15; Out: 4; Cache create: 0; Cache read: 0; Total: 19),\n", - " 'use': In: 94; Out: 138; Cache create: 0; Cache read: 0; Total: 232,\n", + " 'result': Message(id='msg_01C1RCFCKuD8jjegJvWpbdfM', content=[TextBlock(citations=None, text='1\\n', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='stop_sequence', stop_sequence='2', type='message', usage=In: 15; Out: 4; Cache create: 0; Cache read: 0; Total: 19),\n", + " 'use': In: 94; Out: 142; Cache create: 0; Cache read: 0; Total: 236,\n", " 'stop_reason': 'stop_sequence',\n", " 'stop_sequence': '2'}" ] @@ -1647,9 +1648,9 @@ "| Metric | Count | Cost (USD) |\n", "|--------|------:|-----:|\n", "| Input tokens | 94 | 0.000282 |\n", - "| Output tokens | 138 | 0.002070 |\n", + "| Output tokens | 142 | 0.002130 |\n", "| Cache tokens | 0 | 0.000000 |\n", - "| **Total** | **232** | **$0.002352** |" + "| **Total** | **236** | **$0.002412** |" ], "text/plain": [ "<__main__.Client>" @@ -1789,12 +1790,12 @@ { "data": { "text/markdown": [ - "ToolUseBlock(id='toolu_01JV5wzXWQebRCZxkXUMJVdN', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", + "ToolUseBlock(id='toolu_016oVVBcvAa7EKGNPQfjFim8', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", "\n", "
\n", "\n", - "- id: `msg_01NnNE8243ogZsZCuoT7DEbc`\n", - "- content: `[{'id': 'toolu_01JV5wzXWQebRCZxkXUMJVdN', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]`\n", + "- id: `msg_01Aq87E19rntCZyPFzBVfXGG`\n", + "- content: `[{'id': 'toolu_016oVVBcvAa7EKGNPQfjFim8', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `tool_use`\n", @@ -1805,7 +1806,7 @@ "
" ], "text/plain": [ - "Message(id='msg_01NnNE8243ogZsZCuoT7DEbc', content=[ToolUseBlock(id='toolu_01JV5wzXWQebRCZxkXUMJVdN', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 442; Out: 53; Cache create: 0; Cache read: 0; Total: 495)" + "Message(id='msg_01Aq87E19rntCZyPFzBVfXGG', content=[ToolUseBlock(id='toolu_016oVVBcvAa7EKGNPQfjFim8', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 442; Out: 53; Cache create: 0; Cache read: 0; Total: 495)" ] }, "execution_count": null, @@ -1889,7 +1890,7 @@ "data": { "text/plain": [ "{'type': 'tool_result',\n", - " 'tool_use_id': 'toolu_01JV5wzXWQebRCZxkXUMJVdN',\n", + " 'tool_use_id': 'toolu_016oVVBcvAa7EKGNPQfjFim8',\n", " 'content': '7063474'}" ] }, @@ -1968,10 +1969,10 @@ "data": { "text/plain": [ "[{'role': 'assistant',\n", - " 'content': [ToolUseBlock(id='toolu_01JV5wzXWQebRCZxkXUMJVdN', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')]},\n", + " 'content': [ToolUseBlock(id='toolu_016oVVBcvAa7EKGNPQfjFim8', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')]},\n", " {'role': 'user',\n", " 'content': [{'type': 'tool_result',\n", - " 'tool_use_id': 'toolu_01JV5wzXWQebRCZxkXUMJVdN',\n", + " 'tool_use_id': 'toolu_016oVVBcvAa7EKGNPQfjFim8',\n", " 'content': '7063474'}]}]" ] }, @@ -2173,12 +2174,12 @@ { "data": { "text/markdown": [ - "ToolUseBlock(id='toolu_01S3Djzi8XkonrgTzwHg7Jym', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", + "ToolUseBlock(id='toolu_01Ubv6pLSLrae1cBDGqW9NGJ', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", "\n", "
\n", "\n", - "- id: `msg_01NFfWp2pAHvd6pC94dAajCK`\n", - "- content: `[{'id': 'toolu_01S3Djzi8XkonrgTzwHg7Jym', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]`\n", + "- id: `msg_01GzHYdKrFK67XT7yemGyPbt`\n", + "- content: `[{'id': 'toolu_01Ubv6pLSLrae1cBDGqW9NGJ', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `tool_use`\n", @@ -2189,7 +2190,7 @@ "
" ], "text/plain": [ - "Message(id='msg_01NFfWp2pAHvd6pC94dAajCK', content=[ToolUseBlock(id='toolu_01S3Djzi8XkonrgTzwHg7Jym', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 438; Out: 57; Cache create: 0; Cache read: 0; Total: 495)" + "Message(id='msg_01GzHYdKrFK67XT7yemGyPbt', content=[ToolUseBlock(id='toolu_01Ubv6pLSLrae1cBDGqW9NGJ', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 438; Out: 57; Cache create: 0; Cache read: 0; Total: 495)" ] }, "execution_count": null, @@ -2291,14 +2292,14 @@ { "data": { "text/markdown": [ - "ToolUseBlock(id='toolu_01Hg7DFuLyNaDkuo6wMtbuer', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", + "ToolUseBlock(id='toolu_019PYDYhWKwaBtgJTPKmiCb3', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')\n", "\n", "| Metric | Count | Cost (USD) |\n", "|--------|------:|-----:|\n", "| Input tokens | 2,981 | 0.008943 |\n", - "| Output tokens | 404 | 0.006060 |\n", + "| Output tokens | 408 | 0.006120 |\n", "| Cache tokens | 0 | 0.000000 |\n", - "| **Total** | **3,385** | **$0.015003** |" + "| **Total** | **3,389** | **$0.015063** |" ], "text/plain": [ "<__main__.Client>" @@ -2613,7 +2614,7 @@ { "data": { "text/plain": [ - "ToolUseBlock(id='toolu_013w7fSL1o74APPE1P4KkDNm', input={'book': {'title': 'War and Peace', 'pages': 950}, 'percent': 50}, name='find_page', type='tool_use')" + "ToolUseBlock(id='toolu_01HcGcJQHK6DJFGCXPobfooF', input={'book': {'title': 'War and Peace', 'pages': 950}, 'percent': 50}, name='find_page', type='tool_use')" ] }, "execution_count": null, @@ -2876,8 +2877,8 @@ "\n", "
\n", "\n", - "- id: `msg_016fbzScjG6YmZ4dLRpsubh8`\n", - "- content: `[{'text': 'Your name is Jeremy.', 'type': 'text'}]`\n", + "- id: `msg_01Li69uBFVWrrHntEJ7esrDJ`\n", + "- content: `[{'citations': None, 'text': 'Your name is Jeremy.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", @@ -2888,7 +2889,7 @@ "
" ], "text/plain": [ - "Message(id='msg_016fbzScjG6YmZ4dLRpsubh8', content=[TextBlock(text='Your name is Jeremy.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 41; Out: 8; Cache create: 0; Cache read: 0; Total: 49)" + "Message(id='msg_01Li69uBFVWrrHntEJ7esrDJ', content=[TextBlock(citations=None, text='Your name is Jeremy.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 41; Out: 8; Cache create: 0; Cache read: 0; Total: 49)" ] }, "execution_count": null, @@ -2954,8 +2955,8 @@ "\n", "
\n", "\n", - "- id: `msg_016fbzScjG6YmZ4dLRpsubh8`\n", - "- content: `[{'text': 'Your name is Jeremy.', 'type': 'text'}]`\n", + "- id: `msg_01Li69uBFVWrrHntEJ7esrDJ`\n", + "- content: `[{'citations': None, 'text': 'Your name is Jeremy.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", @@ -2966,7 +2967,7 @@ "
" ], "text/plain": [ - "Message(id='msg_016fbzScjG6YmZ4dLRpsubh8', content=[TextBlock(text='Your name is Jeremy.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 41; Out: 8; Cache create: 0; Cache read: 0; Total: 49)" + "Message(id='msg_01Li69uBFVWrrHntEJ7esrDJ', content=[TextBlock(citations=None, text='Your name is Jeremy.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 41; Out: 8; Cache create: 0; Cache read: 0; Total: 49)" ] }, "execution_count": null, @@ -2991,8 +2992,8 @@ "\n", "
\n", "\n", - "- id: `msg_012D1LGE7Q821mHsDxwgoxJJ`\n", - "- content: `[{'text': \"According to Douglas Adams,42. But seriously: To find purpose, create meaning, love, grow, and make a positive impact while experiencing life's journey.\", 'type': 'text'}]`\n", + "- id: `msg_017udLkUxGjdmrUEH1saVEA6`\n", + "- content: `[{'citations': None, 'text': \"According to Douglas Adams,42. But seriously: To find purpose, create meaning, love, grow, and make a positive impact while experiencing life's journey.\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", @@ -3003,7 +3004,7 @@ "
" ], "text/plain": [ - "Message(id='msg_012D1LGE7Q821mHsDxwgoxJJ', content=[TextBlock(text=\"According to Douglas Adams,42. But seriously: To find purpose, create meaning, love, grow, and make a positive impact while experiencing life's journey.\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 69; Out: 30; Cache create: 0; Cache read: 0; Total: 99)" + "Message(id='msg_017udLkUxGjdmrUEH1saVEA6', content=[TextBlock(citations=None, text=\"According to Douglas Adams,42. But seriously: To find purpose, create meaning, love, grow, and make a positive impact while experiencing life's journey.\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 69; Out: 30; Cache create: 0; Cache read: 0; Total: 99)" ] }, "execution_count": null, @@ -3059,23 +3060,23 @@ { "data": { "text/markdown": [ - "To connect with others, pursue knowledge, overcome challenges, express creativity, help those in need, appreciate beauty, find joy in small moments, leave the world better than we found it, and discover our own unique path while respecting all living things.\n", + "To build meaningful relationships, pursue passions, learn continuously, help others, appreciate beauty, overcome challenges, leave a positive legacy, and find personal fulfillment through both small daily moments and larger life achievements. Each person ultimately defines their own unique meaning.\n", "\n", "
\n", "\n", - "- id: `msg_01AeYa7TorVomph7nZzXeaNG`\n", - "- content: `[{'text': 'To connect with others, pursue knowledge, overcome challenges, express creativity, help those in need, appreciate beauty, find joy in small moments, leave the world better than we found it, and discover our own unique path while respecting all living things.', 'type': 'text'}]`\n", + "- id: `msg_01Ug9aQm74iLdxCrSKFx9cec`\n", + "- content: `[{'citations': None, 'text': 'To build meaningful relationships, pursue passions, learn continuously, help others, appreciate beauty, overcome challenges, leave a positive legacy, and find personal fulfillment through both small daily moments and larger life achievements. Each person ultimately defines their own unique meaning.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 105, 'output_tokens': 53}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 105, 'output_tokens': 54}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01AeYa7TorVomph7nZzXeaNG', content=[TextBlock(text='To connect with others, pursue knowledge, overcome challenges, express creativity, help those in need, appreciate beauty, find joy in small moments, leave the world better than we found it, and discover our own unique path while respecting all living things.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 105; Out: 53; Cache create: 0; Cache read: 0; Total: 158)" + "Message(id='msg_01Ug9aQm74iLdxCrSKFx9cec', content=[TextBlock(citations=None, text='To build meaningful relationships, pursue passions, learn continuously, help others, appreciate beauty, overcome challenges, leave a positive legacy, and find personal fulfillment through both small daily moments and larger life achievements. Each person ultimately defines their own unique meaning.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 105; Out: 54; Cache create: 0; Cache read: 0; Total: 159)" ] }, "execution_count": null, @@ -3106,7 +3107,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Hello Jeremy! Nice to meet you. How are you today?" + "Hi Jeremy! Nice to meet you. How are you today?" ] } ], @@ -3125,7 +3126,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "According to Douglas Adams, it's 42. More seriously: to find purpose, grow, love, and make a positive impact while experiencing what existence has to offer." + "According to Douglas Adams, 42. More seriously: to find purpose, create meaning, and positively impact others while experiencing joy and growth." ] } ], @@ -3191,8 +3192,8 @@ "\n", "
\n", "\n", - "- id: `msg_015vfjkFwE4RJ4DyPVmGoiA9`\n", - "- content: `[{'text': 'Let me calculate that sum for you.', 'type': 'text'}, {'id': 'toolu_01RKEKvgVY5gev8W4htCWUAn', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]`\n", + "- id: `msg_01RVMXrHxsfv9x83mPtF57B9`\n", + "- content: `[{'citations': None, 'text': 'Let me calculate that sum for you.', 'type': 'text'}, {'id': 'toolu_01NAvzdsD8Aj7tuiFu3TYY7F', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `tool_use`\n", @@ -3203,7 +3204,7 @@ "
" ], "text/plain": [ - "Message(id='msg_015vfjkFwE4RJ4DyPVmGoiA9', content=[TextBlock(text='Let me calculate that sum for you.', type='text'), ToolUseBlock(id='toolu_01RKEKvgVY5gev8W4htCWUAn', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 437; Out: 81; Cache create: 0; Cache read: 0; Total: 518)" + "Message(id='msg_01RVMXrHxsfv9x83mPtF57B9', content=[TextBlock(citations=None, text='Let me calculate that sum for you.', type='text'), ToolUseBlock(id='toolu_01NAvzdsD8Aj7tuiFu3TYY7F', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 437; Out: 81; Cache create: 0; Cache read: 0; Total: 518)" ] }, "execution_count": null, @@ -3234,23 +3235,23 @@ { "data": { "text/markdown": [ - "The sum of 604542 and 6458932 is 7063474.\n", + "604542 + 6458932 = 7063474\n", "\n", "
\n", "\n", - "- id: `msg_01Rf4k15MbftnqusU4TUv63k`\n", - "- content: `[{'text': 'The sum of 604542 and 6458932 is 7063474.', 'type': 'text'}]`\n", + "- id: `msg_014cRkz6ddr4wSkqZ9e3E3gh`\n", + "- content: `[{'citations': None, 'text': '604542 + 6458932 = 7063474', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 532, 'output_tokens': 23}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 532, 'output_tokens': 18}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01Rf4k15MbftnqusU4TUv63k', content=[TextBlock(text='The sum of 604542 and 6458932 is 7063474.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 532; Out: 23; Cache create: 0; Cache read: 0; Total: 555)" + "Message(id='msg_014cRkz6ddr4wSkqZ9e3E3gh', content=[TextBlock(citations=None, text='604542 + 6458932 = 7063474', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 532; Out: 18; Cache create: 0; Cache read: 0; Total: 550)" ] }, "execution_count": null, @@ -3308,23 +3309,23 @@ { "data": { "text/markdown": [ - "Let me help you find the page number that represents 75% (three quarters) of your Tao Te Ching edition.\n", + "Let me find the page number that represents 75% of your book.\n", "\n", "
\n", "\n", - "- id: `msg_01JfT3QkeB6HshMY6gCWXGon`\n", - "- content: `[{'text': 'Let me help you find the page number that represents 75% (three quarters) of your Tao Te Ching edition.', 'type': 'text'}, {'id': 'toolu_01TuNUABauJUfXkeEqbCoRMV', 'input': {'book': {'title': 'Tao Te Ching', 'pages': 80}, 'percent': 75}, 'name': 'find_page', 'type': 'tool_use'}]`\n", + "- id: `msg_01XuKrTorkbv9tJSNhTyx25F`\n", + "- content: `[{'citations': None, 'text': 'Let me find the page number that represents 75% of your book.', 'type': 'text'}, {'id': 'toolu_01DVcCndJJL83zK9VfjpeS4v', 'input': {'book': {'title': 'Tao Te Ching', 'pages': 80}, 'percent': 75}, 'name': 'find_page', 'type': 'tool_use'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `tool_use`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 547, 'output_tokens': 115}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 547, 'output_tokens': 102}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01JfT3QkeB6HshMY6gCWXGon', content=[TextBlock(text='Let me help you find the page number that represents 75% (three quarters) of your Tao Te Ching edition.', type='text'), ToolUseBlock(id='toolu_01TuNUABauJUfXkeEqbCoRMV', input={'book': {'title': 'Tao Te Ching', 'pages': 80}, 'percent': 75}, name='find_page', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 547; Out: 115; Cache create: 0; Cache read: 0; Total: 662)" + "Message(id='msg_01XuKrTorkbv9tJSNhTyx25F', content=[TextBlock(citations=None, text='Let me find the page number that represents 75% of your book.', type='text'), ToolUseBlock(id='toolu_01DVcCndJJL83zK9VfjpeS4v', input={'book': {'title': 'Tao Te Ching', 'pages': 80}, 'percent': 75}, name='find_page', type='tool_use')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 547; Out: 102; Cache create: 0; Cache read: 0; Total: 649)" ] }, "execution_count": null, @@ -3355,23 +3356,23 @@ { "data": { "text/markdown": [ - "Page 60 marks three quarters of the way through your 80-page edition of the Tao Te Ching.\n", + "Three quarters (75%) of the way through your 80-page edition of Tao Te Ching would be page 60.\n", "\n", "
\n", "\n", - "- id: `msg_01JHf9XzCe69PFwrf1zNmoq1`\n", - "- content: `[{'text': 'Page 60 marks three quarters of the way through your 80-page edition of the Tao Te Ching.', 'type': 'text'}]`\n", + "- id: `msg_01DmgTApLPCD6N4nwLLyBiDk`\n", + "- content: `[{'citations': None, 'text': 'Three quarters (75%) of the way through your 80-page edition of Tao Te Ching would be page 60.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 674, 'output_tokens': 31}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 661, 'output_tokens': 33}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01JHf9XzCe69PFwrf1zNmoq1', content=[TextBlock(text='Page 60 marks three quarters of the way through your 80-page edition of the Tao Te Ching.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 674; Out: 31; Cache create: 0; Cache read: 0; Total: 705)" + "Message(id='msg_01DmgTApLPCD6N4nwLLyBiDk', content=[TextBlock(citations=None, text='Three quarters (75%) of the way through your 80-page edition of Tao Te Ching would be page 60.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 661; Out: 33; Cache create: 0; Cache read: 0; Total: 694)" ] }, "execution_count": null, @@ -3453,26 +3454,26 @@ { "data": { "text/markdown": [ - "Page 60 marks three quarters of the way through your 80-page edition of the Tao Te Ching.\n", + "Three quarters (75%) of the way through your 80-page edition of Tao Te Ching would be page 60.\n", "\n", "
\n", "History\n", "\n", "**user**: H\n", "\n", - "**assistant**: Let me help you find the page number that represents 75% (three quarters) of your Tao Te Ching edition.\n", + "**assistant**: Let me find the page number that represents 75% of your book.\n", "\n", "**user**: 60\n", "\n", - "**assistant**: Page 60 marks three quarters of the way through your 80-page edition of the Tao Te Ching.\n", + "**assistant**: Three quarters (75%) of the way through your 80-page edition of Tao Te Ching would be page 60.\n", "
\n", "\n", "| Metric | Count | Cost (USD) |\n", "|--------|------:|-----:|\n", - "| Input tokens | 1,221 | 0.003663 |\n", - "| Output tokens | 146 | 0.002190 |\n", + "| Input tokens | 1,208 | 0.003624 |\n", + "| Output tokens | 135 | 0.002025 |\n", "| Cache tokens | 0 | 0.000000 |\n", - "| **Total** | **1,367** | **$0.005853** |" + "| **Total** | **1,343** | **$0.005649** |" ], "text/plain": [ "<__main__.Chat>" @@ -3592,8 +3593,8 @@ "\n", "
\n", "\n", - "- id: `msg_01NKAeLiVC5phZ2eJ54MfVQj`\n", - "- content: `[{'text': 'In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', 'type': 'text'}]`\n", + "- id: `msg_01UT6vURZKEezMrBmZjK8zUw`\n", + "- content: `[{'citations': None, 'text': 'In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", @@ -3604,7 +3605,7 @@ "
" ], "text/plain": [ - "Message(id='msg_01NKAeLiVC5phZ2eJ54MfVQj', content=[TextBlock(text='In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 47; Cache create: 0; Cache read: 0; Total: 157)" + "Message(id='msg_01UT6vURZKEezMrBmZjK8zUw', content=[TextBlock(citations=None, text='In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 47; Cache create: 0; Cache read: 0; Total: 157)" ] }, "execution_count": null, @@ -3647,8 +3648,8 @@ "\n", "
\n", "\n", - "- id: `msg_016WMiRufVaTD42gAvTdLrh2`\n", - "- content: `[{'text': 'In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', 'type': 'text'}]`\n", + "- id: `msg_01PATo4tC42d7E9NbACT4dKD`\n", + "- content: `[{'citations': None, 'text': 'In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", @@ -3659,7 +3660,7 @@ "
" ], "text/plain": [ - "Message(id='msg_016WMiRufVaTD42gAvTdLrh2', content=[TextBlock(text='In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 47; Cache create: 0; Cache read: 0; Total: 157)" + "Message(id='msg_01PATo4tC42d7E9NbACT4dKD', content=[TextBlock(citations=None, text='In the background of this adorable Cavalier King Charles Spaniel puppy, there are purple/lavender colored flowers, which appear to be some type of aster or daisy-like blooms.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 47; Cache create: 0; Cache read: 0; Total: 157)" ] }, "execution_count": null, @@ -3679,7 +3680,6 @@ "metadata": {}, "outputs": [], "source": [ - "#| exports\n", "def contents(r):\n", " \"Helper to get the contents from Claude response `r`.\"\n", " blk = find_block(r)\n", @@ -3858,8 +3858,8 @@ "\n", "
\n", "\n", - "- id: `msg_01Vyqa2uSguRnwao2HvwxTH1`\n", - "- content: `[{'text': 'Hello Jeremy! Nice to meet you. How are you today?', 'type': 'text'}]`\n", + "- id: `msg_01V6DFy3tc1BbCFSyvhYYr2j`\n", + "- content: `[{'citations': None, 'text': 'Hello Jeremy! Nice to meet you. How are you today?', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", @@ -3870,7 +3870,7 @@ "
" ], "text/plain": [ - "Message(id='msg_01Vyqa2uSguRnwao2HvwxTH1', content=[TextBlock(text='Hello Jeremy! Nice to meet you. How are you today?', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 20; Out: 16; Cache create: 0; Cache read: 0; Total: 36)" + "Message(id='msg_01V6DFy3tc1BbCFSyvhYYr2j', content=[TextBlock(citations=None, text='Hello Jeremy! Nice to meet you. How are you today?', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 20; Out: 16; Cache create: 0; Cache read: 0; Total: 36)" ] }, "execution_count": null, @@ -3899,23 +3899,23 @@ { "data": { "text/markdown": [ - "I notice you've shared a long block of \"Lorem ipsum\" placeholder text. While I can process this text, perhaps you'd like to have a more meaningful conversation? Is there something specific you'd like to discuss or ask about?\n", + "I notice you've shared a very long block of \"Lorem ipsum\" placeholder text. While I can process this text, it doesn't contain any meaningful content for us to discuss. Is there something specific you'd like to talk about or ask me? I'm happy to help with any real questions or topics you have in mind.\n", "\n", "
\n", "\n", - "- id: `msg_016mAL1zuve8qngNZF28nz11`\n", - "- content: `[{'text': 'I notice you\\'ve shared a long block of \"Lorem ipsum\" placeholder text. While I can process this text, perhaps you\\'d like to have a more meaningful conversation? Is there something specific you\\'d like to discuss or ask about?', 'type': 'text'}]`\n", + "- id: `msg_01DdD47RTm5gnmqnWzYrXxVq`\n", + "- content: `[{'citations': None, 'text': 'I notice you\\'ve shared a very long block of \"Lorem ipsum\" placeholder text. While I can process this text, it doesn\\'t contain any meaningful content for us to discuss. Is there something specific you\\'d like to talk about or ask me? I\\'m happy to help with any real questions or topics you have in mind.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 1083, 'cache_read_input_tokens': 0, 'input_tokens': 4, 'output_tokens': 50}`\n", + "- usage: `{'cache_creation_input_tokens': 1083, 'cache_read_input_tokens': 0, 'input_tokens': 4, 'output_tokens': 69}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_016mAL1zuve8qngNZF28nz11', content=[TextBlock(text='I notice you\\'ve shared a long block of \"Lorem ipsum\" placeholder text. While I can process this text, perhaps you\\'d like to have a more meaningful conversation? Is there something specific you\\'d like to discuss or ask about?', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 4; Out: 50; Cache create: 1083; Cache read: 0; Total: 1137)" + "Message(id='msg_01DdD47RTm5gnmqnWzYrXxVq', content=[TextBlock(citations=None, text='I notice you\\'ve shared a very long block of \"Lorem ipsum\" placeholder text. While I can process this text, it doesn\\'t contain any meaningful content for us to discuss. Is there something specific you\\'d like to talk about or ask me? I\\'m happy to help with any real questions or topics you have in mind.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 4; Out: 69; Cache create: 1083; Cache read: 0; Total: 1156)" ] }, "execution_count": null, @@ -3944,23 +3944,23 @@ { "data": { "text/markdown": [ - "No problem at all! These things happen. It's good we can laugh about a runaway lorem ipsum generator! What would you like to chat about instead?\n", + "No problem at all! It happens! At least it wasn't a cat walking across your keyboard 😄 What would you like to chat about?\n", "\n", "
\n", "\n", - "- id: `msg_01Lpfs3LEPaUfKptJcSqxCP6`\n", - "- content: `[{'text': \"No problem at all! These things happen. It's good we can laugh about a runaway lorem ipsum generator! What would you like to chat about instead?\", 'type': 'text'}]`\n", + "- id: `msg_011kLDePUodkyWXjUtLH2dAC`\n", + "- content: `[{'citations': None, 'text': \"No problem at all! It happens! At least it wasn't a cat walking across your keyboard 😄 What would you like to chat about?\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 68, 'cache_read_input_tokens': 1083, 'input_tokens': 4, 'output_tokens': 35}`\n", + "- usage: `{'cache_creation_input_tokens': 87, 'cache_read_input_tokens': 1083, 'input_tokens': 4, 'output_tokens': 34}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01Lpfs3LEPaUfKptJcSqxCP6', content=[TextBlock(text=\"No problem at all! These things happen. It's good we can laugh about a runaway lorem ipsum generator! What would you like to chat about instead?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 4; Out: 35; Cache create: 68; Cache read: 1083; Total: 1190)" + "Message(id='msg_011kLDePUodkyWXjUtLH2dAC', content=[TextBlock(citations=None, text=\"No problem at all! It happens! At least it wasn't a cat walking across your keyboard 😄 What would you like to chat about?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 4; Out: 34; Cache create: 87; Cache read: 1083; Total: 1208)" ] }, "execution_count": null, @@ -4024,7 +4024,7 @@ { "cell_type": "code", "execution_count": null, - "id": "0436c60f", + "id": "7b3779b4", "metadata": {}, "outputs": [ { @@ -4033,9 +4033,9 @@ "{'type': 'document',\n", " 'source': {'type': 'text',\n", " 'media_type': 'text/plain',\n", - " 'data': 'The grass is green. The sky is blue.'},\n", + " 'data': 'Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n*Claudette* is a wrapper for Anthropic’s [Python\\nSDK](https://github.com/anthropics/anthropic-sdk-python).\\n\\nThe SDK works well, but it is quite low level – it leaves the developer\\nto do a lot of stuff manually. That’s a lot of extra work and\\nboilerplate! Claudette automates pretty much everything that can be\\nautomated, whilst providing full control. Amongst the features provided:\\n\\n- A [`Chat`](https://claudette.answer.ai/core.html#chat) class that\\n creates stateful dialogs\\n- Support for *prefill*, which tells Claude what to use as the first few\\n words of its response\\n- Convenient image support\\n- Simple and convenient support for Claude’s new Tool Use API.\\n\\nYou’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\nNote that this library is the first ever “literate nbdev” p'},\n", " 'citations': {'enabled': True},\n", - " 'title': 'My Document',\n", + " 'title': 'Claudette LLM Context',\n", " 'context': 'This is a trustworthy document.'}" ] }, @@ -4045,76 +4045,17 @@ } ], "source": [ - "doc = mk_doc(\"The grass is green. The sky is blue.\", title=\"My Document\", context=\"This is a trustworthy document.\", citation=True)\n", + "llms_ctx = xget(\"https://claudette.answer.ai/llms-ctx.txt\").text[:2_048]\n", + "doc = mk_doc(llms_ctx, title=\"Claudette LLM Context\", context=\"This is a trustworthy document.\", citation=True)\n", "doc" ] }, - { - "cell_type": "markdown", - "id": "1455effe", - "metadata": {}, - "source": [ - "Let's use the document with a message." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6a77d714", - "metadata": {}, - "outputs": [], - "source": [ - "c = Chat(model)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "eacea213", - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "```json\n", - "{ 'content': [ { 'citations': {'enabled': True},\n", - " 'context': 'This is a trustworthy document.',\n", - " 'source': { 'data': 'The grass is green. The sky is blue.',\n", - " 'media_type': 'text/plain',\n", - " 'type': 'text'},\n", - " 'title': 'My Document',\n", - " 'type': 'document'},\n", - " {'text': 'What color is the grass and sky?', 'type': 'text'}],\n", - " 'role': 'user'}\n", - "```" - ], - "text/plain": [ - "{'role': 'user',\n", - " 'content': [{'type': 'document',\n", - " 'source': {'type': 'text',\n", - " 'media_type': 'text/plain',\n", - " 'data': 'The grass is green. The sky is blue.'},\n", - " 'citations': {'enabled': True},\n", - " 'title': 'My Document',\n", - " 'context': 'This is a trustworthy document.'},\n", - " {'type': 'text', 'text': 'What color is the grass and sky?'}]}" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "mk_msg([doc, \"What color is the grass and sky?\"])" - ] - }, { "cell_type": "markdown", "id": "21a52343", "metadata": {}, "source": [ - "The response contains text and citations alternating back and forth." + "Let's use the document with a message. The response contains text and citations alternating back and forth." ] }, { @@ -4126,23 +4067,23 @@ { "data": { "text/markdown": [ - "Based on the provided document,\n", + "Based on the provided document, I can give you a comprehensive explanation of Claudette:\n", "\n", "
\n", "\n", - "- id: `msg_01W9SvULG3mdvoUProc7GEJo`\n", - "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': 'The grass is green. ', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 20, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'the grass is green', 'type': 'text'}, {'citations': None, 'text': ' and ', 'type': 'text'}, {'citations': [{'cited_text': 'The sky is blue.', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 20, 'type': 'char_location'}], 'text': 'the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", + "- id: `msg_01MRCVSLwBtZyZvjZgrdMcGH`\n", + "- content: `[{'citations': None, 'text': 'Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1187, 'start_char_index': 323, 'type': 'char_location'}], 'text': \"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", 'type': 'text'}, {'citations': None, 'text': '\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1989, 'start_char_index': 1854, 'type': 'char_location'}], 'text': 'To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 610, 'output_tokens': 52}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1232, 'output_tokens': 409}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01W9SvULG3mdvoUProc7GEJo', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" + "Message(id='msg_01MRCVSLwBtZyZvjZgrdMcGH', content=[TextBlock(citations=None, text='Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1187, start_char_index=323, type='char_location')], text=\"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", type='text'), TextBlock(citations=None, text='\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1989, start_char_index=1854, type='char_location')], text='To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 1232; Out: 409; Cache create: 0; Cache read: 0; Total: 1641)" ] }, "execution_count": null, @@ -4151,7 +4092,8 @@ } ], "source": [ - "q = \"What color is the grass and sky?\"\n", + "c = Chat(model)\n", + "q = \"What is Claudette?\"\n", "c([doc, q])" ] }, @@ -4175,11 +4117,14 @@ " \"\"\"Render a Claude message with citations as markdown.\"\"\"\n", " result = []\n", " for block in msg.content:\n", + " result.append(block.text)\n", " if block.citations:\n", " for c in block.citations:\n", - " result.append(f\"\\n> {c.cited_text}\\n\\n\")\n", - " else:\n", - " result.append(block.text)\n", + " cite_desc = f'{c.document_title} - start: {c.start_char_index} end: {c.end_char_index}'\n", + " lines = c.cited_text.splitlines()\n", + " quoted_lines = '\\n'.join(f\"> {ln}\" for ln in lines)\n", + " f = f\"\\n> {cite_desc}\\n> \\n> {quoted_lines}\\n\\n\"\n", + " result.append(f)\n", " return ''.join(result)" ] }, @@ -4224,29 +4169,98 @@ { "data": { "text/markdown": [ - "Based on the provided document, \n", - "> The grass is green. \n", + "Based on the provided document, I can give you a comprehensive explanation of Claudette:\n", + "\n", + "Claudette is a Python library that serves as a wrapper for Anthropic's Claude API, providing a higher-level interface for creating AI applications. It automates common patterns while still maintaining full control, and includes features like stateful chat, prefill support, image handling, and streamlined tool use.\n", + "> Claudette LLM Context - start: 0 end: 323\n", + "> \n", + "> > Claudette LLM Context - start: 1187 end: 1539\n", + "> \n", + "> > *Claudette* is a wrapper for Anthropic’s [Python\n", + "> SDK](https://github.com/anthropics/anthropic-sdk-python).\n", + "> \n", + "> The SDK works well, but it is quite low level – it leaves the developer\n", + "> to do a lot of stuff manually. That’s a lot of extra work and\n", + "> boilerplate! Claudette automates pretty much everything that can be\n", + "> automated, whilst providing full control. \n", + "\n", + "\n", + "\n", + "Key features of Claudette include:\n", + "\n", + "- A `Chat` class for creating stateful dialogs\n", + "- Prefill support that allows you to specify the first few words of Claude's response\n", + "- Convenient image support\n", + "- Simple and streamlined support for Claude's Tool Use API\n", + "> Claudette LLM Context - start: 1539 end: 1854\n", + "> \n", + "> > Amongst the features provided:\n", + "> \n", + "> - A [`Chat`](https://claudette.answer.ai/core.html#chat) class that\n", + "> creates stateful dialogs\n", + "> - Support for *prefill*, which tells Claude what to use as the first few\n", + "> words of its response\n", + "> - Convenient image support\n", + "> - Simple and convenient support for Claude’s new Tool Use API.\n", + "> \n", + "\n", + "\n", + "\n", + "Important technical details:\n", + "\n", + "- It's designed to work with Claude 3 models (Opus, Sonnet, Haiku)\n", + "- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\n", + "- The library offers both synchronous and asynchronous interfaces\n", + "- Image support is available but only on compatible models (not Haiku)\n", + "> Claudette LLM Context - start: 323 end: 1187\n", + "> \n", + "> > \">Things to remember when using Claudette:\n", + "> \n", + "> - You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\n", + "> - Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\n", + "> - The library provides both synchronous and asynchronous interfaces\n", + "> - Use `Chat()` for maintaining conversation state and handling tool interactions\n", + "> - When using tools, the library automatically handles the request/response loop\n", + "> - Image support is built in but only available on compatible models (not Haiku)# claudette\n", + "> \n", + "> \n", + "> \n", + "> > **NB**: If you are reading this in GitHub’s readme, we recommend you\n", + "> > instead read the much more nicely formatted [documentation\n", + "> > format](https://claudette.answer.ai/) of this tutorial.\n", + "> \n", + "\n", + "\n", + "\n", + "To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.\n", + "> Claudette LLM Context - start: 1854 end: 1989\n", + "> \n", + "> > You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\n", + "> key provided to you by Anthropic in order to use this library.\n", + "> \n", "\n", - " and \n", - "> The sky is blue.\n", "\n", - ".\n", "\n", "
\n", "\n", - "- id: `msg_01AQsSJf4Xd96ojvWVGQSx4C`\n", - "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': 'The grass is green. ', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 20, 'start_char_index': 0, 'type': 'char_location'}], 'text': 'the grass is green', 'type': 'text'}, {'citations': None, 'text': ' and ', 'type': 'text'}, {'citations': [{'cited_text': 'The sky is blue.', 'document_index': 0, 'document_title': 'My Document', 'end_char_index': 36, 'start_char_index': 20, 'type': 'char_location'}], 'text': 'the sky is blue', 'type': 'text'}, {'citations': None, 'text': '.', 'type': 'text'}]`\n", + "- id: `msg_01BXwf9cCbfDrsEHwziVeXHY`\n", + "- content: `[{'citations': None, 'text': 'Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1187, 'start_char_index': 323, 'type': 'char_location'}], 'text': \"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", 'type': 'text'}, {'citations': None, 'text': '\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1989, 'start_char_index': 1854, 'type': 'char_location'}], 'text': 'To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 610, 'output_tokens': 52}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 1232, 'output_tokens': 408}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01AQsSJf4Xd96ojvWVGQSx4C', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The grass is green. ', document_index=0, document_title='My Document', end_char_index=20, start_char_index=0, type='char_location')], text='the grass is green', type='text'), TextBlock(citations=None, text=' and ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='The sky is blue.', document_index=0, document_title='My Document', end_char_index=36, start_char_index=20, type='char_location')], text='the sky is blue', type='text'), TextBlock(citations=None, text='.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 610; Out: 52; Cache create: 0; Cache read: 0; Total: 662)" + "Message(id='msg_01BXwf9cCbfDrsEHwziVeXHY', content=[TextBlock(citations=None, text='Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1187, start_char_index=323, type='char_location')], text=\"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", type='text'), TextBlock(citations=None, text='\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1989, start_char_index=1854, type='char_location')], text='To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 1232; Out: 408; Cache create: 0; Cache read: 0; Total: 1640)" ] }, "execution_count": null, @@ -4256,50 +4270,118 @@ ], "source": [ "c = Chat(model)\n", - "q = \"What color is the grass and sky?\"\n", - "c([doc, q])" + "q = \"What is Claudette?\"\n", + "r = c([doc, q])\n", + "r" ] }, { "cell_type": "code", "execution_count": null, - "id": "c09e70ce", + "id": "63c36f2f", "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "Based on the provided document, \n", - "> The grass is green. \n", - "\n", - " and \n", - "> The sky is blue.\n", - "\n", - ".\n", + "Hello! How can I help you today?\n", "\n", "
\n", "History\n", "\n", "**user**: *Media Type - document*\n", "\n", - "**assistant**: Based on the provided document, \n", - "> The grass is green. \n", + "**assistant**: Based on the provided document, I can give you a comprehensive explanation of Claudette:\n", "\n", - " and \n", - "> The sky is blue.\n", + "Claudette is a Python library that serves as a wrapper for Anthropic's Claude API, providing a higher-level interface for creating AI applications. It automates common patterns while still maintaining full control, and includes features like stateful chat, prefill support, image handling, and streamlined tool use.\n", + "> Claudette LLM Context - start: 0 end: 323\n", + "> \n", + "> > Claudette LLM Context - start: 1187 end: 1539\n", + "> \n", + "> > *Claudette* is a wrapper for Anthropic’s [Python\n", + "> SDK](https://github.com/anthropics/anthropic-sdk-python).\n", + "> \n", + "> The SDK works well, but it is quite low level – it leaves the developer\n", + "> to do a lot of stuff manually. That’s a lot of extra work and\n", + "> boilerplate! Claudette automates pretty much everything that can be\n", + "> automated, whilst providing full control. \n", + "\n", + "\n", + "\n", + "Key features of Claudette include:\n", + "\n", + "- A `Chat` class for creating stateful dialogs\n", + "- Prefill support that allows you to specify the first few words of Claude's response\n", + "- Convenient image support\n", + "- Simple and streamlined support for Claude's Tool Use API\n", + "> Claudette LLM Context - start: 1539 end: 1854\n", + "> \n", + "> > Amongst the features provided:\n", + "> \n", + "> - A [`Chat`](https://claudette.answer.ai/core.html#chat) class that\n", + "> creates stateful dialogs\n", + "> - Support for *prefill*, which tells Claude what to use as the first few\n", + "> words of its response\n", + "> - Convenient image support\n", + "> - Simple and convenient support for Claude’s new Tool Use API.\n", + "> \n", + "\n", + "\n", + "\n", + "Important technical details:\n", + "\n", + "- It's designed to work with Claude 3 models (Opus, Sonnet, Haiku)\n", + "- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\n", + "- The library offers both synchronous and asynchronous interfaces\n", + "- Image support is available but only on compatible models (not Haiku)\n", + "> Claudette LLM Context - start: 323 end: 1187\n", + "> \n", + "> > \">Things to remember when using Claudette:\n", + "> \n", + "> - You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\n", + "> - Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\n", + "> - The library provides both synchronous and asynchronous interfaces\n", + "> - Use `Chat()` for maintaining conversation state and handling tool interactions\n", + "> - When using tools, the library automatically handles the request/response loop\n", + "> - Image support is built in but only available on compatible models (not Haiku)# claudette\n", + "> \n", + "> \n", + "> \n", + "> > **NB**: If you are reading this in GitHub’s readme, we recommend you\n", + "> > instead read the much more nicely formatted [documentation\n", + "> > format](https://claudette.answer.ai/) of this tutorial.\n", + "> \n", + "\n", + "\n", + "\n", + "To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.\n", + "> Claudette LLM Context - start: 1854 end: 1989\n", + "> \n", + "> > You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\n", + "> key provided to you by Anthropic in order to use this library.\n", + "> \n", + "\n", + "\n", + "\n", + "**user**: H\n", + "\n", + "**assistant**: Hello! How can I help you today?\n", "
\n", "\n", "| Metric | Count | Cost (USD) |\n", "|--------|------:|-----:|\n", - "| Input tokens | 610 | 0.001830 |\n", - "| Output tokens | 52 | 0.000780 |\n", + "| Input tokens | 2,854 | 0.008562 |\n", + "| Output tokens | 420 | 0.006300 |\n", "| Cache tokens | 0 | 0.000000 |\n", - "| **Total** | **662** | **$0.002610** |" + "| **Total** | **3,274** | **$0.014862** |" ], "text/plain": [ - "" + "<__main__.Chat>" ] }, "execution_count": null, @@ -4308,6 +4390,7 @@ } ], "source": [ + "c('Hi')\n", "c" ] }, diff --git a/claudette/core.py b/claudette/core.py index fadf6c4..4efb87e 100644 --- a/claudette/core.py +++ b/claudette/core.py @@ -4,8 +4,8 @@ __all__ = ['empty', 'model_types', 'all_models', 'models', 'models_aws', 'models_goog', 'text_only_models', 'has_streaming_models', 'has_system_prompt_models', 'has_temperature_models', 'pricing', 'can_stream', 'can_set_system_prompt', 'can_set_temperature', 'find_block', 'usage', 'Client', 'get_pricing', 'get_costs', - 'mk_tool_choice', 'mk_funcres', 'mk_toolres', 'get_types', 'tool', 'Chat', 'contents', 'cite_msgs', - 'has_citations', 'mk_msg', 'mk_msgs'] + 'mk_tool_choice', 'mk_funcres', 'mk_toolres', 'get_types', 'tool', 'Chat', 'cite_msgs', 'has_citations', + 'contents', 'mk_msg', 'mk_msgs'] # %% ../00_core.ipynb import inspect, typing, json @@ -401,26 +401,19 @@ def fmt_msg(m): {det}""" -# %% ../00_core.ipynb -def contents(r): - "Helper to get the contents from Claude response `r`." - blk = find_block(r) - if not blk and r.content: blk = r.content[0] - if hasattr(blk,'text'): return blk.text.strip() - elif hasattr(blk,'content'): return blk.content.strip() - elif hasattr(blk,'source'): return f'*Media Type - {blk.type}*' - return str(blk) - # %% ../00_core.ipynb def cite_msgs(msg) -> str: """Render a Claude message with citations as markdown.""" result = [] for block in msg.content: + result.append(block.text) if block.citations: for c in block.citations: - result.append(f"\n> {c.cited_text}\n\n") - else: - result.append(block.text) + cite_desc = f'{c.document_title} - start: {c.start_char_index} end: {c.end_char_index}' + lines = c.cited_text.splitlines() + quoted_lines = '\n'.join(f"> {ln}" for ln in lines) + f = f"\n> {cite_desc}\n> \n> {quoted_lines}\n\n" + result.append(f) return ''.join(result) # %% ../00_core.ipynb From 3cbccb9d38fb25e83b99a041af2cb1829e93aa5d Mon Sep 17 00:00:00 2001 From: Jay Suh Date: Mon, 24 Feb 2025 22:17:04 -0600 Subject: [PATCH 5/6] Fix typos --- 00_core.ipynb | 96 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/00_core.ipynb b/00_core.ipynb index e9c1e46..839d4a5 100644 --- a/00_core.ipynb +++ b/00_core.ipynb @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "f1ad998e-4bb1-4bed-abf4-6e8606cb2453", "metadata": {}, "outputs": [], @@ -57,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "033c76fd", "metadata": {}, "outputs": [], @@ -84,12 +84,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "13866a72", "metadata": {}, "outputs": [], "source": [ "#| hide\n", + "from httpx import get as xget\n", "from nbdev import show_doc\n", "\n", "# Used to show available models from the anthropic SDK\n", @@ -100,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "c1cefa1e", "metadata": {}, "outputs": [], @@ -111,7 +112,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "f5fa6b92", "metadata": {}, "outputs": [], @@ -136,7 +137,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "0fff8869", "metadata": {}, "outputs": [], @@ -166,7 +167,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "6e9da53c", "metadata": {}, "outputs": [ @@ -174,7 +175,6 @@ "name": "stdout", "output_type": "stream", "text": [ - "Available models as of 2025-02-23:\n", "Available models as of 2025-02-24:\n", "\n" ] @@ -195,7 +195,7 @@ " 'claude-2.0']" ] }, - "execution_count": null, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -210,7 +210,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "4f03dcad", "metadata": {}, "outputs": [], @@ -221,7 +221,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "669696aa", "metadata": {}, "outputs": [], @@ -232,7 +232,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "2411f28d", "metadata": {}, "outputs": [], @@ -245,7 +245,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "980bfdfb", "metadata": {}, "outputs": [ @@ -266,7 +266,7 @@ " 'claude-3-sonnet@20240229'}" ] }, - "execution_count": null, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -277,7 +277,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "12a68d54", "metadata": {}, "outputs": [], @@ -299,7 +299,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "55036062", "metadata": {}, "outputs": [], @@ -317,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "dacf2bd2", "metadata": {}, "outputs": [ @@ -327,7 +327,7 @@ "'claude-3-5-sonnet-20241022'" ] }, - "execution_count": null, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -354,7 +354,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "70b53a51", "metadata": {}, "outputs": [], @@ -384,33 +384,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "6ec40731", "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\n", + "Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant. How can I help you today?\n", "\n", "
\n", "\n", - "- id: `msg_01XUgk5vUP7FNF9w1GJqt6kN`\n", - "- content: `[{'text': \"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", 'type': 'text'}]`\n", + "- id: `msg_01EPZvaQKs14NzX3nA1deSqx`\n", + "- content: `[{'citations': None, 'text': \"Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant. How can I help you today?\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 22}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 26}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01XUgk5vUP7FNF9w1GJqt6kN', content=[TextBlock(text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32)" + "Message(id='msg_01EPZvaQKs14NzX3nA1deSqx', content=[TextBlock(citations=None, text=\"Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 26; Cache create: 0; Cache read: 0; Total: 36)" ] }, - "execution_count": null, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -459,7 +459,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "eba620ce", "metadata": {}, "outputs": [], @@ -482,17 +482,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "10af0e65", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "TextBlock(text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')" + "TextBlock(citations=None, text=\"Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant. How can I help you today?\", type='text')" ] }, - "execution_count": null, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -503,7 +503,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "id": "ae99799d", "metadata": {}, "outputs": [], @@ -525,17 +525,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "id": "6d5f2107", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\"" + "\"Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant. How can I help you today?\"" ] }, - "execution_count": null, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -546,7 +546,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "id": "17924d0c", "metadata": {}, "outputs": [], @@ -3993,7 +3993,7 @@ "source": [ "Claude is capable of providing detailed citations when answering questions about documents, helping you track and verify information sources in responses.\n", "\n", - "Claude expects an documents to have the following structure\n", + "Claude expects a document to have the following structure.\n", "\n", "``` python\n", "{\n", @@ -4103,6 +4103,16 @@ "c([doc, q])" ] }, + { + "cell_type": "markdown", + "id": "155a8a7c", + "metadata": {}, + "source": [ + "This is an interesting finding[^1].\n", + "\n", + "[^1]: Smith, J. (2023). \"Title of Paper\". Journal Name, 10(2), 123-456.\n" + ] + }, { "cell_type": "markdown", "id": "fc52b9da", @@ -4585,9 +4595,21 @@ ], "metadata": { "kernelspec": { - "display_name": "python3", + "display_name": "Python 3 (ipykernel)", "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.11" } }, "nbformat": 4, From ec6c6dcf45b8019e61d545aceaf75867ecc3b811 Mon Sep 17 00:00:00 2001 From: Jay Suh Date: Tue, 25 Feb 2025 17:01:55 -0600 Subject: [PATCH 6/6] Trim output and minor style changes --- 00_core.ipynb | 253 +++++++++++--------------------------------------- 1 file changed, 54 insertions(+), 199 deletions(-) diff --git a/00_core.ipynb b/00_core.ipynb index 839d4a5..38213ba 100644 --- a/00_core.ipynb +++ b/00_core.ipynb @@ -137,7 +137,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "0fff8869", "metadata": {}, "outputs": [], @@ -167,7 +167,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "id": "6e9da53c", "metadata": {}, "outputs": [ @@ -175,7 +175,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Available models as of 2025-02-24:\n", + "Available models as of 2025-02-25:\n", "\n" ] }, @@ -195,7 +195,7 @@ " 'claude-2.0']" ] }, - "execution_count": 8, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -210,7 +210,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "id": "4f03dcad", "metadata": {}, "outputs": [], @@ -317,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 9, "id": "dacf2bd2", "metadata": {}, "outputs": [ @@ -327,7 +327,7 @@ "'claude-3-5-sonnet-20241022'" ] }, - "execution_count": 15, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -838,33 +838,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "id": "0ffa2c14", "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "Hi Jeremy! Nice to meet you. How can I help you today?\n", + "Hi Jeremy, nice to meet you! I'm Claude. How can I help you today?\n", "\n", "
\n", "\n", - "- id: `msg_01VAqrPtTzD1uraEnzQMt194`\n", - "- content: `[{'text': \"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", 'type': 'text'}]`\n", + "- id: `msg_01GkzrxKr3x22fWHVj7Sdjsa`\n", + "- content: `[{'citations': None, 'text': \"Hi Jeremy, nice to meet you! I'm Claude. How can I help you today?\", 'type': 'text'}]`\n", "- model: `claude-3-5-sonnet-20241022`\n", "- role: `assistant`\n", "- stop_reason: `end_turn`\n", "- stop_sequence: `None`\n", "- type: `message`\n", - "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 18}`\n", + "- usage: `{'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 10, 'output_tokens': 22}`\n", "\n", "
" ], "text/plain": [ - "Message(id='msg_01VAqrPtTzD1uraEnzQMt194', content=[TextBlock(text=\"Hi Jeremy! Nice to meet you. I'm Claude. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32)" + "Message(id='msg_01GkzrxKr3x22fWHVj7Sdjsa', content=[TextBlock(citations=None, text=\"Hi Jeremy, nice to meet you! I'm Claude. How can I help you today?\", type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 22; Cache create: 0; Cache read: 0; Total: 32)" ] }, - "execution_count": null, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -4029,7 +4029,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "7b3779b4", "metadata": {}, "outputs": [ @@ -4039,19 +4039,19 @@ "{'type': 'document',\n", " 'source': {'type': 'text',\n", " 'media_type': 'text/plain',\n", - " 'data': 'Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n*Claudette* is a wrapper for Anthropic’s [Python\\nSDK](https://github.com/anthropics/anthropic-sdk-python).\\n\\nThe SDK works well, but it is quite low level – it leaves the developer\\nto do a lot of stuff manually. That’s a lot of extra work and\\nboilerplate! Claudette automates pretty much everything that can be\\nautomated, whilst providing full control. Amongst the features provided:\\n\\n- A [`Chat`](https://claudette.answer.ai/core.html#chat) class that\\n creates stateful dialogs\\n- Support for *prefill*, which tells Claude what to use as the first few\\n words of its response\\n- Convenient image support\\n- Simple and convenient support for Claude’s new Tool Use API.\\n\\nYou’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\nNote that this library is the first ever “literate nbdev” p'},\n", + " 'data': 'Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opu'},\n", " 'citations': {'enabled': True},\n", " 'title': 'Claudette LLM Context',\n", " 'context': 'This is a trustworthy document.'}" ] }, - "execution_count": null, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "llms_ctx = xget(\"https://claudette.answer.ai/llms-ctx.txt\").text[:2_048]\n", + "llms_ctx = xget(\"https://claudette.answer.ai/llms-ctx.txt\").text[:512]\n", "doc = mk_doc(llms_ctx, title=\"Claudette LLM Context\", context=\"This is a trustworthy document.\", citation=True)\n", "doc" ] @@ -4066,53 +4066,48 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "31a575c4", "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "Based on the provided document, I can give you a comprehensive explanation of Claudette:\n", + "Based on the provided document, Claudette is a Python library that provides a higher-level interface for Anthropic's Claude API. It helps developers create AI applications by automating common patterns while maintaining control, with features including stateful chat, prefill support, image handling, and streamlined tool use\n", + "> Claudette LLM Context - start: 0 end: 323\n", + "> \n", + "> > \n", "\n", - "- id: `msg_01FqKD3pYnVto32fApFRE4JU`\n", - "- content: `[{'citations': None, 'text': 'Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1187, 'start_char_index': 323, 'type': 'char_location'}], 'text': \"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", 'type': 'text'}, {'citations': None, 'text': '\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1989, 'start_char_index': 1854, 'type': 'char_location'}], 'text': 'To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', 'type': 'text'}]`\n", + "- id: `msg_01KVYtr5AqmHiHisvArFpExo`\n", + "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': '" ], "text/plain": [ - "Message(id='msg_01FqKD3pYnVto32fApFRE4JU', content=[TextBlock(citations=None, text='Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1187, start_char_index=323, type='char_location')], text=\"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", type='text'), TextBlock(citations=None, text='\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1989, start_char_index=1854, type='char_location')], text='To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 1232; Out: 409; Cache create: 0; Cache read: 0; Total: 1641)" + "Message(id='msg_01KVYtr5AqmHiHisvArFpExo', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text=' str:\n", + "def cite_md_msgs(msg) -> str:\n", " \"\"\"Render a Claude message with citations as markdown.\"\"\"\n", " result = []\n", " for block in msg.content:\n", @@ -4146,21 +4141,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "da3c7b60", "metadata": {}, "outputs": [], "source": [ "#| exports\n", "def has_citations(r):\n", - " \"\"\"Check if a Claude response contains any citations\"\"\"\n", + " \"\"\"Check if a Claude response contains any citation.\"\"\"\n", " return any(getattr(block, 'citations', None) and isinstance(block.citations, list)\n", " for block in r.content)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "aa168512", "metadata": {}, "outputs": [], @@ -4168,7 +4163,7 @@ "#| exports\n", "def contents(r):\n", " \"Helper to get the contents from Claude response `r`.\"\n", - " blk = cite_msgs(r) if has_citations(r) else find_block(r)\n", + " blk = cite_md_msgs(r) if has_citations(r) else find_block(r)\n", " if not blk and r.content: blk = r.content[0]\n", " if hasattr(blk,'text'): return blk.text.strip()\n", " elif hasattr(blk,'content'): return blk.content.strip()\n", @@ -4178,122 +4173,52 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "4cb7e85a", "metadata": {}, "outputs": [ { "data": { "text/markdown": [ - "Based on the provided document, I can give you a comprehensive explanation of Claudette:\n", - "\n", - "Claudette is a Python library that serves as a wrapper for Anthropic's Claude API, providing a higher-level interface for creating AI applications. It automates common patterns while still maintaining full control, and includes features like stateful chat, prefill support, image handling, and streamlined tool use.\n", + "Based on the provided document, Claudette is a Python library that provides a higher-level interface for Anthropic's Claude API. It helps developers create AI applications by automating common patterns while maintaining control, with features including stateful chat, prefill support, image handling, and streamlined tool use\n", "> Claudette LLM Context - start: 0 end: 323\n", "> \n", "> > Claudette LLM Context - start: 1187 end: 1539\n", - "> \n", - "> > *Claudette* is a wrapper for Anthropic’s [Python\n", - "> SDK](https://github.com/anthropics/anthropic-sdk-python).\n", - "> \n", - "> The SDK works well, but it is quite low level – it leaves the developer\n", - "> to do a lot of stuff manually. That’s a lot of extra work and\n", - "> boilerplate! Claudette automates pretty much everything that can be\n", - "> automated, whilst providing full control. \n", - "\n", - "\n", - "\n", - "Key features of Claudette include:\n", - "\n", - "- A `Chat` class for creating stateful dialogs\n", - "- Prefill support that allows you to specify the first few words of Claude's response\n", - "- Convenient image support\n", - "- Simple and streamlined support for Claude's Tool Use API\n", - "> Claudette LLM Context - start: 1539 end: 1854\n", - "> \n", - "> > Amongst the features provided:\n", - "> \n", - "> - A [`Chat`](https://claudette.answer.ai/core.html#chat) class that\n", - "> creates stateful dialogs\n", - "> - Support for *prefill*, which tells Claude what to use as the first few\n", - "> words of its response\n", - "> - Convenient image support\n", - "> - Simple and convenient support for Claude’s new Tool Use API.\n", - "> \n", - "\n", - "\n", - "\n", - "Important technical details:\n", - "\n", - "- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\n", - "- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\n", - "- The library offers both synchronous and asynchronous interfaces\n", - "- Image support is available but only on compatible models (not Haiku)\n", - "> Claudette LLM Context - start: 323 end: 1187\n", - "> \n", - "> > \">Things to remember when using Claudette:\n", - "> \n", - "> - You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\n", - "> - Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\n", - "> - The library provides both synchronous and asynchronous interfaces\n", - "> - Use `Chat()` for maintaining conversation state and handling tool interactions\n", - "> - When using tools, the library automatically handles the request/response loop\n", - "> - Image support is built in but only available on compatible models (not Haiku)# claudette\n", - "> \n", - "> \n", - "> \n", - "> > **NB**: If you are reading this in GitHub’s readme, we recommend you\n", - "> > instead read the much more nicely formatted [documentation\n", - "> > format](https://claudette.answer.ai/) of this tutorial.\n", - "> \n", - "\n", - "\n", - "\n", - "To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.\n", - "> Claudette LLM Context - start: 1854 end: 1989\n", - "> \n", - "> > You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\n", - "> key provided to you by Anthropic in order to use this library.\n", - "> \n", - "\n", - "\n", + ".\n", "\n", "
\n", "\n", - "- id: `msg_014QsRm5YjNpz3FuNZ5izDJN`\n", - "- content: `[{'citations': None, 'text': 'Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1187, 'start_char_index': 323, 'type': 'char_location'}], 'text': \"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", 'type': 'text'}, {'citations': None, 'text': '\\n\\n', 'type': 'text'}, {'citations': [{'cited_text': 'You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', 'document_index': 0, 'document_title': 'Claudette LLM Context', 'end_char_index': 1989, 'start_char_index': 1854, 'type': 'char_location'}], 'text': 'To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', 'type': 'text'}]`\n", + "- id: `msg_016nSztUQx55w6j74NobbE2T`\n", + "- content: `[{'citations': None, 'text': 'Based on the provided document, ', 'type': 'text'}, {'citations': [{'cited_text': '" ], "text/plain": [ - "Message(id='msg_014QsRm5YjNpz3FuNZ5izDJN', content=[TextBlock(citations=None, text='Based on the provided document, I can give you a comprehensive explanation of Claudette:\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='Things to remember when using Claudette:\\n\\n- You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\\n- Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\\n- The library provides both synchronous and asynchronous interfaces\\n- Use `Chat()` for maintaining conversation state and handling tool interactions\\n- When using tools, the library automatically handles the request/response loop\\n- Image support is built in but only available on compatible models (not Haiku)# claudette\\n\\n\\n\\n> **NB**: If you are reading this in GitHub’s readme, we recommend you\\n> instead read the much more nicely formatted [documentation\\n> format](https://claudette.answer.ai/) of this tutorial.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1187, start_char_index=323, type='char_location')], text=\"\\n- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\\n- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\\n- The library offers both synchronous and asynchronous interfaces\\n- Image support is available but only on compatible models (not Haiku)\", type='text'), TextBlock(citations=None, text='\\n\\n', type='text'), TextBlock(citations=[CitationCharLocation(cited_text='You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\\nkey provided to you by Anthropic in order to use this library.\\n\\n', document_index=0, document_title='Claudette LLM Context', end_char_index=1989, start_char_index=1854, type='char_location')], text='To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 1232; Out: 409; Cache create: 0; Cache read: 0; Total: 1641)" + "Message(id='msg_016nSztUQx55w6j74NobbE2T', content=[TextBlock(citations=None, text='Based on the provided document, ', type='text'), TextBlock(citations=[CitationCharLocation(cited_text=' Claudette LLM Context - start: 0 end: 323\n", "> \n", "> > Claudette LLM Context - start: 1187 end: 1539\n", - "> \n", - "> > *Claudette* is a wrapper for Anthropic’s [Python\n", - "> SDK](https://github.com/anthropics/anthropic-sdk-python).\n", - "> \n", - "> The SDK works well, but it is quite low level – it leaves the developer\n", - "> to do a lot of stuff manually. That’s a lot of extra work and\n", - "> boilerplate! Claudette automates pretty much everything that can be\n", - "> automated, whilst providing full control. \n", - "\n", - "\n", - "\n", - "Key features of Claudette include:\n", - "\n", - "- A `Chat` class for creating stateful dialogs\n", - "- Prefill support that allows you to specify the first few words of Claude's response\n", - "- Convenient image support\n", - "- Simple and streamlined support for Claude's Tool Use API\n", - "> Claudette LLM Context - start: 1539 end: 1854\n", - "> \n", - "> > Amongst the features provided:\n", - "> \n", - "> - A [`Chat`](https://claudette.answer.ai/core.html#chat) class that\n", - "> creates stateful dialogs\n", - "> - Support for *prefill*, which tells Claude what to use as the first few\n", - "> words of its response\n", - "> - Convenient image support\n", - "> - Simple and convenient support for Claude’s new Tool Use API.\n", - "> \n", - "\n", - "\n", - "\n", - "Important technical details:\n", - "\n", - "- It's designed to work with Claude 3 models (Opus, Sonnet, and Haiku)\n", - "- It supports multiple providers including Anthropic direct, AWS Bedrock, and Google Vertex\n", - "- The library offers both synchronous and asynchronous interfaces\n", - "- Image support is available but only on compatible models (not Haiku)\n", - "> Claudette LLM Context - start: 323 end: 1187\n", - "> \n", - "> > \">Things to remember when using Claudette:\n", - "> \n", - "> - You must set the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key\n", - "> - Claudette is designed to work with Claude 3 models (Opus, Sonnet, Haiku) and supports multiple providers (Anthropic direct, AWS Bedrock, Google Vertex)\n", - "> - The library provides both synchronous and asynchronous interfaces\n", - "> - Use `Chat()` for maintaining conversation state and handling tool interactions\n", - "> - When using tools, the library automatically handles the request/response loop\n", - "> - Image support is built in but only available on compatible models (not Haiku)# claudette\n", - "> \n", - "> \n", - "> \n", - "> > **NB**: If you are reading this in GitHub’s readme, we recommend you\n", - "> > instead read the much more nicely formatted [documentation\n", - "> > format](https://claudette.answer.ai/) of this tutorial.\n", - "> \n", - "\n", - "\n", - "\n", - "To use Claudette, you need to set up the `ANTHROPIC_API_KEY` environment variable with your Anthropic API key.\n", - "> Claudette LLM Context - start: 1854 end: 1989\n", - "> \n", - "> > You’ll need to set the `ANTHROPIC_API_KEY` environment variable to the\n", - "> key provided to you by Anthropic in order to use this library.\n", - "> \n", - "\n", - "\n", + ".\n", "\n", "**user**: H\n", "\n", @@ -4391,16 +4246,16 @@ "\n", "| Metric | Count | Cost (USD) |\n", "|--------|------:|-----:|\n", - "| Input tokens | 2,855 | 0.008565 |\n", - "| Output tokens | 421 | 0.006315 |\n", + "| Input tokens | 1,576 | 0.004728 |\n", + "| Output tokens | 98 | 0.001470 |\n", "| Cache tokens | 0 | 0.000000 |\n", - "| **Total** | **3,276** | **$0.014880** |" + "| **Total** | **1,674** | **$0.006198** |" ], "text/plain": [ - "<__main__.Chat>" + "" ] }, - "execution_count": null, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" }