Skip to content

Commit 0d78b87

Browse files
committed
chore(docs): Add documentation for PGChatMessageHistory
1 parent a4846f3 commit 0d78b87

File tree

1 file changed

+330
-0
lines changed

1 file changed

+330
-0
lines changed
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# PGChatMessageHistory\n",
8+
"\n",
9+
"`PGChatMessageHistory` is a an implementation of the the LangChain ChatMessageHistory abstraction using `postgres` as the backend.\n"
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {
15+
"id": "IR54BmgvdHT_"
16+
},
17+
"source": [
18+
"## Install\n",
19+
"\n",
20+
"Install the `langchain-postgres` package."
21+
]
22+
},
23+
{
24+
"cell_type": "code",
25+
"execution_count": null,
26+
"metadata": {
27+
"colab": {
28+
"base_uri": "https://localhost:8080/",
29+
"height": 1000
30+
},
31+
"id": "0ZITIDE160OD",
32+
"outputId": "e184bc0d-6541-4e0a-82d2-1e216db00a2d",
33+
"tags": []
34+
},
35+
"outputs": [],
36+
"source": [
37+
"%pip install --upgrade --quiet langchain-postgres"
38+
]
39+
},
40+
{
41+
"cell_type": "markdown",
42+
"metadata": {
43+
"id": "QuQigs4UoFQ2"
44+
},
45+
"source": [
46+
"## Create an engine\n",
47+
"\n",
48+
"The first step is to create a `PGEngine` instance, which does the following:\n",
49+
"\n",
50+
"1. Allows you to create tables for storing documents and embeddings.\n",
51+
"2. Maintains a connection pool that manages connections to the database. This allows sharing of the connection pool and helps to reduce latency for database calls."
52+
]
53+
},
54+
{
55+
"cell_type": "code",
56+
"execution_count": null,
57+
"metadata": {
58+
"tags": []
59+
},
60+
"outputs": [],
61+
"source": [
62+
"from langchain_postgres import PGEngine\n",
63+
"\n",
64+
"# See docker command above to launch a Postgres instance with pgvector enabled.\n",
65+
"# Replace these values with your own configuration.\n",
66+
"POSTGRES_USER = \"langchain\"\n",
67+
"POSTGRES_PASSWORD = \"langchain\"\n",
68+
"POSTGRES_HOST = \"localhost\"\n",
69+
"POSTGRES_PORT = \"6024\"\n",
70+
"POSTGRES_DB = \"langchain\"\n",
71+
"\n",
72+
"CONNECTION_STRING = (\n",
73+
" f\"postgresql+asyncpg://{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}\"\n",
74+
" f\":{POSTGRES_PORT}/{POSTGRES_DB}\"\n",
75+
")\n",
76+
"\n",
77+
"pg_engine = PGEngine.from_connection_string(url=CONNECTION_STRING)"
78+
]
79+
},
80+
{
81+
"cell_type": "markdown",
82+
"metadata": {},
83+
"source": [
84+
"To use psycopg3 driver, set your connection string to `postgresql+psycopg://`"
85+
]
86+
},
87+
{
88+
"cell_type": "markdown",
89+
"metadata": {
90+
"id": "D9Xs2qhm6X56"
91+
},
92+
"source": [
93+
"### Initialize a table\n",
94+
"The `PGChatMessageHistory` class requires a database table with a specific schema in order to store the chat message history.\n",
95+
"\n",
96+
"The `PGEngine` engine has a helper method `init_chat_history_table()` that can be used to create a table with the proper schema for you."
97+
]
98+
},
99+
{
100+
"cell_type": "code",
101+
"execution_count": null,
102+
"metadata": {
103+
"tags": []
104+
},
105+
"outputs": [],
106+
"source": [
107+
"TABLE_NAME = \"chat history\"\n",
108+
"\n",
109+
"pg_engine.init_chat_history_table(table_name=TABLE_NAME)"
110+
]
111+
},
112+
{
113+
"cell_type": "markdown",
114+
"metadata": {},
115+
"source": [
116+
"#### Optional Tip: 💡\n",
117+
"You can also specify a schema name by passing `schema_name` wherever you pass `table_name`. Eg:\n",
118+
"\n",
119+
"```python\n",
120+
"SCHEMA_NAME=\"my_schema\"\n",
121+
"\n",
122+
"engine.init_chat_history_table(\n",
123+
" table_name=TABLE_NAME,\n",
124+
" schema_name=SCHEMA_NAME # Default: \"public\"\n",
125+
")\n",
126+
"```"
127+
]
128+
},
129+
{
130+
"cell_type": "markdown",
131+
"metadata": {},
132+
"source": [
133+
"### PGChatMessageHistory\n",
134+
"\n",
135+
"To initialize the `PGChatMessageHistory` class you need to provide only 3 things:\n",
136+
"\n",
137+
"1. `engine` - An instance of a `PGEngine` engine.\n",
138+
"1. `session_id` - A unique identifier string that specifies an id for the session.\n",
139+
"1. `table_name` : The name of the table within the PG database to store the chat message history.\n",
140+
"1. `schema_name` : The name of the database schema containing the chat message history table."
141+
]
142+
},
143+
{
144+
"cell_type": "code",
145+
"execution_count": null,
146+
"metadata": {
147+
"id": "z-AZyzAQ7bsf",
148+
"tags": []
149+
},
150+
"outputs": [],
151+
"source": [
152+
"from langchain_postgres import PGChatMessageHistory\n",
153+
"\n",
154+
"history = PGChatMessageHistory.create_sync(\n",
155+
" pg_engine,\n",
156+
" session_id=\"test_session\",\n",
157+
" table_name=TABLE_NAME,\n",
158+
" # schema_name=SCHEMA_NAME,\n",
159+
")\n",
160+
"history.add_user_message(\"hi!\")\n",
161+
"history.add_ai_message(\"whats up?\")"
162+
]
163+
},
164+
{
165+
"cell_type": "code",
166+
"execution_count": null,
167+
"metadata": {},
168+
"outputs": [],
169+
"source": [
170+
"history.messages"
171+
]
172+
},
173+
{
174+
"cell_type": "markdown",
175+
"metadata": {},
176+
"source": [
177+
"#### Cleaning up\n",
178+
"When the history of a specific session is obsolete and can be deleted, it can be done the following way.\n",
179+
"\n",
180+
"**Note:** Once deleted, the data is no longer stored in Postgres and is gone forever."
181+
]
182+
},
183+
{
184+
"cell_type": "code",
185+
"execution_count": null,
186+
"metadata": {
187+
"tags": []
188+
},
189+
"outputs": [],
190+
"source": [
191+
"history.clear()"
192+
]
193+
},
194+
{
195+
"cell_type": "markdown",
196+
"metadata": {},
197+
"source": [
198+
"## 🔗 Chaining\n",
199+
"\n",
200+
"We can easily combine this message history class with [LCEL Runnables](/docs/expression_language/how_to/message_history)\n",
201+
"\n",
202+
"To do this we will use one of [Google's Vertex AI chat models](https://python.langchain.com/docs/integrations/chat/google_vertex_ai_palm)\n"
203+
]
204+
},
205+
{
206+
"cell_type": "code",
207+
"execution_count": null,
208+
"metadata": {},
209+
"outputs": [],
210+
"source": [
211+
"# enable Vertex AI API\n",
212+
"!gcloud services enable aiplatform.googleapis.com"
213+
]
214+
},
215+
{
216+
"cell_type": "code",
217+
"execution_count": null,
218+
"metadata": {},
219+
"outputs": [],
220+
"source": [
221+
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
222+
"from langchain_core.runnables.history import RunnableWithMessageHistory\n",
223+
"from langchain_google_vertexai import ChatVertexAI"
224+
]
225+
},
226+
{
227+
"cell_type": "code",
228+
"execution_count": null,
229+
"metadata": {
230+
"tags": []
231+
},
232+
"outputs": [],
233+
"source": [
234+
"GOOGLE_CLOUD_PROJECT_ID = \"\"\n",
235+
"\n",
236+
"prompt = ChatPromptTemplate.from_messages(\n",
237+
" [\n",
238+
" (\"system\", \"You are a helpful assistant.\"),\n",
239+
" MessagesPlaceholder(variable_name=\"history\"),\n",
240+
" (\"human\", \"{question}\"),\n",
241+
" ]\n",
242+
")\n",
243+
"\n",
244+
"chain = prompt | ChatVertexAI(\n",
245+
" project=GOOGLE_CLOUD_PROJECT_ID, model_name=\"gemini-2.0-flash-exp\"\n",
246+
")"
247+
]
248+
},
249+
{
250+
"cell_type": "code",
251+
"execution_count": null,
252+
"metadata": {
253+
"tags": []
254+
},
255+
"outputs": [],
256+
"source": [
257+
"chain_with_history = RunnableWithMessageHistory(\n",
258+
" chain,\n",
259+
" lambda session_id: PGChatMessageHistory.create_sync(\n",
260+
" pg_engine,\n",
261+
" session_id=session_id,\n",
262+
" table_name=TABLE_NAME,\n",
263+
" # schema_name=SCHEMA_NAME,\n",
264+
" ),\n",
265+
" input_messages_key=\"question\",\n",
266+
" history_messages_key=\"history\",\n",
267+
")"
268+
]
269+
},
270+
{
271+
"cell_type": "code",
272+
"execution_count": null,
273+
"metadata": {
274+
"tags": []
275+
},
276+
"outputs": [],
277+
"source": [
278+
"# This is where we configure the session id\n",
279+
"config = {\"configurable\": {\"session_id\": \"test_session\"}}"
280+
]
281+
},
282+
{
283+
"cell_type": "code",
284+
"execution_count": null,
285+
"metadata": {
286+
"tags": []
287+
},
288+
"outputs": [],
289+
"source": [
290+
"chain_with_history.invoke({\"question\": \"Hi! I'm bob\"}, config=config)"
291+
]
292+
},
293+
{
294+
"cell_type": "code",
295+
"execution_count": null,
296+
"metadata": {
297+
"tags": []
298+
},
299+
"outputs": [],
300+
"source": [
301+
"chain_with_history.invoke({\"question\": \"Whats my name\"}, config=config)"
302+
]
303+
}
304+
],
305+
"metadata": {
306+
"colab": {
307+
"provenance": [],
308+
"toc_visible": true
309+
},
310+
"kernelspec": {
311+
"display_name": "Python 3 (ipykernel)",
312+
"language": "python",
313+
"name": "python3"
314+
},
315+
"language_info": {
316+
"codemirror_mode": {
317+
"name": "ipython",
318+
"version": 3
319+
},
320+
"file_extension": ".py",
321+
"mimetype": "text/x-python",
322+
"name": "python",
323+
"nbconvert_exporter": "python",
324+
"pygments_lexer": "ipython3",
325+
"version": "3.11.4"
326+
}
327+
},
328+
"nbformat": 4,
329+
"nbformat_minor": 4
330+
}

0 commit comments

Comments
 (0)