SPB Git

Repository Public

langgraph-example.md 9.4 KB 229 lines markdown

1LangGraph is a framework for building stateful LLM applications, making it a2good choice for constructing ReAct (Reasoning and Acting) Agents.34ReAct agents combine LLM reasoning with action execution. They iteratively5think, use tools, and act on observations to achieve user goals, dynamically6adapting their approach. Introduced in ["ReAct: Synergizing Reasoning and Acting7in Language Models"](https://arxiv.org/abs/2210.03629) (2023), this pattern8tries to mirror human-like, flexible problem-solving over rigid workflows.910LangGraph offers a prebuilt ReAct agent ([`create_react_agent`](https://langchain-ai.github.io/langgraph/reference/prebuilt/#langgraph.prebuilt.chat_agent_executor.create_react_agent)),11that shines when you need more control and customization for your ReAct12implementations. This guide will show you a simplified version.1314LangGraph models agents as graphs using three key components:1516- `State`: Shared data structure (typically `TypedDict` or `Pydantic BaseModel`) representing the application's current snapshot.17- `Nodes`: Encodes logic of your agents. They receive the current State as input, perform some computation or side-effect, and return an updated State, such as LLM calls or tool calls.18- `Edges`: Define the next `Node` to execute based on the current `State`, allowing for conditional logic and fixed transitions.1920If you don't have an API Key yet, you can get one from [Google AI21Studio](https://aistudio.google.com/apikey).2223    pip install langgraph langchain-google-genai geopy requests2425Set your API key in the environment variable `GEMINI_API_KEY`.2627    import os2829    # Read your API key from the environment variable or set it manually30    api_key = os.getenv("GEMINI_API_KEY")3132To better understand how to implement a ReAct agent using LangGraph, this guide33will walk through a practical example. You will create an agent whose goal is to34use a tool to find the current weather for a specified location.3536For this weather agent, the `State` will maintain the ongoing conversation37history (as a list of messages) and a counter (as an integer) for the number of38steps taken, for illustrative purposes.3940LangGraph provides a helper function, `add_messages`, for updating state message41lists. It functions as a [reducer](https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers),42taking the current list, plus the new messages, and returns a combined list. It43handles updates by message ID and defaults to an "append-only" behavior for new,44unseen messages.4546> [!NOTE]47> **Note:** Since having a list of messages in the state is common, there exists a prebuilt state called `MessagesState` that you can use as a base class. For this example the messages will be listed explicitly.4849    from typing import Annotated,Sequence, TypedDict5051    from langchain_core.messages import BaseMessage52    from langgraph.graph.message import add_messages  # helper function to add messages to the state5354    class AgentState(TypedDict):55        """The state of the agent."""56        messages: Annotated[Sequence[BaseMessage], add_messages]57        number_of_steps: int5859Next, define your weather tool.6061    from langchain_core.tools import tool62    from geopy.geocoders import Nominatim63    from pydantic import BaseModel, Field64    import requests6566    geolocator = Nominatim(user_agent="weather-app")6768    class SearchInput(BaseModel):69        location:str = Field(description="The city and state, e.g., San Francisco")70        date:str = Field(description="the forecasting date for when to get the weather format (yyyy-mm-dd)")7172    @tool("get_weather_forecast", args_schema=SearchInput, return_direct=True)73    def get_weather_forecast(location: str, date: str):74        """Retrieves the weather using Open-Meteo API.7576        Takes a given location (city) and a date (yyyy-mm-dd).7778        Returns:79            A dict with the time and temperature for each hour.80        """81        # Note that Colab may experience rate limiting on this service. If this82        # happens, use a machine to which you have exclusive access.83        location = geolocator.geocode(location)84        if location:85            try:86                response = requests.get(f"https://api.open-meteo.com/v1/forecast?latitude={location.latitude}&longitude={location.longitude}&hourly=temperature_2m&start_date={date}&end_date={date}")87                data = response.json()88                return dict(zip(data["hourly"]["time"], data["hourly"]["temperature_2m"]))89            except Exception as e:90                return {"error": str(e)}91        else:92            return {"error": "Location not found"}9394    tools = [get_weather_forecast]9596Now initialize the model and bind the tools to the model.9798    from datetime import datetime99    from langchain_google_genai import ChatGoogleGenerativeAI100101    # Create LLM class102    llm = ChatGoogleGenerativeAI(103        model= "gemini-3.8-flash",104        temperature=1.0,105        max_retries=2,106        google_api_key=api_key,107    )108109    # Bind tools to the model110    model = llm.bind_tools([get_weather_forecast])111112    # Test the model with tools113    res=model.invoke(f"What is the weather in Berlin on {datetime.today()}?")114115    print(res)116117The last step before you can run your agent is to define your nodes and edges.118In this example, you have two nodes and one edge.119120- `call_tool` node that executes your tool method. LangGraph has a prebuilt node for this called [ToolNode](https://langchain-ai.github.io/langgraph/how-tos/tool-calling/).121- `call_model` node that uses the `model_with_tools` to call the model.122- `should_continue` edge that decides whether to call the tool or the model.123124The number of nodes and edges is not fixed. You can add as many nodes and edges125as you want to your graph. For example, you could add a node for adding126structured output or a self-verification/reflection node to check the model127output before calling the tool or the model.128129    from langchain_core.messages import ToolMessage130    from langchain_core.runnables import RunnableConfig131132    tools_by_name = {tool.name: tool for tool in tools}133134    # Define our tool node135    def call_tool(state: AgentState):136        outputs = []137        # Iterate over the tool calls in the last message138        for tool_call in state["messages"][-1].tool_calls:139            # Get the tool by name140            tool_result = tools_by_name[tool_call["name"]].invoke(tool_call["args"])141            outputs.append(142                ToolMessage(143                    content=tool_result,144                    name=tool_call["name"],145                    tool_call_id=tool_call["id"],146                )147            )148        return {"messages": outputs}149150    def call_model(151        state: AgentState,152        config: RunnableConfig,153    ):154        # Invoke the model with the system prompt and the messages155        response = model.invoke(state["messages"], config)156        # This returns a list, which combines with the existing messages state157        # using the add_messages reducer.158        return {"messages": [response]}159160    # Define the conditional edge that determines whether to continue or not161    def should_continue(state: AgentState):162        messages = state["messages"]163        # If the last message is not a tool call, then finish164        if not messages[-1].tool_calls:165            return "end"166        # default to continue167        return "continue"168169With all of the agent components ready, you can now assemble them.170171    from langgraph.graph import StateGraph, END172173    # Define a new graph with our state174    workflow = StateGraph(AgentState)175176    # 1. Add the nodes177    workflow.add_node("llm", call_model)178    workflow.add_node("tools",  call_tool)179    # 2. Set the entrypoint as `agent`, this is the first node called180    workflow.set_entry_point("llm")181    # 3. Add a conditional edge after the `llm` node is called.182    workflow.add_conditional_edges(183        # Edge is used after the `llm` node is called.184        "llm",185        # The function that will determine which node is called next.186        should_continue,187        # Mapping for where to go next, keys are strings from the function return,188        # and the values are other nodes.189        # END is a special node marking that the graph is finish.190        {191            # If `tools`, then we call the tool node.192            "continue": "tools",193            # Otherwise we finish.194            "end": END,195        },196    )197    # 4. Add a normal edge after `tools` is called, `llm` node is called next.198    workflow.add_edge("tools", "llm")199200    # Now we can compile and visualize our graph201    graph = workflow.compile()202203You can visualize your graph using the `draw_mermaid_png` method.204205    from IPython.display import Image, display206207    display(Image(graph.get_graph().draw_mermaid_png()))208209![png](https://ai.google.dev/static/gemini-api/docs/images/langgraph-react-agent_16_0.png)210211Now run the agent.212213    from datetime import datetime214    # Create our initial message dictionary215    inputs = {"messages": [("user", f"What is the weather in Berlin on {datetime.today()}?")]}216217    # call our graph with streaming to see the steps218    for state in graph.stream(inputs, stream_mode="values"):219        last_message = state["messages"][-1]220        last_message.pretty_print()221222You can now continue with your conversation, ask for the weather in another223city, or request a comparison.224225    state["messages"].append(("user", "Would it be warmer in Munich?"))226227    for state in graph.stream(state, stream_mode="values"):228        last_message = state["messages"][-1]229        last_message.pretty_print()
Files main
Menu

Theme