From 301d71ec34ca0dc315337772bc5c2c0df238a7e9 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Thu, 2 May 2024 18:57:06 -0700 Subject: [PATCH] cr --- examples/configuration.ipynb | 293 +++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 examples/configuration.ipynb diff --git a/examples/configuration.ipynb b/examples/configuration.ipynb new file mode 100644 index 000000000..5a8d4cb02 --- /dev/null +++ b/examples/configuration.ipynb @@ -0,0 +1,293 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6e6a0a39-9a4c-47ae-a238-1a3a847eea5b", + "metadata": {}, + "source": [ + "# Configuration\n", + "\n", + "Sometimes you want to be able to configure your agent when calling it. \n", + "Examples of this include configuring which LLM to use.\n", + "Below we walk through an example of doing so." + ] + }, + { + "cell_type": "markdown", + "id": "df1ff9cf-f8d2-4109-adf9-2adec83f5a95", + "metadata": {}, + "source": [ + "## Base\n", + "\n", + "First, let's create a very simple graph" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "816523d0-0b59-47cf-9f4c-4838024efe22", + "metadata": {}, + "outputs": [], + "source": [ + "from langgraph.graph import StateGraph, END\n", + "from langchain_anthropic import ChatAnthropic\n", + "from typing import TypedDict, Annotated, Sequence\n", + "import operator\n", + "from langchain_core.messages import BaseMessage, HumanMessage\n", + "\n", + "\n", + "model = ChatAnthropic(model_name=\"claude-2.1\")\n", + "\n", + "\n", + "class AgentState(TypedDict):\n", + " messages: Annotated[Sequence[BaseMessage], operator.add]\n", + "\n", + "\n", + "def _call_model(state):\n", + " response = model.invoke(state['messages'])\n", + " return {\"messages\": [response]}\n", + "\n", + "# Define a new graph\n", + "workflow = StateGraph(AgentState)\n", + "workflow.add_node(\"model\", _call_model)\n", + "workflow.set_entry_point(\"model\")\n", + "workflow.add_edge(\"model\", END)\n", + "\n", + "app = workflow.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "070f11a6-2441-4db5-9df6-e318f110e281", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'messages': [HumanMessage(content='hi'),\n", + " AIMessage(content='Hello!', response_metadata={'id': 'msg_01YZj7CVCUSc76faX4VM9i5d', 'model': 'claude-2.1', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 10, 'output_tokens': 6}}, id='run-d343db34-598c-46a2-93d6-ffa886d9b264-0')]}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "app.invoke({\"messages\": [HumanMessage(content=\"hi\")]})" + ] + }, + { + "cell_type": "markdown", + "id": "69a1dd47-c5b3-4e04-af56-45682f74d61f", + "metadata": {}, + "source": [ + "## Configure the graph\n", + "\n", + "Great! Now let's suppose that we want to extend this example so the user is able to choose from multiple llms.\n", + "We can easily do that by passing in a config.\n", + "This config is meant to contain things are not part of the input (and therefor that we don't want to track as part of the state)." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "c01f1e7c-8e8b-4e26-98f7-56ac225077b4", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_openai import ChatOpenAI\n", + "\n", + "openai_model = ChatOpenAI()\n", + "\n", + "models = {\n", + " \"anthropic\": model,\n", + " \"openai\": openai_model,\n", + "}\n", + "\n", + "def _call_model(state, config):\n", + " m = models[config['configurable'].get('model', 'anthropic')]\n", + " response = m.invoke(state['messages'])\n", + " return {\"messages\": [response]}\n", + "\n", + "# Define a new graph\n", + "workflow = StateGraph(AgentState)\n", + "workflow.add_node(\"model\", _call_model)\n", + "workflow.set_entry_point(\"model\")\n", + "workflow.add_edge(\"model\", END)\n", + "\n", + "app = workflow.compile()" + ] + }, + { + "cell_type": "markdown", + "id": "7741b75c-55ba-4c78-bbb1-5dc20a210f11", + "metadata": {}, + "source": [ + "If we call it with no configuration, it will use the default as we defined it (Anthropic)." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "ef50f048-fc43-40c0-b713-346408fcf052", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'messages': [HumanMessage(content='hi'),\n", + " AIMessage(content='Hello!', response_metadata={'id': 'msg_01EedReFyXmonWXPKhYre7Jb', 'model': 'claude-2.1', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 10, 'output_tokens': 6}}, id='run-1c6feaa0-bd6f-433a-8264-209d72c85db7-0')]}" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "app.invoke({\"messages\": [HumanMessage(content=\"hi\")]})" + ] + }, + { + "cell_type": "markdown", + "id": "f6896b32-9b25-4342-bfd0-29a3d329a06a", + "metadata": {}, + "source": [ + "We can also call it with a config to get it to use a different model." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "f2f7c74b-9fb0-41c6-9728-dcf9d8a3c397", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'messages': [HumanMessage(content='hi'),\n", + " AIMessage(content='Hello! How can I assist you today?', response_metadata={'token_usage': {'completion_tokens': 9, 'prompt_tokens': 8, 'total_tokens': 17}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_3b956da36b', 'finish_reason': 'stop', 'logprobs': None}, id='run-d41ffb62-e164-45a1-862c-d288c6ad100a-0')]}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config = {\"configurable\": {\"model\": \"openai\"}}\n", + "app.invoke({\"messages\": [HumanMessage(content=\"hi\")]}, config=config)" + ] + }, + { + "cell_type": "markdown", + "id": "b4c7eaf1-4ee0-42b3-971d-273a108f205f", + "metadata": {}, + "source": [ + "We can also adapt our graph to take in more configuration! Like a system message for example." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "f0393a43-9fbe-4056-972f-3e91ea329041", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_core.messages import SystemMessage\n", + "\n", + "def _call_model(state, config):\n", + " m = models[config['configurable'].get('model', 'anthropic')]\n", + " messages = state['messages']\n", + " if 'system_message' in config['configurable']:\n", + " messages = [SystemMessage(content=config['configurable']['system_message'])] + messages\n", + " response = m.invoke(messages)\n", + " return {\"messages\": [response]}\n", + "\n", + "# Define a new graph\n", + "workflow = StateGraph(AgentState)\n", + "workflow.add_node(\"model\", _call_model)\n", + "workflow.set_entry_point(\"model\")\n", + "workflow.add_edge(\"model\", END)\n", + "\n", + "app = workflow.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "718685f7-4cdd-4181-9fc8-e7762d584727", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'messages': [HumanMessage(content='hi'),\n", + " AIMessage(content='Hello!', response_metadata={'id': 'msg_01Ts56eVLSrUbzVMbzLnXc3M', 'model': 'claude-2.1', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 10, 'output_tokens': 6}}, id='run-f75a4389-b72e-4d47-8f3e-bedc6a060f66-0')]}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "app.invoke({\"messages\": [HumanMessage(content=\"hi\")]})" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "e043a719-f197-46ef-9d45-84740a39aeb0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'messages': [HumanMessage(content='hi'),\n", + " AIMessage(content='Ciao!', response_metadata={'id': 'msg_01RzFCii8WhbbkFm16nUquxk', 'model': 'claude-2.1', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 14, 'output_tokens': 7}}, id='run-9492f0e4-f223-41c2-81a6-6f0cb6a14fe6-0')]}" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "config = {\"configurable\": {\"system_message\": \"respond in italian\"}}\n", + "app.invoke({\"messages\": [HumanMessage(content=\"hi\")]}, config=config)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a5c5f7f4-4b0e-4cde-93a6-c1c6329b8591", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}