This directory contains a simple LangGraph. This directory contains a single graph, located inside the index.ts
file.
To set up the intro project, install the dependencies:
yarn install
The intro project requires Tavily and OpenAI API keys to run. Sign up here:
Once you have your API keys, create a .env
file in this directory and add the following:
TAVILY_API_KEY=YOUR_API_KEY
OPENAI_API_KEY=YOUR_API_KEY
The LangGraph configuration file for the intro project is located inside langgraph.json
. This file defines the single graph implemented in the project: simple_agent
.
Follow these steps to obtain access to the Tavily API:
-
Sign Up
- Go to Tavily's official website and create an account.
- Verify your email address to complete the registration process.
-
Access the Dashboard
- Once logged in, navigate to the Dashboard.
- Here, you can manage your API keys, monitor usage, and configure settings.
-
Generate Your API Key
- Go to the API Keys section in the dashboard.
- Click on Generate API Key to create a new API key.
- Copy the API key, as you will need it for all API requests.
To edit the project, open the index.ts
file and make changes to the graph.
-
Imports
This section imports necessary modules and components from
@langchain/langgraph
,@langchain/core/messages
, andmodel.js
.import { ToolNode } from "@langchain/langgraph/prebuilt"; import { END, MessagesAnnotation, START, StateGraph, } from "@langchain/langgraph"; import { AIMessage, BaseMessage, HumanMessage } from "@langchain/core/messages"; import { TavilySearchResults } from "@langchain/community/tools/tavily_search"; import { model } from "model.js";
Look at
model.js
, it contains the model that will be used in the graph. We are using the Groq API. -
Tools
const webSearchTool = new TavilySearchResults({ maxResults: 4, }); const tools = [webSearchTool]; const toolNode = new ToolNode(tools as any);
- Initializes a web search tool with a maximum of 4 results.
- Creates a
ToolNode
with the initialized tools.
-
Model
const callModel = async (state: typeof MessagesAnnotation.State) => { const { messages } = state; const llmWithTools = model.bindTools(tools); const result = await llmWithTools.invoke(messages); return { messages: [result] }; };
- Defines an asynchronous function
callModel
that binds tools to the model and invokes it with the current messages.
- Defines an asynchronous function
-
Conditionals
const shouldContinue = (state: typeof MessagesAnnotation.State) => { const { messages } = state; const lastMessage = messages[messages.length - 1]; if ( lastMessage._getType() !== "ai" || !(lastMessage as AIMessage).tool_calls?.length ) { return END; } return "tools"; };
- Defines a function
shouldContinue
to determine whether the workflow should continue or end based on the last message.
- Defines a function
-
Graph
const workflow = new StateGraph(MessagesAnnotation) .addNode("agent", callModel) .addEdge(START, "agent") .addNode("tools", toolNode) .addEdge("tools", "agent") .addConditionalEdges("agent", shouldContinue, ["tools", END]); export const graph = workflow.compile({ // Uncomment if running locally // checkpointer: new MemorySaver(), }); graph.name = "graph";
- Creates a
StateGraph
with nodes and edges, defining the workflow of the graph.
- Creates a
-
Draw Graph
import { saveGraphAsImage } from "drawGraph.js"; await saveGraphAsImage(graph);
- Imports a function to save the graph as an image and calls it.
-
Usage
const agentFinalState = await graph.invoke( { messages: [new HumanMessage("what is the current weather in sf")] }, { configurable: { thread_id: "42" } }, ); console.log( agentFinalState.messages[agentFinalState.messages.length - 1].content, ); const agentNextState = await graph.invoke( { messages: [new HumanMessage("what about ny")] }, { configurable: { thread_id: "42" } }, ); console.log( agentNextState.messages[agentNextState.messages.length - 1].content, );
- Demonstrates how to invoke the graph with initial messages and log the final state messages.
To run the intro project, use the following commands:
yarn install
yarn run build
yarn run start