Intelligent systems, especially those powered by large language models (LLMs), are revolutionizing the way we interact with technology. Frameworks like CrewAI, LangGraph, and autogen facilitate the development of agentic applications.
Let’s explore some real-world use cases where these agents can be incredibly beneficial.
Imagine if your Siri or Alexa were enhanced with the capabilities of LLM-powered agents. These upgraded assistants could perform a wide array of tasks beyond their current capabilities. You could ask your Alexa to:
Book a reservation at your preferred hotel.
Check and compare flight prices to various destinations.
Send emails on your behalf.
It’s like having a personal assistant who can handle all your tasks efficiently.
Introducing LangGraph
LangGraph is a powerful framework designed to simplify the creation of intelligent agents powered by large language models. It builds on LangChain, enabling the creation of robust, stateful, multi-actor applications by modeling steps as edges and nodes in a graph. It facilitates effective state management, easy integration of tools and APIs, and dynamic decision-making based on the current context, making it ideal for building complex, agentic applications. For more details, visit the LangGraph documentation.
Creating a Simple Agent Using LangGraph
Let’s create a simple agent using LangGraph that has access to the DuckDuckGo Search Engine.
The Agent Class
The Agent
class creates a state graph with the agent's state schema. It adds nodes for LLMs and actions, and sets conditional edges to transition between nodes based on the existence of actions. The entry point of the graph is set to the LLM.
call_openai: This method invokes the OpenAI model with the current state messages. The LLM model decides whether a call to the tool would be necessary to evaluate the result of the user query. The tool calls are based on the function calling feature provided by OpenAI. You can read about function calling here.
exists_action: This method checks if there are any tool calls in the latest message. If tool calls are present, the execution goes to the
take_action
method.take_action: This method executes the tool call and returns the results.
Here is the implementation of the Agent
class:
class Agent:
def __init__(self, model, tools, system=""):
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()
self.tools = {t.name: t for t in tools}
self.model = model.bind_tools(tools)
def exists_action(self, state: AgentState):
result = state['messages'][-1]
return len(result.tool_calls) > 0
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 take_action(self, state: AgentState):
tool_calls = state['messages'][-1].tool_calls
results = []
for t in tool_calls:
print(f"Calling: {t}")
if not t['name'] in self.tools: # check for bad tool name from LLM
print("\n ....bad tool name....")
result = "bad tool name, retry" # instruct LLM to retry if bad
else:
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}
Instantiating and Testing the Agent
We now create an instance of our agent and provide it with the models and the tools you want to use, and you have your assistant ready to serve you.
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!
"""
tools = [DuckDuckGoSearchRun(args_schema=DDGInput)]
model = ChatOpenAI(model="gpt-4o", api_key="").bind_tools(tools)
abot = Agent(model, tools, system=prompt)
Let's test it.
messages = [HumanMessage(content="Can you tell me flight prices from London to NewYork?")]
result = abot.graph.invoke({"messages": messages})
print(result['messages'][-1].content)
Output
Here is the output that I got for my query. Imagine this enabled in your Alexa, Siri, or Google Mini apps.
Calling: {'name': 'duckduckgo_search', 'args': {'query': 'flight prices from London to New York'}, 'id': 'call_szYpmXLAHm97gWp878swQraf'}
Back to the model!
Flight prices from London to New York can vary. Here are some recent prices:
- **One-way tickets:** Starting at around $332.
- **Round-trip tickets:** Starting at around $600.
These prices can fluctuate based on the time of booking, the airline, and the travel dates. For the most accurate and updated prices, it's advisable to check flight comparison websites like KAYAK or Momondo.
By following the above steps, you can create a simple assistant capable of performing various tasks using LangGraph and LLMs. This demonstrates the potential of LLM-powered agents to enhance digital assistants, making them more capable and efficient in handling a wide range of tasks.
References: https://www.deeplearning.ai/
You can find the colab for this here.