Lesson 5: Human in the LoopĀ¶
Note: This notebook is running in a later version of langgraph that it was filmed with. The later version has a couple of key additions:
- Additional state information is stored to memory and displayed when using
get_state()
orget_state_history()
. - State is additionally stored every state transition while previously it was stored at an interrupt or at the end. These change the command output slightly, but are a useful addtion to the information available.
from dotenv import load_dotenv
_ = load_dotenv()
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage, ToolMessage
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langgraph.checkpoint.sqlite import SqliteSaver
memory = SqliteSaver.from_conn_string(":memory:")
from uuid import uuid4
from langchain_core.messages import AnyMessage, SystemMessage, HumanMessage, AIMessage
"""
In previous examples we've annotated the `messages` state key
with the default `operator.add` or `+` reducer, which always
appends new messages to the end of the existing messages array.
Now, to support replacing existing messages, we annotate the
`messages` key with a customer reducer function, which replaces
messages with the same `id`, and appends them otherwise.
"""
def reduce_messages(left: list[AnyMessage], right: list[AnyMessage]) -> list[AnyMessage]:
# assign ids to messages that don't have them
for message in right:
if not message.id:
message.id = str(uuid4())
# merge the new messages with the existing messages
merged = left.copy()
for message in right:
for i, existing in enumerate(merged):
# replace any existing messages with the same id
if existing.id == message.id:
merged[i] = message
break
else:
# append any new messages to the end
merged.append(message)
return merged
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], reduce_messages]
tool = TavilySearchResults(max_results=2)
Manual human approvalĀ¶
class Agent:
def __init__(self, model, tools, system="", checkpointer=None):
self.system = system
graph = StateGraph(AgentState)
graph.add_node("llm", self.call_openai)
graph.add_node("action", self.take_action)
graph.add_conditional_edges("llm", self.exists_action, {True: "action", False: END})
graph.add_edge("action", "llm")
graph.set_entry_point("llm")
self.graph = graph.compile(
checkpointer=checkpointer,
interrupt_before=["action"] # new modification. Let the human decide before call action (tool)
)
self.tools = {t.name: t for t in tools}
self.model = model.bind_tools(tools)
def call_openai(self, state: AgentState):
messages = state['messages']
if self.system:
messages = [SystemMessage(content=self.system)] + messages
message = self.model.invoke(messages)
return {'messages': [message]}
def exists_action(self, state: AgentState):
print(state)
result = state['messages'][-1]
return len(result.tool_calls) > 0
def take_action(self, state: AgentState):
tool_calls = state['messages'][-1].tool_calls
results = []
for t in tool_calls:
print(f"Calling: {t}")
result = self.tools[t['name']].invoke(t['args'])
results.append(ToolMessage(tool_call_id=t['id'], name=t['name'], content=str(result)))
print("Back to the model!")
return {'messages': results}
prompt = """You are a smart research assistant. Use the search engine to look up information. \
You are allowed to make multiple calls (either together or in sequence). \
Only look up information when you are sure of what you want. \
If you need to look up some information before asking a follow up question, you are allowed to do that!
"""
model = ChatOpenAI(model="gpt-3.5-turbo")
abot = Agent(model, [tool], system=prompt, checkpointer=memory)
messages = [HumanMessage(content="Whats the weather in SF?")]
thread = {"configurable": {"thread_id": "1"}}
for event in abot.graph.stream({"messages": messages}, thread):
for v in event.values():
print(v)
{'messages': [HumanMessage(content='Whats the weather in SF?', id='d36a5d4f-3b0d-4aff-b9e8-ac2951698903'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_EQFPPpdUKSYJclesArn26nEX', 'function': {'arguments': '{"query":"weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-cb2f6ae7-f422-46d5-863b-6f6188043d2f-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX'}])]} {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_EQFPPpdUKSYJclesArn26nEX', 'function': {'arguments': '{"query":"weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-cb2f6ae7-f422-46d5-863b-6f6188043d2f-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX'}])]}
The agent was stopped before use the tool as we indiceted in the agent
abot.graph.get_state(thread) # state of the graph at this point
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in SF?', id='d36a5d4f-3b0d-4aff-b9e8-ac2951698903'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-cb2f6ae7-f422-46d5-863b-6f6188043d2f-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX'}])]}, next=('action',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eeaf-8751-6628-8001-242195b90c7c'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'llm': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-cb2f6ae7-f422-46d5-863b-6f6188043d2f-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX'}])]}}}, created_at='2024-06-20T09:53:39.742244+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eeaf-8131-62e3-8000-cc7113841e8d'}})
abot.graph.get_state(thread).next # what is the next step in the agent. Call the tool obviously
('action',)
continue after interruptĀ¶
for event in abot.graph.stream(None, thread):
for v in event.values():
print(v)
Calling: {'name': 'tavily_search_results_json', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX'} Back to the model! {'messages': [ToolMessage(content='[{\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'San Francisco\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 37.78, \'lon\': -122.42, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718877205, \'localtime\': \'2024-06-20 2:53\'}, \'current\': {\'last_updated_epoch\': 1718876700, \'last_updated\': \'2024-06-20 02:45\', \'temp_c\': 12.2, \'temp_f\': 54.0, \'is_day\': 0, \'condition\': {\'text\': \'Partly cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 6.9, \'wind_kph\': 11.2, \'wind_degree\': 280, \'wind_dir\': \'W\', \'pressure_mb\': 1013.0, \'pressure_in\': 29.92, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 86, \'cloud\': 75, \'feelslike_c\': 11.1, \'feelslike_f\': 52.0, \'windchill_c\': 10.0, \'windchill_f\': 50.1, \'heatindex_c\': 11.5, \'heatindex_f\': 52.8, \'dewpoint_c\': 9.7, \'dewpoint_f\': 49.5, \'vis_km\': 16.0, \'vis_miles\': 9.0, \'uv\': 1.0, \'gust_mph\': 9.8, \'gust_kph\': 15.8}}"}, {\'url\': \'https://world-weather.info/forecast/usa/san_francisco/june-2024/\', \'content\': \'Extended weather forecast in San Francisco. Hourly Week 10 days 14 days 30 days Year. Detailed ā” San Francisco Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info.\'}]', name='tavily_search_results_json', id='352c4ae8-74c3-498e-a1ad-036bbc082647', tool_call_id='call_EQFPPpdUKSYJclesArn26nEX')]} {'messages': [HumanMessage(content='Whats the weather in SF?', id='d36a5d4f-3b0d-4aff-b9e8-ac2951698903'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-cb2f6ae7-f422-46d5-863b-6f6188043d2f-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX'}]), ToolMessage(content='[{\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'San Francisco\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 37.78, \'lon\': -122.42, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718877205, \'localtime\': \'2024-06-20 2:53\'}, \'current\': {\'last_updated_epoch\': 1718876700, \'last_updated\': \'2024-06-20 02:45\', \'temp_c\': 12.2, \'temp_f\': 54.0, \'is_day\': 0, \'condition\': {\'text\': \'Partly cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 6.9, \'wind_kph\': 11.2, \'wind_degree\': 280, \'wind_dir\': \'W\', \'pressure_mb\': 1013.0, \'pressure_in\': 29.92, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 86, \'cloud\': 75, \'feelslike_c\': 11.1, \'feelslike_f\': 52.0, \'windchill_c\': 10.0, \'windchill_f\': 50.1, \'heatindex_c\': 11.5, \'heatindex_f\': 52.8, \'dewpoint_c\': 9.7, \'dewpoint_f\': 49.5, \'vis_km\': 16.0, \'vis_miles\': 9.0, \'uv\': 1.0, \'gust_mph\': 9.8, \'gust_kph\': 15.8}}"}, {\'url\': \'https://world-weather.info/forecast/usa/san_francisco/june-2024/\', \'content\': \'Extended weather forecast in San Francisco. Hourly Week 10 days 14 days 30 days Year. Detailed ā” San Francisco Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info.\'}]', name='tavily_search_results_json', id='352c4ae8-74c3-498e-a1ad-036bbc082647', tool_call_id='call_EQFPPpdUKSYJclesArn26nEX'), AIMessage(content='The current weather in San Francisco is partly cloudy with a temperature of 12.2Ā°C (54.0Ā°F). The wind speed is 6.9 mph coming from the west. The humidity is at 86%, and the visibility is 16.0 km (9.0 miles).', response_metadata={'token_usage': {'completion_tokens': 61, 'prompt_tokens': 676, 'total_tokens': 737}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-7ace7e72-d49d-4014-a077-a938ffc76874-0')]} {'messages': [AIMessage(content='The current weather in San Francisco is partly cloudy with a temperature of 12.2Ā°C (54.0Ā°F). The wind speed is 6.9 mph coming from the west. The humidity is at 86%, and the visibility is 16.0 km (9.0 miles).', response_metadata={'token_usage': {'completion_tokens': 61, 'prompt_tokens': 676, 'total_tokens': 737}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-7ace7e72-d49d-4014-a077-a938ffc76874-0')]}
abot.graph.get_state(thread) # now the state contains the full list of messages
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in SF?', id='d36a5d4f-3b0d-4aff-b9e8-ac2951698903'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-cb2f6ae7-f422-46d5-863b-6f6188043d2f-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_EQFPPpdUKSYJclesArn26nEX'}]), ToolMessage(content='[{\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'San Francisco\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 37.78, \'lon\': -122.42, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718877205, \'localtime\': \'2024-06-20 2:53\'}, \'current\': {\'last_updated_epoch\': 1718876700, \'last_updated\': \'2024-06-20 02:45\', \'temp_c\': 12.2, \'temp_f\': 54.0, \'is_day\': 0, \'condition\': {\'text\': \'Partly cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 6.9, \'wind_kph\': 11.2, \'wind_degree\': 280, \'wind_dir\': \'W\', \'pressure_mb\': 1013.0, \'pressure_in\': 29.92, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 86, \'cloud\': 75, \'feelslike_c\': 11.1, \'feelslike_f\': 52.0, \'windchill_c\': 10.0, \'windchill_f\': 50.1, \'heatindex_c\': 11.5, \'heatindex_f\': 52.8, \'dewpoint_c\': 9.7, \'dewpoint_f\': 49.5, \'vis_km\': 16.0, \'vis_miles\': 9.0, \'uv\': 1.0, \'gust_mph\': 9.8, \'gust_kph\': 15.8}}"}, {\'url\': \'https://world-weather.info/forecast/usa/san_francisco/june-2024/\', \'content\': \'Extended weather forecast in San Francisco. Hourly Week 10 days 14 days 30 days Year. Detailed ā” San Francisco Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info.\'}]', name='tavily_search_results_json', id='352c4ae8-74c3-498e-a1ad-036bbc082647', tool_call_id='call_EQFPPpdUKSYJclesArn26nEX'), AIMessage(content='The current weather in San Francisco is partly cloudy with a temperature of 12.2Ā°C (54.0Ā°F). The wind speed is 6.9 mph coming from the west. The humidity is at 86%, and the visibility is 16.0 km (9.0 miles).', response_metadata={'finish_reason': 'stop', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 61, 'prompt_tokens': 676, 'total_tokens': 737}}, id='run-7ace7e72-d49d-4014-a077-a938ffc76874-0')]}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eeb4-a218-679c-8003-bd2ce956edc3'}}, metadata={'source': 'loop', 'step': 3, 'writes': {'llm': {'messages': [AIMessage(content='The current weather in San Francisco is partly cloudy with a temperature of 12.2Ā°C (54.0Ā°F). The wind speed is 6.9 mph coming from the west. The humidity is at 86%, and the visibility is 16.0 km (9.0 miles).', response_metadata={'finish_reason': 'stop', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 61, 'prompt_tokens': 676, 'total_tokens': 737}}, id='run-7ace7e72-d49d-4014-a077-a938ffc76874-0')]}}}, created_at='2024-06-20T09:55:56.767815+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eeb4-92e9-6895-8002-df4aee06f554'}})
abot.graph.get_state(thread).next # empty. Nothing left to be done
()
messages = [HumanMessage("Whats the weather in LA?")]
thread = {"configurable": {"thread_id": "2"}}
for event in abot.graph.stream({"messages": messages}, thread):
for v in event.values():
print(v)
while abot.graph.get_state(thread).next:
print("\n", abot.graph.get_state(thread),"\n")
_input = input("proceed?")
if _input != "y":
print("aborting")
break
for event in abot.graph.stream(None, thread):
for v in event.values():
print(v)
{'messages': [HumanMessage(content='Whats the weather in LA?', id='3bdd5e93-7873-4889-9442-64fb4649d921'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul', 'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-7d8c107d-4362-4661-990a-38dbaab7b258-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul'}])]} {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul', 'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-7d8c107d-4362-4661-990a-38dbaab7b258-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul'}])]} StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='3bdd5e93-7873-4889-9442-64fb4649d921'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-7d8c107d-4362-4661-990a-38dbaab7b258-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul'}])]}, next=('action',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeb8-d4f6-67ac-8001-5792c654027b'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'llm': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-7d8c107d-4362-4661-990a-38dbaab7b258-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul'}])]}}}, created_at='2024-06-20T09:57:49.475814+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeb8-cec3-6ba3-8000-177040d6d295'}}) proceed?y Calling: {'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul'} Back to the model! {'messages': [ToolMessage(content='[{\'url\': \'https://www.weathertab.com/en/c/e/06/united-states/california/los-angeles/\', \'content\': \'Temperature Forecast Normal. Avg High Temps 75 to 85 Ā°F. Avg Low Temps 50 to 60 Ā°F. Explore comprehensive June 2024 weather forecasts for Los Angeles, including daily high and low temperatures, precipitation risks, and monthly temperature trends. Featuring detailed day-by-day forecasts, dynamic graphs of daily rain probabilities, and ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Los Angeles\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 34.05, \'lon\': -118.24, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718877385, \'localtime\': \'2024-06-20 2:56\'}, \'current\': {\'last_updated_epoch\': 1718876700, \'last_updated\': \'2024-06-20 02:45\', \'temp_c\': 17.2, \'temp_f\': 63.0, \'is_day\': 0, \'condition\': {\'text\': \'Partly cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 3.8, \'wind_kph\': 6.1, \'wind_degree\': 220, \'wind_dir\': \'SW\', \'pressure_mb\': 1010.0, \'pressure_in\': 29.81, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 81, \'cloud\': 50, \'feelslike_c\': 17.2, \'feelslike_f\': 63.0, \'windchill_c\': 18.7, \'windchill_f\': 65.6, \'heatindex_c\': 18.7, \'heatindex_f\': 65.6, \'dewpoint_c\': 13.0, \'dewpoint_f\': 55.5, \'vis_km\': 16.0, \'vis_miles\': 9.0, \'uv\': 1.0, \'gust_mph\': 4.0, \'gust_kph\': 6.4}}"}]', name='tavily_search_results_json', id='bbb5066d-f5ba-4ff6-84f5-058953161458', tool_call_id='call_2Sq5pX6O7Ct6eaHpTCSd5Pul')]} {'messages': [HumanMessage(content='Whats the weather in LA?', id='3bdd5e93-7873-4889-9442-64fb4649d921'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-7d8c107d-4362-4661-990a-38dbaab7b258-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_2Sq5pX6O7Ct6eaHpTCSd5Pul'}]), ToolMessage(content='[{\'url\': \'https://www.weathertab.com/en/c/e/06/united-states/california/los-angeles/\', \'content\': \'Temperature Forecast Normal. Avg High Temps 75 to 85 Ā°F. Avg Low Temps 50 to 60 Ā°F. Explore comprehensive June 2024 weather forecasts for Los Angeles, including daily high and low temperatures, precipitation risks, and monthly temperature trends. Featuring detailed day-by-day forecasts, dynamic graphs of daily rain probabilities, and ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Los Angeles\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 34.05, \'lon\': -118.24, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718877385, \'localtime\': \'2024-06-20 2:56\'}, \'current\': {\'last_updated_epoch\': 1718876700, \'last_updated\': \'2024-06-20 02:45\', \'temp_c\': 17.2, \'temp_f\': 63.0, \'is_day\': 0, \'condition\': {\'text\': \'Partly cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 3.8, \'wind_kph\': 6.1, \'wind_degree\': 220, \'wind_dir\': \'SW\', \'pressure_mb\': 1010.0, \'pressure_in\': 29.81, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 81, \'cloud\': 50, \'feelslike_c\': 17.2, \'feelslike_f\': 63.0, \'windchill_c\': 18.7, \'windchill_f\': 65.6, \'heatindex_c\': 18.7, \'heatindex_f\': 65.6, \'dewpoint_c\': 13.0, \'dewpoint_f\': 55.5, \'vis_km\': 16.0, \'vis_miles\': 9.0, \'uv\': 1.0, \'gust_mph\': 4.0, \'gust_kph\': 6.4}}"}]', name='tavily_search_results_json', id='bbb5066d-f5ba-4ff6-84f5-058953161458', tool_call_id='call_2Sq5pX6O7Ct6eaHpTCSd5Pul'), AIMessage(content='The current weather in Los Angeles is partly cloudy with a temperature of 63.0Ā°F. The wind speed is 6.1 km/h coming from the southwest direction. The humidity is at 81%, and the visibility is 9.0 miles.', response_metadata={'token_usage': {'completion_tokens': 53, 'prompt_tokens': 699, 'total_tokens': 752}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-207f8666-6fc8-4007-9c9c-621fb0d8a8b7-0')]} {'messages': [AIMessage(content='The current weather in Los Angeles is partly cloudy with a temperature of 63.0Ā°F. The wind speed is 6.1 km/h coming from the southwest direction. The humidity is at 81%, and the visibility is 9.0 miles.', response_metadata={'token_usage': {'completion_tokens': 53, 'prompt_tokens': 699, 'total_tokens': 752}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-207f8666-6fc8-4007-9c9c-621fb0d8a8b7-0')]}
Modify StateĀ¶
Examples to work with snapshots of the state agent
Run until the interrupt and then modify the state.
messages = [HumanMessage("Whats the weather in LA?")]
thread = {"configurable": {"thread_id": "3"}}
for event in abot.graph.stream({"messages": messages}, thread):
for v in event.values():
print(v)
{'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]} {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}
abot.graph.get_state(thread) # at this point we have Human and AI message which is saying to use tavily for search
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}, next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-0e4f-6d1a-8001-cf450db28fe8'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'llm': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}}}, created_at='2024-06-20T10:01:03.394104+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a9-6c86-8000-69c69733b30d'}})
Let's modify the ai message to search for Louisiana instead.
current_values = abot.graph.get_state(thread)
current_values.values['messages'][-1] # ai message, current weather in los angeles.
AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])
current_values.values['messages'][-1].tool_calls
[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}]
replace tool call
_id = current_values.values['messages'][-1].tool_calls[0]['id']
current_values.values['messages'][-1].tool_calls = [
{'name': 'tavily_search_results_json',
'args': {'query': 'current weather in Louisiana'},
'id': _id}
]
current_values.values
{'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}
abot.graph.update_state(thread, current_values.values)
{'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}
{'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec9-2579-6dfe-8002-1a44dd0ad0a5'}}
abot.graph.get_state(thread)
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}, next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec9-2579-6dfe-8002-1a44dd0ad0a5'}}, metadata={'source': 'update', 'step': 2, 'writes': {'llm': {'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}}}, created_at='2024-06-20T10:05:07.414976+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-0e4f-6d1a-8001-cf450db28fe8'}})
for event in abot.graph.stream(None, thread):
for v in event.values():
print(v)
Calling: {'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'} Back to the model! {'messages': [ToolMessage(content='[{\'url\': \'https://world-weather.info/forecast/usa/louisiana/june-2024/\', \'content\': \'Detailed ā” Louisiana Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info. Add the current city. Search. Weather; Archive; Widgets Ā°F. World; United States; Missouri; Weather in Louisiana; ... 20 +86Ā° +70Ā° 21 +82Ā° +72Ā° 22 ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Louisiana\', \'region\': \'Missouri\', \'country\': \'USA United States of America\', \'lat\': 39.44, \'lon\': -91.06, \'tz_id\': \'America/Chicago\', \'localtime_epoch\': 1718877879, \'localtime\': \'2024-06-20 5:04\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 05:00\', \'temp_c\': 22.4, \'temp_f\': 72.4, \'is_day\': 0, \'condition\': {\'text\': \'Partly Cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 4.5, \'wind_kph\': 7.2, \'wind_degree\': 211, \'wind_dir\': \'SSW\', \'pressure_mb\': 1024.0, \'pressure_in\': 30.23, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 77, \'cloud\': 26, \'feelslike_c\': 24.7, \'feelslike_f\': 76.5, \'windchill_c\': 22.4, \'windchill_f\': 72.4, \'heatindex_c\': 24.7, \'heatindex_f\': 76.5, \'dewpoint_c\': 18.5, \'dewpoint_f\': 65.3, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 8.7, \'gust_kph\': 14.0}}"}]', name='tavily_search_results_json', id='03b3dfaf-d652-414c-b2c5-e89da7a645d2', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs')]} {'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}]), ToolMessage(content='[{\'url\': \'https://world-weather.info/forecast/usa/louisiana/june-2024/\', \'content\': \'Detailed ā” Louisiana Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info. Add the current city. Search. Weather; Archive; Widgets Ā°F. World; United States; Missouri; Weather in Louisiana; ... 20 +86Ā° +70Ā° 21 +82Ā° +72Ā° 22 ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Louisiana\', \'region\': \'Missouri\', \'country\': \'USA United States of America\', \'lat\': 39.44, \'lon\': -91.06, \'tz_id\': \'America/Chicago\', \'localtime_epoch\': 1718877879, \'localtime\': \'2024-06-20 5:04\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 05:00\', \'temp_c\': 22.4, \'temp_f\': 72.4, \'is_day\': 0, \'condition\': {\'text\': \'Partly Cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 4.5, \'wind_kph\': 7.2, \'wind_degree\': 211, \'wind_dir\': \'SSW\', \'pressure_mb\': 1024.0, \'pressure_in\': 30.23, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 77, \'cloud\': 26, \'feelslike_c\': 24.7, \'feelslike_f\': 76.5, \'windchill_c\': 22.4, \'windchill_f\': 72.4, \'heatindex_c\': 24.7, \'heatindex_f\': 76.5, \'dewpoint_c\': 18.5, \'dewpoint_f\': 65.3, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 8.7, \'gust_kph\': 14.0}}"}]', name='tavily_search_results_json', id='03b3dfaf-d652-414c-b2c5-e89da7a645d2', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs'), AIMessage(content='The current weather in Louisiana is partly cloudy with a temperature of 72.4Ā°F. The wind speed is 7.2 km/h coming from the SSW direction. The humidity is at 77%, and the visibility is 6.0 miles.', response_metadata={'token_usage': {'completion_tokens': 53, 'prompt_tokens': 700, 'total_tokens': 753}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-1f59441f-7c01-44fc-9a75-3b0e8d8753f1-0')]} {'messages': [AIMessage(content='The current weather in Louisiana is partly cloudy with a temperature of 72.4Ā°F. The wind speed is 7.2 km/h coming from the SSW direction. The humidity is at 77%, and the visibility is 6.0 miles.', response_metadata={'token_usage': {'completion_tokens': 53, 'prompt_tokens': 700, 'total_tokens': 753}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-1f59441f-7c01-44fc-9a75-3b0e8d8753f1-0')]}
Time TravelĀ¶
states = []
for state in abot.graph.get_state_history(thread):
print(state)
print('--')
states.append(state)
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}]), ToolMessage(content='[{\'url\': \'https://world-weather.info/forecast/usa/louisiana/june-2024/\', \'content\': \'Detailed ā” Louisiana Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info. Add the current city. Search. Weather; Archive; Widgets Ā°F. World; United States; Missouri; Weather in Louisiana; ... 20 +86Ā° +70Ā° 21 +82Ā° +72Ā° 22 ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Louisiana\', \'region\': \'Missouri\', \'country\': \'USA United States of America\', \'lat\': 39.44, \'lon\': -91.06, \'tz_id\': \'America/Chicago\', \'localtime_epoch\': 1718877879, \'localtime\': \'2024-06-20 5:04\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 05:00\', \'temp_c\': 22.4, \'temp_f\': 72.4, \'is_day\': 0, \'condition\': {\'text\': \'Partly Cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 4.5, \'wind_kph\': 7.2, \'wind_degree\': 211, \'wind_dir\': \'SSW\', \'pressure_mb\': 1024.0, \'pressure_in\': 30.23, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 77, \'cloud\': 26, \'feelslike_c\': 24.7, \'feelslike_f\': 76.5, \'windchill_c\': 22.4, \'windchill_f\': 72.4, \'heatindex_c\': 24.7, \'heatindex_f\': 76.5, \'dewpoint_c\': 18.5, \'dewpoint_f\': 65.3, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 8.7, \'gust_kph\': 14.0}}"}]', name='tavily_search_results_json', id='03b3dfaf-d652-414c-b2c5-e89da7a645d2', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs'), AIMessage(content='The current weather in Louisiana is partly cloudy with a temperature of 72.4Ā°F. The wind speed is 7.2 km/h coming from the SSW direction. The humidity is at 77%, and the visibility is 6.0 miles.', response_metadata={'finish_reason': 'stop', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 53, 'prompt_tokens': 700, 'total_tokens': 753}}, id='run-1f59441f-7c01-44fc-9a75-3b0e8d8753f1-0')]}, next=(), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eeca-0698-6ba6-8004-5e5963f42e2a'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'llm': {'messages': [AIMessage(content='The current weather in Louisiana is partly cloudy with a temperature of 72.4Ā°F. The wind speed is 7.2 km/h coming from the SSW direction. The humidity is at 77%, and the visibility is 6.0 miles.', response_metadata={'finish_reason': 'stop', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 53, 'prompt_tokens': 700, 'total_tokens': 753}}, id='run-1f59441f-7c01-44fc-9a75-3b0e8d8753f1-0')]}}}, created_at='2024-06-20T10:05:31.020566+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec9-fbae-6561-8003-04b86a574dd5'}}) -- StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}]), ToolMessage(content='[{\'url\': \'https://world-weather.info/forecast/usa/louisiana/june-2024/\', \'content\': \'Detailed ā” Louisiana Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info. Add the current city. Search. Weather; Archive; Widgets Ā°F. World; United States; Missouri; Weather in Louisiana; ... 20 +86Ā° +70Ā° 21 +82Ā° +72Ā° 22 ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Louisiana\', \'region\': \'Missouri\', \'country\': \'USA United States of America\', \'lat\': 39.44, \'lon\': -91.06, \'tz_id\': \'America/Chicago\', \'localtime_epoch\': 1718877879, \'localtime\': \'2024-06-20 5:04\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 05:00\', \'temp_c\': 22.4, \'temp_f\': 72.4, \'is_day\': 0, \'condition\': {\'text\': \'Partly Cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 4.5, \'wind_kph\': 7.2, \'wind_degree\': 211, \'wind_dir\': \'SSW\', \'pressure_mb\': 1024.0, \'pressure_in\': 30.23, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 77, \'cloud\': 26, \'feelslike_c\': 24.7, \'feelslike_f\': 76.5, \'windchill_c\': 22.4, \'windchill_f\': 72.4, \'heatindex_c\': 24.7, \'heatindex_f\': 76.5, \'dewpoint_c\': 18.5, \'dewpoint_f\': 65.3, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 8.7, \'gust_kph\': 14.0}}"}]', name='tavily_search_results_json', id='03b3dfaf-d652-414c-b2c5-e89da7a645d2', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs')]}, next=('llm',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec9-fbae-6561-8003-04b86a574dd5'}}, metadata={'source': 'loop', 'step': 3, 'writes': {'action': {'messages': [ToolMessage(content='[{\'url\': \'https://world-weather.info/forecast/usa/louisiana/june-2024/\', \'content\': \'Detailed ā” Louisiana Weather Forecast for June 2024 - day/night š”ļø temperatures, precipitations - World-Weather.info. Add the current city. Search. Weather; Archive; Widgets Ā°F. World; United States; Missouri; Weather in Louisiana; ... 20 +86Ā° +70Ā° 21 +82Ā° +72Ā° 22 ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Louisiana\', \'region\': \'Missouri\', \'country\': \'USA United States of America\', \'lat\': 39.44, \'lon\': -91.06, \'tz_id\': \'America/Chicago\', \'localtime_epoch\': 1718877879, \'localtime\': \'2024-06-20 5:04\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 05:00\', \'temp_c\': 22.4, \'temp_f\': 72.4, \'is_day\': 0, \'condition\': {\'text\': \'Partly Cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/116.png\', \'code\': 1003}, \'wind_mph\': 4.5, \'wind_kph\': 7.2, \'wind_degree\': 211, \'wind_dir\': \'SSW\', \'pressure_mb\': 1024.0, \'pressure_in\': 30.23, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 77, \'cloud\': 26, \'feelslike_c\': 24.7, \'feelslike_f\': 76.5, \'windchill_c\': 22.4, \'windchill_f\': 72.4, \'heatindex_c\': 24.7, \'heatindex_f\': 76.5, \'dewpoint_c\': 18.5, \'dewpoint_f\': 65.3, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 8.7, \'gust_kph\': 14.0}}"}]', name='tavily_search_results_json', id='03b3dfaf-d652-414c-b2c5-e89da7a645d2', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs')]}}}, created_at='2024-06-20T10:05:29.875981+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec9-2579-6dfe-8002-1a44dd0ad0a5'}}) -- StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}, next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec9-2579-6dfe-8002-1a44dd0ad0a5'}}, metadata={'source': 'update', 'step': 2, 'writes': {'llm': {'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in Louisiana'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}}}, created_at='2024-06-20T10:05:07.414976+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-0e4f-6d1a-8001-cf450db28fe8'}}) -- StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}, next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-0e4f-6d1a-8001-cf450db28fe8'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'llm': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}}}, created_at='2024-06-20T10:01:03.394104+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a9-6c86-8000-69c69733b30d'}}) -- StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe')]}, next=('llm',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a9-6c86-8000-69c69733b30d'}}, metadata={'source': 'loop', 'step': 0, 'writes': None}, created_at='2024-06-20T10:01:02.696959+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a7-68cc-bfff-42202db50b48'}}) -- StateSnapshot(values={'messages': []}, next=('__start__',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a7-68cc-bfff-42202db50b48'}}, metadata={'source': 'input', 'step': -1, 'writes': {'messages': [HumanMessage(content='Whats the weather in LA?')]}}, created_at='2024-06-20T10:01:02.696048+00:00', parent_config=None) --
To fetch the same state as was filmed, the offset below is changed to -3
from -1
. This accounts for the initial state __start__
and the first state that are now stored to state memory with the latest version of software.
to_replay = states[-3]
to_replay
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}, next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-0e4f-6d1a-8001-cf450db28fe8'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'llm': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}}}, created_at='2024-06-20T10:01:03.394104+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a9-6c86-8000-69c69733b30d'}})
for event in abot.graph.stream(None, to_replay.config):
for k, v in event.items():
print(v)
Calling: {'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'} Back to the model! {'messages': [ToolMessage(content='[{\'url\': \'https://www.weathertab.com/en/c/e/06/united-states/california/los-angeles/\', \'content\': \'Temperature Forecast Normal. Avg High Temps 75 to 85 Ā°F. Avg Low Temps 50 to 60 Ā°F. Explore comprehensive June 2024 weather forecasts for Los Angeles, including daily high and low temperatures, precipitation risks, and monthly temperature trends. Featuring detailed day-by-day forecasts, dynamic graphs of daily rain probabilities, and ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Los Angeles\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 34.05, \'lon\': -118.24, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718878062, \'localtime\': \'2024-06-20 3:07\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 03:00\', \'temp_c\': 18.4, \'temp_f\': 65.2, \'is_day\': 0, \'condition\': {\'text\': \'Clear\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/113.png\', \'code\': 1000}, \'wind_mph\': 2.5, \'wind_kph\': 4.0, \'wind_degree\': 208, \'wind_dir\': \'SSW\', \'pressure_mb\': 1009.0, \'pressure_in\': 29.78, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 70, \'cloud\': 0, \'feelslike_c\': 18.4, \'feelslike_f\': 65.2, \'windchill_c\': 18.4, \'windchill_f\': 65.2, \'heatindex_c\': 18.4, \'heatindex_f\': 65.2, \'dewpoint_c\': 12.8, \'dewpoint_f\': 55.1, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 3.4, \'gust_kph\': 5.5}}"}]', name='tavily_search_results_json', id='1e5626a2-69d1-47fb-abaa-5ec9b64dc67c', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs')]} {'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}]), ToolMessage(content='[{\'url\': \'https://www.weathertab.com/en/c/e/06/united-states/california/los-angeles/\', \'content\': \'Temperature Forecast Normal. Avg High Temps 75 to 85 Ā°F. Avg Low Temps 50 to 60 Ā°F. Explore comprehensive June 2024 weather forecasts for Los Angeles, including daily high and low temperatures, precipitation risks, and monthly temperature trends. Featuring detailed day-by-day forecasts, dynamic graphs of daily rain probabilities, and ...\'}, {\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Los Angeles\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 34.05, \'lon\': -118.24, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718878062, \'localtime\': \'2024-06-20 3:07\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 03:00\', \'temp_c\': 18.4, \'temp_f\': 65.2, \'is_day\': 0, \'condition\': {\'text\': \'Clear\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/113.png\', \'code\': 1000}, \'wind_mph\': 2.5, \'wind_kph\': 4.0, \'wind_degree\': 208, \'wind_dir\': \'SSW\', \'pressure_mb\': 1009.0, \'pressure_in\': 29.78, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 70, \'cloud\': 0, \'feelslike_c\': 18.4, \'feelslike_f\': 65.2, \'windchill_c\': 18.4, \'windchill_f\': 65.2, \'heatindex_c\': 18.4, \'heatindex_f\': 65.2, \'dewpoint_c\': 12.8, \'dewpoint_f\': 55.1, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 3.4, \'gust_kph\': 5.5}}"}]', name='tavily_search_results_json', id='1e5626a2-69d1-47fb-abaa-5ec9b64dc67c', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs'), AIMessage(content='The current weather in Los Angeles is clear with a temperature of 65.2Ā°F. The wind speed is 4.0 km/h coming from the SSW direction. The humidity is at 70%, and there is no precipitation at the moment.', response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 698, 'total_tokens': 750}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-5027f5ca-8f8d-40ba-8b90-03548de3ae50-0')]} {'messages': [AIMessage(content='The current weather in Los Angeles is clear with a temperature of 65.2Ā°F. The wind speed is 4.0 km/h coming from the SSW direction. The humidity is at 70%, and there is no precipitation at the moment.', response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 698, 'total_tokens': 750}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-5027f5ca-8f8d-40ba-8b90-03548de3ae50-0')]}
Go back in time and editĀ¶
to_replay
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}, next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-0e4f-6d1a-8001-cf450db28fe8'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'llm': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}}}, created_at='2024-06-20T10:01:03.394104+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a9-6c86-8000-69c69733b30d'}})
_id = to_replay.values['messages'][-1].tool_calls[0]['id']
to_replay.values['messages'][-1].tool_calls = [{'name': 'tavily_search_results_json',
'args': {'query': 'current weather in LA, accuweather'}, # change the query speciifying accuweather
'id': _id}]
branch_state = abot.graph.update_state(to_replay.config, to_replay.values)
{'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in LA, accuweather'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}
for event in abot.graph.stream(None, branch_state):
for k, v in event.items():
if k != "__end__":
print(v)
Calling: {'name': 'tavily_search_results_json', 'args': {'query': 'current weather in LA, accuweather'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'} Back to the model! {'messages': [ToolMessage(content='[{\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Los Angeles\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 34.05, \'lon\': -118.24, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718878062, \'localtime\': \'2024-06-20 3:07\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 03:00\', \'temp_c\': 18.4, \'temp_f\': 65.2, \'is_day\': 0, \'condition\': {\'text\': \'Clear\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/113.png\', \'code\': 1000}, \'wind_mph\': 2.5, \'wind_kph\': 4.0, \'wind_degree\': 208, \'wind_dir\': \'SSW\', \'pressure_mb\': 1009.0, \'pressure_in\': 29.78, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 70, \'cloud\': 0, \'feelslike_c\': 18.4, \'feelslike_f\': 65.2, \'windchill_c\': 18.4, \'windchill_f\': 65.2, \'heatindex_c\': 18.4, \'heatindex_f\': 65.2, \'dewpoint_c\': 12.8, \'dewpoint_f\': 55.1, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 3.4, \'gust_kph\': 5.5}}"}, {\'url\': \'https://www.accuweather.com/en/us/los-angeles/90012/current-weather/347625\', \'content\': \'Current weather in Los Angeles, CA. Check current conditions in Los Angeles, CA with radar, hourly, and more.\'}]', name='tavily_search_results_json', id='f7f367ff-ed8b-4cd4-8f10-d1c221c032b0', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs')]} {'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in LA, accuweather'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}]), ToolMessage(content='[{\'url\': \'https://www.weatherapi.com/\', \'content\': "{\'location\': {\'name\': \'Los Angeles\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 34.05, \'lon\': -118.24, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1718878062, \'localtime\': \'2024-06-20 3:07\'}, \'current\': {\'last_updated_epoch\': 1718877600, \'last_updated\': \'2024-06-20 03:00\', \'temp_c\': 18.4, \'temp_f\': 65.2, \'is_day\': 0, \'condition\': {\'text\': \'Clear\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/night/113.png\', \'code\': 1000}, \'wind_mph\': 2.5, \'wind_kph\': 4.0, \'wind_degree\': 208, \'wind_dir\': \'SSW\', \'pressure_mb\': 1009.0, \'pressure_in\': 29.78, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 70, \'cloud\': 0, \'feelslike_c\': 18.4, \'feelslike_f\': 65.2, \'windchill_c\': 18.4, \'windchill_f\': 65.2, \'heatindex_c\': 18.4, \'heatindex_f\': 65.2, \'dewpoint_c\': 12.8, \'dewpoint_f\': 55.1, \'vis_km\': 10.0, \'vis_miles\': 6.0, \'uv\': 1.0, \'gust_mph\': 3.4, \'gust_kph\': 5.5}}"}, {\'url\': \'https://www.accuweather.com/en/us/los-angeles/90012/current-weather/347625\', \'content\': \'Current weather in Los Angeles, CA. Check current conditions in Los Angeles, CA with radar, hourly, and more.\'}]', name='tavily_search_results_json', id='f7f367ff-ed8b-4cd4-8f10-d1c221c032b0', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs'), AIMessage(content='The current weather in Los Angeles is clear with a temperature of 65.2Ā°F (18.4Ā°C). The wind speed is 4.0 km/h coming from SSW.', response_metadata={'token_usage': {'completion_tokens': 39, 'prompt_tokens': 654, 'total_tokens': 693}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-f9cc1229-d6c1-4af6-95f7-29ef11b5fd0d-0')]} {'messages': [AIMessage(content='The current weather in Los Angeles is clear with a temperature of 65.2Ā°F (18.4Ā°C). The wind speed is 4.0 km/h coming from SSW.', response_metadata={'token_usage': {'completion_tokens': 39, 'prompt_tokens': 654, 'total_tokens': 693}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-f9cc1229-d6c1-4af6-95f7-29ef11b5fd0d-0')]}
Add message to a state at a given timeĀ¶
to_replay
StateSnapshot(values={'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in LA, accuweather'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}, next=('action',), config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-0e4f-6d1a-8001-cf450db28fe8'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'llm': {'messages': [AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}])]}}}, created_at='2024-06-20T10:01:03.394104+00:00', parent_config={'configurable': {'thread_id': '3', 'thread_ts': '1ef2eec0-07a9-6c86-8000-69c69733b30d'}})
_id = to_replay.values['messages'][-1].tool_calls[0]['id']
# adding manually the response of the tool
state_update = {"messages": [ToolMessage(
tool_call_id=_id,
name="tavily_search_results_json",
content="54 degree celcius",
)]}
branch_and_add = abot.graph.update_state(
to_replay.config,
state_update,
as_node="action") # look at the new parameter. The modiification is like an action node
for event in abot.graph.stream(None, branch_and_add):
for k, v in event.items():
print(v)
{'messages': [HumanMessage(content='Whats the weather in LA?', id='4e2b2618-5490-462a-a4d6-5cacb50683fe'), AIMessage(content='', additional_kwargs={'tool_calls': [{'function': {'arguments': '{"query":"weather in Los Angeles"}', 'name': 'tavily_search_results_json'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs', 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'token_usage': {'completion_tokens': 21, 'prompt_tokens': 152, 'total_tokens': 173}}, id='run-59d9ee45-dd65-4406-98f1-912e7647d7ef-0', tool_calls=[{'name': 'tavily_search_results_json', 'args': {'query': 'weather in Los Angeles'}, 'id': 'call_olBQ82ovcX3KMuZzXVzKnaYs'}]), ToolMessage(content='54 degree celcius', name='tavily_search_results_json', id='05f685ab-0a63-46b4-bbdf-fcfa4bdfccee', tool_call_id='call_olBQ82ovcX3KMuZzXVzKnaYs'), AIMessage(content='The current weather in Los Angeles is 54 degrees Celsius.', response_metadata={'token_usage': {'completion_tokens': 13, 'prompt_tokens': 190, 'total_tokens': 203}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-ab24c24b-de66-4a62-bc3a-a5f666fe8a31-0')]} {'messages': [AIMessage(content='The current weather in Los Angeles is 54 degrees Celsius.', response_metadata={'token_usage': {'completion_tokens': 13, 'prompt_tokens': 190, 'total_tokens': 203}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-ab24c24b-de66-4a62-bc3a-a5f666fe8a31-0')]}
Extra PracticeĀ¶
Build a small graphĀ¶
This is a small simple graph you can tinker with if you want more insight into controlling state memory.
from dotenv import load_dotenv
_ = load_dotenv()
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
from langgraph.checkpoint.sqlite import SqliteSaver
Define a simple 2 node graph with the following state: -lnode
: last node -scratch
: a scratchpad location -count
: a counter that is incremented each step
class AgentState(TypedDict):
lnode: str
scratch: str
count: Annotated[int, operator.add]
def node1(state: AgentState):
print(f"node1, count:{state['count']}")
return {"lnode": "node_1",
"count": 1,
}
def node2(state: AgentState):
print(f"node2, count:{state['count']}")
return {"lnode": "node_2",
"count": 1,
}
The graph goes N1->N2->N1... but breaks after count reaches 3.
def should_continue(state):
return state["count"] < 3
builder = StateGraph(AgentState)
builder.add_node("Node1", node1)
builder.add_node("Node2", node2)
builder.add_edge("Node1", "Node2")
builder.add_conditional_edges("Node2",
should_continue,
{True: "Node1", False: END})
builder.set_entry_point("Node1")
memory = SqliteSaver.from_conn_string(":memory:")
graph = builder.compile(checkpointer=memory)
Run it!Ā¶
Now, set the thread and run!
thread = {"configurable": {"thread_id": str(1)}}
graph.invoke({"count":0, "scratch":"hi"},thread)
node1, count:0 node2, count:1 node1, count:2 node2, count:3
{'lnode': 'node_2', 'scratch': 'hi', 'count': 4}
Look at current stateĀ¶
Get the current state. Note the values
which are the AgentState. Note the config
and the thread_ts
. You will be using those to refer to snapshots below.
graph.get_state(thread)
StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 4}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a1c-63f9-8004-353e583a5987'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:14:38.326255+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a19-64a0-8003-f450376a5d13'}})
View all the statesnapshots in memory. You can use the displayed count
agentstate variable to help track what you see. Notice the most recent snapshots are returned by the iterator first. Also note that there is a handy step
variable in the metadata that counts the number of steps in the graph execution. This is a bit detailed - but you can also notice that the parent_config is the config of the previous node. At initial startup, additional states are inserted into memory to create a parent. This is something to check when you branch or time travel below.
Look at state historyĀ¶
for state in graph.get_state_history(thread):
print(state, "\n")
StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 4}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a1c-63f9-8004-353e583a5987'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:14:38.326255+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a19-64a0-8003-f450376a5d13'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 3}, next=('Node2',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a19-64a0-8003-f450376a5d13'}}, metadata={'source': 'loop', 'step': 3, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:14:38.325048+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a17-628c-8002-83289f850838'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 2}, next=('Node1',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a17-628c-8002-83289f850838'}}, metadata={'source': 'loop', 'step': 2, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:14:38.324174+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 1}, next=('Node2',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:14:38.322167+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0e-62e5-8000-e9c2de78c1d0'}}) StateSnapshot(values={'scratch': 'hi', 'count': 0}, next=('Node1',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0e-62e5-8000-e9c2de78c1d0'}}, metadata={'source': 'loop', 'step': 0, 'writes': None}, created_at='2024-06-20T10:14:38.320495+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0b-693d-bfff-b5a8094535c7'}}) StateSnapshot(values={'count': 0}, next=('__start__',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0b-693d-bfff-b5a8094535c7'}}, metadata={'source': 'input', 'step': -1, 'writes': {'count': 0, 'scratch': 'hi'}}, created_at='2024-06-20T10:14:38.319430+00:00', parent_config=None)
Store just the config
into an list. Note the sequence of counts on the right. get_state_history
returns the most recent snapshots first.
states = []
for state in graph.get_state_history(thread):
states.append(state.config)
print(state.config, state.values['count'])
{'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a1c-63f9-8004-353e583a5987'}} 4 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a19-64a0-8003-f450376a5d13'}} 3 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a17-628c-8002-83289f850838'}} 2 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}} 1 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0e-62e5-8000-e9c2de78c1d0'}} 0 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0b-693d-bfff-b5a8094535c7'}} 0
Grab an early state.
states[-3]
{'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}}
This is the state after Node1 completed for the first time. Note next
is Node2
and count
is 1.
graph.get_state(states[-3])
StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 1}, next=('Node2',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:14:38.322167+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0e-62e5-8000-e9c2de78c1d0'}})
Go Back in TimeĀ¶
Use that state in invoke
to go back in time. Notice it uses states[-3] as current_state and continues to node2,
graph.invoke(None, states[-3])
node2, count:1 node1, count:2 node2, count:3
{'lnode': 'node_2', 'scratch': 'hi', 'count': 4}
Notice the new states are now in state history. Notice the counts on the far right.
thread = {"configurable": {"thread_id": str(1)}}
for state in graph.get_state_history(thread):
print(state.config, state.values['count'])
{'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-798c-6481-8004-fc6ff1c01c0d'}} 4 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-7989-6520-8003-226efb90a295'}} 3 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-7986-6ef1-8002-506614bdb108'}} 2 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a1c-63f9-8004-353e583a5987'}} 4 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a19-64a0-8003-f450376a5d13'}} 3 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a17-628c-8002-83289f850838'}} 2 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}} 1 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0e-62e5-8000-e9c2de78c1d0'}} 0 {'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0b-693d-bfff-b5a8094535c7'}} 0
You can see the details below. Lots of text, but try to find the node that start the new branch. Notice the parent config is not the previous entry in the stack, but is the entry from state[-3].
thread = {"configurable": {"thread_id": str(1)}}
for state in graph.get_state_history(thread):
print(state,"\n")
StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 4}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-798c-6481-8004-fc6ff1c01c0d'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:18:41.536916+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-7989-6520-8003-226efb90a295'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 3}, next=('Node2',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-7989-6520-8003-226efb90a295'}}, metadata={'source': 'loop', 'step': 3, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:18:41.535709+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-7986-6ef1-8002-506614bdb108'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 2}, next=('Node1',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eee7-7986-6ef1-8002-506614bdb108'}}, metadata={'source': 'loop', 'step': 2, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:18:41.534728+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 4}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a1c-63f9-8004-353e583a5987'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:14:38.326255+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a19-64a0-8003-f450376a5d13'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 3}, next=('Node2',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a19-64a0-8003-f450376a5d13'}}, metadata={'source': 'loop', 'step': 3, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:14:38.325048+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a17-628c-8002-83289f850838'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 2}, next=('Node1',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a17-628c-8002-83289f850838'}}, metadata={'source': 'loop', 'step': 2, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:14:38.324174+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 1}, next=('Node2',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a12-6432-8001-f66f1cb52fdb'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:14:38.322167+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0e-62e5-8000-e9c2de78c1d0'}}) StateSnapshot(values={'scratch': 'hi', 'count': 0}, next=('Node1',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0e-62e5-8000-e9c2de78c1d0'}}, metadata={'source': 'loop', 'step': 0, 'writes': None}, created_at='2024-06-20T10:14:38.320495+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0b-693d-bfff-b5a8094535c7'}}) StateSnapshot(values={'count': 0}, next=('__start__',), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef2eede-6a0b-693d-bfff-b5a8094535c7'}}, metadata={'source': 'input', 'step': -1, 'writes': {'count': 0, 'scratch': 'hi'}}, created_at='2024-06-20T10:14:38.319430+00:00', parent_config=None)
Modify StateĀ¶
Let's start by starting a fresh thread and running to clean out history.
thread2 = {"configurable": {"thread_id": str(2)}}
graph.invoke({"count":0, "scratch":"hi"},thread2)
node1, count:0 node2, count:1 node1, count:2 node2, count:3
{'lnode': 'node_2', 'scratch': 'hi', 'count': 4}
from IPython.display import Image
Image(graph.get_graph().draw_png())
states2 = []
for state in graph.get_state_history(thread2):
states2.append(state.config)
print(state.config, state.values['count'])
{'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-960a-6ee6-8004-8ab15b356aa2'}} 4 {'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9607-6b16-8003-45ff2a2ab38c'}} 3 {'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9604-6dac-8002-e5c338fc84fd'}} 2 {'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9601-6232-8001-0459111d94cf'}} 1 {'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fd-6f08-8000-d6447fc02c73'}} 0 {'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fb-6dcd-bfff-13fd28ab4cea'}} 0
Start by grabbing a state.
save_state = graph.get_state(states2[-3])
save_state
StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 1}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9601-6232-8001-0459111d94cf'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:20:05.051436+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fd-6f08-8000-d6447fc02c73'}})
Now modify the values. One subtle item to note: Recall when agent state was defined, count
used operator.add
to indicate that values are added to the current value. Here, -3
will be added to the current count value rather than replace it.
save_state.values["count"] = -3
save_state.values["scratch"] = "hello"
save_state
StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': -3}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9601-6232-8001-0459111d94cf'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:20:05.051436+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fd-6f08-8000-d6447fc02c73'}})
Now update the state. This creates a new entry at the top, or latest entry in memory. This will become the current state.
graph.update_state(thread2,save_state.values)
{'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeeb-fac4-6fea-8005-b6c43f6425ef'}}
Current state is at the top. You can match the thread_ts
. Notice the parent_config
, thread_ts
of the new node - it is the previous node.
for i, state in enumerate(graph.get_state_history(thread2)):
if i >= 3: #print latest 3
break
print(state, '\n')
StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': 1}, next=('Node1',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeeb-fac4-6fea-8005-b6c43f6425ef'}}, metadata={'source': 'update', 'step': 5, 'writes': {'Node2': {'count': -3, 'lnode': 'node_1', 'scratch': 'hello'}}}, created_at='2024-06-20T10:20:42.460966+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-960a-6ee6-8004-8ab15b356aa2'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 4}, next=(), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-960a-6ee6-8004-8ab15b356aa2'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:20:05.055448+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9607-6b16-8003-45ff2a2ab38c'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 3}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9607-6b16-8003-45ff2a2ab38c'}}, metadata={'source': 'loop', 'step': 3, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:20:05.054119+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9604-6dac-8002-e5c338fc84fd'}})
Try again with as_node
Ā¶
When writing using update_state()
, you want to define to the graph logic which node should be assumed as the writer. What this does is allow th graph logic to find the node on the graph. After writing the values, the next()
value is computed by travesing the graph using the new state. In this case, the state we have was written by Node1
. The graph can then compute the next state as being Node2
. Note that in some graphs, this may involve going through conditional edges! Let's try this out.
graph.update_state(thread2,save_state.values, as_node="Node1")
{'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeec-e45e-69aa-8006-ff342d63bc41'}}
for i, state in enumerate(graph.get_state_history(thread2)):
if i >= 3: #print latest 3
break
print(state, '\n')
StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': -2}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeec-e45e-69aa-8006-ff342d63bc41'}}, metadata={'source': 'update', 'step': 6, 'writes': {'Node1': {'count': -3, 'lnode': 'node_1', 'scratch': 'hello'}}}, created_at='2024-06-20T10:21:06.955699+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeeb-fac4-6fea-8005-b6c43f6425ef'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': 1}, next=('Node1',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeeb-fac4-6fea-8005-b6c43f6425ef'}}, metadata={'source': 'update', 'step': 5, 'writes': {'Node2': {'count': -3, 'lnode': 'node_1', 'scratch': 'hello'}}}, created_at='2024-06-20T10:20:42.460966+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-960a-6ee6-8004-8ab15b356aa2'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 4}, next=(), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-960a-6ee6-8004-8ab15b356aa2'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:20:05.055448+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9607-6b16-8003-45ff2a2ab38c'}})
invoke
will run from the current state if not given a particular thread_ts
. This is now the entry that was just added.
graph.invoke(None,thread2)
node2, count:-2 node1, count:-1 node2, count:0 node1, count:1 node2, count:2
{'lnode': 'node_2', 'scratch': 'hello', 'count': 3}
Print out the state history, notice the scratch
value change on the latest entries.
for state in graph.get_state_history(thread2):
print(state,"\n")
StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hello', 'count': 3}, next=(), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00d7-6ff7-800b-b376ab8018f2'}}, metadata={'source': 'loop', 'step': 11, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:21:36.784967+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00d5-642d-800a-690e1405c7c4'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': 2}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00d5-642d-800a-690e1405c7c4'}}, metadata={'source': 'loop', 'step': 10, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:21:36.783863+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00d2-683f-8009-095cb71f415f'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hello', 'count': 1}, next=('Node1',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00d2-683f-8009-095cb71f415f'}}, metadata={'source': 'loop', 'step': 9, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:21:36.782739+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00cf-67ba-8008-3f2303678829'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': 0}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00cf-67ba-8008-3f2303678829'}}, metadata={'source': 'loop', 'step': 8, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:21:36.781495+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00cd-620d-8007-737ce4a524ac'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hello', 'count': -1}, next=('Node1',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeee-00cd-620d-8007-737ce4a524ac'}}, metadata={'source': 'loop', 'step': 7, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:21:36.780528+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeec-e45e-69aa-8006-ff342d63bc41'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': -2}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeec-e45e-69aa-8006-ff342d63bc41'}}, metadata={'source': 'update', 'step': 6, 'writes': {'Node1': {'count': -3, 'lnode': 'node_1', 'scratch': 'hello'}}}, created_at='2024-06-20T10:21:06.955699+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeeb-fac4-6fea-8005-b6c43f6425ef'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hello', 'count': 1}, next=('Node1',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeeb-fac4-6fea-8005-b6c43f6425ef'}}, metadata={'source': 'update', 'step': 5, 'writes': {'Node2': {'count': -3, 'lnode': 'node_1', 'scratch': 'hello'}}}, created_at='2024-06-20T10:20:42.460966+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-960a-6ee6-8004-8ab15b356aa2'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 4}, next=(), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-960a-6ee6-8004-8ab15b356aa2'}}, metadata={'source': 'loop', 'step': 4, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:20:05.055448+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9607-6b16-8003-45ff2a2ab38c'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 3}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9607-6b16-8003-45ff2a2ab38c'}}, metadata={'source': 'loop', 'step': 3, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:20:05.054119+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9604-6dac-8002-e5c338fc84fd'}}) StateSnapshot(values={'lnode': 'node_2', 'scratch': 'hi', 'count': 2}, next=('Node1',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9604-6dac-8002-e5c338fc84fd'}}, metadata={'source': 'loop', 'step': 2, 'writes': {'Node2': {'count': 1, 'lnode': 'node_2'}}}, created_at='2024-06-20T10:20:05.052958+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9601-6232-8001-0459111d94cf'}}) StateSnapshot(values={'lnode': 'node_1', 'scratch': 'hi', 'count': 1}, next=('Node2',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-9601-6232-8001-0459111d94cf'}}, metadata={'source': 'loop', 'step': 1, 'writes': {'Node1': {'count': 1, 'lnode': 'node_1'}}}, created_at='2024-06-20T10:20:05.051436+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fd-6f08-8000-d6447fc02c73'}}) StateSnapshot(values={'scratch': 'hi', 'count': 0}, next=('Node1',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fd-6f08-8000-d6447fc02c73'}}, metadata={'source': 'loop', 'step': 0, 'writes': None}, created_at='2024-06-20T10:20:05.050125+00:00', parent_config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fb-6dcd-bfff-13fd28ab4cea'}}) StateSnapshot(values={'count': 0}, next=('__start__',), config={'configurable': {'thread_id': '2', 'thread_ts': '1ef2eeea-95fb-6dcd-bfff-13fd28ab4cea'}}, metadata={'source': 'input', 'step': -1, 'writes': {'count': 0, 'scratch': 'hi'}}, created_at='2024-06-20T10:20:05.049275+00:00', parent_config=None)
Continue to experiment!
Created: 2024-10-23