diff --git a/02_async.ipynb b/02_async.ipynb
index 0cbdcba..c196614 100644
--- a/02_async.ipynb
+++ b/02_async.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"id": "efe78920",
"metadata": {},
"outputs": [],
@@ -28,7 +28,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"id": "033c76fd",
"metadata": {},
"outputs": [],
@@ -40,7 +40,8 @@
"except: display=None\n",
"\n",
"from anthropic import AsyncAnthropic\n",
- "from toolslm.funccall import get_schema\n",
+ "from anthropic.types import ToolUseBlock\n",
+ "from toolslm.funccall import get_schema, mk_ns, call_func\n",
"from fastcore.meta import delegates\n",
"from fastcore.utils import *\n",
"from claudette.core import *"
@@ -48,7 +49,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 3,
"id": "13866a72",
"metadata": {},
"outputs": [],
@@ -67,7 +68,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"id": "70b53a51",
"metadata": {},
"outputs": [],
@@ -78,33 +79,33 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 5,
"id": "6ec40731",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
- "Hello Jeremy! It's nice to meet you. How can I assist you today? Is there anything specific you'd like to talk about or any questions you have?\n",
+ "Hi Jeremy! Nice to meet you. I'm Claude, an AI assistant created by Anthropic. How can I help you today?\n",
"\n",
"\n",
"\n",
- "- id: `msg_019gsEQs5dqb3kgwNJbTH27M`\n",
- "- content: `[{'text': \"Hello Jeremy! It's nice to meet you. How can I assist you today? Is there anything specific you'd like to talk about or any questions you have?\", 'type': 'text'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_01UBPA1yCoPZdk4vDbCwdXGm`\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",
+ "- model: `claude-3-5-sonnet-20241022`\n",
"- role: `assistant`\n",
"- stop_reason: `end_turn`\n",
"- stop_sequence: `None`\n",
"- type: `message`\n",
- "- usage: `{'input_tokens': 10, 'output_tokens': 36}`\n",
+ "- usage: `{'input_tokens': 10, 'output_tokens': 31}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_019gsEQs5dqb3kgwNJbTH27M', content=[TextBlock(text=\"Hello Jeremy! It's nice to meet you. How can I assist you today? Is there anything specific you'd like to talk about or any questions you have?\", type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 10; Out: 36; Total: 46)"
+ "Message(id='msg_01UBPA1yCoPZdk4vDbCwdXGm', 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)"
]
},
- "execution_count": null,
+ "execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
@@ -117,7 +118,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 6,
"id": "3b873aaf",
"metadata": {},
"outputs": [],
@@ -132,7 +133,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 7,
"id": "d01e9ccf",
"metadata": {},
"outputs": [],
@@ -142,17 +143,17 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 8,
"id": "0181f7b3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "In: 10; Out: 36; Total: 46"
+ "In: 10; Out: 31; Cache create: 0; Cache read: 0; Total: 41"
]
},
- "execution_count": null,
+ "execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
@@ -164,7 +165,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 9,
"id": "6520a355",
"metadata": {},
"outputs": [],
@@ -180,7 +181,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 10,
"id": "835638bb",
"metadata": {},
"outputs": [],
@@ -196,8 +197,12 @@
" prefill='', # Optional prefill to pass to Claude as start of its response\n",
" stream:bool=False, # Stream response?\n",
" stop=None, # Stop sequence\n",
+ " tools:Optional[list]=None, # List of tools to make available to Claude\n",
+ " tool_choice:Optional[dict]=None, # Optionally force use of some tool\n",
" **kwargs):\n",
" \"Make an async call to Claude.\"\n",
+ " if tools: kwargs['tools'] = [get_schema(o) for o in listify(tools)]\n",
+ " if tool_choice: kwargs['tool_choice'] = mk_tool_choice(tool_choice)\n",
" msgs = self._precall(msgs, prefill, stop, kwargs)\n",
" if stream: return self._stream(msgs, prefill=prefill, max_tokens=maxtok, system=sp, temperature=temp, **kwargs)\n",
" res = await self.c.messages.create(\n",
@@ -207,17 +212,17 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"id": "881b5e78",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "In: 0; Out: 0; Total: 0"
+ "In: 0; Out: 0; Cache create: 0; Cache read: 0; Total: 0"
]
},
- "execution_count": null,
+ "execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
@@ -229,33 +234,33 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 12,
"id": "c1220856",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
- "Hello! How can I assist you today? Feel free to ask any questions or let me know if you need help with anything.\n",
+ "Hello! How can I help you today?\n",
"\n",
"\n",
"\n",
- "- id: `msg_01L9vqP9r1LcmvSk8vWGLbPo`\n",
- "- content: `[{'text': 'Hello! How can I assist you today? Feel free to ask any questions or let me know if you need help with anything.', 'type': 'text'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_01TC5wq1bS1ZcJMopq8bZ4o2`\n",
+ "- content: `[{'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",
"- stop_sequence: `None`\n",
"- type: `message`\n",
- "- usage: `{'input_tokens': 8, 'output_tokens': 29, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
+ "- usage: `{'input_tokens': 8, 'output_tokens': 12, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_01L9vqP9r1LcmvSk8vWGLbPo', content=[TextBlock(text='Hello! How can I assist you today? Feel free to ask any questions or let me know if you need help with anything.', type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 8; Out: 29; Total: 37)"
+ "Message(id='msg_01TC5wq1bS1ZcJMopq8bZ4o2', 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)"
]
},
- "execution_count": null,
+ "execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
@@ -267,17 +272,17 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
"id": "ae9f7e06",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "In: 8; Out: 29; Total: 37"
+ "In: 8; Out: 12; Cache create: 0; Cache read: 0; Total: 20"
]
},
- "execution_count": null,
+ "execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
@@ -288,33 +293,33 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 14,
"id": "7f479429",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
- "According to Douglas Adams, the meaning of life is 42. More seriously, there's no universally agreed upon meaning of life. Many philosophers and religions have proposed different answers, but it remains an open question that individuals must grapple with for themselves.\n",
+ "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 following spiritual/religious beliefs.\n",
"\n",
"\n",
"\n",
- "- id: `msg_01KAJbCneA2oCRPVm9EkyDXF`\n",
- "- content: `[{'text': \"According to Douglas Adams, the meaning of life is 42. More seriously, there's no universally agreed upon meaning of life. Many philosophers and religions have proposed different answers, but it remains an open question that individuals must grapple with for themselves.\", 'type': 'text'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_012ZvrAoNyBherFi2q4fDRWq`\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 following spiritual/religious beliefs.\", '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: `{'input_tokens': 24, 'output_tokens': 51, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
+ "- usage: `{'input_tokens': 24, 'output_tokens': 50, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_01KAJbCneA2oCRPVm9EkyDXF', content=[TextBlock(text=\"According to Douglas Adams, the meaning of life is 42. More seriously, there's no universally agreed upon meaning of life. Many philosophers and religions have proposed different answers, but it remains an open question that individuals must grapple with for themselves.\", type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 24; Out: 51; Total: 75)"
+ "Message(id='msg_012ZvrAoNyBherFi2q4fDRWq', 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 following spiritual/religious beliefs.\", 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)"
]
},
- "execution_count": null,
+ "execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
@@ -327,7 +332,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 15,
"id": "c0230a8c",
"metadata": {},
"outputs": [
@@ -335,7 +340,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Hello! How can I assist you today? Feel free to ask any questions or let me know if you need help with anything."
+ "Hello! How can I help you today?"
]
}
],
@@ -345,17 +350,17 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 16,
"id": "beb25f2a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "In: 40; Out: 109; Total: 149"
+ "In: 40; Out: 74; Cache create: 0; Cache read: 0; Total: 114"
]
},
- "execution_count": null,
+ "execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
@@ -366,7 +371,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 17,
"id": "db1c75ef",
"metadata": {},
"outputs": [
@@ -374,7 +379,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "According to Douglas Adams, the meaning of life is 42. More seriously, there's no universally agreed upon meaning of life. Many philosophers and religions have proposed different answers, but it remains an open question that individuals must grapple with for themselves."
+ "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 following spiritual/religious beliefs."
]
}
],
@@ -384,17 +389,17 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 18,
"id": "e36eddc9",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "In: 64; Out: 160; Total: 224"
+ "In: 64; Out: 124; Cache create: 0; Cache read: 0; Total: 188"
]
},
- "execution_count": null,
+ "execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
@@ -405,7 +410,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 19,
"id": "046e8cc3",
"metadata": {},
"outputs": [],
@@ -421,7 +426,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 20,
"id": "d51f2bdf",
"metadata": {},
"outputs": [],
@@ -433,7 +438,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 21,
"id": "bff81d52",
"metadata": {},
"outputs": [],
@@ -444,8 +449,8 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "8bae7694",
+ "execution_count": 22,
+ "id": "9f7292b0",
"metadata": {},
"outputs": [
{
@@ -458,21 +463,96 @@
{
"data": {
"text/plain": [
- "'As a summing expert, I\\'m happy to help you with this addition. The sum of 604542 and 6458932 is 7063474.\\n\\nTo break it down:\\n604542 (first number)\\n+ 6458932 (second number)\\n= 7063474 (total sum)\\n\\nThis result was calculated using the \"sums\" function, which adds two numbers together. Is there anything else you\\'d like me to sum for you?'"
+ "'The sum of 604542 and 6458932 is 7063474.'"
]
},
- "execution_count": null,
+ "execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "tools = [get_schema(sums)]\n",
"msgs = mk_msgs(pr)\n",
- "r = await c(msgs, sp=sp, tools=tools, tool_choice=choice)\n",
+ "r = await c(msgs, sp=sp, tools=sums, tool_choice=sums)\n",
"tr = mk_toolres(r, ns=globals())\n",
"msgs += tr\n",
- "contents(await c(msgs, sp=sp, tools=tools))"
+ "contents(await c(msgs, sp=sp, tools=sums))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "8bae7694",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# tools = [get_schema(sums)]\n",
+ "# msgs = mk_msgs(pr)\n",
+ "# r = await c(msgs, sp=sp, tools=tools, tool_choice=choice)\n",
+ "# tr = mk_toolres(r, ns=globals())\n",
+ "# msgs += tr\n",
+ "# contents(await c(msgs, sp=sp, tools=tools))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b5c7af80",
+ "metadata": {},
+ "source": [
+ "## Structured Output"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "b68060dc",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "@patch\n",
+ "@delegates(Client.__call__)\n",
+ "async def structured(self:AsyncClient,\n",
+ " msgs:list, # List of messages in the dialog\n",
+ " tools:Optional[list]=None, # List of tools to make available to Claude\n",
+ " obj:Optional=None, # Class to search for tools \n",
+ " ns:Optional[abc.Mapping]=None, # Namespace to search for tools\n",
+ " **kwargs):\n",
+ " \"Return the value of all tool calls (generally used for structured outputs)\"\n",
+ " tools = listify(tools)\n",
+ " if ns is None: ns=mk_ns(*tools)\n",
+ " if obj is not None: ns = mk_ns(obj)\n",
+ " res = await self(msgs, tools=tools, tool_choice=tools,**kwargs)\n",
+ " cts = getattr(res, 'content', [])\n",
+ " tcs = [call_func(o.name, o.input, ns=ns) for o in cts if isinstance(o,ToolUseBlock)]\n",
+ " return tcs"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "id": "30a71b2e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Finding the sum of 604542 and 6458932\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[7063474]"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "await c.structured(pr, sums)"
]
},
{
@@ -485,7 +565,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 26,
"id": "a77d1edb",
"metadata": {},
"outputs": [],
@@ -504,17 +584,17 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 27,
"id": "04b837c5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "(In: 0; Out: 0; Total: 0, [])"
+ "(In: 0; Out: 0; Cache create: 0; Cache read: 0; Total: 0, [])"
]
},
- "execution_count": null,
+ "execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
@@ -527,7 +607,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 28,
"id": "42a05df9",
"metadata": {},
"outputs": [],
@@ -541,7 +621,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 29,
"id": "8e5ab3be",
"metadata": {},
"outputs": [],
@@ -556,7 +636,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 30,
"id": "bec85e37",
"metadata": {},
"outputs": [],
@@ -571,42 +651,41 @@
" prefill='', # Optional prefill to pass to Claude as start of its response\n",
" **kw):\n",
" await self._append_pr(pr)\n",
- " if self.tools: kw['tools'] = [get_schema(o) for o in self.tools]\n",
" res = await self.c(self.h, stream=stream, prefill=prefill, sp=self.sp, temp=temp, maxtok=maxtok, **kw)\n",
" if stream: return self._stream(res)\n",
- " self.h += mk_toolres(self.c.result, ns=self.tools, obj=self)\n",
+ " self.h += mk_toolres(self.c.result, ns=mk_ns(*listify(self.tools)), obj=self)\n",
" return res"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 31,
"id": "40073f42",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
- "Your name is Jeremy, as you mentioned in your previous message.\n",
+ "Your name is Jeremy.\n",
"\n",
"\n",
"\n",
- "- id: `msg_01NMugMXWpDP9iuTXeLkHarn`\n",
- "- content: `[{'text': 'Your name is Jeremy, as you mentioned in your previous message.', 'type': 'text'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_01BNxuSzZGanZupYuJxFDTgi`\n",
+ "- content: `[{'text': '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: `{'input_tokens': 64, 'output_tokens': 16, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
+ "- usage: `{'input_tokens': 41, 'output_tokens': 8, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_01NMugMXWpDP9iuTXeLkHarn', content=[TextBlock(text='Your name is Jeremy, as you mentioned in your previous message.', type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 64; Out: 16; Total: 80)"
+ "Message(id='msg_01BNxuSzZGanZupYuJxFDTgi', 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)"
]
},
- "execution_count": null,
+ "execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
@@ -618,41 +697,33 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 32,
"id": "20a32de0",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
- "According to Douglas Adams, the meaning of life is 42. More seriously, there's no universally agreed upon answer. Common philosophical perspectives include:\n",
- "\n",
- "1. Finding personal fulfillment\n",
- "2. Serving others\n",
- "3. Pursuing happiness\n",
- "4. Creating meaning through our choices\n",
- "5. Experiencing and appreciating existence\n",
- "\n",
- "Ultimately, many believe each individual must determine their own life's meaning.\n",
+ "According to Douglas Adams, 42. But more seriously: to find purpose, create meaning, love, grow, and make a positive impact during our time here.\n",
"\n",
"\n",
"\n",
- "- id: `msg_01VPWUQn5Do1Kst8RYUDQvCu`\n",
- "- content: `[{'text': \"According to Douglas Adams, the meaning of life is 42. More seriously, there's no universally agreed upon answer. Common philosophical perspectives include:\\n\\n1. Finding personal fulfillment\\n2. Serving others\\n3. Pursuing happiness\\n4. Creating meaning through our choices\\n5. Experiencing and appreciating existence\\n\\nUltimately, many believe each individual must determine their own life's meaning.\", 'type': 'text'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_012WB8YcoMyPk2Uuh69eUxnF`\n",
+ "- content: `[{'text': 'According to Douglas Adams, 42. But more seriously: to find purpose, create meaning, love, grow, and make a positive impact during our time here.', '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: `{'input_tokens': 100, 'output_tokens': 82, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
+ "- usage: `{'input_tokens': 69, 'output_tokens': 31, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_01VPWUQn5Do1Kst8RYUDQvCu', content=[TextBlock(text=\"According to Douglas Adams, the meaning of life is 42. More seriously, there's no universally agreed upon answer. Common philosophical perspectives include:\\n\\n1. Finding personal fulfillment\\n2. Serving others\\n3. Pursuing happiness\\n4. Creating meaning through our choices\\n5. Experiencing and appreciating existence\\n\\nUltimately, many believe each individual must determine their own life's meaning.\", type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 100; Out: 82; Total: 182)"
+ "Message(id='msg_012WB8YcoMyPk2Uuh69eUxnF', content=[TextBlock(text='According to Douglas Adams, 42. But more seriously: to find purpose, create meaning, love, grow, and make a positive impact during our time here.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 69; Out: 31; Cache create: 0; Cache read: 0; Total: 100)"
]
},
- "execution_count": null,
+ "execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
@@ -665,7 +736,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 33,
"id": "529104ec",
"metadata": {},
"outputs": [
@@ -673,7 +744,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Hello Jeremy! It's nice to meet you. How are you doing today? Is there anything in particular you'd like to chat about or any questions I can help you with?"
+ "Hello Jeremy! Nice to meet you. How are you today?"
]
}
],
@@ -684,40 +755,33 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 40,
"id": "ee6535cf",
"metadata": {},
"outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Finding the sum of 604542 and 6458932\n"
- ]
- },
{
"data": {
"text/markdown": [
- "To answer this question, I can use the \"sums\" function to add these two numbers together. Let me do that for you.\n",
+ "7,063,474\n",
"\n",
"\n",
"\n",
- "- id: `msg_015z1rffSWFxvj7rSpzc43ZE`\n",
- "- content: `[{'text': 'To answer this question, I can use the \"sums\" function to add these two numbers together. Let me do that for you.', 'type': 'text'}, {'id': 'toolu_01SNKhtfnDQBC4RGY4mUCq1v', 'input': {'a': 604542, 'b': 6458932}, 'name': 'sums', 'type': 'tool_use'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_013c9kT2obX52nLMf9PmWWHH`\n",
+ "- content: `[{'text': '7,063,474', 'type': 'text'}]`\n",
+ "- model: `claude-3-5-sonnet-20241022`\n",
"- role: `assistant`\n",
- "- stop_reason: `tool_use`\n",
+ "- stop_reason: `end_turn`\n",
"- stop_sequence: `None`\n",
"- type: `message`\n",
- "- usage: `{'input_tokens': 428, 'output_tokens': 101, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
+ "- usage: `{'input_tokens': 24, 'output_tokens': 9, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_015z1rffSWFxvj7rSpzc43ZE', content=[TextBlock(text='To answer this question, I can use the \"sums\" function to add these two numbers together. Let me do that for you.', type='text'), ToolUseBlock(id='toolu_01SNKhtfnDQBC4RGY4mUCq1v', input={'a': 604542, 'b': 6458932}, name='sums', type='tool_use')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='tool_use', stop_sequence=None, type='message', usage=In: 428; Out: 101; Total: 529)"
+ "Message(id='msg_013c9kT2obX52nLMf9PmWWHH', content=[TextBlock(text='7,063,474', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 24; Out: 9; Cache create: 0; Cache read: 0; Total: 33)"
]
},
- "execution_count": null,
+ "execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
@@ -731,44 +795,47 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "0979c832",
+ "execution_count": 41,
+ "id": "2dc85163",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
- "The sum of 604542 and 6458932 is 7063474.\n",
+ "The sum of 604,542 and 6,458,932 is 7,063,474.\n",
"\n",
"\n",
"\n",
- "- id: `msg_018KAsE2YGiXWjUJkLPrXpb2`\n",
- "- content: `[{'text': 'The sum of 604542 and 6458932 is 7063474.', 'type': 'text'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_01F6Jms2nhe8VEDN16ZUGomv`\n",
+ "- content: `[{'text': 'The sum of 604,542 and 6,458,932 is 7,063,474.', '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: `{'input_tokens': 543, 'output_tokens': 23, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
+ "- usage: `{'input_tokens': 31, 'output_tokens': 27, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_018KAsE2YGiXWjUJkLPrXpb2', content=[TextBlock(text='The sum of 604542 and 6458932 is 7063474.', type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 543; Out: 23; Total: 566)"
+ "Message(id='msg_01F6Jms2nhe8VEDN16ZUGomv', content=[TextBlock(text='The sum of 604,542 and 6,458,932 is 7,063,474.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 31; Out: 27; Cache create: 0; Cache read: 0; Total: 58)"
]
},
- "execution_count": null,
+ "execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "await chat()"
+ "pr += \"Say the answer in a sentence.\"\n",
+ "chat = AsyncChat(model, sp=sp, tools=[sums])\n",
+ "r = await chat(pr)\n",
+ "r"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 42,
"id": "5d35d564",
"metadata": {},
"outputs": [],
@@ -779,33 +846,33 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 43,
"id": "0c0eed5d",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
- "The flowers in this image are purple. They appear to be small, daisy-like flowers, possibly asters or some type of purple daisy, blooming in the background behind the adorable puppy in the foreground.\n",
+ "In this adorable puppy photo, there are purple/lavender colored flowers (appears to be asters or similar daisy-like flowers) in the background.\n",
"\n",
"\n",
"\n",
- "- id: `msg_017qgZggLjUY915mWbWCkb9X`\n",
- "- content: `[{'text': 'The flowers in this image are purple. They appear to be small, daisy-like flowers, possibly asters or some type of purple daisy, blooming in the background behind the adorable puppy in the foreground.', 'type': 'text'}]`\n",
- "- model: `claude-3-5-sonnet-20240620`\n",
+ "- id: `msg_01MLGBSn2QYJoKnthg7W2Tkj`\n",
+ "- content: `[{'text': 'In this adorable puppy photo, there are purple/lavender colored flowers (appears to be asters or similar daisy-like flowers) in the background.', '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: `{'input_tokens': 110, 'output_tokens': 50, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
+ "- usage: `{'input_tokens': 110, 'output_tokens': 37, 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0}`\n",
"\n",
" "
],
"text/plain": [
- "Message(id='msg_017qgZggLjUY915mWbWCkb9X', content=[TextBlock(text='The flowers in this image are purple. They appear to be small, daisy-like flowers, possibly asters or some type of purple daisy, blooming in the background behind the adorable puppy in the foreground.', type='text')], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 50; Total: 160)"
+ "Message(id='msg_01MLGBSn2QYJoKnthg7W2Tkj', content=[TextBlock(text='In this adorable puppy photo, there are purple/lavender colored flowers (appears to be asters or similar daisy-like flowers) in the background.', type='text')], model='claude-3-5-sonnet-20241022', role='assistant', stop_reason='end_turn', stop_sequence=None, type='message', usage=In: 110; Out: 37; Cache create: 0; Cache read: 0; Total: 147)"
]
},
- "execution_count": null,
+ "execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
@@ -826,7 +893,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 44,
"id": "1e9ee5c1",
"metadata": {},
"outputs": [],
@@ -848,9 +915,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.12.7"
}
},
"nbformat": 4,
diff --git a/claudette/asink.py b/claudette/asink.py
index 08181dd..9f90883 100644
--- a/claudette/asink.py
+++ b/claudette/asink.py
@@ -10,7 +10,8 @@
except: display=None
from anthropic import AsyncAnthropic
-from toolslm.funccall import get_schema
+from anthropic.types import ToolUseBlock
+from toolslm.funccall import get_schema, mk_ns, call_func
from fastcore.meta import delegates
from fastcore.utils import *
from .core import *
@@ -41,8 +42,12 @@ async def __call__(self:AsyncClient,
prefill='', # Optional prefill to pass to Claude as start of its response
stream:bool=False, # Stream response?
stop=None, # Stop sequence
+ tools:Optional[list]=None, # List of tools to make available to Claude
+ tool_choice:Optional[dict]=None, # Optionally force use of some tool
**kwargs):
"Make an async call to Claude."
+ if tools: kwargs['tools'] = [get_schema(o) for o in listify(tools)]
+ if tool_choice: kwargs['tool_choice'] = mk_tool_choice(tool_choice)
msgs = self._precall(msgs, prefill, stop, kwargs)
if stream: return self._stream(msgs, prefill=prefill, max_tokens=maxtok, system=sp, temperature=temp, **kwargs)
res = await self.c.messages.create(
@@ -83,8 +88,7 @@ async def __call__(self:AsyncChat,
prefill='', # Optional prefill to pass to Claude as start of its response
**kw):
await self._append_pr(pr)
- if self.tools: kw['tools'] = [get_schema(o) for o in self.tools]
res = await self.c(self.h, stream=stream, prefill=prefill, sp=self.sp, temp=temp, maxtok=maxtok, **kw)
if stream: return self._stream(res)
- self.h += mk_toolres(self.c.result, ns=self.tools, obj=self)
+ self.h += mk_toolres(self.c.result, ns=mk_ns(*listify(self.tools)), obj=self)
return res