Skip to content

Instantly share code, notes, and snippets.

@kwnath
Created September 13, 2024 15:14
Show Gist options
  • Save kwnath/f42737c023767d5effdcca20cb5bd0a6 to your computer and use it in GitHub Desktop.
Save kwnath/f42737c023767d5effdcca20cb5bd0a6 to your computer and use it in GitHub Desktop.
anthropic_streaming_client.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Anthropic Streaming\n",
"\n",
"The following use examples from the [Anthropic sdk readme](https://github.com/anthropics/anthropic-sdk-python?tab=readme-ov-file#tool-use) that link to tool use (function calling) [here](https://docs.anthropic.com/en/docs/build-with-claude/tool-use)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# First initialise the client\n",
"\n",
"from anthropic import Anthropic\n",
"import os \n",
"\n",
"client = Anthropic(api_key=os.environ.get(\"ANTHROPIC_API_KEY\"))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Then let's try the expected outcome:\n",
"\n",
"message = client.messages.create(\n",
" model=\"claude-3-5-sonnet-20240620\",\n",
" max_tokens=2048,\n",
" temperature=0.0,\n",
" tools=[\n",
" {\n",
" \"name\": \"get_weather\",\n",
" \"description\": \"Get the current weather in a given location\",\n",
" \"input_schema\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"location\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city and state, e.g. San Francisco, CA\",\n",
" }\n",
" },\n",
" \"required\": [\"location\"],\n",
" },\n",
" }\n",
" ],\n",
" stream=False,\n",
" messages=[{\"role\": \"user\", \"content\": \"What's the weather like in San Francisco?\"}],\n",
")\n",
"\n",
"print(message) \n",
"# In the below output we get the tool use and the following chunks... \n",
"# ToolUseBlock(id='toolu_01761DvCk3yuAJZgHWe9ocNZ', input={'location': 'San Francisco, CA'}, name='get_weather', type='tool_use')\n",
"\n",
"\n",
"# [2024-09-13 15:54:37,483] #51119 INFO (httpx) - HTTP Request: POST https://api.anthropic.com/v1/messages \"HTTP/1.1 200 OK\"\n",
"# ('id', 'msg_01LSBCVYJZz824RMhZojNxxE')\n",
"# ('content', [TextBlock(text=\"Certainly! I can help you get the current weather information for San Francisco. To do that, I'll use the get_weather function. Let me fetch that information for you right away.\", type='text'), ToolUseBlock(id='toolu_01761DvCk3yuAJZgHWe9ocNZ', input={'location': 'San Francisco, CA'}, name='get_weather', type='tool_use')])\n",
"# ('model', 'claude-3-5-sonnet-20240620')\n",
"# ('role', 'assistant')\n",
"# ('stop_reason', 'tool_use')\n",
"# ('stop_sequence', None)\n",
"# ('type', 'message')\n",
"# ('usage', Usage(input_tokens=384, output_tokens=95))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Now with streaming"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"stream = client.messages.create(\n",
" model=\"claude-3-5-sonnet-20240620\",\n",
" max_tokens=2048,\n",
" temperature=0.0,\n",
" tools=[\n",
" {\n",
" \"name\": \"get_weather\",\n",
" \"description\": \"Get the current weather in a given location\",\n",
" \"input_schema\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"location\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city and state, e.g. San Francisco, CA\",\n",
" }\n",
" },\n",
" \"required\": [\"location\"],\n",
" },\n",
" }\n",
" ],\n",
" tool_choice={\"type\": \"any\"},\n",
" stream=True,\n",
" messages=[{\"role\": \"user\", \"content\": \"What's the weather like in San Francisco?\"}],\n",
")\n",
"for event in stream:\n",
" print(event)\n",
"\n",
"\n",
" \n",
"# Only two chunks are being sent back where we expected several.\n",
"# \n",
"# 1. RawMessageStartEvent(message=Message(id='msg_015Ve4hQLg4DjJK5WUBFY2Dc', content=[], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason=None, stop_sequence=None, type='message', usage=Usage(input_tokens=366, output_tokens=10)), type='message_start')\n",
"# 2. RawContentBlockStartEvent(content_block=ToolUseBlock(id='toolu_01Jw9TVHwfUm5BQPXWz5zn15', input={}, name='get_weather', type='tool_use'), index=0, type='content_block_start')\n",
"# \n",
"# We can confirm this if we monkey patch the httpx client. Which you can see in the output below:\n",
"\n",
"# Request body: {\"max_tokens\": 2048, \"messages\": [{\"role\": \"user\", \"content\": \"What's the weather like in San Francisco?\"}], \"model\": \"claude-3-5-sonnet-20240620\", \"stream\": true, \"temperature\": 0.0, \"tool_choice\": {\"type\": \"any\"}, \"tools\": [{\"name\": \"get_weather\", \"description\": \"Get the current weather in a given location\", \"input_schema\": {\"type\": \"object\", \"properties\": {\"location\": {\"type\": \"string\", \"description\": \"The city and state, e.g. San Francisco, CA\"}}, \"required\": [\"location\"]}}]}\n",
"# [2024-09-13 16:03:52,173] #68695 INFO (httpx) - HTTP Request: POST https://api.anthropic.com/v1/messages \"HTTP/1.1 200 OK\"\n",
"# Response body: \n",
"# event: message_start\n",
"# data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01ReJV59o2NGBhuXNVBnNn75\",\"type\":\"message\",\"role\":\"assistant\",\"model\":\"claude-3-5-sonnet-20240620\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"usage\":{\"input_tokens\":366,\"output_tokens\":10}} }\n",
"\n",
"# event: content_block_start\n",
"# data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01BKidtwXDb5SXp3qkQLqx3g\",\"name\":\"get_weather\",\"input\":{}} }\n",
"\n",
"# event: ping\n",
"# data: {\"type\": \"ping\"}\n",
"\n",
"# event: content_block_delta\n",
"# data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"} }\n",
"\n",
"# event: content_block_delta\n",
"# data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"lo\"} }\n",
"\n",
"# event: content_block_delta\n",
"# data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"cation\\\": \\\"Sa\"} }\n",
"\n",
"# event: content_block_delta\n",
"# data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"n Francisco\"} }\n",
"\n",
"# event: content_block_delta\n",
"# data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\", C\"} }\n",
"\n",
"# event: content_block_delta\n",
"# data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"A\\\"}\"} }\n",
"\n",
"# event: content_block_stop\n",
"# data: {\"type\":\"content_block_stop\",\"index\":0 }\n",
"\n",
"# event: message_delta\n",
"# data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null},\"usage\":{\"output_tokens\":41} }\n",
"\n",
"# event: message_stop\n",
"# data: {\"type\":\"message_stop\" }"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Now with streaming and changing the tool choice to 'auto'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"stream = client.messages.create(\n",
" model=\"claude-3-5-sonnet-20240620\",\n",
" max_tokens=2048,\n",
" temperature=0.0,\n",
" tools=[\n",
" {\n",
" \"name\": \"get_weather\",\n",
" \"description\": \"Get the current weather in a given location\",\n",
" \"input_schema\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"location\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city and state, e.g. San Francisco, CA\",\n",
" }\n",
" },\n",
" \"required\": [\"location\"],\n",
" },\n",
" }\n",
" ],\n",
" tool_choice={\"type\": \"auto\"},\n",
" stream=True,\n",
" messages=[{\"role\": \"user\", \"content\": \"What's the weather like in San Francisco?\"}],\n",
")\n",
"for event in stream:\n",
" print(event)\n",
" \n",
" \n",
"# However if we change the tool choice to \"auto\" we get back all the chunks but still not inputs for the tool use.\n",
"\n",
"\n",
"# RawMessageStartEvent(message=Message(id='msg_0172tqQYZ6BdoV6eA6JMZS17', content=[], model='claude-3-5-sonnet-20240620', role='assistant', stop_reason=None, stop_sequence=None, type='message', usage=Usage(input_tokens=384, output_tokens=1)), type='message_start')\n",
"# RawContentBlockStartEvent(content_block=TextBlock(text='', type='text'), index=0, type='content_block_start')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text='Certainly', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text='!', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' I', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' can', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' help', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' you get', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' the current weather information', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' for San Francisco.', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' To', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' ', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=\"do that, I'll use\", type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' the get_weather function', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text='.', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' Let', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' me fetch', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' that', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' information', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' for you right', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text=' away', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockDeltaEvent(delta=TextDelta(text='.', type='text_delta'), index=0, type='content_block_delta')\n",
"# RawContentBlockStopEvent(index=0, type='content_block_stop')\n",
"# RawContentBlockStartEvent(content_block=ToolUseBlock(id='toolu_01K579Ws9JYaxt4jniaGxBcn', input={}, name='get_weather', type='tool_use'), index=1, type='content_block_start')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from anthropic import AsyncAnthropic\n",
"\n",
"a_client = AsyncAnthropic(api_key=os.environ.get(\"ANTHROPIC_API_KEY\"))\n",
"\n",
"async with a_client.messages.stream(\n",
" model=\"claude-3-5-sonnet-20240620\",\n",
" max_tokens=2048,\n",
" temperature=0.0,\n",
" tools=[\n",
" {\n",
" \"name\": \"get_weather\",\n",
" \"description\": \"Get the current weather in a given location\",\n",
" \"input_schema\": {\n",
" \"type\": \"object\",\n",
" \"properties\": {\n",
" \"location\": {\n",
" \"type\": \"string\",\n",
" \"description\": \"The city and state, e.g. San Francisco, CA\",\n",
" }\n",
" },\n",
" \"required\": [\"location\"],\n",
" },\n",
" }\n",
" ],\n",
" tool_choice={\"type\": \"any\"},\n",
" messages=[{\"role\": \"user\", \"content\": \"What's the weather like in San Francisco?\"}]\n",
") as stream:\n",
" async for text in stream.text_stream:\n",
" print(text, end=\"\", flush=True)\n",
" print()\n",
" \n",
"message = await stream.get_final_message()\n",
"print(message.to_json())\n",
"\n",
"# This is essentially the same thing as stream=True but it's clearer to see the expected output where the\n",
"# Tool call also provides an input arg.\n",
"\n",
"# Sending async request: POST https://api.anthropic.com/v1/messages\n",
"# Request body: {\"max_tokens\": 2048, \"messages\": [{\"role\": \"user\", \"content\": \"What's the weather like in San Francisco?\"}], \"model\": \"claude-3-5-sonnet-20240620\", \"temperature\": 0.0, \"tools\": [{\"name\": \"get_weather\", \"description\": \"Get the current weather in a given location\", \"input_schema\": {\"type\": \"object\", \"properties\": {\"location\": {\"type\": \"string\", \"description\": \"The city and state, e.g. San Francisco, CA\"}}, \"required\": [\"location\"]}}], \"tool_choice\": {\"type\": \"any\"}, \"stream\": true}\n",
"# [2024-09-13 16:03:53,495] #68695 INFO (httpx) - HTTP Request: POST https://api.anthropic.com/v1/messages \"HTTP/1.1 200 OK\"\n",
"\n",
"# {\n",
"# \"id\": \"msg_01Qsd7oBD9EcoAa12iyQSabZ\",\n",
"# \"content\": [\n",
"# {\n",
"# \"id\": \"toolu_01NKLPqDLZFYa5sXvYRfPUwp\",\n",
"# \"input\": {\n",
"# \"location\": \"San Francisco, CA\"\n",
"# },\n",
"# \"name\": \"get_weather\",\n",
"# \"type\": \"tool_use\"\n",
"# }\n",
"# ],\n",
"# \"model\": \"claude-3-5-sonnet-20240620\",\n",
"# \"role\": \"assistant\",\n",
"# \"stop_reason\": \"tool_use\",\n",
"# \"stop_sequence\": null,\n",
"# \"type\": \"message\",\n",
"# \"usage\": {\n",
"# \"input_tokens\": 366,\n",
"# \"output_tokens\": 41\n",
"# }\n",
"# }"
]
}
],
"metadata": {
"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.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment