You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
langchain/docs/docs/integrations/chat/anthropic.ipynb

679 lines
51 KiB
Plaintext

{
"cells": [
{
"cell_type": "raw",
"id": "a016701c",
"metadata": {},
"source": [
"---\n",
"sidebar_label: Anthropic\n",
"---"
]
},
{
"cell_type": "markdown",
"id": "bf733a38-db84-4363-89e2-de6735c37230",
"metadata": {},
"source": [
"# ChatAnthropic\n",
"\n",
"This notebook covers how to get started with Anthropic chat models.\n",
"\n",
"## Setup\n",
"\n",
"For setup instructions, please see the Installation and Environment Setup sections of the [Anthropic Platform page](/docs/integrations/platforms/anthropic.mdx)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "91be2e12",
"metadata": {},
"outputs": [],
"source": [
"%pip install -qU langchain-anthropic"
]
},
{
"cell_type": "markdown",
"id": "584ed5ec",
"metadata": {},
"source": [
"## Environment Setup\n",
"\n",
"We'll need to get an [Anthropic](https://console.anthropic.com/settings/keys) API key and set the `ANTHROPIC_API_KEY` environment variable:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "01578ae3",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from getpass import getpass\n",
"\n",
"os.environ[\"ANTHROPIC_API_KEY\"] = getpass()"
]
},
{
"cell_type": "markdown",
"id": "d1f9df276476f0bc",
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"source": [
"The code provided assumes that your ANTHROPIC_API_KEY is set in your environment variables. If you would like to manually specify your API key and also choose a different model, you can use the following code:\n",
"```python\n",
"chat = ChatAnthropic(temperature=0, api_key=\"YOUR_API_KEY\", model_name=\"claude-3-opus-20240229\")\n",
"\n",
"```\n",
"\n",
"In these demos, we will use the Claude 3 Opus model, and you can also use the launch version of the Sonnet model with `claude-3-sonnet-20240229`.\n",
"\n",
"You can check the model comparison doc [here](https://docs.anthropic.com/claude/docs/models-overview#model-comparison)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "238bdbaa-526a-4130-89e9-523aa44bb196",
"metadata": {},
"outputs": [],
"source": [
"from langchain_anthropic import ChatAnthropic\n",
"from langchain_core.prompts import ChatPromptTemplate"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8199ef8f-eb8b-4253-9ea0-6c24a013ca4c",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:07.274418Z",
"start_time": "2024-01-19T11:25:05.898031Z"
},
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='저는 파이썬을 사랑합니다.\\n\\nTranslation:\\nI love Python.')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat = ChatAnthropic(temperature=0, model_name=\"claude-3-opus-20240229\")\n",
"\n",
"system = (\n",
" \"You are a helpful assistant that translates {input_language} to {output_language}.\"\n",
")\n",
"human = \"{text}\"\n",
"prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])\n",
"\n",
"chain = prompt | chat\n",
"chain.invoke(\n",
" {\n",
" \"input_language\": \"English\",\n",
" \"output_language\": \"Korean\",\n",
" \"text\": \"I love Python\",\n",
" }\n",
")"
]
},
{
"cell_type": "markdown",
"id": "c361ab1e-8c0c-4206-9e3c-9d1424a12b9c",
"metadata": {},
"source": [
"## `ChatAnthropic` also supports async and streaming functionality:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "c5fac0e9-05a4-4fc1-a3b3-e5bbb24b971b",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:10.448733Z",
"start_time": "2024-01-19T11:25:08.866277Z"
},
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='Sure, here\\'s a joke about a bear:\\n\\nA bear walks into a bar and says to the bartender, \"I\\'ll have a pint of beer and a.......... packet of peanuts.\"\\n\\nThe bartender asks, \"Why the big pause?\"\\n\\nThe bear replies, \"I don\\'t know, I\\'ve always had them!\"')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat = ChatAnthropic(temperature=0, model_name=\"claude-3-opus-20240229\")\n",
"prompt = ChatPromptTemplate.from_messages([(\"human\", \"Tell me a joke about {topic}\")])\n",
"chain = prompt | chat\n",
"await chain.ainvoke({\"topic\": \"bear\"})"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "025be980-e50d-4a68-93dc-c9c7b500ce34",
"metadata": {
"ExecuteTime": {
"end_time": "2024-01-19T11:25:24.438696Z",
"start_time": "2024-01-19T11:25:14.687480Z"
},
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Here is a list of famous tourist attractions in Japan:\n",
"\n",
"1. Tokyo Skytree (Tokyo)\n",
"2. Senso-ji Temple (Tokyo)\n",
"3. Meiji Shrine (Tokyo)\n",
"4. Tokyo DisneySea (Urayasu, Chiba)\n",
"5. Fushimi Inari Taisha (Kyoto)\n",
"6. Kinkaku-ji (Golden Pavilion) (Kyoto)\n",
"7. Kiyomizu-dera (Kyoto)\n",
"8. Nijo Castle (Kyoto)\n",
"9. Osaka Castle (Osaka)\n",
"10. Dotonbori (Osaka)\n",
"11. Hiroshima Peace Memorial Park (Hiroshima)\n",
"12. Itsukushima Shrine (Miyajima Island, Hiroshima)\n",
"13. Himeji Castle (Himeji)\n",
"14. Todai-ji Temple (Nara)\n",
"15. Nara Park (Nara)\n",
"16. Mount Fuji (Shizuoka and Yamanashi Prefectures)\n",
"17."
]
}
],
"source": [
"chat = ChatAnthropic(temperature=0.3, model_name=\"claude-3-opus-20240229\")\n",
"prompt = ChatPromptTemplate.from_messages(\n",
" [(\"human\", \"Give me a list of famous tourist attractions in Japan\")]\n",
")\n",
"chain = prompt | chat\n",
"for chunk in chain.stream({}):\n",
" print(chunk.content, end=\"\", flush=True)"
]
},
{
"cell_type": "markdown",
"id": "ab0174d8-7140-413c-80a9-7cf3a8b81bb4",
"metadata": {},
"source": [
"## [Beta] Tool-calling\n",
"\n",
"With Anthropic's [tool-calling, or tool-use, API](https://docs.anthropic.com/claude/docs/functions-external-tools), you can define tools for the model to invoke. This is extremely useful for building tool-using chains and agents, as well as for getting structured outputs from a model.\n",
"\n",
":::note\n",
"\n",
"Anthropic's tool-calling functionality is still in beta.\n",
"\n",
":::\n",
"\n",
"### bind_tools()\n",
"\n",
"With `ChatAnthropic.bind_tools`, we can easily pass in Pydantic classes, dict schemas, LangChain tools, or even functions as tools to the model. Under the hood these are converted to an Anthropic tool schemas, which looks like:\n",
"```\n",
"{\n",
" \"name\": \"...\",\n",
" \"description\": \"...\",\n",
" \"input_schema\": {...} # JSONSchema\n",
"}\n",
"```\n",
"and passed in every model invocation."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "42f87466-cb8e-490d-a9f8-aa0f8e9b4217",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/bagatur/langchain/libs/core/langchain_core/_api/beta_decorator.py:87: LangChainBetaWarning: The function `bind_tools` is in beta. It is actively being worked on, so the API may change.\n",
" warn_beta(\n"
]
}
],
"source": [
"from langchain_core.pydantic_v1 import BaseModel, Field\n",
"\n",
"llm = ChatAnthropic(model=\"claude-3-opus-20240229\", temperature=0)\n",
"\n",
"\n",
"class GetWeather(BaseModel):\n",
" \"\"\"Get the current weather in a given location\"\"\"\n",
"\n",
" location: str = Field(..., description=\"The city and state, e.g. San Francisco, CA\")\n",
"\n",
"\n",
"llm_with_tools = llm.bind_tools([GetWeather])"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "997be6ff-3fd3-4b1c-b7e3-2e5fed4ac964",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content=[{'text': '<thinking>\\nThe user is asking about the current weather in a specific location, San Francisco. The relevant tool to answer this is the GetWeather function.\\n\\nLooking at the parameters for GetWeather:\\n- location (required): The user directly provided the location in the query - \"San Francisco\"\\n\\nSince the required \"location\" parameter is present, we can proceed with calling the GetWeather function.\\n</thinking>', 'type': 'text'}, {'id': 'toolu_01StzxdWQSZhAMbR1CCchQV9', 'input': {'location': 'San Francisco, CA'}, 'name': 'GetWeather', 'type': 'tool_use'}], response_metadata={'id': 'msg_01HepCTzqXJed5iNuLgV1VCZ', 'model': 'claude-3-opus-20240229', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'input_tokens': 487, 'output_tokens': 143}}, id='run-1a1b3289-ba2c-47ae-8be1-8929d7cc547e-0', tool_calls=[{'name': 'GetWeather', 'args': {'location': 'San Francisco, CA'}, 'id': 'toolu_01StzxdWQSZhAMbR1CCchQV9'}])"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ai_msg = llm_with_tools.invoke(\n",
" \"what is the weather like in San Francisco\",\n",
")\n",
"ai_msg"
]
},
{
"cell_type": "markdown",
"id": "1e63ac67-8c42-4468-8178-e54f13c3c5c3",
"metadata": {},
"source": [
"Notice that the output message content is a list that contains a text block and then a tool_use block:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "7c4cd4c4-1c78-4d6c-8607-759e32a8903b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'text': '<thinking>\\nThe user is asking about the current weather in a specific location, San Francisco. The relevant tool to answer this is the GetWeather function.\\n\\nLooking at the parameters for GetWeather:\\n- location (required): The user directly provided the location in the query - \"San Francisco\"\\n\\nSince the required \"location\" parameter is present, we can proceed with calling the GetWeather function.\\n</thinking>',\n",
" 'type': 'text'},\n",
" {'id': 'toolu_01StzxdWQSZhAMbR1CCchQV9',\n",
" 'input': {'location': 'San Francisco, CA'},\n",
" 'name': 'GetWeather',\n",
" 'type': 'tool_use'}]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ai_msg.content"
]
},
{
"cell_type": "markdown",
"id": "d446bd0f-06cc-4aa6-945d-74335d5a8780",
"metadata": {},
"source": [
"Crucially, the tool calls are also extracted into the `tool_calls` where they are in a standardized, model-agnostic format:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "e36f254e-bb89-4978-9351-a463b13eb3c7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'name': 'GetWeather',\n",
" 'args': {'location': 'San Francisco, CA'},\n",
" 'id': 'toolu_01StzxdWQSZhAMbR1CCchQV9'}]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ai_msg.tool_calls"
]
},
{
"cell_type": "markdown",
"id": "90e015e0-c6e5-4ff5-8fb9-be0cd3c86395",
"metadata": {},
"source": [
"::: {.callout-tip}\n",
"\n",
"ChatAnthropic model outputs are always a single AI message that can have either a single string or a list of content blocks. The content blocks can be text blocks or tool-duse blocks. There can be multiple of each and they can be interspersed.\n",
"\n",
":::"
]
},
{
"cell_type": "markdown",
"id": "8652ee98-814c-4ed6-9def-275eeaa9651e",
"metadata": {},
"source": [
"### Parsing tool calls\n",
"\n",
"The `langchain_anthropic.output_parsers.ToolsOutputParser` makes it easy to parse the tool calls from an Anthropic AI message into Pydantic objects if we'd like:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "59c175b1-0929-4ed4-a608-f0006031a3c2",
"metadata": {},
"outputs": [],
"source": [
"from langchain_anthropic.output_parsers import ToolsOutputParser"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "08f6c62c-923b-400e-9bc8-8aff417466b2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[GetWeather(location='New York City, NY'),\n",
" GetWeather(location='Los Angeles, CA'),\n",
" GetWeather(location='San Francisco, CA'),\n",
" GetWeather(location='Cleveland, OH')]"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parser = ToolsOutputParser(pydantic_schemas=[GetWeather])\n",
"chain = llm_with_tools | parser\n",
"chain.invoke(\"What is the weather like in nyc, la, sf and cleveland\")"
]
},
{
"cell_type": "markdown",
"id": "ab05dd51-0a9e-4b7b-b182-65cec44941ac",
"metadata": {},
"source": [
"### with_structured_output()\n",
"\n",
"The [BaseChatModel.with_structured_output interface](/docs/modules/model_io/chat/structured_output) makes it easy to get structured output from chat models. You can use `ChatAnthropic.with_structured_output`, which uses tool-calling under the hood), to get the model to more reliably return an output in a specific format:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "e047b831-2338-4c2d-9ee4-0763f74e80e1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"GetWeather(location='San Francisco, CA')"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"structured_llm = llm.with_structured_output(GetWeather)\n",
"structured_llm.invoke(\n",
" \"what is the weather like in San Francisco\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "2d74b83e-bcd3-47e6-911e-82b5dcfbd20e",
"metadata": {},
"source": [
"The main difference between using \n",
"```python\n",
"llm.with_structured_output(GetWeather)\n",
"``` \n",
"vs \n",
"\n",
"```python\n",
"llm.bind_tools([GetWeather]) | ToolsOutputParser(pydantic_schemas=[GetWeather])\n",
"``` \n",
"is that it will return only the first GetWeather call, whereas the second approach will return a list."
]
},
{
"cell_type": "markdown",
"id": "5b61884e-3e4e-4145-b10d-188987ae1eb6",
"metadata": {},
"source": [
"### Passing tool results to model\n",
"\n",
"We can use `ToolMessage`s with the appropriate `tool_call_id`s to pass tool results back to the model:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "9d07a1c1-4542-440e-a1fb-392542267fb8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='Based on calling the GetWeather function, the weather in San Francisco, CA is:\\nRain with a high temperature of 54°F and winds from the southwest at 15-25 mph. There is a 100% chance of rain.', response_metadata={'id': 'msg_01J7nWVRPPTgae4eDpf9yR3M', 'model': 'claude-3-opus-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 670, 'output_tokens': 56}}, id='run-44fcd34f-9c24-464f-94dd-63bd0d22870d-0')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import AIMessage, HumanMessage, ToolMessage\n",
"\n",
"messages = [\n",
" HumanMessage(\"What is the weather like in San Francisco\"),\n",
" AIMessage(\n",
" content=[\n",
" {\n",
" \"text\": '<thinking>\\nBased on the user\\'s question, the relevant function to call is GetWeather, which requires the \"location\" parameter.\\n\\nThe user has directly specified the location as \"San Francisco\". Since San Francisco is a well known city, I can reasonably infer they mean San Francisco, CA without needing the state specified.\\n\\nAll the required parameters are provided, so I can proceed with the API call.\\n</thinking>',\n",
" \"type\": \"text\",\n",
" },\n",
" {\n",
" \"type\": \"tool_use\",\n",
" \"id\": \"toolu_01SCgExKzQ7eqSkMHfygvYuu\",\n",
" \"name\": \"GetWeather\",\n",
" \"input\": {\"location\": \"San Francisco, CA\"},\n",
" \"text\": None,\n",
" },\n",
" ],\n",
" ),\n",
" ToolMessage(\n",
" \"Rain. High 54F. Winds SW at 15 to 25 mph. Chance of rain 100%.\",\n",
" tool_call_id=\"toolu_01SCgExKzQ7eqSkMHfygvYuu\",\n",
" ),\n",
"]\n",
"llm_with_tools.invoke(messages)"
]
},
{
"cell_type": "markdown",
"id": "1c82d198-77ce-4d5a-a65b-a98fd3c10740",
"metadata": {},
"source": [
"### Streaming\n",
"\n",
"::: {.callout-warning}\n",
"\n",
"Anthropic does not currently support streaming tool calls. Attempting to stream will yield a single final message.\n",
"\n",
":::"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "d1284ddc-eb82-44be-b034-5046809536de",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/bagatur/langchain/libs/partners/anthropic/langchain_anthropic/chat_models.py:328: UserWarning: stream: Tool use is not yet supported in streaming mode.\n",
" warnings.warn(\"stream: Tool use is not yet supported in streaming mode.\")\n"
]
},
{
"data": {
"text/plain": [
"[AIMessage(content=[{'text': '<thinking>\\nThe user is asking for the current weather in a specific location, San Francisco. The GetWeather function is the relevant tool to answer this request, as it returns the current weather for a given location.\\n\\nThe GetWeather function has one required parameter:\\nlocation: The city and state, e.g. San Francisco, CA\\n\\nThe user provided the city San Francisco in their request. They did not specify the state, but it can be reasonably inferred that they are referring to San Francisco, California since that is the most well known city with that name.\\n\\nSince the required location parameter has been provided by the user, we can proceed with calling the GetWeather function.\\n</thinking>', 'type': 'text'}, {'text': None, 'type': 'tool_use', 'id': 'toolu_01V9ZripoQzuY8HubspJy6fP', 'name': 'GetWeather', 'input': {'location': 'San Francisco, CA'}}], id='run-b825206b-5b6b-48bc-ad8d-802dee310c7f')]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(llm_with_tools.stream(\"What's the weather in san francisco\"))"
]
},
{
"cell_type": "markdown",
"id": "70d5e0fb",
"metadata": {},
"source": [
"## Multimodal\n",
"\n",
"Anthropic's Claude-3 models are compatible with both image and text inputs. You can use this as follows:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "3e9d1ab5",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\"/>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# open ../../../static/img/brand/wordmark.png as base64 str\n",
"import base64\n",
"from pathlib import Path\n",
"\n",
"from IPython.display import HTML\n",
"\n",
"img_path = Path(\"../../../static/img/brand/wordmark.png\")\n",
"img_base64 = base64.b64encode(img_path.read_bytes()).decode(\"utf-8\")\n",
"\n",
"# display b64 image in notebook\n",
"HTML(f'<img src=\"data:image/png;base64,{img_base64}\"/>')"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "b6bb2aa2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='This logo is for LangChain, which appears to be some kind of software or technology platform based on the name and minimalist design style of the logo featuring a silhouette of a bird (likely an eagle or hawk) and the company name in a simple, modern font.')"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import HumanMessage\n",
"\n",
"chat = ChatAnthropic(model=\"claude-3-opus-20240229\")\n",
"messages = [\n",
" HumanMessage(\n",
" content=[\n",
" {\n",
" \"type\": \"image_url\",\n",
" \"image_url\": {\n",
" # langchain logo\n",
" \"url\": f\"data:image/png;base64,{img_base64}\", # noqa: E501\n",
" },\n",
" },\n",
" {\"type\": \"text\", \"text\": \"What is this logo for?\"},\n",
" ]\n",
" )\n",
"]\n",
"chat.invoke(messages)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}