diff --git a/docs/docs/integrations/chat/naver.ipynb b/docs/docs/integrations/chat/naver.ipynb index c44d6f9e07b..4997c10b485 100644 --- a/docs/docs/integrations/chat/naver.ipynb +++ b/docs/docs/integrations/chat/naver.ipynb @@ -1,356 +1,651 @@ { - "cells": [ - { - "cell_type": "raw", - "id": "afaf8039", - "metadata": {}, - "source": [ - "---\n", - "sidebar_label: Naver\n", - "---" - ] - }, - { - "cell_type": "markdown", - "id": "c8444f1a-e907-4f07-b8b6-68fbedfb868e", - "metadata": {}, - "source": [ - "# ChatClovaX\n", - "\n", - "This notebook provides a quick overview for getting started with Naver’s HyperCLOVA X [chat models](https://python.langchain.com/docs/concepts/chat_models) via CLOVA Studio. For detailed documentation of all ChatClovaX features and configurations head to the [API reference](https://guide.ncloud-docs.com/docs/clovastudio-dev-langchain).\n", - "\n", - "[CLOVA Studio](http://clovastudio.ncloud.com/) has several chat models. You can find information about latest models and their costs, context windows, and supported input types in the CLOVA Studio Guide [documentation](https://guide.ncloud-docs.com/docs/clovastudio-model).\n", - "\n", - "## Overview\n", - "### Integration details\n", - "\n", - "| Class | Package | Local | Serializable | JS support | Package downloads | Package latest |\n", - "| :--- | :--- |:-----:| :---: |:------------------------------------------------------------------------:| :---: | :---: |\n", - "| [ChatClovaX](https://guide.ncloud-docs.com/docs/clovastudio-dev-langchain#HyperCLOVAX%EB%AA%A8%EB%8D%B8%EC%9D%B4%EC%9A%A9) | [langchain-naver](https://pypi.org/project/langchain-naver/) | ❌ | ❌ | ❌ | ![PyPI - Downloads](https://img.shields.io/pypi/dm/langchain_naver?style=flat-square&label=%20) | ![PyPI - Version](https://img.shields.io/pypi/v/langchain_naver?style=flat-square&label=%20) |\n", - "\n", - "### Model features\n", - "| [Tool calling](/docs/how_to/tool_calling/) | [Structured output](/docs/how_to/structured_output/) | JSON mode | [Image input](/docs/how_to/multimodal_inputs/) | Audio input | Video input | [Token-level streaming](/docs/how_to/chat_streaming/) | Native async | [Token usage](/docs/how_to/chat_token_usage_tracking/) | [Logprobs](/docs/how_to/logprobs/) |\n", - "|:------------------------------------------:| :---: | :---: | :---: | :---: | :---: |:-----------------------------------------------------:| :---: |:------------------------------------------------------:|:----------------------------------:|\n", - "|✅| ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ |\n", - "\n", - "## Setup\n", - "\n", - "Before using the chat model, you must go through the four steps below.\n", - "\n", - "1. Creating [NAVER Cloud Platform](https://www.ncloud.com/) account\n", - "2. Apply to use [CLOVA Studio](https://www.ncloud.com/product/aiService/clovaStudio)\n", - "3. Create a CLOVA Studio Test App or Service App of a model to use (See [here](https://guide.ncloud-docs.com/docs/clovastudio-playground-testapp).)\n", - "4. Issue a Test or Service API key (See [here](https://api.ncloud-docs.com/docs/ai-naver-clovastudio-summary#API%ED%82%A4).)\n", - "\n", - "### Credentials\n", - "\n", - "Set the `CLOVASTUDIO_API_KEY` environment variable with your API key.\n", - "\n", - "You can add them to your environment variables as below:\n", - "\n", - "``` bash\n", - "export CLOVASTUDIO_API_KEY=\"your-api-key-here\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "2def81b5-b023-4f40-a97b-b2c5ca59d6a9", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "if not os.getenv(\"CLOVASTUDIO_API_KEY\"):\n", - " os.environ[\"CLOVASTUDIO_API_KEY\"] = getpass.getpass(\n", - " \"Enter your CLOVA Studio API Key: \"\n", - " )" - ] - }, - { - "cell_type": "markdown", - "id": "7c695442", - "metadata": {}, - "source": [ - "To enable automated tracing of your model calls, set your [LangSmith](https://docs.smith.langchain.com/) API key:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6151aeb6", - "metadata": {}, - "outputs": [], - "source": [ - "# os.environ[\"LANGSMITH_TRACING\"] = \"true\"\n", - "# os.environ[\"LANGSMITH_API_KEY\"] = getpass.getpass(\"Enter your LangSmith API key: \")" - ] - }, - { - "cell_type": "markdown", - "id": "17bf9053-90c5-4955-b239-55a35cb07566", - "metadata": {}, - "source": [ - "### Installation\n", - "\n", - "The LangChain Naver integration lives in the `langchain-naver` package:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a15d341e-3e26-4ca3-830b-5aab30ed66de", - "metadata": {}, - "outputs": [], - "source": [ - "# install package\n", - "%pip install -qU langchain-naver" - ] - }, - { - "cell_type": "markdown", - "id": "a38cde65-254d-4219-a441-068766c0d4b5", - "metadata": {}, - "source": [ - "## Instantiation\n", - "\n", - "Now we can instantiate our model object and generate chat completions:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "cb09c344-1836-4e0c-acf8-11d13ac1dbae", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain_naver import ChatClovaX\n", - "\n", - "chat = ChatClovaX(\n", - " model=\"HCX-005\",\n", - " temperature=0.5,\n", - " max_tokens=None,\n", - " timeout=None,\n", - " max_retries=2,\n", - " # other params...\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "47752b59", - "metadata": {}, - "source": [ - "## Invocation\n", - "\n", - "In addition to invoke, `ChatClovaX` also support batch and stream functionalities." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "62e0dbc3", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "data": { - "text/plain": [ - "AIMessage(content='네이버 인공지능을 사용하는 것을 정말 좋아합니다.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 28, 'total_tokens': 39, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'HCX-005', 'system_fingerprint': None, 'id': 'b70c26671cd247a0864115bacfb5fc12', 'finish_reason': 'stop', 'logprobs': None}, id='run-3faf6a8d-d5da-49ad-9fbb-7b56ed23b484-0', usage_metadata={'input_tokens': 28, 'output_tokens': 11, 'total_tokens': 39, 'input_token_details': {}, 'output_token_details': {}})" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "messages = [\n", - " (\n", - " \"system\",\n", - " \"You are a helpful assistant that translates English to Korean. Translate the user sentence.\",\n", - " ),\n", - " (\"human\", \"I love using NAVER AI.\"),\n", - "]\n", - "\n", - "ai_msg = chat.invoke(messages)\n", - "ai_msg" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "24e7377f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "네이버 인공지능을 사용하는 것을 정말 좋아합니다.\n" - ] - } - ], - "source": [ - "print(ai_msg.content)" - ] - }, - { - "cell_type": "markdown", - "id": "18e2bfc0-7e78-4528-a73f-499ac150dca8", - "metadata": {}, - "source": [ - "## Chaining\n", - "\n", - "We can [chain](/docs/how_to/sequence/) our model with a prompt template like so:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "e197d1d7-a070-4c96-9f8a-a0e86d046e0b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "AIMessage(content='저는 네이버 인공지능을 사용하는 것을 좋아합니다.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 28, 'total_tokens': 38, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'HCX-005', 'system_fingerprint': None, 'id': 'b7a826d17fcf4fee8386fca2ebc63284', 'finish_reason': 'stop', 'logprobs': None}, id='run-35957816-3325-4d9c-9441-e40704912be6-0', usage_metadata={'input_tokens': 28, 'output_tokens': 10, 'total_tokens': 38, 'input_token_details': {}, 'output_token_details': {}})" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from langchain_core.prompts import ChatPromptTemplate\n", - "\n", - "prompt = ChatPromptTemplate.from_messages(\n", - " [\n", - " (\n", - " \"system\",\n", - " \"You are a helpful assistant that translates {input_language} to {output_language}. Translate the user sentence.\",\n", - " ),\n", - " (\"human\", \"{input}\"),\n", - " ]\n", - ")\n", - "\n", - "chain = prompt | chat\n", - "chain.invoke(\n", - " {\n", - " \"input_language\": \"English\",\n", - " \"output_language\": \"Korean\",\n", - " \"input\": \"I love using NAVER AI.\",\n", - " }\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "66e69286", - "metadata": {}, - "source": [ - "## Streaming" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "2c07af21-dda5-4514-b4de-1f214c2cebcd", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "In Korean, the informal way of saying 'hi' is \"안녕\" (annyeong). If you're addressing someone older or showing more respect, you would use \"안녕하세요\" (annjeonghaseyo). Both phrases are used as greetings similar to 'hello'. Remember, pronunciation is key so make sure to pronounce each syllable clearly: 안-녀-엉 (an-nyeo-eong) and 안-녕-하-세-요 (an-nyeong-ha-se-yo)." - ] - } - ], - "source": [ - "system = \"You are a helpful assistant that can teach Korean pronunciation.\"\n", - "human = \"Could you let me know how to say '{phrase}' in Korean?\"\n", - "prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])\n", - "\n", - "chain = prompt | chat\n", - "\n", - "for chunk in chain.stream({\"phrase\": \"Hi\"}):\n", - " print(chunk.content, end=\"\", flush=True)" - ] - }, - { - "cell_type": "markdown", - "id": "d1ee55bc-ffc8-4cfa-801c-993953a08cfd", - "metadata": {}, - "source": [ - "## Additional functionalities\n", - "\n", - "### Using fine-tuned models\n", - "\n", - "You can call fine-tuned models by passing the `task_id` to the `model` parameter as: `ft:{task_id}`.\n", - "\n", - "You can check `task_id` from corresponding Test App or Service App details." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cb436788", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "AIMessage(content='네이버 인공지능을 사용하는 것을 정말 좋아합니다.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 28, 'total_tokens': 39, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'HCX-005', 'system_fingerprint': None, 'id': '2222d6d411a948c883aac1e03ca6cebe', 'finish_reason': 'stop', 'logprobs': None}, id='run-9696d7e2-7afa-4bb4-9c03-b95fcf678ab8-0', usage_metadata={'input_tokens': 28, 'output_tokens': 11, 'total_tokens': 39, 'input_token_details': {}, 'output_token_details': {}})" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fine_tuned_model = ChatClovaX(\n", - " model=\"ft:a1b2c3d4\", # set as `ft:{task_id}` with your fine-tuned model's task id\n", - " # other params...\n", - ")\n", - "\n", - "fine_tuned_model.invoke(messages)" - ] - }, - { - "cell_type": "markdown", - "id": "3a5bb5ca-c3ae-4a58-be67-2cd18574b9a3", - "metadata": {}, - "source": [ - "## API reference\n", - "\n", - "For detailed documentation of all ChatClovaX features and configurations head to the [API reference](https://guide.ncloud-docs.com/docs/clovastudio-dev-langchain)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.8" - } + "cells": [ + { + "cell_type": "raw", + "id": "afaf8039", + "metadata": {}, + "source": [ + "---\n", + "sidebar_label: Naver\n", + "---" + ] }, - "nbformat": 4, - "nbformat_minor": 5 + { + "cell_type": "markdown", + "id": "c8444f1a-e907-4f07-b8b6-68fbedfb868e", + "metadata": {}, + "source": [ + "# ChatClovaX\n", + "\n", + "This notebook provides a quick overview for getting started with Naver’s HyperCLOVA X [chat models](https://python.langchain.com/docs/concepts/chat_models) via CLOVA Studio. For detailed documentation of all ChatClovaX features and configurations head to the [API reference](https://guide.ncloud-docs.com/docs/clovastudio-dev-langchain).\n", + "\n", + "[CLOVA Studio](http://clovastudio.ncloud.com/) has several chat models. You can find information about the latest models, including their costs, context windows, and supported input types, in the CLOVA Studio Guide [documentation](https://guide.ncloud-docs.com/docs/clovastudio-model).\n", + "\n", + "## Overview\n", + "### Integration details\n", + "\n", + "| Class | Package | Local | Serializable | JS support | Package downloads | Package latest |\n", + "| :--- | :--- |:-----:| :---: |:------------------------------------------------------------------------:| :---: | :---: |\n", + "| [ChatClovaX](https://guide.ncloud-docs.com/docs/clovastudio-dev-langchain#HyperCLOVAX%EB%AA%A8%EB%8D%B8%EC%9D%B4%EC%9A%A9) | [langchain-naver](https://pypi.org/project/langchain-naver/) | ❌ | ❌ | ❌ | ![PyPI - Downloads](https://img.shields.io/pypi/dm/langchain_naver?style=flat-square&label=%20) | ![PyPI - Version](https://img.shields.io/pypi/v/langchain_naver?style=flat-square&label=%20) |\n", + "\n", + "### Model features\n", + "| [Tool calling](/docs/how_to/tool_calling/) | [Structured output](/docs/how_to/structured_output/) | JSON mode | [Image input](/docs/how_to/multimodal_inputs/) | Audio input | Video input | [Token-level streaming](/docs/how_to/chat_streaming/) | Native async | [Token usage](/docs/how_to/chat_token_usage_tracking/) | [Logprobs](/docs/how_to/logprobs/) |\n", + "|:------------------------------------------:| :---: | :---: | :---: | :---: | :---: |:-----------------------------------------------------:| :---: |:------------------------------------------------------:|:----------------------------------:|\n", + "|✅| ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ |\n", + "\n", + "## Setup\n", + "\n", + "Before using the chat model, you must go through the four steps below.\n", + "\n", + "1. Creating [NAVER Cloud Platform](https://www.ncloud.com/) account\n", + "2. Apply to use [CLOVA Studio](https://www.ncloud.com/product/aiService/clovaStudio)\n", + "3. Create a CLOVA Studio Test App or Service App of a model to use (See [here](https://guide.ncloud-docs.com/docs/clovastudio-playground-testapp).)\n", + "4. Issue a Test or Service API key (See [here](https://api.ncloud-docs.com/docs/ai-naver-clovastudio-summary#API%ED%82%A4).)\n", + "\n", + "### Credentials\n", + "\n", + "Set the `CLOVASTUDIO_API_KEY` environment variable with your API key.\n", + "\n", + "You can add them to your environment variables as below:\n", + "\n", + "``` bash\n", + "export CLOVASTUDIO_API_KEY=\"your-api-key-here\"\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2def81b5-b023-4f40-a97b-b2c5ca59d6a9", + "metadata": {}, + "outputs": [], + "source": [ + "import getpass\n", + "import os\n", + "\n", + "if not os.getenv(\"CLOVASTUDIO_API_KEY\"):\n", + " os.environ[\"CLOVASTUDIO_API_KEY\"] = getpass.getpass(\n", + " \"Enter your CLOVA Studio API Key: \"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "7c695442", + "metadata": {}, + "source": [ + "To enable automated tracing of your model calls, set your [LangSmith](https://docs.smith.langchain.com/) API key:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6151aeb6", + "metadata": {}, + "outputs": [], + "source": [ + "# os.environ[\"LANGSMITH_TRACING\"] = \"true\"\n", + "# os.environ[\"LANGSMITH_API_KEY\"] = getpass.getpass(\"Enter your LangSmith API key: \")" + ] + }, + { + "cell_type": "markdown", + "id": "17bf9053-90c5-4955-b239-55a35cb07566", + "metadata": {}, + "source": [ + "### Installation\n", + "\n", + "The LangChain Naver integration lives in the `langchain-naver` package:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a15d341e-3e26-4ca3-830b-5aab30ed66de", + "metadata": {}, + "outputs": [], + "source": [ + "# install package\n", + "%pip install -qU langchain-naver" + ] + }, + { + "cell_type": "markdown", + "id": "a38cde65-254d-4219-a441-068766c0d4b5", + "metadata": {}, + "source": [ + "## Instantiation\n", + "\n", + "Now we can instantiate our model object and generate chat completions:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "cb09c344-1836-4e0c-acf8-11d13ac1dbae", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_naver import ChatClovaX\n", + "\n", + "chat = ChatClovaX(\n", + " model=\"HCX-005\",\n", + " temperature=0.5,\n", + " max_tokens=None,\n", + " timeout=None,\n", + " max_retries=2,\n", + " # other params...\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "47752b59", + "metadata": {}, + "source": [ + "## Invocation\n", + "\n", + "In addition to `invoke` below, `ChatClovaX` also supports batch, stream and their async functionalities." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "62e0dbc3", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "AIMessage(content='네이버 인공지능을 사용하는 것이 정말 좋아요.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 28, 'total_tokens': 38, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'HCX-005', 'system_fingerprint': None, 'id': 'd685424a78d34009a7b07f5b0110a10b', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--9bd4df90-d88d-4f9a-b208-c41760f107f8-0', usage_metadata={'input_tokens': 28, 'output_tokens': 10, 'total_tokens': 38, 'input_token_details': {}, 'output_token_details': {}})" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "messages = [\n", + " (\n", + " \"system\",\n", + " \"You are a helpful assistant that translates English to Korean. Translate the user sentence.\",\n", + " ),\n", + " (\"human\", \"I love using NAVER AI.\"),\n", + "]\n", + "\n", + "ai_msg = chat.invoke(messages)\n", + "ai_msg" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "24e7377f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "네이버 인공지능을 사용하는 것이 정말 좋아요.\n" + ] + } + ], + "source": [ + "print(ai_msg.content)" + ] + }, + { + "cell_type": "markdown", + "id": "18e2bfc0-7e78-4528-a73f-499ac150dca8", + "metadata": {}, + "source": [ + "## Chaining\n", + "\n", + "We can [chain](/docs/how_to/sequence/) our model with a prompt template like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e197d1d7-a070-4c96-9f8a-a0e86d046e0b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AIMessage(content='저는 NAVER AI를 사용하는 것을 좋아합니다.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 28, 'total_tokens': 39, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'HCX-005', 'system_fingerprint': None, 'id': '3918787e422846958cbf995cc93ee7a4', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--1a78accd-be5d-4a03-ad8b-7753d4d47ffd-0', usage_metadata={'input_tokens': 28, 'output_tokens': 11, 'total_tokens': 39, 'input_token_details': {}, 'output_token_details': {}})" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from langchain_core.prompts import ChatPromptTemplate\n", + "\n", + "prompt = ChatPromptTemplate.from_messages(\n", + " [\n", + " (\n", + " \"system\",\n", + " \"You are a helpful assistant that translates {input_language} to {output_language}. Translate the user sentence.\",\n", + " ),\n", + " (\"human\", \"{input}\"),\n", + " ]\n", + ")\n", + "\n", + "chain = prompt | chat\n", + "chain.invoke(\n", + " {\n", + " \"input_language\": \"English\",\n", + " \"output_language\": \"Korean\",\n", + " \"input\": \"I love using NAVER AI.\",\n", + " }\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "66e69286", + "metadata": {}, + "source": [ + "## Streaming" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2c07af21-dda5-4514-b4de-1f214c2cebcd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "In Korean, 'Hi' is typically translated as '안녕하세요' (annyeonghaseyo). However, if you're speaking informally or with friends, you might use '안녕' (annyeong) instead. Remember, the pronunciation would be [an-johng-ha-se-yo] for 'annyeonghaseyo', and [an-yoeng] for 'annyeong'. The stress usually falls on the second syllable of each word. Keep practicing!" + ] + } + ], + "source": [ + "system = \"You are a helpful assistant that can teach Korean pronunciation.\"\n", + "human = \"Could you let me know how to say '{phrase}' in Korean?\"\n", + "prompt = ChatPromptTemplate.from_messages([(\"system\", system), (\"human\", human)])\n", + "\n", + "chain = prompt | chat\n", + "\n", + "for chunk in chain.stream({\"phrase\": \"Hi\"}):\n", + " print(chunk.content, end=\"\", flush=True)" + ] + }, + { + "cell_type": "markdown", + "id": "2cbb0e5d", + "metadata": {}, + "source": [ + "## Tool calling\n", + "\n", + "CLOVA Studio supports tool calling (also known as \"[function calling](https://api.ncloud-docs.com/docs/clovastudio-chatcompletionsv3-fc)\") that lets you describe tools and their arguments, and have the model return a JSON object with a tool to invoke and the inputs to that tool. It is extremely useful for building tool-using chains and agents, and for getting structured outputs from models more generally.\n", + "\n", + "**Note**: You should set `max_tokens` larger than 1024 to utilize the tool calling feature in CLOVA Studio. \n", + "\n", + "### ChatClovaX.bind_tools()\n", + "\n", + "With `ChatClovaX.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 OpenAI-compatible tool schemas, which looks like:\n", + "\n", + "```\n", + "{\n", + " \"name\": \"...\",\n", + " \"description\": \"...\",\n", + " \"parameters\": {...} # JSONSchema\n", + "}\n", + "```\n", + "\n", + "and passed in every model invocation." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "3fd50ca3", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_naver import ChatClovaX\n", + "\n", + "chat = ChatClovaX(\n", + " model=\"HCX-005\",\n", + " max_tokens=1024, # Set max tokens larger than 1024 to use tool calling\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "963ce9af", + "metadata": {}, + "outputs": [], + "source": [ + "from pydantic import BaseModel, Field\n", + "\n", + "\n", + "class GetWeather(BaseModel):\n", + " \"\"\"Get the current weather in a given location\"\"\"\n", + "\n", + " location: str = Field(\n", + " ..., description=\"The city and province, e.g. Seongnam-si, Gyeonggi-do\"\n", + " )\n", + "\n", + "\n", + "chat_with_tools = chat.bind_tools([GetWeather])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "138bb069", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_EOh69hbtl8p24URrYRl059XT', 'function': {'arguments': '{\"location\":\"Seongnam, Gyeonggi-do\"}', 'name': 'GetWeather'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 37, 'prompt_tokens': 16, 'total_tokens': 53, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'HCX-005', 'system_fingerprint': None, 'id': '085c74d930a84dc7b7cb59fde476e710', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--f3b46b02-81fe-4ab3-bcb5-f0a6cb7f2be0-0', tool_calls=[{'name': 'GetWeather', 'args': {'location': 'Seongnam, Gyeonggi-do'}, 'id': 'call_EOh69hbtl8p24URrYRl059XT', 'type': 'tool_call'}], usage_metadata={'input_tokens': 16, 'output_tokens': 37, 'total_tokens': 53, 'input_token_details': {}, 'output_token_details': {}})" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ai_msg = chat_with_tools.invoke(\n", + " \"what is the weather like in Bundang-gu?\",\n", + ")\n", + "ai_msg" + ] + }, + { + "cell_type": "markdown", + "id": "11ec57b2", + "metadata": {}, + "source": [ + "### AIMessage.tool_calls\n", + "\n", + "Notice that the AIMessage has a `tool_calls` attribute. This contains in a standardized ToolCall format that is model-provider agnostic." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "265605a1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'name': 'GetWeather',\n", + " 'args': {'location': 'Seongnam, Gyeonggi-do'},\n", + " 'id': 'call_EOh69hbtl8p24URrYRl059XT',\n", + " 'type': 'tool_call'}]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ai_msg.tool_calls" + ] + }, + { + "cell_type": "markdown", + "id": "5f2d54f2", + "metadata": {}, + "source": [ + "## Structured Outputs\n", + "\n", + "For supporting model(s), you can use the [Structured Outputs](https://api.ncloud-docs.com/docs/clovastudio-chatcompletionsv3-so) feature to force the model to generates responses in a specific structure, such as Pydantic model or TypedDict or JSON.\n", + "\n", + "**Note**: Structured Outputs requires Thinking mode to be disabled. Set `thinking.effort` to `none`." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "2af3730f", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_naver import ChatClovaX\n", + "\n", + "chat = ChatClovaX(\n", + " model=\"HCX-007\",\n", + " thinking={\n", + " \"effort\": \"none\" # Set to \"none\" to disable thinking, as structured outputs are incompatible with thinking\n", + " },\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "a9ed4514", + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Optional\n", + "from pydantic import BaseModel, Field\n", + "\n", + "\n", + "# Pydantic model example\n", + "class Weather(BaseModel):\n", + " \"\"\"Virtual weather info to tell user.\"\"\"\n", + "\n", + " temp_high_c: int = Field(description=\"The highest temperature in Celsius\")\n", + " temp_low_c: int = Field(description=\"The lowest temperature in Celsius\")\n", + " condition: str = Field(description=\"The weather condition (e.g., sunny, rainy)\")\n", + " precipitation_percent: Optional[int] = Field(\n", + " default=None,\n", + " description=\"The chance of precipitation in percent (optional, can be None)\",\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "690b785f", + "metadata": {}, + "source": [ + "**Note**: CLOVA Studio supports Structured Outputs with a json schema method. Set `method` to `json_schema`." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "041fcefd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Weather(temp_high_c=30, temp_low_c=20, condition='sunny', precipitation_percent=None)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structured_chat = chat.with_structured_output(Weather, method=\"json_schema\")\n", + "ai_msg = structured_chat.invoke(\n", + " \"what is the weather like in Bundang-gu?\",\n", + ")\n", + "ai_msg" + ] + }, + { + "cell_type": "markdown", + "id": "86ac1fed", + "metadata": {}, + "source": [ + "## Thinking\n", + "\n", + "For supporting model(s), when [Thinking](https://api.ncloud-docs.com/docs/clovastudio-chatcompletionsv3-thinking) feature is enabled (by default), it will output the step-by-step reasoning process that led to its final answer.\n", + "\n", + "Specify the `thinking` parameter to control the feature—enable or disable the thinking process and configure its depth." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "42ccba84", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The value of \\(3^3\\) (3 cubed) is calculated as follows:\n", + "\n", + "\\[\n", + "3^3 = 3 \\times 3 \\times 3\n", + "\\]\n", + "\n", + "Breaking it into steps:\n", + "1. First multiplication: \n", + " \\(3 \\times 3 = 9\\)\n", + "\n", + "2. Second multiplication using the previous result: \n", + " \\(9 \\times 3 = 27\\)\n", + "\n", + "Thus, **\\(3^3 = 27\\)**. This represents 3 multiplied by itself three times. Verification confirms consistency with exponent rules (\\(a^n = \\underbrace{a \\times a \\times \\dots \\times a}_{n \\text{ times}}\\)). No ambiguity exists in standard mathematical notation here. Answer: **27**. \n", + "\n", + "Final token count: ~500 (within limit). \n", + "Answer: \\boxed{27}\n" + ] + } + ], + "source": [ + "from langchain_naver import ChatClovaX\n", + "\n", + "chat = ChatClovaX(\n", + " model=\"HCX-007\",\n", + " thinking={\n", + " \"effort\": \"low\" # 'none' (disabling), 'low' (default), 'medium', or 'high'\n", + " },\n", + ")\n", + "ai_msg = chat.invoke(\"What is 3^3?\")\n", + "print(ai_msg.content)" + ] + }, + { + "cell_type": "markdown", + "id": "2cada4aa", + "metadata": {}, + "source": [ + "### Accessing the thinking process\n", + "\n", + "When Thinking mode is enabled, you can access the thinking process through the `thinking_content` attribute in `AIMessage.additional_kwargs`." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "8b23d219", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Okay, let's see. The user asked what 3 cubed is. Hmm, exponentiation basics here. So 3 to the power of 3 means multiplying 3 by itself three times.\n", + "\n", + "First, I should recall how exponents work. For any number a raised to n, it's a multiplied by itself n-1 more times. In this case, a is 3 and n is 3. \n", + "\n", + "So breaking it down: 3 × 3 = 9 first. Then take that result and multiply by another 3. That would be 9 × 3. Let me calculate that... 9 times 3 equals 27. Wait, does that make sense? Yeah, because 3 squared is 9, then adding another factor of 3 gives 27. \n", + "\n", + "I think there's no trick question here. Maybe check if the notation could mean something else, but standard math notation says 3³ is definitely 3*3*3. No parentheses or other operations involved. Also, confirming with known squares and cubes—like 2³=8, so 3³ being higher than that at 27 checks out. Yep, answer must be 27. Shouldn't overcomplicate it. Just straightforward multiplication. Alright, confident now.\n" + ] + } + ], + "source": [ + "print(ai_msg.additional_kwargs[\"thinking_content\"])" + ] + }, + { + "cell_type": "markdown", + "id": "d1ee55bc-ffc8-4cfa-801c-993953a08cfd", + "metadata": {}, + "source": [ + "## Additional functionalities\n", + "\n", + "### Using fine-tuned models\n", + "\n", + "You can call fine-tuned models by passing the `task_id` to the `model` parameter as: `ft:{task_id}`.\n", + "\n", + "You can check `task_id` from corresponding Test App or Service App details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb436788", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AIMessage(content='네이버 인공지능을 사용하는 것을 정말 좋아합니다.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 11, 'prompt_tokens': 28, 'total_tokens': 39, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'HCX-005', 'system_fingerprint': None, 'id': '2222d6d411a948c883aac1e03ca6cebe', 'finish_reason': 'stop', 'logprobs': None}, id='run-9696d7e2-7afa-4bb4-9c03-b95fcf678ab8-0', usage_metadata={'input_tokens': 28, 'output_tokens': 11, 'total_tokens': 39, 'input_token_details': {}, 'output_token_details': {}})" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fine_tuned_model = ChatClovaX(\n", + " model=\"ft:a1b2c3d4\", # set as `ft:{task_id}` with your fine-tuned model's task id\n", + " # other params...\n", + ")\n", + "\n", + "fine_tuned_model.invoke(messages)" + ] + }, + { + "cell_type": "markdown", + "id": "3a5bb5ca-c3ae-4a58-be67-2cd18574b9a3", + "metadata": {}, + "source": [ + "## API reference\n", + "\n", + "For detailed documentation of all ChatClovaX features and configurations head to the [API reference](https://guide.ncloud-docs.com/docs/clovastudio-dev-langchain)" + ] + } + ], + "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.13.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 }