{ "cells": [ { "cell_type": "code", "execution_count": 3, "id": "124c8be0-1c20-4ea1-aeee-106d3fb7143f", "metadata": {}, "outputs": [], "source": [ "from langchain_huggingface import HuggingFacePipeline, ChatHuggingFace\n", "from transformers import AutoTokenizer, AutoModelForSequenceClassification, AutoModelForCausalLM, pipeline\n", "import torch\n", "from langchain_core.messages import (\n", " HumanMessage,\n", " SystemMessage,\n", " BaseMessage\n", ")\n", "from typing import (\n", " Any,\n", " Callable,\n", " Dict,\n", " List,\n", " Literal,\n", " Optional,\n", " Sequence,\n", " Type,\n", " Union,\n", " cast,\n", ")\n", "\n", "class HuggingFaceAI(ChatHuggingFace):\n", " \n", " def _to_chat_prompt(\n", " self,\n", " messages: List[BaseMessage],\n", " ) -> str:\n", " \"\"\"Convert a list of messages into a prompt format expected by wrapped LLM.\"\"\"\n", " if not messages:\n", " raise ValueError(\"At least one HumanMessage must be provided!\")\n", "\n", " if not isinstance(messages[-1], HumanMessage) and not isinstance(messages[-1], SystemMessage) :\n", " raise ValueError(\"Last message must be a HumanMessage or SystemMessage!!!\")\n", "\n", " messages_dicts = [self._to_chatml_format(m) for m in messages]\n", "\n", " return self.tokenizer.apply_chat_template(\n", " messages_dicts, tokenize=False, add_generation_prompt=True\n", " )" ] }, { "cell_type": "code", "execution_count": 4, "id": "3ab4c82b-4268-4ffa-b814-967cf5e347d2", "metadata": { "tags": [] }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "bb1698c756e946beb49a2afcfde2e51e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "tokenizer_config.json: 0%| | 0.00/137k [00:00[INST] Hugging Face is [/INST] Hugging Face is a technology company that specializes in natural language processing (NLP). They are best known for their transformers library, which is a state-of-the-art machine learning framework for NLP tasks. The transformers library includes pre-trained models for a wide range of NLP tasks such as language translation, text classification, and question answering. Hugging Face also provides a platform for training, sharing, and using NLP models, called the Hugging Face Model Hub', id='run-9b0b07cc-2121-4c78-8ebf-61df58694193-0')" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from langchain_huggingface import ChatHuggingFace, HuggingFacePipeline\n", "\n", "llm = HuggingFacePipeline.from_model_id(\n", " model_id=\"mistralai/Mistral-7B-Instruct-v0.3\",\n", " device_map=\"auto\",\n", " task=\"text-generation\",\n", " pipeline_kwargs={\n", " \"max_new_tokens\": 100,\n", " \"top_k\": 50,\n", " },\n", ")\n", "\n", "llm_engine_hf = HuggingFaceAI(llm=llm)\n", "llm_engine_hf.invoke(\"Hugging Face is\")" ] }, { "cell_type": "code", "execution_count": 5, "id": "8cf48c8f-27c2-4c22-a219-965ad3621bc2", "metadata": { "tags": [] }, "outputs": [], "source": [ "from langchain.agents import AgentExecutor, create_openai_tools_agent\n", "from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage, AIMessage\n", "from langchain_openai import ChatOpenAI\n", "\n", "\n", "def create_agent(llm: ChatHuggingFace, tools: list, system_prompt: str):\n", " # Each worker node will be given a name and some tools.\n", " prompt = ChatPromptTemplate.from_messages(\n", " [\n", " (\n", " \"system\",\n", " system_prompt,\n", " ),\n", " MessagesPlaceholder(variable_name=\"messages\"),\n", " MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n", " ]\n", " )\n", " agent = create_openai_tools_agent(llm, tools, prompt)\n", " executor = AgentExecutor(agent=agent, tools=tools)\n", " return executor" ] }, { "cell_type": "code", "execution_count": 6, "id": "b2968526-9c48-45fe-b783-707873af7436", "metadata": { "tags": [] }, "outputs": [], "source": [ "from typing import Annotated, List, Tuple, Union\n", "\n", "from langchain_core.tools import tool\n", "from langchain_experimental.tools import PythonREPLTool\n", "\n", "\n", "# This executes code locally, which can be unsafe\n", "python_repl_tool = PythonREPLTool()" ] }, { "cell_type": "code", "execution_count": 7, "id": "fd6d6e2f-d327-4a03-8693-9b6e20170826", "metadata": { "tags": [] }, "outputs": [], "source": [ "chat_model = llm_engine_hf" ] }, { "cell_type": "code", "execution_count": 8, "id": "5cf6d454-81fb-43cd-a472-519df681ca32", "metadata": { "tags": [] }, "outputs": [], "source": [ "def agent_node(state, agent, name):\n", " result = agent.invoke(state)\n", " return {\"messages\": [HumanMessage(content=result[\"output\"], name=name)]}" ] }, { "cell_type": "code", "execution_count": 9, "id": "d35ca09b-1310-466d-924a-31f761a1f700", "metadata": {}, "outputs": [], "source": [ "from langchain_core.tools import tool\n", "\n", "@tool\n", "def multiply(a: int, b: int) -> int:\n", " \"\"\"Multiply two numbers.\"\"\"\n", " print(\"Multiply used\")\n", " return a * b" ] }, { "cell_type": "code", "execution_count": 22, "id": "1579a0b5-bc37-45d4-aba4-244c3891f0f6", "metadata": { "tags": [] }, "outputs": [], "source": [ "from langchain_core.output_parsers import StrOutputParser\n", "from langchain_core.prompts import PromptTemplate, ChatPromptTemplate, MessagesPlaceholder\n", "from langchain_core.runnables import RunnableLambda \n", "\n", "def stripPrompt(info):\n", " print(info)\n", " eot_token = \"[/INST] \"\n", " i = info.content.rfind(eot_token)\n", " if i == -1:\n", " return info\n", " \n", " info.content = info.content[i + len(eot_token):]\n", " \n", " return info.content\n", " \n", "members = [\"Multiplier\", \"Coder\"]\n", "# Our team supervisor is an LLM node. It just picks the next agent to process\n", "# and decides when the work is completed\n", "options = [\"FINISH\"] + members\n", "system_prompt = (\n", " \"You are a supervisor tasked with managing a conversation between the\"\n", " \" following workers: {members}. Given the following user request,\"\n", " \" respond with the worker to act next. Each worker will perform a\"\n", " \" task and respond with their results and status. When finished,\"\n", " \" respond with FINISH.\"\n", ")\n", "\n", "\n", "prompt = ChatPromptTemplate.from_messages(\n", " [\n", " (\"human\", system_prompt),\n", " (\"assistant\", \"ok\"),\n", " MessagesPlaceholder(variable_name=\"messages\"),\n", " (\"assistant\", \"ok\"),\n", " (\n", " \"human\",\n", " \"Given the conversation above, who should act next?\"\n", " \" Or should we FINISH? Select one of: {options}\",\n", " ),\n", " ]\n", ").partial(options=str(options), members=\", \".join(members))\n", "\n", "chain = ( prompt | chat_model | RunnableLambda(stripPrompt))" ] }, { "cell_type": "code", "execution_count": 23, "id": "dbe4efe7-220a-42f9-badc-0e27329c8225", "metadata": { "tags": [] }, "outputs": [], "source": [ "import operator\n", "from typing import Annotated, Any, Dict, List, Optional, Sequence, TypedDict\n", "import functools\n", "\n", "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n", "from langgraph.graph import StateGraph, END\n", "\n", "\n", "\n", "\n", "\n", "multiply_agent = create_agent(chat_model, [multiply], \"You multiply numbers\")\n", "multiply_node = functools.partial(agent_node, agent=multiply_agent, name=\"Multiplier\")\n", "#research_node = functools.partial(agent_node, agent=research_agent, name=\"Researcher\")\n", "\n", "# NOTE: THIS PERFORMS ARBITRARY CODE EXECUTION. PROCEED WITH CAUTION\n", "code_agent = create_agent(\n", " chat_model,\n", " [python_repl_tool],\n", " \"You may generate safe python code to analyze data and generate charts using matplotlib.\",\n", ")\n", "code_node = functools.partial(agent_node, agent=code_agent, name=\"Coder\")\n", "\n", "workflow = StateGraph(AgentState)\n", "workflow.add_node(\"Multiplier\", multiply_node)\n", "workflow.add_node(\"Coder\", code_node)\n", "workflow.add_node(\"supervisor\", chain)" ] }, { "cell_type": "code", "execution_count": 24, "id": "74714d27-60b1-4ae3-9993-d0c10b77e417", "metadata": { "tags": [] }, "outputs": [], "source": [ "for member in members:\n", " # We want our workers to ALWAYS \"report back\" to the supervisor when done\n", " workflow.add_edge(member, \"supervisor\")\n", "# The supervisor populates the \"next\" field in the graph state\n", "# which routes to a node or finishes\n", "conditional_map = {k: k for k in members}\n", "conditional_map[\"FINISH\"] = END\n", "workflow.add_conditional_edges(\"supervisor\", lambda x: x[\"next\"], conditional_map)\n", "# Finally, add entrypoint\n", "workflow.set_entry_point(\"supervisor\")\n", "\n", "graph = workflow.compile()" ] }, { "cell_type": "code", "execution_count": 25, "id": "e6dc680d-15ec-484b-9a72-dc8af0f04234", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "content=\"[INST] You are a supervisor tasked with managing a conversation between the following workers: Multiplier, Coder. Given the following user request, respond with the worker to act next. Each worker will perform a task and respond with their results and status. When finished, respond with FINISH. [/INST]ok[INST] What is 4 multiplied by 35 [/INST]ok[INST] Given the conversation above, who should act next? Or should we FINISH? Select one of: ['FINISH', 'Multiplier', 'Coder'] [/INST] Multiplier (since they provided the result of the multiplication)\" id='run-8c0df905-9902-4ac2-8327-f4e4fb612cc2-0'\n" ] }, { "ename": "InvalidUpdateError", "evalue": "Expected dict, got Multiplier (since they provided the result of the multiplication)", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mInvalidUpdateError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[25], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m s \u001b[38;5;129;01min\u001b[39;00m graph\u001b[38;5;241m.\u001b[39mstream(\n\u001b[1;32m 2\u001b[0m {\n\u001b[1;32m 3\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmessages\u001b[39m\u001b[38;5;124m\"\u001b[39m: [\n\u001b[1;32m 4\u001b[0m HumanMessage(content\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mWhat is 4 multiplied by 35\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 5\u001b[0m ]\n\u001b[1;32m 6\u001b[0m }\n\u001b[1;32m 7\u001b[0m ):\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m__end__\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m s:\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28mprint\u001b[39m(s)\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/pregel/__init__.py:963\u001b[0m, in \u001b[0;36mPregel.stream\u001b[0;34m(self, input, config, stream_mode, output_keys, input_keys, interrupt_before, interrupt_after, debug)\u001b[0m\n\u001b[1;32m 960\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m fut, task\n\u001b[1;32m 962\u001b[0m \u001b[38;5;66;03m# panic on failure or timeout\u001b[39;00m\n\u001b[0;32m--> 963\u001b[0m \u001b[43m_panic_or_proceed\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdone\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minflight\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstep\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 964\u001b[0m \u001b[38;5;66;03m# don't keep futures around in memory longer than needed\u001b[39;00m\n\u001b[1;32m 965\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m done, inflight, futures\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/pregel/__init__.py:1489\u001b[0m, in \u001b[0;36m_panic_or_proceed\u001b[0;34m(done, inflight, step)\u001b[0m\n\u001b[1;32m 1487\u001b[0m inflight\u001b[38;5;241m.\u001b[39mpop()\u001b[38;5;241m.\u001b[39mcancel()\n\u001b[1;32m 1488\u001b[0m \u001b[38;5;66;03m# raise the exception\u001b[39;00m\n\u001b[0;32m-> 1489\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[1;32m 1491\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m inflight:\n\u001b[1;32m 1492\u001b[0m \u001b[38;5;66;03m# if we got here means we timed out\u001b[39;00m\n\u001b[1;32m 1493\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m inflight:\n\u001b[1;32m 1494\u001b[0m \u001b[38;5;66;03m# cancel all pending tasks\u001b[39;00m\n", "File \u001b[0;32m~/miniconda/lib/python3.9/concurrent/futures/thread.py:52\u001b[0m, in \u001b[0;36m_WorkItem.run\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 49\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[1;32m 51\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 52\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 53\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 54\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfuture\u001b[38;5;241m.\u001b[39mset_exception(exc)\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/pregel/retry.py:66\u001b[0m, in \u001b[0;36mrun_with_retry\u001b[0;34m(task, retry_policy)\u001b[0m\n\u001b[1;32m 64\u001b[0m task\u001b[38;5;241m.\u001b[39mwrites\u001b[38;5;241m.\u001b[39mclear()\n\u001b[1;32m 65\u001b[0m \u001b[38;5;66;03m# run the task\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[43mtask\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mproc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtask\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minput\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtask\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;66;03m# if successful, end\u001b[39;00m\n\u001b[1;32m 68\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langchain_core/runnables/base.py:2495\u001b[0m, in \u001b[0;36mRunnableSequence.invoke\u001b[0;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[1;32m 2493\u001b[0m \u001b[38;5;28minput\u001b[39m \u001b[38;5;241m=\u001b[39m step\u001b[38;5;241m.\u001b[39minvoke(\u001b[38;5;28minput\u001b[39m, config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 2494\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 2495\u001b[0m \u001b[38;5;28minput\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[43mstep\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2496\u001b[0m \u001b[38;5;66;03m# finish the root run\u001b[39;00m\n\u001b[1;32m 2497\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/utils.py:86\u001b[0m, in \u001b[0;36mRunnableCallable.invoke\u001b[0;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[1;32m 84\u001b[0m kwargs \u001b[38;5;241m=\u001b[39m {\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mkwargs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs}\n\u001b[1;32m 85\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrace:\n\u001b[0;32m---> 86\u001b[0m ret \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_with_config\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 87\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfunc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmerge_configs\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconfig\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\n\u001b[1;32m 88\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 89\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 90\u001b[0m config \u001b[38;5;241m=\u001b[39m merge_configs(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconfig, config)\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langchain_core/runnables/base.py:1596\u001b[0m, in \u001b[0;36mRunnable._call_with_config\u001b[0;34m(self, func, input, config, run_type, **kwargs)\u001b[0m\n\u001b[1;32m 1592\u001b[0m context \u001b[38;5;241m=\u001b[39m copy_context()\n\u001b[1;32m 1593\u001b[0m context\u001b[38;5;241m.\u001b[39mrun(_set_config_context, child_config)\n\u001b[1;32m 1594\u001b[0m output \u001b[38;5;241m=\u001b[39m cast(\n\u001b[1;32m 1595\u001b[0m Output,\n\u001b[0;32m-> 1596\u001b[0m \u001b[43mcontext\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1597\u001b[0m \u001b[43m \u001b[49m\u001b[43mcall_func_with_variable_args\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore[arg-type]\u001b[39;49;00m\n\u001b[1;32m 1598\u001b[0m \u001b[43m \u001b[49m\u001b[43mfunc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore[arg-type]\u001b[39;49;00m\n\u001b[1;32m 1599\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore[arg-type]\u001b[39;49;00m\n\u001b[1;32m 1600\u001b[0m \u001b[43m \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1601\u001b[0m \u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1602\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1603\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m,\n\u001b[1;32m 1604\u001b[0m )\n\u001b[1;32m 1605\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 1606\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langchain_core/runnables/config.py:380\u001b[0m, in \u001b[0;36mcall_func_with_variable_args\u001b[0;34m(func, input, config, run_manager, **kwargs)\u001b[0m\n\u001b[1;32m 378\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m run_manager \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m accepts_run_manager(func):\n\u001b[1;32m 379\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_manager\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m run_manager\n\u001b[0;32m--> 380\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/pregel/write.py:97\u001b[0m, in \u001b[0;36mChannelWrite._write\u001b[0;34m(self, input, config)\u001b[0m\n\u001b[1;32m 93\u001b[0m \u001b[38;5;66;03m# process entries into values\u001b[39;00m\n\u001b[1;32m 94\u001b[0m values \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 95\u001b[0m \u001b[38;5;28minput\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m write\u001b[38;5;241m.\u001b[39mvalue \u001b[38;5;129;01mis\u001b[39;00m PASSTHROUGH \u001b[38;5;28;01melse\u001b[39;00m write\u001b[38;5;241m.\u001b[39mvalue \u001b[38;5;28;01mfor\u001b[39;00m write \u001b[38;5;129;01min\u001b[39;00m entries\n\u001b[1;32m 96\u001b[0m ]\n\u001b[0;32m---> 97\u001b[0m values \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 98\u001b[0m val \u001b[38;5;28;01mif\u001b[39;00m write\u001b[38;5;241m.\u001b[39mmapper \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;28;01melse\u001b[39;00m write\u001b[38;5;241m.\u001b[39mmapper\u001b[38;5;241m.\u001b[39minvoke(val, config)\n\u001b[1;32m 99\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m val, write \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(values, entries)\n\u001b[1;32m 100\u001b[0m ]\n\u001b[1;32m 101\u001b[0m values \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 102\u001b[0m (write\u001b[38;5;241m.\u001b[39mchannel, val)\n\u001b[1;32m 103\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m val, write \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(values, entries)\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m write\u001b[38;5;241m.\u001b[39mskip_none \u001b[38;5;129;01mor\u001b[39;00m val \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 105\u001b[0m ]\n\u001b[1;32m 106\u001b[0m \u001b[38;5;66;03m# write packets and values\u001b[39;00m\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/pregel/write.py:98\u001b[0m, in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 93\u001b[0m \u001b[38;5;66;03m# process entries into values\u001b[39;00m\n\u001b[1;32m 94\u001b[0m values \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 95\u001b[0m \u001b[38;5;28minput\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m write\u001b[38;5;241m.\u001b[39mvalue \u001b[38;5;129;01mis\u001b[39;00m PASSTHROUGH \u001b[38;5;28;01melse\u001b[39;00m write\u001b[38;5;241m.\u001b[39mvalue \u001b[38;5;28;01mfor\u001b[39;00m write \u001b[38;5;129;01min\u001b[39;00m entries\n\u001b[1;32m 96\u001b[0m ]\n\u001b[1;32m 97\u001b[0m values \u001b[38;5;241m=\u001b[39m [\n\u001b[0;32m---> 98\u001b[0m val \u001b[38;5;28;01mif\u001b[39;00m write\u001b[38;5;241m.\u001b[39mmapper \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;28;01melse\u001b[39;00m \u001b[43mwrite\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmapper\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[43mval\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 99\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m val, write \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(values, entries)\n\u001b[1;32m 100\u001b[0m ]\n\u001b[1;32m 101\u001b[0m values \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 102\u001b[0m (write\u001b[38;5;241m.\u001b[39mchannel, val)\n\u001b[1;32m 103\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m val, write \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(values, entries)\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m write\u001b[38;5;241m.\u001b[39mskip_none \u001b[38;5;129;01mor\u001b[39;00m val \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 105\u001b[0m ]\n\u001b[1;32m 106\u001b[0m \u001b[38;5;66;03m# write packets and values\u001b[39;00m\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/utils.py:95\u001b[0m, in \u001b[0;36mRunnableCallable.invoke\u001b[0;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[1;32m 93\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m accepts_config(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunc):\n\u001b[1;32m 94\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mconfig\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m config\n\u001b[0;32m---> 95\u001b[0m ret \u001b[38;5;241m=\u001b[39m \u001b[43mcontext\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfunc\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(ret, Runnable) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrecurse:\n\u001b[1;32m 97\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m ret\u001b[38;5;241m.\u001b[39minvoke(\u001b[38;5;28minput\u001b[39m, config)\n", "File \u001b[0;32m~/miniconda/lib/python3.9/site-packages/langgraph/graph/state.py:300\u001b[0m, in \u001b[0;36mCompiledStateGraph.attach_node.._get_state_key\u001b[0;34m(input, config, key)\u001b[0m\n\u001b[1;32m 298\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m value \u001b[38;5;28;01mif\u001b[39;00m value \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;28;01melse\u001b[39;00m SKIP_WRITE\n\u001b[1;32m 299\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 300\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m InvalidUpdateError(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpected dict, got \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28minput\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", "\u001b[0;31mInvalidUpdateError\u001b[0m: Expected dict, got Multiplier (since they provided the result of the multiplication)" ] } ], "source": [ "for s in graph.stream(\n", " {\n", " \"messages\": [\n", " HumanMessage(content=\"What is 4 multiplied by 35\")\n", " ]\n", " }\n", "):\n", " if \"__end__\" not in s:\n", " print(s)\n", " print(\"----\")" ] }, { "cell_type": "code", "execution_count": null, "id": "6ff7b4d7-189a-4c31-9366-c42e3a0a7d47", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "2d14d9f3-bcc8-476a-b5f9-34987183636c", "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.9.5" } }, "nbformat": 4, "nbformat_minor": 5 }