Skip to content

Commit b5d8e1b

Browse files
Rename docs to examples
1 parent d8cb5e1 commit b5d8e1b

9 files changed

+1696
-0
lines changed

examples/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# .gitignore for /docs directory
2+
.ipynb_checkpoints
3+
*.pyc
4+
__pycache__

examples/Dockerfile.jupyter

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
FROM python:3.11
2+
3+
# Set up a non-root user
4+
RUN useradd -m jupyter
5+
6+
WORKDIR /home/jupyter/workspace
7+
8+
# Copy the library files
9+
COPY . /home/jupyter/workspace
10+
11+
# Create necessary directories and set permissions
12+
RUN mkdir -p /home/jupyter/workspace/libs/checkpoint-redis/docs && \
13+
chown -R jupyter:jupyter /home/jupyter/workspace
14+
15+
# Switch to non-root user
16+
USER jupyter
17+
18+
# Set up virtual environment
19+
RUN python -m venv /home/jupyter/venv
20+
ENV PATH="/home/jupyter/venv/bin:$PATH"
21+
22+
# Install dependencies
23+
RUN pip install --no-cache-dir --upgrade pip && \
24+
pip install --no-cache-dir langgraph && \
25+
pip install --no-cache-dir -e /home/jupyter/workspace/libs/checkpoint-redis && \
26+
pip install --no-cache-dir jupyter redis
27+
28+
# Set the working directory to the docs folder
29+
WORKDIR /home/jupyter/workspace/libs/checkpoint-redis/docs
30+
31+
# Expose Jupyter port
32+
EXPOSE 8888
33+
34+
# Start Jupyter Notebook with checkpoints disabled
35+
CMD ["jupyter", "notebook", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--NotebookApp.token=''", "--NotebookApp.password=''", "--NotebookApp.allow_root=True", "--NotebookApp.disable_check_xsrf=True", "--FileContentsManager.checkpoints_kwargs={'root_dir':'/tmp/checkpoints'}"]

examples/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Redis Notebooks for LangGraph
2+
3+
This directory contains Jupyter notebooks demonstrating the usage of the Redis with LangGraph.
4+
5+
## Running Notebooks with Docker
6+
7+
To run these notebooks using the local development versions of LangChain and the Redis partner package:
8+
9+
1. Ensure you have Docker and Docker Compose installed on your system.
10+
2. Navigate to this directory (`langgraph/docs`) in your terminal.
11+
3. Run the following command:
12+
```bash
13+
docker compose up
14+
```
15+
4. Look for a URL in the console output that starts with `http://127.0.0.1:8888/tree`. Open this URL in your web browser to access Jupyter Notebook.
16+
5. You can now run the notebooks, which will use the local development versions of LangChain and the Redis partner package.
17+
18+
Note: The first time you run this, it may take a few minutes to build the Docker image.
19+
20+
To stop the Docker containers, use Ctrl+C in the terminal where you ran `docker compose up`, then run:
21+
```bash
22+
docker compose down
23+
```
24+
25+
## Notebook Contents
26+
27+
- `persistence_redis.ipynb`: Demonstrates the usage of `RedisSaver` and `AsyncRedisSaver` checkpoint savers with LangGraph.
28+
29+
These notebooks are designed to work both within this Docker environment (using local package builds) and standalone (using installed packages via pip).
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "992c4695-ec4f-428d-bd05-fb3b5fbd70f4",
6+
"metadata": {},
7+
"source": [
8+
"# How to add thread-level memory to a ReAct Agent\n",
9+
"\n",
10+
"<div class=\"admonition tip\">\n",
11+
" <p class=\"admonition-title\">Prerequisites</p>\n",
12+
" <p>\n",
13+
" This guide assumes familiarity with the following:\n",
14+
" <ul>\n",
15+
" <li> \n",
16+
" <a href=\"https://langchain-ai.github.io/langgraph/concepts/persistence/\">\n",
17+
" LangGraph Persistence\n",
18+
" </a>\n",
19+
" </li>\n",
20+
" <li> \n",
21+
" <a href=\"https://langchain-ai.github.io/langgraph/concepts/persistence/#checkpointer-interface\">\n",
22+
" Checkpointer interface\n",
23+
" </a>\n",
24+
" </li>\n",
25+
" <li>\n",
26+
" <a href=\"https://langchain-ai.github.io/langgraph/concepts/agentic_concepts/\">\n",
27+
" Agent Architectures\n",
28+
" </a> \n",
29+
" </li>\n",
30+
" <li>\n",
31+
" <a href=\"https://python.langchain.com/docs/concepts/chat_models/\">\n",
32+
" Chat Models\n",
33+
" </a>\n",
34+
" </li>\n",
35+
" <li>\n",
36+
" <a href=\"https://python.langchain.com/docs/concepts/tools/\">\n",
37+
" Tools\n",
38+
" </a>\n",
39+
" </li>\n",
40+
" </ul>\n",
41+
" </p>\n",
42+
"</div> \n",
43+
"\n",
44+
"This guide will show how to add memory to the prebuilt ReAct agent. Please see [this tutorial](../create-react-agent) for how to get started with the prebuilt ReAct agent\n",
45+
"\n",
46+
"We can add memory to the agent, by passing a [checkpointer](https://langchain-ai.github.io/langgraph/reference/checkpoints/) to the [create_react_agent](https://langchain-ai.github.io/langgraph/reference/prebuilt/#langgraph.prebuilt.chat_agent_executor.create_react_agent) function."
47+
]
48+
},
49+
{
50+
"cell_type": "markdown",
51+
"id": "7be3889f-3c17-4fa1-bd2b-84114a2c7247",
52+
"metadata": {},
53+
"source": [
54+
"## Setup\n",
55+
"\n",
56+
"First, let's install the required packages and set our API keys"
57+
]
58+
},
59+
{
60+
"cell_type": "code",
61+
"execution_count": 1,
62+
"id": "a213e11a-5c62-4ddb-a707-490d91add383",
63+
"metadata": {},
64+
"outputs": [],
65+
"source": [
66+
"%%capture --no-stderr\n",
67+
"%pip install -U langgraph langchain-openai"
68+
]
69+
},
70+
{
71+
"cell_type": "code",
72+
"execution_count": 2,
73+
"id": "23a1885c-04ab-4750-aefa-105891fddf3e",
74+
"metadata": {},
75+
"outputs": [
76+
{
77+
"name": "stdin",
78+
"output_type": "stream",
79+
"text": [
80+
"OPENAI_API_KEY: ········\n"
81+
]
82+
}
83+
],
84+
"source": [
85+
"import getpass\n",
86+
"import os\n",
87+
"\n",
88+
"\n",
89+
"def _set_env(var: str):\n",
90+
" if not os.environ.get(var):\n",
91+
" os.environ[var] = getpass.getpass(f\"{var}: \")\n",
92+
"\n",
93+
"\n",
94+
"_set_env(\"OPENAI_API_KEY\")"
95+
]
96+
},
97+
{
98+
"cell_type": "markdown",
99+
"id": "87a00ce9",
100+
"metadata": {},
101+
"source": [
102+
"<div class=\"admonition tip\">\n",
103+
" <p class=\"admonition-title\">Set up <a href=\"https://smith.langchain.com\">LangSmith</a> for LangGraph development</p>\n",
104+
" <p style=\"padding-top: 5px;\">\n",
105+
" Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started <a href=\"https://docs.smith.langchain.com\">here</a>. \n",
106+
" </p>\n",
107+
"</div>"
108+
]
109+
},
110+
{
111+
"cell_type": "markdown",
112+
"id": "03c0f089-070c-4cd4-87e0-6c51f2477b82",
113+
"metadata": {},
114+
"source": [
115+
"## Code"
116+
]
117+
},
118+
{
119+
"cell_type": "code",
120+
"execution_count": 3,
121+
"id": "7a154152-973e-4b5d-aa13-48c617744a4c",
122+
"metadata": {},
123+
"outputs": [
124+
{
125+
"name": "stdout",
126+
"output_type": "stream",
127+
"text": [
128+
"22:31:51 redisvl.index.index INFO Index already exists, not overwriting.\n",
129+
"22:31:51 redisvl.index.index INFO Index already exists, not overwriting.\n",
130+
"22:31:51 redisvl.index.index INFO Index already exists, not overwriting.\n"
131+
]
132+
}
133+
],
134+
"source": [
135+
"from typing import Literal\n",
136+
"\n",
137+
"from langchain_core.tools import tool\n",
138+
"\n",
139+
"# First we initialize the model we want to use.\n",
140+
"from langchain_openai import ChatOpenAI\n",
141+
"\n",
142+
"from langgraph.checkpoint.redis import RedisSaver\n",
143+
"from langgraph.prebuilt import create_react_agent\n",
144+
"\n",
145+
"model = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n",
146+
"\n",
147+
"\n",
148+
"# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF)\n",
149+
"@tool\n",
150+
"def get_weather(city: Literal[\"nyc\", \"sf\"]):\n",
151+
" \"\"\"Use this to get weather information.\"\"\"\n",
152+
" if city == \"nyc\":\n",
153+
" return \"It might be cloudy in nyc\"\n",
154+
" elif city == \"sf\":\n",
155+
" return \"It's always sunny in sf\"\n",
156+
" else:\n",
157+
" raise AssertionError(\"Unknown city\")\n",
158+
"\n",
159+
"\n",
160+
"tools = [get_weather]\n",
161+
"\n",
162+
"# We can add \"chat memory\" to the graph with LangGraph's Redis checkpointer\n",
163+
"# to retain the chat context between interactions\n",
164+
"\n",
165+
"\n",
166+
"REDIS_URI = \"redis://redis:6379\"\n",
167+
"memory = None\n",
168+
"with RedisSaver.from_conn_string(REDIS_URI) as cp:\n",
169+
" cp.setup()\n",
170+
" memory = cp\n",
171+
"\n",
172+
"# Define the graph\n",
173+
"\n",
174+
"\n",
175+
"graph = create_react_agent(model, tools=tools, checkpointer=memory)"
176+
]
177+
},
178+
{
179+
"cell_type": "markdown",
180+
"id": "00407425-506d-4ffd-9c86-987921d8c844",
181+
"metadata": {},
182+
"source": [
183+
"## Usage\n",
184+
"\n",
185+
"Let's interact with it multiple times to show that it can remember"
186+
]
187+
},
188+
{
189+
"cell_type": "code",
190+
"execution_count": 4,
191+
"id": "16636975-5f2d-4dc7-ab8e-d0bea0830a28",
192+
"metadata": {},
193+
"outputs": [],
194+
"source": [
195+
"def print_stream(stream):\n",
196+
" for s in stream:\n",
197+
" message = s[\"messages\"][-1]\n",
198+
" if isinstance(message, tuple):\n",
199+
" print(message)\n",
200+
" else:\n",
201+
" message.pretty_print()"
202+
]
203+
},
204+
{
205+
"cell_type": "code",
206+
"execution_count": 5,
207+
"id": "9ffff6c3-a4f5-47c9-b51d-97caaee85cd6",
208+
"metadata": {},
209+
"outputs": [
210+
{
211+
"name": "stdout",
212+
"output_type": "stream",
213+
"text": [
214+
"================================\u001b[1m Human Message \u001b[0m=================================\n",
215+
"\n",
216+
"What's the weather in NYC?\n",
217+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
218+
"Tool Calls:\n",
219+
" get_weather (call_Edwfw0WiyIJ7vt9xzU9xvyeg)\n",
220+
" Call ID: call_Edwfw0WiyIJ7vt9xzU9xvyeg\n",
221+
" Args:\n",
222+
" city: nyc\n",
223+
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
224+
"Name: get_weather\n",
225+
"\n",
226+
"It might be cloudy in nyc\n",
227+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
228+
"\n",
229+
"The weather in NYC might be cloudy.\n"
230+
]
231+
}
232+
],
233+
"source": [
234+
"config = {\"configurable\": {\"thread_id\": \"1\"}}\n",
235+
"inputs = {\"messages\": [(\"user\", \"What's the weather in NYC?\")]}\n",
236+
"\n",
237+
"print_stream(graph.stream(inputs, config=config, stream_mode=\"values\"))"
238+
]
239+
},
240+
{
241+
"cell_type": "markdown",
242+
"id": "838a043f-90ad-4e69-9d1d-6e22db2c346c",
243+
"metadata": {},
244+
"source": [
245+
"Notice that when we pass the same the same thread ID, the chat history is preserved"
246+
]
247+
},
248+
{
249+
"cell_type": "code",
250+
"execution_count": 6,
251+
"id": "187479f9-32fa-4611-9487-cf816ba2e147",
252+
"metadata": {},
253+
"outputs": [
254+
{
255+
"name": "stdout",
256+
"output_type": "stream",
257+
"text": [
258+
"================================\u001b[1m Human Message \u001b[0m=================================\n",
259+
"\n",
260+
"What's it known for?\n",
261+
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
262+
"\n",
263+
"Could you please specify what \"it\" refers to? Are you asking about a specific city, person, event, or something else?\n"
264+
]
265+
}
266+
],
267+
"source": [
268+
"inputs = {\"messages\": [(\"user\", \"What's it known for?\")]}\n",
269+
"print_stream(graph.stream(inputs, config=config, stream_mode=\"values\"))"
270+
]
271+
}
272+
],
273+
"metadata": {
274+
"kernelspec": {
275+
"display_name": "Python 3 (ipykernel)",
276+
"language": "python",
277+
"name": "python3"
278+
},
279+
"language_info": {
280+
"codemirror_mode": {
281+
"name": "ipython",
282+
"version": 3
283+
},
284+
"file_extension": ".py",
285+
"mimetype": "text/x-python",
286+
"name": "python",
287+
"nbconvert_exporter": "python",
288+
"pygments_lexer": "ipython3",
289+
"version": "3.11.11"
290+
}
291+
},
292+
"nbformat": 4,
293+
"nbformat_minor": 5
294+
}
295+

0 commit comments

Comments
 (0)