Agjent ReAct nga e para me Gemini dhe LangGraph

LangGraph është një kornizë për ndërtimin e aplikacioneve LLM me gjendje statefull, duke e bërë atë një zgjedhje të mirë për ndërtimin e agjentëve ReAct (Reasoning and Acting).

Agjentët ReAct kombinojnë arsyetimin LLM me ekzekutimin e veprimeve. Ata mendojnë, përdorin mjete dhe veprojnë në mënyrë iterative mbi vëzhgimet për të arritur qëllimet e përdoruesit, duke e përshtatur në mënyrë dinamike qasjen e tyre. I prezantuar në "ReAct: Sinergjizimi i Arsyetimit dhe Veprimit në Modelet Gjuhësore" (2023), ky model përpiqet të pasqyrojë zgjidhjen e problemeve fleksibile dhe të ngjashme me ato njerëzore mbi rrjedhat e punës të ngurta.

LangGraph ofron një agjent ReAct të parapërgatitur ( create_react_agent ), i cili shkëlqen kur keni nevojë për më shumë kontroll dhe përshtatje për implementimet tuaja të ReAct. Ky udhëzues do t'ju tregojë një version të thjeshtuar.

LangGraph modelon agjentët si grafe duke përdorur tre komponentë kryesorë:

  • State : Struktura e të dhënave të përbashkëta (zakonisht TypedDict ose Pydantic BaseModel ) që përfaqëson pamjen aktuale të aplikacionit.
  • Nodes : Kodojnë logjikën e agjentëve tuaj. Ata marrin gjendjen aktuale si të dhëna hyrëse, kryejnë disa llogaritje ose efekte anësore dhe kthejnë një gjendje të përditësuar, siç janë thirrjet LLM ose thirrjet e mjeteve.
  • Edges : Përcaktoni Node tjetër që do të ekzekutohet bazuar në State aktuale, duke lejuar logjikën e kushtëzuar dhe tranzicionet fikse.

Nëse nuk keni ende një Çelës API, mund ta merrni një nga Google AI Studio .

pip install langgraph langchain-google-genai geopy requests

Vendosni çelësin tuaj API në variablin e mjedisit GEMINI_API_KEY .

import os

# Read your API key from the environment variable or set it manually
api_key = os.getenv("GEMINI_API_KEY")

Për të kuptuar më mirë se si të implementohet një agjent ReAct duke përdorur LangGraph, ky udhëzues do të shpjegojë një shembull praktik. Do të krijoni një agjent qëllimi i të cilit është të përdorë një mjet për të gjetur motin aktual për një vendndodhje të caktuar.

Për këtë agjent meteorologjik, State do të mirëmbajë historikun e bisedave në vazhdim (si një listë mesazhesh) dhe një numërues (si një numër të plotë) për numrin e hapave të ndërmarrë, për qëllime ilustruese.

LangGraph ofron një funksion ndihmës, add_messages , për përditësimin e listave të mesazheve të gjendjes. Ai funksionon si një reduktues , duke marrë listën aktuale, plus mesazhet e reja, dhe kthen një listë të kombinuar. Ai trajton përditësimet sipas ID-së së mesazhit dhe parazgjedhur vendoset në një sjellje "vetëm për shtim" për mesazhet e reja, të papara.

from typing import Annotated,Sequence, TypedDict

from langchain_core.messages import BaseMessage
from langgraph.graph.message import add_messages  # helper function to add messages to the state


class AgentState(TypedDict):
    """The state of the agent."""
    messages: Annotated[Sequence[BaseMessage], add_messages]
    number_of_steps: int

Tjetra, përcaktoni mjetin tuaj të motit.

from langchain_core.tools import tool
from geopy.geocoders import Nominatim
from pydantic import BaseModel, Field
import requests

geolocator = Nominatim(user_agent="weather-app")

class SearchInput(BaseModel):
    location:str = Field(description="The city and state, e.g., San Francisco")
    date:str = Field(description="the forecasting date for when to get the weather format (yyyy-mm-dd)")

@tool("get_weather_forecast", args_schema=SearchInput, return_direct=True)
def get_weather_forecast(location: str, date: str):
    """Retrieves the weather using Open-Meteo API.

    Takes a given location (city) and a date (yyyy-mm-dd).

    Returns:
        A dict with the time and temperature for each hour.
    """
    # Note that Colab may experience rate limiting on this service. If this
    # happens, use a machine to which you have exclusive access.
    location = geolocator.geocode(location)
    if location:
        try:
            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}")
            data = response.json()
            return dict(zip(data["hourly"]["time"], data["hourly"]["temperature_2m"]))
        except Exception as e:
            return {"error": str(e)}
    else:
        return {"error": "Location not found"}

