Merge pull request #260 from langchain-ai/nc/1apr/test-both-checkpoint-at

Add tests for both values of CheckpointAt
This commit is contained in:
Nuno Campos
2024-04-01 17:51:38 -07:00
committed by GitHub
7 changed files with 1797 additions and 153 deletions
File diff suppressed because one or more lines are too long
+19 -21
View File
@@ -369,7 +369,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 9,
"id": "cfd140f0-a5a6-4697-8115-322242f197b5",
"metadata": {},
"outputs": [
@@ -377,23 +377,23 @@
"name": "stdout",
"output_type": "stream",
"text": [
"content='Hello Bob! How can I assist you today?'\n"
"content='Hello Bob! How can I assist you today?' id='a34fcaf6-a812-47f8-921d-4ba57b8271cd'\n"
]
}
],
"source": [
"from langchain_core.messages import HumanMessage\n",
"\n",
"inputs = [HumanMessage(content=\"hi! I'm bob\")]\n",
"for event in app.stream(inputs, {\"configurable\": {\"thread_id\": \"2\"}}):\n",
" for k, v in event.items():\n",
" if k != \"__end__\":\n",
" print(v)"
"thread = {\"configurable\": {\"thread_id\": \"2\"}}\n",
"inputs = HumanMessage(content=\"hi! I'm bob\")\n",
"for event in app.stream(inputs, thread):\n",
" for v in event.values():\n",
" print(v)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 10,
"id": "08ae8246-11d5-40e1-8567-361e5bef8917",
"metadata": {},
"outputs": [
@@ -401,16 +401,15 @@
"name": "stdout",
"output_type": "stream",
"text": [
"content='Your name is Bob.'\n"
"content='Your name is Bob. How can I help you, Bob?' id='dcf332e8-f9be-41c1-8a09-7a815a7de6d0'\n"
]
}
],
"source": [
"inputs = [HumanMessage(content=\"what is my name?\")]\n",
"for event in app.stream(inputs, {\"configurable\": {\"thread_id\": \"2\"}}):\n",
" for k, v in event.items():\n",
" if k != \"__end__\":\n",
" print(v)"
"inputs = HumanMessage(content=\"what is my name?\")\n",
"for event in app.stream(inputs, thread):\n",
" for v in event.values():\n",
" print(v)"
]
},
{
@@ -423,7 +422,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 11,
"id": "273d56a8-f40f-4a51-a27f-7c6bb2bda0ba",
"metadata": {},
"outputs": [
@@ -431,16 +430,15 @@
"name": "stdout",
"output_type": "stream",
"text": [
"content=\"I'm sorry, but I don't have access to personal information.\"\n"
"content=\"I'm sorry, but I don't have access to your personal information, including your name. How can I assist you today?\" id='d7ef71f4-0393-4770-b8aa-969756791ec6'\n"
]
}
],
"source": [
"inputs = [HumanMessage(content=\"what is my name?\")]\n",
"inputs = HumanMessage(content=\"what is my name?\")\n",
"for event in app.stream(inputs, {\"configurable\": {\"thread_id\": \"3\"}}):\n",
" for k, v in event.items():\n",
" if k != \"__end__\":\n",
" print(v)"
" for v in event.values():\n",
" print(v)"
]
},
{
@@ -468,7 +466,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
"version": "3.11.8"
}
},
"nbformat": 4,
+28 -48
View File
@@ -377,7 +377,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"content='Hello Bob! How can I assist you today?' response_metadata={'finish_reason': 'stop', 'logprobs': None} id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'\n"
"content='Hello Bob! How can I assist you today?' id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0'\n"
]
}
],
@@ -385,11 +385,10 @@
"from langchain_core.messages import HumanMessage\n",
"\n",
"thread = {\"configurable\": {\"thread_id\": '3'}}\n",
"inputs = [HumanMessage(content=\"hi! I'm bob\")]\n",
"inputs = HumanMessage(content=\"hi! I'm bob\")\n",
"for event in app.stream(inputs, thread):\n",
" for k, v in event.items():\n",
" if k != \"__end__\":\n",
" print(v)"
" for v in event.values():\n",
" print(v)"
]
},
{
@@ -409,7 +408,7 @@
{
"data": {
"text/plain": [
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1')], next=(), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:10.780714+00:00'}})"
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='774c03a0-4f61-49f1-8447-6fa5cbc3e56e'), AIMessage(content='Hello Bob! How can I assist you today?', id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0')], next=(), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-04-02T00:09:43.801248+00:00'}}, parent_config=None)"
]
},
"execution_count": 10,
@@ -439,16 +438,15 @@
"name": "stdout",
"output_type": "stream",
"text": [
"content='' additional_kwargs={'function_call': {'arguments': '{\"query\":\"current weather in San Francisco\"}', 'name': 'tavily_search_results_json'}} response_metadata={'finish_reason': 'function_call', 'logprobs': None} id='af48af47-01bc-4099-a7d6-14cc2df5709e'\n"
"content='' additional_kwargs={'function_call': {'arguments': '{\"query\":\"current weather in San Francisco\"}', 'name': 'tavily_search_results_json'}} id='79bcb08c-0cb4-4b37-aa68-4df08b3a290f'\n"
]
}
],
"source": [
"inputs = [HumanMessage(content=\"what is the weather in sf currently\")]\n",
"inputs = HumanMessage(content=\"what is the weather in sf currently\")\n",
"for event in app.stream(inputs, thread):\n",
" for k, v in event.items():\n",
" if k != \"__end__\":\n",
" print(v)"
" for v in event.values():\n",
" print(v)"
]
},
{
@@ -511,7 +509,7 @@
"data": {
"text/plain": [
"{'configurable': {'thread_id': '3',\n",
" 'thread_ts': '2024-03-15T21:24:37.208417+00:00'}}"
" 'thread_ts': '2024-04-02T00:09:44.323782+00:00'}}"
]
},
"execution_count": 14,
@@ -540,7 +538,7 @@
{
"data": {
"text/plain": [
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e')], next=('agent:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:37.208417+00:00'}})"
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='774c03a0-4f61-49f1-8447-6fa5cbc3e56e'), AIMessage(content='Hello Bob! How can I assist you today?', id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0'), HumanMessage(content='what is the weather in sf currently', id='4138a1b0-3053-4b12-ad15-6198be969947'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, id='79bcb08c-0cb4-4b37-aa68-4df08b3a290f')], next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-04-02T00:09:44.323782+00:00'}}, parent_config=None)"
]
},
"execution_count": 15,
@@ -570,16 +568,15 @@
"name": "stdout",
"output_type": "stream",
"text": [
"content='[{\\'url\\': \\'https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US\\', \\'content\\': \"Today\\'s and tonight\\'s San Francisco, CA weather forecast, weather conditions and Doppler radar from The Weather Channel and Weather.com\"}]' name='tavily_search_results_json' id='dbba7582-c1b3-4d6a-8727-9421c431f7dc'\n",
"content='You can check the current weather in San Francisco by visiting [The Weather Channel](https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US).' response_metadata={'finish_reason': 'stop', 'logprobs': None} id='4a32c94c-63bc-4f65-b9dd-bbaeaff3c54a'\n"
"content=\"[{'url': 'https://forecast.weather.gov/zipcity.php?inputstring=San francisco,CA', 'content': 'Detailed Forecast. Today. Mostly sunny, with a high near 62. Light and variable wind becoming west southwest 5 to 8 mph in the afternoon. Tonight. Mostly clear, with a low around 49. West wind 5 to 8 mph becoming north northwest after midnight. Monday. Sunny, with a high near 67.'}]\" name='tavily_search_results_json' id='388a34ca-6b79-4eb2-84e7-34849ce7c4cf'\n",
"content='The weather in San Francisco today is mostly sunny with a high near 62 degrees Fahrenheit. The wind is light and variable, becoming west-southwest at 5 to 8 mph in the afternoon. Tonight will be mostly clear with a low around 49 degrees Fahrenheit. Tomorrow is expected to be sunny with a high near 67 degrees Fahrenheit.' id='5d5ac23c-0e64-462d-b9ef-c499a417e906'\n"
]
}
],
"source": [
"for event in app.stream(None, thread):\n",
" for k, v in event.items():\n",
" if k != \"__end__\":\n",
" print(v)"
" for v in event.values():\n",
" print(v)"
]
},
{
@@ -594,7 +591,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 19,
"id": "8578a66d-6489-4e03-8c23-fd0530278455",
"metadata": {},
"outputs": [
@@ -602,31 +599,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e'), FunctionMessage(content='[{\\'url\\': \\'https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US\\', \\'content\\': \"Today\\'s and tonight\\'s San Francisco, CA weather forecast, weather conditions and Doppler radar from The Weather Channel and Weather.com\"}]', name='tavily_search_results_json', id='dbba7582-c1b3-4d6a-8727-9421c431f7dc'), AIMessage(content='You can check the current weather in San Francisco by visiting [The Weather Channel](https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US).', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='4a32c94c-63bc-4f65-b9dd-bbaeaff3c54a')], next=(), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:59.635105+00:00'}})\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='774c03a0-4f61-49f1-8447-6fa5cbc3e56e'), AIMessage(content='Hello Bob! How can I assist you today?', id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0'), HumanMessage(content='what is the weather in sf currently', id='4138a1b0-3053-4b12-ad15-6198be969947'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, id='79bcb08c-0cb4-4b37-aa68-4df08b3a290f'), FunctionMessage(content=\"[{'url': 'https://forecast.weather.gov/zipcity.php?inputstring=San francisco,CA', 'content': 'Detailed Forecast. Today. Mostly sunny, with a high near 62. Light and variable wind becoming west southwest 5 to 8 mph in the afternoon. Tonight. Mostly clear, with a low around 49. West wind 5 to 8 mph becoming north northwest after midnight. Monday. Sunny, with a high near 67.'}]\", name='tavily_search_results_json', id='388a34ca-6b79-4eb2-84e7-34849ce7c4cf'), AIMessage(content='The weather in San Francisco today is mostly sunny with a high near 62 degrees Fahrenheit. The wind is light and variable, becoming west-southwest at 5 to 8 mph in the afternoon. Tonight will be mostly clear with a low around 49 degrees Fahrenheit. Tomorrow is expected to be sunny with a high near 67 degrees Fahrenheit.', id='5d5ac23c-0e64-462d-b9ef-c499a417e906')], next=(), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-04-02T00:09:48.961894+00:00'}}, parent_config=None)\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e'), FunctionMessage(content='[{\\'url\\': \\'https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US\\', \\'content\\': \"Today\\'s and tonight\\'s San Francisco, CA weather forecast, weather conditions and Doppler radar from The Weather Channel and Weather.com\"}]', name='tavily_search_results_json', id='dbba7582-c1b3-4d6a-8727-9421c431f7dc'), AIMessage(content='You can check the current weather in San Francisco by visiting [The Weather Channel](https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US).', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='4a32c94c-63bc-4f65-b9dd-bbaeaff3c54a')], next=('agent:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:59.629900+00:00'}})\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='774c03a0-4f61-49f1-8447-6fa5cbc3e56e'), AIMessage(content='Hello Bob! How can I assist you today?', id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0'), HumanMessage(content='what is the weather in sf currently', id='4138a1b0-3053-4b12-ad15-6198be969947'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, id='79bcb08c-0cb4-4b37-aa68-4df08b3a290f')], next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-04-02T00:09:44.323782+00:00'}}, parent_config=None)\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e'), FunctionMessage(content='[{\\'url\\': \\'https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US\\', \\'content\\': \"Today\\'s and tonight\\'s San Francisco, CA weather forecast, weather conditions and Doppler radar from The Weather Channel and Weather.com\"}]', name='tavily_search_results_json', id='dbba7582-c1b3-4d6a-8727-9421c431f7dc')], next=('agent',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:58.501730+00:00'}})\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='774c03a0-4f61-49f1-8447-6fa5cbc3e56e'), AIMessage(content='Hello Bob! How can I assist you today?', id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0'), HumanMessage(content='what is the weather in sf currently', id='4138a1b0-3053-4b12-ad15-6198be969947'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"current weather in San Francisco\"}', 'name': 'tavily_search_results_json'}}, id='79bcb08c-0cb4-4b37-aa68-4df08b3a290f')], next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-04-02T00:09:44.242352+00:00'}}, parent_config=None)\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e'), FunctionMessage(content='[{\\'url\\': \\'https://weather.com/weather/today/l/San+Francisco+CA+USCA0987:1:US\\', \\'content\\': \"Today\\'s and tonight\\'s San Francisco, CA weather forecast, weather conditions and Doppler radar from The Weather Channel and Weather.com\"}]', name='tavily_search_results_json', id='dbba7582-c1b3-4d6a-8727-9421c431f7dc')], next=('action:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:58.498596+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e')], next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:57.092121+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"weather in San Francisco today\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e')], next=('agent:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:37.208417+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"current weather in San Francisco\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'logprobs': None}, id='af48af47-01bc-4099-a7d6-14cc2df5709e')], next=('agent:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:20.413423+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63')], next=('agent',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:19.721216+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63')], next=('__start__:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:19.717873+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1')], next=(), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:10.780714+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1')], next=('agent:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:10.773938+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d')], next=('agent',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:10.163843+00:00'}})\n",
"--\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d')], next=('__start__:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:10.162581+00:00'}})\n",
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='774c03a0-4f61-49f1-8447-6fa5cbc3e56e'), AIMessage(content='Hello Bob! How can I assist you today?', id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0')], next=(), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-04-02T00:09:43.801248+00:00'}}, parent_config=None)\n",
"--\n"
]
}
@@ -635,7 +614,7 @@
"for state in app.get_state_history(thread):\n",
" print(state)\n",
" print('--')\n",
" if len(state.values) == 3:\n",
" if len(state.values) == 4:\n",
" to_replay = state"
]
},
@@ -649,17 +628,17 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 20,
"id": "21e7fc18-6fd9-4e11-a84b-e0325c9640c8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='5e326da4-44ee-4334-b2e6-869dd6d3218d'), AIMessage(content='Hello Bob! How can I assist you today?', response_metadata={'finish_reason': 'stop', 'logprobs': None}, id='9467300a-f8ea-47db-9ade-3d9130c9f6d1'), HumanMessage(content='what is the weather in sf currently', id='bc16849a-fa20-4f07-815c-b254c6d77f63')], next=('__start__:edges',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-03-15T21:24:19.717873+00:00'}})"
"StateSnapshot(values=[HumanMessage(content=\"hi! I'm bob\", id='774c03a0-4f61-49f1-8447-6fa5cbc3e56e'), AIMessage(content='Hello Bob! How can I assist you today?', id='019fe7a8-f43d-4f83-8bbd-b1c553f32aa0'), HumanMessage(content='what is the weather in sf currently', id='4138a1b0-3053-4b12-ad15-6198be969947'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"current weather in San Francisco\"}', 'name': 'tavily_search_results_json'}}, id='79bcb08c-0cb4-4b37-aa68-4df08b3a290f')], next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '2024-04-02T00:09:44.242352+00:00'}}, parent_config=None)"
]
},
"execution_count": 18,
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
@@ -678,7 +657,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 21,
"id": "e986f94f-706f-4b6f-b3c4-f95483b9e9b8",
"metadata": {},
"outputs": [
@@ -686,7 +665,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"content='' additional_kwargs={'function_call': {'arguments': '{\"query\":\"current weather in San Francisco\"}', 'name': 'tavily_search_results_json'}} response_metadata={'finish_reason': 'function_call', 'logprobs': None} id='3a853de3-bdd9-4186-9f10-56bd151f63da'\n"
"content=\"[{'url': 'https://www.accuweather.com/en/us/san-francisco/94103/current-weather/347629', 'content': 'Current weather in San Francisco, CA. Check current conditions in San Francisco, CA with radar, hourly, and more.'}]\" name='tavily_search_results_json' id='6ce0ce23-4fb7-4d3a-acbf-f882f8d52054'\n",
"content='You can check the current weather in San Francisco by visiting [AccuWeather](https://www.accuweather.com/en/us/san-francisco/94103/current-weather/347629).' id='0f071adc-a949-4242-ac3e-7ccd2132653d'\n"
]
}
],
@@ -722,7 +702,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.1"
"version": "3.11.8"
}
},
"nbformat": 4,
+15 -6
View File
@@ -407,7 +407,9 @@ class Pregel(
)
# if two nodes updated the state at the same time, it's ambiguous
if last_seen_by_node:
if last_seen_by_node[-1][0] != last_seen_by_node[-2][0]:
if len(last_seen_by_node) == 1:
as_node = last_seen_by_node[0][1]
elif last_seen_by_node[-1][0] != last_seen_by_node[-2][0]:
as_node = last_seen_by_node[-1][1]
if as_node is None:
raise InvalidUpdateError("Ambiguous update, specify as_node")
@@ -464,7 +466,9 @@ class Pregel(
)
# if two nodes updated the state at the same time, it's ambiguous
if last_seen_by_node:
if last_seen_by_node[-1][0] != last_seen_by_node[-2][0]:
if len(last_seen_by_node) == 1:
as_node = last_seen_by_node[0][1]
elif last_seen_by_node[-1][0] != last_seen_by_node[-2][0]:
as_node = last_seen_by_node[-1][1]
if as_node is None:
raise InvalidUpdateError("Ambiguous update, specify as_node")
@@ -611,7 +615,7 @@ class Pregel(
# channels are guaranteed to be immutable for the duration of the step,
# with channel updates applied only at the transition between steps
for step in range(config["recursion_limit"] + 1):
checkpoint, next_tasks = _prepare_next_tasks(
next_checkpoint, next_tasks = _prepare_next_tasks(
checkpoint, processes, channels, for_execution=True
)
@@ -636,6 +640,8 @@ class Pregel(
next_tasks,
):
break
else:
checkpoint = next_checkpoint
if debug:
print_step_start(step, next_tasks)
@@ -816,7 +822,7 @@ class Pregel(
# channels are guaranteed to be immutable for the duration of the step,
# channel updates being applied only at the transition between steps
for step in range(config["recursion_limit"] + 1):
checkpoint, next_tasks = _prepare_next_tasks(
next_checkpoint, next_tasks = _prepare_next_tasks(
checkpoint, processes, channels, for_execution=True
)
@@ -841,6 +847,8 @@ class Pregel(
next_tasks,
):
break
else:
checkpoint = next_checkpoint
if debug:
print_step_start(step, next_tasks)
@@ -1038,11 +1046,12 @@ def _should_interrupt(
snapshot_channels: Sequence[str],
tasks: list[PregelExecutableTask],
) -> bool:
# defaultdicts are mutated on access :( so we need to copy
seen = checkpoint["versions_seen"].copy()[INTERRUPT].copy()
return (
# interrupt if any of snapshopt_channels has been updated since last interrupt
any(
checkpoint["channel_versions"][chan]
> checkpoint["versions_seen"][INTERRUPT][chan]
checkpoint["channel_versions"][chan] > seen[chan]
for chan in snapshot_channels
)
# and any channel written to is in interrupt_nodes list
File diff suppressed because it is too large Load Diff
+73 -21
View File
@@ -16,6 +16,7 @@ from langgraph.channels.binop import BinaryOperatorAggregate
from langgraph.channels.context import Context
from langgraph.channels.last_value import LastValue
from langgraph.channels.topic import Topic
from langgraph.checkpoint.base import CheckpointAt
from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.graph import END, Graph
from langgraph.graph.message import MessageGraph
@@ -188,12 +189,17 @@ def test_invoke_two_processes_in_out(mocker: MockerFixture) -> None:
assert step == 2
def test_invoke_two_processes_in_out_interrupt(mocker: MockerFixture) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_invoke_two_processes_in_out_interrupt(
mocker: MockerFixture, checkpoint_at: CheckpointAt
) -> None:
add_one = mocker.Mock(side_effect=lambda x: x + 1)
one = Channel.subscribe_to("input") | add_one | Channel.write_to("inbox")
two = Channel.subscribe_to("inbox") | add_one | Channel.write_to("output")
memory = MemorySaverAssertImmutable()
memory = MemorySaverAssertImmutable(at=checkpoint_at)
app = Pregel(
nodes={"one": one, "two": two},
checkpointer=memory,
@@ -391,7 +397,10 @@ def test_invoke_two_processes_two_in_two_out_valid(mocker: MockerFixture) -> Non
assert app.invoke(2) == [3, 3]
def test_invoke_checkpoint(mocker: MockerFixture) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_invoke_checkpoint(mocker: MockerFixture, checkpoint_at: CheckpointAt) -> None:
add_one = mocker.Mock(side_effect=lambda x: x["total"] + x["input"])
def raise_if_above_10(input: int) -> int:
@@ -406,7 +415,7 @@ def test_invoke_checkpoint(mocker: MockerFixture) -> None:
| raise_if_above_10
)
memory = MemorySaverAssertImmutable()
memory = MemorySaverAssertImmutable(at=checkpoint_at)
app = Pregel(
nodes={"one": one},
@@ -441,7 +450,12 @@ def test_invoke_checkpoint(mocker: MockerFixture) -> None:
assert checkpoint["channel_values"].get("total") == 5
def test_invoke_checkpoint_sqlite(mocker: MockerFixture) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_invoke_checkpoint_sqlite(
mocker: MockerFixture, checkpoint_at: CheckpointAt
) -> None:
add_one = mocker.Mock(side_effect=lambda x: x["total"] + x["input"])
def raise_if_above_10(input: int) -> int:
@@ -457,6 +471,7 @@ def test_invoke_checkpoint_sqlite(mocker: MockerFixture) -> None:
)
with SqliteSaver.from_conn_string(":memory:") as memory:
memory.at = checkpoint_at
app = Pregel(
nodes={"one": one},
channels={"total": BinaryOperatorAggregate(int, operator.add)},
@@ -683,7 +698,12 @@ def test_channel_enter_exit_timing(mocker: MockerFixture) -> None:
assert cleanup.call_count == 1, "Expected cleanup to be called once"
def test_conditional_graph(snapshot: SnapshotAssertion) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_conditional_graph(
snapshot: SnapshotAssertion, checkpoint_at: CheckpointAt
) -> None:
from copy import deepcopy
from langchain.llms.fake import FakeStreamingListLLM
@@ -885,7 +905,8 @@ def test_conditional_graph(snapshot: SnapshotAssertion) -> None:
# test state get/update methods with interrupt_after
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["agent"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["agent"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -1034,7 +1055,8 @@ def test_conditional_graph(snapshot: SnapshotAssertion) -> None:
# test state get/update methods with interrupt_before
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_before=["tools"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_before=["tools"],
)
config = {"configurable": {"thread_id": "2"}}
llm.i = 0 # reset the llm
@@ -1178,7 +1200,8 @@ def test_conditional_graph(snapshot: SnapshotAssertion) -> None:
# test re-invoke to continue with interrupt_before
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_before=["tools"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_before=["tools"],
)
config = {"configurable": {"thread_id": "2"}}
llm.i = 0 # reset the llm
@@ -1344,7 +1367,12 @@ def test_conditional_entrypoint_graph(snapshot: SnapshotAssertion) -> None:
]
def test_conditional_graph_state(snapshot: SnapshotAssertion) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_conditional_graph_state(
snapshot: SnapshotAssertion, checkpoint_at: CheckpointAt
) -> None:
from langchain.llms.fake import FakeStreamingListLLM
from langchain_community.tools import tool
from langchain_core.agents import AgentAction, AgentFinish
@@ -1511,7 +1539,8 @@ def test_conditional_graph_state(snapshot: SnapshotAssertion) -> None:
# test state get/update methods with interrupt_after
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["agent"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["agent"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -1625,7 +1654,7 @@ def test_conditional_graph_state(snapshot: SnapshotAssertion) -> None:
# test state get/update methods with interrupt_before
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(),
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_before=["tools"],
debug=True,
)
@@ -2104,8 +2133,13 @@ def test_prebuilt_chat(snapshot: SnapshotAssertion) -> None:
]
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_message_graph(
snapshot: SnapshotAssertion, deterministic_uuids: MockerFixture
snapshot: SnapshotAssertion,
checkpoint_at: CheckpointAt,
deterministic_uuids: MockerFixture,
) -> None:
from copy import deepcopy
@@ -2317,7 +2351,8 @@ def test_message_graph(
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["agent"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["agent"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -2463,7 +2498,8 @@ def test_message_graph(
)
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_before=["action"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_before=["action"],
)
config = {"configurable": {"thread_id": "2"}}
model.i = 0 # reset the llm
@@ -2676,7 +2712,10 @@ def test_in_one_fan_out_out_one_graph_state() -> None:
]
def test_in_one_fan_out_state_graph_waiting_edge() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_in_one_fan_out_state_graph_waiting_edge(checkpoint_at: CheckpointAt) -> None:
def sorted_add(
x: list[str], y: Union[list[str], list[tuple[str, str]]]
) -> list[str]:
@@ -2776,7 +2815,8 @@ def test_in_one_fan_out_state_graph_waiting_edge() -> None:
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["retriever_one"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["retriever_one"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -2796,7 +2836,12 @@ def test_in_one_fan_out_state_graph_waiting_edge() -> None:
]
def test_in_one_fan_out_state_graph_waiting_edge_via_branch() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_in_one_fan_out_state_graph_waiting_edge_via_branch(
checkpoint_at: CheckpointAt,
) -> None:
def sorted_add(
x: list[str], y: Union[list[str], list[tuple[str, str]]]
) -> list[str]:
@@ -2898,7 +2943,8 @@ def test_in_one_fan_out_state_graph_waiting_edge_via_branch() -> None:
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["retriever_one"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["retriever_one"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -2918,7 +2964,12 @@ def test_in_one_fan_out_state_graph_waiting_edge_via_branch() -> None:
]
def test_in_one_fan_out_state_graph_waiting_edge_plus_regular() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
def test_in_one_fan_out_state_graph_waiting_edge_plus_regular(
checkpoint_at: CheckpointAt,
) -> None:
def sorted_add(
x: list[str], y: Union[list[str], list[tuple[str, str]]]
) -> list[str]:
@@ -2987,7 +3038,8 @@ def test_in_one_fan_out_state_graph_waiting_edge_plus_regular() -> None:
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["retriever_one"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["retriever_one"],
)
config = {"configurable": {"thread_id": "1"}}
+70 -20
View File
@@ -23,6 +23,7 @@ from langgraph.channels.context import Context
from langgraph.channels.last_value import LastValue
from langgraph.channels.topic import Topic
from langgraph.checkpoint.aiosqlite import AsyncSqliteSaver
from langgraph.checkpoint.base import CheckpointAt
from langgraph.graph import END, Graph, StateGraph
from langgraph.graph.message import MessageGraph
from langgraph.prebuilt.chat_agent_executor import (
@@ -196,12 +197,17 @@ async def test_invoke_two_processes_in_out(mocker: MockerFixture) -> None:
assert step == 2
async def test_invoke_two_processes_in_out_interrupt(mocker: MockerFixture) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_invoke_two_processes_in_out_interrupt(
mocker: MockerFixture, checkpoint_at: CheckpointAt
) -> None:
add_one = mocker.Mock(side_effect=lambda x: x + 1)
one = Channel.subscribe_to("input") | add_one | Channel.write_to("inbox")
two = Channel.subscribe_to("inbox") | add_one | Channel.write_to("output")
memory = MemorySaverAssertImmutable()
memory = MemorySaverAssertImmutable(at=checkpoint_at)
app = Pregel(
nodes={"one": one, "two": two},
checkpointer=memory,
@@ -408,7 +414,12 @@ async def test_invoke_two_processes_two_in_two_out_valid(mocker: MockerFixture)
assert await app.ainvoke(2) == [3, 3]
async def test_invoke_checkpoint(mocker: MockerFixture) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_invoke_checkpoint(
mocker: MockerFixture, checkpoint_at: CheckpointAt
) -> None:
add_one = mocker.Mock(side_effect=lambda x: x["total"] + x["input"])
def raise_if_above_10(input: int) -> int:
@@ -423,7 +434,7 @@ async def test_invoke_checkpoint(mocker: MockerFixture) -> None:
| raise_if_above_10
)
memory = MemorySaverAssertImmutable()
memory = MemorySaverAssertImmutable(at=checkpoint_at)
app = Pregel(
nodes={"one": one},
@@ -458,7 +469,12 @@ async def test_invoke_checkpoint(mocker: MockerFixture) -> None:
assert checkpoint["channel_values"].get("total") == 5
async def test_invoke_checkpoint_aiosqlite(mocker: MockerFixture) -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_invoke_checkpoint_aiosqlite(
mocker: MockerFixture, checkpoint_at: CheckpointAt
) -> None:
add_one = mocker.Mock(side_effect=lambda x: x["total"] + x["input"])
def raise_if_above_10(input: int) -> int:
@@ -474,6 +490,7 @@ async def test_invoke_checkpoint_aiosqlite(mocker: MockerFixture) -> None:
)
async with AsyncSqliteSaver.from_conn_string(":memory:") as memory:
memory.at = checkpoint_at
app = Pregel(
nodes={"one": one},
channels={"total": BinaryOperatorAggregate(int, operator.add)},
@@ -726,7 +743,10 @@ async def test_channel_enter_exit_timing(mocker: MockerFixture) -> None:
assert cleanup_async.call_count == 1, "Expected cleanup to be called once"
async def test_conditional_graph() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_conditional_graph(checkpoint_at: CheckpointAt) -> None:
from copy import deepcopy
from langchain.llms.fake import FakeStreamingListLLM
@@ -931,7 +951,8 @@ async def test_conditional_graph() -> None:
# test state get/update methods with interrupt_after
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["agent"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["agent"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -1077,7 +1098,8 @@ async def test_conditional_graph() -> None:
# test state get/update methods with interrupt_before
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_before=["tools"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_before=["tools"],
)
config = {"configurable": {"thread_id": "2"}}
llm.i = 0
@@ -1224,7 +1246,8 @@ async def test_conditional_graph() -> None:
# test re-invoke to continue with interrupt_before
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_before=["tools"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_before=["tools"],
)
config = {"configurable": {"thread_id": "2"}}
llm.i = 0 # reset the llm
@@ -1349,7 +1372,10 @@ async def test_conditional_graph() -> None:
]
async def test_conditional_graph_state() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_conditional_graph_state(checkpoint_at: CheckpointAt) -> None:
from langchain.llms.fake import FakeStreamingListLLM
from langchain_community.tools import tool
from langchain_core.agents import AgentAction, AgentFinish
@@ -1511,7 +1537,8 @@ async def test_conditional_graph_state() -> None:
# test state get/update methods with interrupt_after
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["agent"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["agent"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -1630,7 +1657,8 @@ async def test_conditional_graph_state() -> None:
# test state get/update methods with interrupt_before
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_before=["tools"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_before=["tools"],
)
config = {"configurable": {"thread_id": "2"}}
llm.i = 0 # reset the llm
@@ -2137,7 +2165,10 @@ async def test_prebuilt_chat() -> None:
]
async def test_message_graph() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_message_graph(checkpoint_at: CheckpointAt) -> None:
from langchain.chat_models.fake import FakeMessagesListChatModel
from langchain_community.tools import tool
from langchain_core.agents import AgentAction
@@ -2306,7 +2337,8 @@ async def test_message_graph() -> None:
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["agent"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["agent"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -2511,7 +2543,12 @@ async def test_in_one_fan_out_out_one_graph_state() -> None:
]
async def test_in_one_fan_out_state_graph_waiting_edge() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_in_one_fan_out_state_graph_waiting_edge(
checkpoint_at: CheckpointAt,
) -> None:
def sorted_add(
x: list[str], y: Union[list[str], list[tuple[str, str]]]
) -> list[str]:
@@ -2575,7 +2612,8 @@ async def test_in_one_fan_out_state_graph_waiting_edge() -> None:
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["retriever_one"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["retriever_one"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -2598,7 +2636,12 @@ async def test_in_one_fan_out_state_graph_waiting_edge() -> None:
]
async def test_in_one_fan_out_state_graph_waiting_edge_via_branch() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_in_one_fan_out_state_graph_waiting_edge_via_branch(
checkpoint_at: CheckpointAt,
) -> None:
def sorted_add(
x: list[str], y: Union[list[str], list[tuple[str, str]]]
) -> list[str]:
@@ -2700,7 +2743,8 @@ async def test_in_one_fan_out_state_graph_waiting_edge_via_branch() -> None:
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["retriever_one"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["retriever_one"],
)
config = {"configurable": {"thread_id": "1"}}
@@ -2723,7 +2767,12 @@ async def test_in_one_fan_out_state_graph_waiting_edge_via_branch() -> None:
]
async def test_in_one_fan_out_state_graph_waiting_edge_plus_regular() -> None:
@pytest.mark.parametrize(
"checkpoint_at", [CheckpointAt.END_OF_RUN, CheckpointAt.END_OF_STEP]
)
async def test_in_one_fan_out_state_graph_waiting_edge_plus_regular(
checkpoint_at: CheckpointAt,
) -> None:
def sorted_add(
x: list[str], y: Union[list[str], list[tuple[str, str]]]
) -> list[str]:
@@ -2792,7 +2841,8 @@ async def test_in_one_fan_out_state_graph_waiting_edge_plus_regular() -> None:
]
app_w_interrupt = workflow.compile(
checkpointer=MemorySaverAssertImmutable(), interrupt_after=["retriever_one"]
checkpointer=MemorySaverAssertImmutable(at=checkpoint_at),
interrupt_after=["retriever_one"],
)
config = {"configurable": {"thread_id": "1"}}