{
"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, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2fe3d3847e4e4cfa8b124211c679597c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer.model: 0%| | 0.00/587k [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8dc27068bab14901a3595e921a34c4ef",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"tokenizer.json: 0%| | 0.00/1.96M [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "bc109fc9216449f19e610b30a9879b27",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"special_tokens_map.json: 0%| | 0.00/414 [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c3180e986f4d411d8511e361e4f3cd8f",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"config.json: 0%| | 0.00/601 [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "4c3c52d9f0c04b1eb3eb0c5ebd3e14c8",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model.safetensors.index.json: 0%| | 0.00/23.9k [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "824ba11de3ba4cc7aa713779f3971025",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Downloading shards: 0%| | 0/3 [00:00, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8c9b9325e7584ccf93733ab371493b1a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model-00001-of-00003.safetensors: 0%| | 0.00/4.95G [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2a5cfc651b7f4b6793305c507bb4f1ca",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model-00002-of-00003.safetensors: 0%| | 0.00/5.00G [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1aefc575e0c34cea950ca2e660024cc2",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"model-00003-of-00003.safetensors: 0%| | 0.00/4.55G [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "511d965c616345eaaa447a3f6ae3d8b8",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Loading checkpoint shards: 0%| | 0/3 [00:00, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a222b677f36e430383e9470d87a143c0",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"generation_config.json: 0%| | 0.00/116 [00:00, ?B/s]"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"AIMessage(content='[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
}