tools = [get_weather_forecast]

Tani inicializoni modelin dhe lidhni mjetet me modelin.

from datetime import datetime
from langchain_google_genai import ChatGoogleGenerativeAI

# Create LLM class
llm = ChatGoogleGenerativeAI(
    model= "gemini-3-flash-preview",
    temperature=1.0,
    max_retries=2,
    google_api_key=api_key,
)

# Bind tools to the model
model = llm.bind_tools([get_weather_forecast])

# Test the model with tools
res=model.invoke(f"What is the weather in Berlin on {datetime.today()}?")

print(res)

Hapi i fundit përpara se të mund të ekzekutoni agjentin tuaj është të përcaktoni nyjet dhe skajet tuaja. Në këtë shembull, keni dy nyje dhe një skaj.

  • nyja call_tool që ekzekuton metodën tuaj tool. LangGraph ka një nyje të parapërgatitur për këtë të quajtur ToolNode .
  • Nyja call_model që përdor model_with_tools për të thirrur modelin.
  • skaji should_continue që vendos nëse do të thirret mjeti apo modeli.

Numri i nyjeve dhe skajeve nuk është i fiksuar. Mund të shtoni sa më shumë nyje dhe skaje të dëshironi në grafikun tuaj. Për shembull, mund të shtoni një nyje për shtimin e rezultatit të strukturuar ose një nyje vetëverifikimi/reflektimi për të kontrolluar rezultatin e modelit para se të thirrni mjetin ose modelin.

from langchain_core.messages import ToolMessage
from langchain_core.runnables import RunnableConfig

tools_by_name = {tool.name: tool for tool in tools}

# Define our tool node
def call_tool(state: AgentState):
    outputs = []
    # Iterate over the tool calls in the last message
    for tool_call in state["messages"][-1].tool_calls:
        # Get the tool by name
        tool_result = tools_by_name[tool_call["name"]].invoke(tool_call["args"])
        outputs.append(
            ToolMessage(
                content=tool_result,
                name=tool_call["name"],
                tool_call_id=tool_call["id"],
            )
        )
    return {"messages": outputs}

def call_model(
    state: AgentState,
    config: RunnableConfig,
):
    # Invoke the model with the system prompt and the messages
    response = model.invoke(state["messages"], config)
    # This returns a list, which combines with the existing messages state
    # using the add_messages reducer.
    return {"messages": [response]}


# Define the conditional edge that determines whether to continue or not
def should_continue(state: AgentState):
    messages = state["messages"]
    # If the last message is not a tool call, then finish
    if not messages[-1].tool_calls:
        return "end"
    # default to continue
    return "continue"

Me të gjithë përbërësit e agjentit gati, tani mund t'i montoni ato.

from langgraph.graph import StateGraph, END

# Define a new graph with our state
workflow = StateGraph(AgentState)

# 1. Add the nodes
workflow.add_node("llm", call_model)
workflow.add_node("tools",  call_tool)
# 2. Set the entrypoint as `agent`, this is the first node called
workflow.set_entry_point("llm")
# 3. Add a conditional edge after the `llm` node is called.
workflow.add_conditional_edges(
    # Edge is used after the `llm` node is called.
    "llm",
    # The function that will determine which node is called next.
    should_continue,
    # Mapping for where to go next, keys are strings from the function return,
    # and the values are other nodes.
    # END is a special node marking that the graph is finish.
    {
        # If `tools`, then we call the tool node.
        "continue": "tools",
        # Otherwise we finish.
        "end": END,
    },
)
# 4. Add a normal edge after `tools` is called, `llm` node is called next.
workflow.add_edge("tools", "llm")

# Now we can compile and visualize our graph
graph = workflow.compile()

Mund ta vizualizoni grafikun tuaj duke përdorur metodën draw_mermaid_png .

from IPython.display import Image, display

display(Image(graph.get_graph().draw_mermaid_png()))

png

Tani ekzekutoni agjentin.

from datetime import datetime
# Create our initial message dictionary
inputs = {"messages": [("user", f"What is the weather in Berlin on {datetime.today()}?")]}

# call our graph with streaming to see the steps
for state in graph.stream(inputs, stream_mode="values"):
    last_message = state["messages"][-1]
    last_message.pretty_print()

Tani mund të vazhdoni me bisedën tuaj, të kërkoni motin në një qytet tjetër ose të kërkoni një krahasim.

state["messages"].append(("user", "Would it be warmer in Munich?"))

for state in graph.stream(state, stream_mode="values"):
    last_message = state["messages"][-1]
    last_message.pretty_print()