mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-21 15:12:26 +02:00
Update tools
This commit is contained in:
committed by
Hunter Lovell
parent
9378ad38dc
commit
17f2f4df5d
@@ -11,11 +11,15 @@ To handle queries that your chatbot can't answer "from memory", integrate a web
|
||||
Before you start this tutorial, ensure you have the following:
|
||||
|
||||
:::python
|
||||
|
||||
- An API key for the [Tavily Search Engine](https://python.langchain.com/docs/integrations/tools/tavily_search/).
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
- An API key for the [Tavily Search Engine](https://docs.tavily.com/).
|
||||
|
||||
- An API key for the [Tavily Search Engine](https://js.langchain.com/docs/integrations/tools/tavily_search/).
|
||||
|
||||
:::
|
||||
|
||||
## 1. Install the search engine
|
||||
@@ -26,20 +30,44 @@ Install the requirements to use the [Tavily Search Engine](https://python.langch
|
||||
```bash
|
||||
pip install -U langchain-tavily
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
Install the requirements to use the [Tavily Search Engine](https://docs.tavily.com/):
|
||||
|
||||
```bash
|
||||
npm install @langchain/community
|
||||
```
|
||||
=== "npm"
|
||||
|
||||
```bash
|
||||
npm install @langchain/community
|
||||
```
|
||||
|
||||
=== "yarn"
|
||||
|
||||
```bash
|
||||
yarn add @langchain/community
|
||||
```
|
||||
|
||||
=== "pnpm"
|
||||
|
||||
```bash
|
||||
pnpm add @langchain/community
|
||||
```
|
||||
|
||||
=== "bun"
|
||||
|
||||
```bash
|
||||
bun add @langchain/community
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 2. Configure your environment
|
||||
|
||||
Configure your environment with your search engine API key:
|
||||
|
||||
:::python
|
||||
|
||||
```bash
|
||||
_set_env("TAVILY_API_KEY")
|
||||
```
|
||||
@@ -47,12 +75,15 @@ _set_env("TAVILY_API_KEY")
|
||||
```
|
||||
os.environ["TAVILY_API_KEY"]: "········"
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```typescript
|
||||
process.env.TAVILY_API_KEY = "tvly-...";
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 3. Define the tool
|
||||
@@ -60,6 +91,7 @@ process.env.TAVILY_API_KEY = "tvly-...";
|
||||
Define the web search tool:
|
||||
|
||||
:::python
|
||||
|
||||
```python
|
||||
from langchain_tavily import TavilySearch
|
||||
|
||||
@@ -67,9 +99,11 @@ tool = TavilySearch(max_results=2)
|
||||
tools = [tool]
|
||||
tool.invoke("What's a 'node' in LangGraph?")
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```typescript
|
||||
import { TavilySearchResults } from "@langchain/community/tools/tavily_search";
|
||||
|
||||
@@ -78,11 +112,13 @@ const tools = [tool];
|
||||
|
||||
await tool.invoke({ query: "What's a 'node' in LangGraph?" });
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The results are page summaries our chat bot can use to answer questions:
|
||||
|
||||
:::python
|
||||
|
||||
```
|
||||
{'query': "What's a 'node' in LangGraph?",
|
||||
'follow_up_questions': None,
|
||||
@@ -100,12 +136,15 @@ The results are page summaries our chat bot can use to answer questions:
|
||||
'raw_content': None}],
|
||||
'response_time': 1.38}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```
|
||||
"[{\"title\":\"Introduction to LangGraph: A Beginner's Guide - Medium\",\"url\":\"https://medium.com/@cplog/introduction-to-langgraph-a-beginners-guide-14f9be027141\",\"content\":\"Stateful Graph: LangGraph revolves around the concept of a stateful graph, where each node in the graph represents a step in your computation, and the graph maintains a state that is passed around and updated as the computation progresses. LangGraph supports conditional edges, allowing you to dynamically determine the next node to execute based on the current state of the graph. We define nodes for classifying the input, handling greetings, and handling search queries. def classify_input_node(state): LangGraph is a versatile tool for building complex, stateful applications with LLMs. By understanding its core concepts and working through simple examples, beginners can start to leverage its power for their projects. Remember to pay attention to state management, conditional edges, and ensuring there are no dead-end nodes in your graph.\",\"score\":0.7065353,\"raw_content\":null},{\"title\":\"LangGraph Tutorial: What Is LangGraph and How to Use It?\",\"url\":\"https://www.datacamp.com/tutorial/langgraph-tutorial\",\"content\":\"LangGraph is a library within the LangChain ecosystem that provides a framework for defining, coordinating, and executing multiple LLM agents (or chains) in a structured and efficient manner. By managing the flow of data and the sequence of operations, LangGraph allows developers to focus on the high-level logic of their applications rather than the intricacies of agent coordination. Whether you need a chatbot that can handle various types of user requests or a multi-agent system that performs complex tasks, LangGraph provides the tools to build exactly what you need. LangGraph significantly simplifies the development of complex LLM applications by providing a structured framework for managing state and coordinating agent interactions.\",\"score\":0.5008063,\"raw_content\":null}]"
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 4. Define the graph
|
||||
@@ -129,19 +168,23 @@ from langchain.chat_models import init_chat_model
|
||||
llm = init_chat_model("anthropic:claude-3-5-sonnet-latest")
|
||||
```
|
||||
-->
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```typescript
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
|
||||
const llm = new ChatOpenAI({ model: "gpt-4o-mini" });
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
We can now incorporate it into a `StateGraph`:
|
||||
|
||||
:::python
|
||||
|
||||
```python hl_lines="15"
|
||||
from typing import Annotated
|
||||
|
||||
@@ -164,9 +207,11 @@ def chatbot(state: State):
|
||||
|
||||
graph_builder.add_node("chatbot", chatbot)
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```typescript
|
||||
import { Annotation } from "@langchain/langgraph";
|
||||
import { BaseMessage } from "@langchain/core/messages";
|
||||
@@ -188,6 +233,7 @@ const chatbot = async (state: typeof StateAnnotation.State) => {
|
||||
|
||||
graphBuilder.addNode("chatbot", chatbot);
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 5. Create a function to run the tools
|
||||
@@ -195,6 +241,7 @@ graphBuilder.addNode("chatbot", chatbot);
|
||||
Now, create a function to run the tools if they are called. Do this by adding the tools to a new node called`BasicToolNode` that checks the most recent message in the state and calls tools if the message contains `tool_calls`. It relies on the LLM's `tool_calling` support, which is available in Anthropic, OpenAI, Google Gemini, and a number of other LLM providers.
|
||||
|
||||
:::python
|
||||
|
||||
```python
|
||||
import json
|
||||
|
||||
@@ -230,9 +277,11 @@ class BasicToolNode:
|
||||
tool_node = BasicToolNode(tools=[tool])
|
||||
graph_builder.add_node("tools", tool_node)
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```typescript
|
||||
import { ToolMessage } from "@langchain/core/messages";
|
||||
import { isAIMessage } from "@langchain/core/messages";
|
||||
@@ -254,14 +303,16 @@ class BasicToolNode {
|
||||
}
|
||||
|
||||
const message = messages[messages.length - 1];
|
||||
|
||||
|
||||
if (!isAIMessage(message) || !message.tool_calls) {
|
||||
throw new Error("Last message is not an AI message with tool calls");
|
||||
}
|
||||
|
||||
const outputs = [];
|
||||
for (const toolCall of message.tool_calls) {
|
||||
const toolResult = await this.toolsByName[toolCall.name].invoke(toolCall.args);
|
||||
const toolResult = await this.toolsByName[toolCall.name].invoke(
|
||||
toolCall.args
|
||||
);
|
||||
outputs.push(
|
||||
new ToolMessage({
|
||||
content: JSON.stringify(toolResult),
|
||||
@@ -277,6 +328,7 @@ class BasicToolNode {
|
||||
const toolNode = new BasicToolNode([tool]);
|
||||
graphBuilder.addNode("tools", toolNode.invoke.bind(toolNode));
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
!!! note
|
||||
@@ -285,7 +337,7 @@ graphBuilder.addNode("tools", toolNode.invoke.bind(toolNode));
|
||||
|
||||
## 6. Define the `conditional_edges`
|
||||
|
||||
With the tool node added, now you can define the `conditional_edges`.
|
||||
With the tool node added, now you can define the `conditional_edges`.
|
||||
|
||||
**Edges** route the control flow from one node to the next. **Conditional edges** start from a single node and usually contain "if" statements to route to different nodes depending on the current graph state. These functions receive the current graph `state` and return a string or list of strings indicating which node(s) to call next.
|
||||
|
||||
@@ -300,6 +352,7 @@ Next, define a router function called `routeTools` that checks for `tool_calls`
|
||||
The condition will route to `tools` if tool calls are present and `END` if not. Because the condition can return `END`, you do not need to explicitly set a `finish_point` this time.
|
||||
|
||||
:::python
|
||||
|
||||
```python
|
||||
def route_tools(
|
||||
state: State,
|
||||
@@ -336,9 +389,11 @@ graph_builder.add_edge("tools", "chatbot")
|
||||
graph_builder.add_edge(START, "chatbot")
|
||||
graph = graph_builder.compile()
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```typescript
|
||||
import { END, START } from "@langchain/langgraph";
|
||||
|
||||
@@ -349,7 +404,7 @@ const routeTools = (state: typeof StateAnnotation.State) => {
|
||||
*/
|
||||
const { messages } = state;
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
|
||||
|
||||
if (isAIMessage(lastMessage) && lastMessage.tool_calls?.length) {
|
||||
return "tools";
|
||||
}
|
||||
@@ -375,11 +430,12 @@ graphBuilder.addEdge(START, "chatbot");
|
||||
|
||||
const graph = graphBuilder.compile();
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
!!! note
|
||||
|
||||
You can replace this with the prebuilt [tools_condition](https://langchain-ai.github.io/langgraph/reference/prebuilt/#tools_condition) to be more concise.
|
||||
You can replace this with the prebuilt [tools_condition](https://langchain-ai.github.io/langgraph/reference/prebuilt/#tools_condition) to be more concise.
|
||||
|
||||
## 7. Visualize the graph (optional)
|
||||
|
||||
@@ -415,6 +471,7 @@ try {
|
||||
console.log("Could not render graph");
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 8. Ask the bot questions
|
||||
@@ -422,6 +479,7 @@ try {
|
||||
Now you can ask the chatbot questions outside its training data:
|
||||
|
||||
:::python
|
||||
|
||||
```python
|
||||
def stream_graph_updates(user_input: str):
|
||||
for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):
|
||||
@@ -444,7 +502,7 @@ while True:
|
||||
break
|
||||
```
|
||||
|
||||
```
|
||||
```
|
||||
Assistant: [{'text': "To provide you with accurate and up-to-date information about LangGraph, I'll need to search for the latest details. Let me do that for you.", 'type': 'text'}, {'id': 'toolu_01Q588CszHaSvvP2MxRq9zRD', 'input': {'query': 'LangGraph AI tool information'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]
|
||||
Assistant: [{"url": "https://www.langchain.com/langgraph", "content": "LangGraph sets the foundation for how we can build and scale AI workloads \u2014 from conversational agents, complex task automation, to custom LLM-backed experiences that 'just work'. The next chapter in building complex production-ready features with LLMs is agentic, and with LangGraph and LangSmith, LangChain delivers an out-of-the-box solution ..."}, {"url": "https://github.com/langchain-ai/langgraph", "content": "Overview. LangGraph is a library for building stateful, multi-actor applications with LLMs, used to create agent and multi-agent workflows. Compared to other LLM frameworks, it offers these core benefits: cycles, controllability, and persistence. LangGraph allows you to define flows that involve cycles, essential for most agentic architectures ..."}]
|
||||
Assistant: Based on the search results, I can provide you with information about LangGraph:
|
||||
@@ -477,9 +535,11 @@ LangGraph appears to be a significant tool in the evolving landscape of LLM-base
|
||||
Goodbye!
|
||||
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
```typescript
|
||||
import { HumanMessage } from "@langchain/core/messages";
|
||||
|
||||
@@ -488,7 +548,7 @@ const streamGraphUpdates = async (userInput: string) => {
|
||||
{ messages: [new HumanMessage(userInput)] },
|
||||
{ streamMode: "values" }
|
||||
);
|
||||
|
||||
|
||||
for await (const event of stream) {
|
||||
const lastMessage = event.messages[event.messages.length - 1];
|
||||
console.log("Assistant:", lastMessage.content);
|
||||
@@ -526,7 +586,7 @@ LangGraph is a library within the LangChain ecosystem designed for building stat
|
||||
|
||||
**Use Cases:**
|
||||
- Conversational agents
|
||||
- Complex task automation
|
||||
- Complex task automation
|
||||
- Custom LLM-backed experiences
|
||||
- Multi-agent systems that perform complex tasks
|
||||
|
||||
@@ -535,6 +595,7 @@ LangGraph allows developers to focus on the high-level logic of their applicatio
|
||||
|
||||
This makes LangGraph a significant tool in the evolving landscape of LLM-based application development.
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 9. Use prebuilts
|
||||
@@ -542,12 +603,12 @@ This makes LangGraph a significant tool in the evolving landscape of LLM-based a
|
||||
For ease of use, adjust your code to replace the following with LangGraph prebuilt components. These have built in functionality like parallel API execution.
|
||||
|
||||
:::python
|
||||
|
||||
- `BasicToolNode` is replaced with the prebuilt [ToolNode](https://langchain-ai.github.io/langgraph/reference/prebuilt/#toolnode)
|
||||
- `route_tools` is replaced with the prebuilt [tools_condition](https://langchain-ai.github.io/langgraph/reference/prebuilt/#tools_condition)
|
||||
|
||||
{% include-markdown "../../../snippets/chat_model_tabs.md" %}
|
||||
|
||||
|
||||
```python hl_lines="25 30"
|
||||
from typing import Annotated
|
||||
|
||||
@@ -585,9 +646,11 @@ graph_builder.add_edge("tools", "chatbot")
|
||||
graph_builder.add_edge(START, "chatbot")
|
||||
graph = graph_builder.compile()
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::js
|
||||
|
||||
- `BasicToolNode` is replaced with the prebuilt [ToolNode](https://langchain-ai.github.io/langgraph/reference/prebuilt/#toolnode)
|
||||
- `routeTools` is replaced with the prebuilt [tools_condition](https://langchain-ai.github.io/langgraph/reference/prebuilt/#tools_condition)
|
||||
|
||||
@@ -629,10 +692,11 @@ graphBuilder.addEdge(START, "chatbot");
|
||||
|
||||
const graph = graphBuilder.compile();
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**Congratulations!** You've created a conversational agent in LangGraph that can use a search engine to retrieve updated information when needed. Now it can handle a wider range of user queries. :::python To inspect all the steps your agent just took, check out this [LangSmith trace](https://smith.langchain.com/public/4fbd7636-25af-4638-9587-5a02fdbb0172/r). :::
|
||||
|
||||
## Next steps
|
||||
|
||||
The chatbot cannot remember past interactions on its own, which limits its ability to have coherent, multi-turn conversations. In the next part, you will [add **memory**](./3-add-memory.md) to address this.
|
||||
The chatbot cannot remember past interactions on its own, which limits its ability to have coherent, multi-turn conversations. In the next part, you will [add **memory**](./3-add-memory.md) to address this.
|
||||
|
||||
Reference in New Issue
Block a user