Skip to content

Commit d53b8be

Browse files
authored
standardize chat history (#98)
1 parent 84b767d commit d53b8be

File tree

2 files changed

+348
-76
lines changed

2 files changed

+348
-76
lines changed

libs/elasticsearch/langchain_elasticsearch/_async/chat_history.py

Lines changed: 174 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,66 +16,202 @@
1616

1717

1818
class AsyncElasticsearchChatMessageHistory(BaseChatMessageHistory):
19-
"""Chat message history that stores history in Elasticsearch.
20-
21-
Args:
22-
es_url: URL of the Elasticsearch instance to connect to.
23-
es_cloud_id: Cloud ID of the Elasticsearch instance to connect to.
24-
es_user: Username to use when connecting to Elasticsearch.
25-
es_password: Password to use when connecting to Elasticsearch.
26-
es_api_key: API key to use when connecting to Elasticsearch.
27-
es_params: Additional parameters for the Elasticsearch client.
28-
es_connection: Optional pre-existing Elasticsearch connection.
29-
esnsure_ascii: Used to escape ASCII symbols in json.dumps. Defaults to True.
30-
index: Name of the index to use.
31-
session_id: Arbitrary key that is used to store the messages
32-
of a single chat session.
19+
"""`Elasticsearch` chat message history.
20+
21+
Stores chat message history in Elasticsearch for persistence across sessions.
22+
23+
Setup:
24+
Install `langchain_elasticsearch` and start Elasticsearch locally using
25+
the start-local script.
26+
27+
```bash
28+
pip install -qU langchain_elasticsearch
29+
curl -fsSL https://elastic.co/start-local | sh
30+
```
31+
32+
This will create an `elastic-start-local` folder. To start Elasticsearch
33+
and Kibana:
34+
```bash
35+
cd elastic-start-local
36+
./start.sh
37+
```
38+
39+
Elasticsearch will be available at `http://localhost:9200`. The password
40+
for the `elastic` user and API key are stored in the `.env` file in the
41+
`elastic-start-local` folder.
42+
43+
Key init args:
44+
index: str
45+
Name of the Elasticsearch index to use for storing messages.
46+
session_id: str
47+
Arbitrary key that is used to store the messages of a single chat
48+
session.
49+
ensure_ascii: Optional[bool]
50+
Used to escape ASCII symbols in json.dumps. Defaults to True.
51+
52+
Key init args — client params:
53+
client: Optional[AsyncElasticsearch or Elasticsearch]
54+
Pre-existing Elasticsearch connection. Either provide this OR
55+
credentials.
56+
es_url: Optional[str]
57+
URL of the Elasticsearch instance to connect to.
58+
es_cloud_id: Optional[str]
59+
Cloud ID of the Elasticsearch instance to connect to.
60+
es_user: Optional[str]
61+
Username to use when connecting to Elasticsearch.
62+
es_api_key: Optional[str]
63+
API key to use when connecting to Elasticsearch.
64+
es_password: Optional[str]
65+
Password to use when connecting to Elasticsearch.
66+
67+
Instantiate:
68+
```python
69+
from langchain_elasticsearch import ElasticsearchChatMessageHistory
70+
71+
history = ElasticsearchChatMessageHistory(
72+
index="chat-history",
73+
session_id="user-123",
74+
es_url="http://localhost:9200"
75+
)
76+
```
77+
78+
Instantiate with API key (URL):
79+
```python
80+
from langchain_elasticsearch import ElasticsearchChatMessageHistory
81+
82+
history = ElasticsearchChatMessageHistory(
83+
index="chat-history",
84+
session_id="user-123",
85+
es_url="http://localhost:9200",
86+
es_api_key="your-api-key"
87+
)
88+
```
89+
90+
Instantiate with username/password (URL):
91+
```python
92+
from langchain_elasticsearch import ElasticsearchChatMessageHistory
93+
94+
history = ElasticsearchChatMessageHistory(
95+
index="chat-history",
96+
session_id="user-123",
97+
es_url="http://localhost:9200",
98+
es_user="elastic",
99+
es_password="password"
100+
)
101+
```
102+
103+
If you want to use a cloud hosted Elasticsearch instance, you can pass in the
104+
es_cloud_id argument instead of the es_url argument.
105+
106+
Instantiate from cloud (with API key):
107+
```python
108+
from langchain_elasticsearch import ElasticsearchChatMessageHistory
109+
110+
history = ElasticsearchChatMessageHistory(
111+
index="chat-history",
112+
session_id="user-123",
113+
es_cloud_id="<cloud_id>",
114+
es_api_key="your-api-key"
115+
)
116+
```
117+
118+
You can also connect to an existing Elasticsearch instance by passing in a
119+
pre-existing Elasticsearch connection via the client argument.
120+
121+
Instantiate from existing connection:
122+
```python
123+
from langchain_elasticsearch import ElasticsearchChatMessageHistory
124+
from elasticsearch import Elasticsearch
125+
126+
client = Elasticsearch("http://localhost:9200")
127+
history = ElasticsearchChatMessageHistory(
128+
index="chat-history",
129+
session_id="user-123",
130+
client=client
131+
)
132+
```
133+
134+
Add messages:
135+
```python
136+
from langchain_core.messages import HumanMessage, AIMessage
137+
138+
history.add_message(HumanMessage(content="Hello!"))
139+
history.add_message(AIMessage(content="Hi there! How can I help?"))
140+
```
141+
142+
Get messages:
143+
```python
144+
messages = history.messages
145+
for msg in messages:
146+
print(f"{msg.type}: {msg.content}")
147+
```
148+
149+
Clear history:
150+
```python
151+
history.clear()
152+
```
33153
34154
For synchronous applications, use the `ElasticsearchChatMessageHistory` class.
35-
For asyhchronous applications, use the `AsyncElasticsearchChatMessageHistory` class.
36-
"""
155+
For asynchronous applications, use the `AsyncElasticsearchChatMessageHistory`
156+
class.
157+
""" # noqa: E501
37158

38159
def __init__(
39160
self,
40161
index: str,
41162
session_id: str,
42163
*,
43-
es_connection: Optional["AsyncElasticsearch"] = None,
164+
ensure_ascii: Optional[bool] = True,
165+
client: Optional["AsyncElasticsearch"] = None,
44166
es_url: Optional[str] = None,
45167
es_cloud_id: Optional[str] = None,
46168
es_user: Optional[str] = None,
47169
es_api_key: Optional[str] = None,
48170
es_password: Optional[str] = None,
49-
es_params: Optional[Dict[str, Any]] = None,
50-
esnsure_ascii: Optional[bool] = True,
51171
):
172+
"""Initialize the ElasticsearchChatMessageHistory instance.
173+
174+
Args:
175+
index (str): Name of the Elasticsearch index to use for storing
176+
messages.
177+
session_id (str): Arbitrary key that is used to store the messages
178+
of a single chat session.
179+
ensure_ascii (bool, optional): Used to escape ASCII symbols in
180+
json.dumps. Defaults to True.
181+
client (AsyncElasticsearch, optional): Pre-existing Elasticsearch
182+
connection. Either provide this OR credentials.
183+
es_url (str, optional): URL of the Elasticsearch instance to
184+
connect to.
185+
es_cloud_id (str, optional): Cloud ID of the Elasticsearch instance.
186+
es_user (str, optional): Username to use when connecting to
187+
Elasticsearch.
188+
es_api_key (str, optional): API key to use when connecting to
189+
Elasticsearch.
190+
es_password (str, optional): Password to use when connecting to
191+
Elasticsearch.
192+
"""
52193
self.index: str = index
53194
self.session_id: str = session_id
54-
self.ensure_ascii = esnsure_ascii
195+
self.ensure_ascii = ensure_ascii
55196

56-
# Initialize Elasticsearch client from passed client arg or connection info
57-
if es_connection is not None:
58-
self.client = es_connection
197+
# Accept either client OR credentials (one required)
198+
if client is not None:
199+
es_connection = client
59200
elif es_url is not None or es_cloud_id is not None:
60-
try:
61-
self.client = create_async_elasticsearch_client(
62-
url=es_url,
63-
username=es_user,
64-
password=es_password,
65-
cloud_id=es_cloud_id,
66-
api_key=es_api_key,
67-
params=es_params,
68-
)
69-
except Exception as err:
70-
logger.error(f"Error connecting to Elasticsearch: {err}")
71-
raise err
201+
es_connection = create_async_elasticsearch_client(
202+
url=es_url,
203+
username=es_user,
204+
password=es_password,
205+
cloud_id=es_cloud_id,
206+
api_key=es_api_key,
207+
)
72208
else:
73209
raise ValueError(
74-
"""Either provide a pre-existing Elasticsearch connection, \
75-
or valid credentials for creating a new connection."""
210+
"Either 'client' or credentials (es_url, es_cloud_id, etc.) "
211+
"must be provided."
76212
)
77213

78-
self.client = async_with_user_agent_header(self.client, "langchain-py-ms")
214+
self.client = async_with_user_agent_header(es_connection, "langchain-py-ms")
79215
self.created = False
80216

81217
async def create_if_missing(self) -> None:

0 commit comments

Comments
 (0)