-
Notifications
You must be signed in to change notification settings - Fork 17.3k
community[minor]: Add native async support to SQLChatMessageHistory #22065
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
community[minor]: Add native async support to SQLChatMessageHistory #22065
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Ignored Deployment
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost ready for merging.
Most important things to address:
- Undo changes in core
- Undo the code that calls async code from a sync function using a new event loop
- Create a separate async session maker in chat history, so we can consolidate the asserts in just two places
libs/community/langchain_community/chat_message_histories/sql.py
Outdated
Show resolved
Hide resolved
libs/community/langchain_community/chat_message_histories/sql.py
Outdated
Show resolved
Hide resolved
libs/community/langchain_community/chat_message_histories/sql.py
Outdated
Show resolved
Hide resolved
libs/community/langchain_community/chat_message_histories/sql.py
Outdated
Show resolved
Hide resolved
libs/community/langchain_community/chat_message_histories/sql.py
Outdated
Show resolved
Hide resolved
…to pprados/fix_sql_chat_history
@pprados back from vacation -- this looks ready to merge, I'll take a final look tomorrow and resolve merge conflict |
table_name: str = "message_store", | ||
session_id_field_name: str = "session_id", | ||
custom_message_converter: Optional[BaseMessageConverter] = None, | ||
connection: Union[None, DBConnection] = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(unrelated to this PR)
@pprados this pattern could be useful if you needed a transaction (e.g., as was the case in the indexing API if I recall correctly)
Allows passing a session maker as part of the init instead of initializing and then mutating a class attribute (the latter pattern is more likely to break in threaded scenarios)
Hello @eyurtsev - package: langchain-comminity - **Description**: Add SQL implementation for docstore. A new implementation, in line with my other PR ([async PGVector](langchain-ai/langchain-postgres#32), [SQLChatMessageMemory](#22065)) - Twitter handler: pprados --------- Signed-off-by: ChengZi <[email protected]> Co-authored-by: Bagatur <[email protected]> Co-authored-by: Piotr Mardziel <[email protected]> Co-authored-by: ChengZi <[email protected]> Co-authored-by: Eugene Yurtsev <[email protected]>
…22065) # package community: Fix SQLChatMessageHistory ## Description Here is a rewrite of `SQLChatMessageHistory` to properly implement the asynchronous approach. The code circumvents [issue 22021](#22021) by accepting a synchronous call to `def add_messages()` in an asynchronous scenario. This bypasses the bug. For the same reasons as in [PR 22](langchain-ai/langchain-postgres#32) of `langchain-postgres`, we use a lazy strategy for table creation. Indeed, the promise of the constructor cannot be fulfilled without this. It is not possible to invoke a synchronous call in a constructor. We compensate for this by waiting for the next asynchronous method call to create the table. The goal of the `PostgresChatMessageHistory` class (in `langchain-postgres`) is, among other things, to be able to recycle database connections. The implementation of the class is problematic, as we have demonstrated in [issue 22021](#22021). Our new implementation of `SQLChatMessageHistory` achieves this by using a singleton of type (`Async`)`Engine` for the database connection. The connection pool is managed by this singleton, and the code is then reentrant. We also accept the type `str` (optionally complemented by `async_mode`. I know you don't like this much, but it's the only way to allow an asynchronous connection string). In order to unify the different classes handling database connections, we have renamed `connection_string` to `connection`, and `Session` to `session_maker`. Now, a single transaction is used to add a list of messages. Thus, a crash during this write operation will not leave the database in an unstable state with a partially added message list. This makes the code resilient. We believe that the `PostgresChatMessageHistory` class is no longer necessary and can be replaced by: ``` PostgresChatMessageHistory = SQLChatMessageHistory ``` This also fixes the bug. ## Issue - [issue 22021](#22021) - Bug in _exit_history() - Bugs in PostgresChatMessageHistory and sync usage - Bugs in PostgresChatMessageHistory and async usage - [issue 36](langchain-ai/langchain-postgres#36) ## Twitter handle: pprados ## Tests - libs/community/tests/unit_tests/chat_message_histories/test_sql.py (add async test) @baskaryan, @eyurtsev or @hwchase17 can you check this PR ? And, I've been waiting a long time for validation from other PRs. Can you take a look? - [PR 32](langchain-ai/langchain-postgres#32) - [PR 15575](#15575) - [PR 13200](#13200) --------- Co-authored-by: Eugene Yurtsev <[email protected]>
Hello @eyurtsev - package: langchain-comminity - **Description**: Add SQL implementation for docstore. A new implementation, in line with my other PR ([async PGVector](langchain-ai/langchain-postgres#32), [SQLChatMessageMemory](#22065)) - Twitter handler: pprados --------- Signed-off-by: ChengZi <[email protected]> Co-authored-by: Bagatur <[email protected]> Co-authored-by: Piotr Mardziel <[email protected]> Co-authored-by: ChengZi <[email protected]> Co-authored-by: Eugene Yurtsev <[email protected]>
Can you add in the documentation readme how to use async connections? Even with the PR, I'm getting errors. |
Use:
|
package community: Fix SQLChatMessageHistory
Description
Here is a rewrite of
SQLChatMessageHistory
to properly implement the asynchronous approach. The code circumvents issue 22021 by accepting a synchronous call todef add_messages()
in an asynchronous scenario. This bypasses the bug.For the same reasons as in PR 22 of
langchain-postgres
, we use a lazy strategy for table creation. Indeed, the promise of the constructor cannot be fulfilled without this. It is not possible to invoke a synchronous call in a constructor. We compensate for this by waiting for the next asynchronous method call to create the table.The goal of the
PostgresChatMessageHistory
class (inlangchain-postgres
) is, among other things, to be able to recycle database connections. The implementation of the class is problematic, as we have demonstrated in issue 22021.Our new implementation of
SQLChatMessageHistory
achieves this by using a singleton of type (Async
)Engine
for the database connection. The connection pool is managed by this singleton, and the code is then reentrant.We also accept the type
str
(optionally complemented byasync_mode
. I know you don't like this much, but it's the only way to allow an asynchronous connection string).In order to unify the different classes handling database connections, we have renamed
connection_string
toconnection
, andSession
tosession_maker
.Now, a single transaction is used to add a list of messages. Thus, a crash during this write operation will not leave the database in an unstable state with a partially added message list. This makes the code resilient.
We believe that the
PostgresChatMessageHistory
class is no longer necessary and can be replaced by:This also fixes the bug.
Issue
Twitter handle:
pprados
Tests
@baskaryan, @eyurtsev or @hwchase17 can you check this PR ?
And, I've been waiting a long time for validation from other PRs. Can you take a look?