Skip to content

fix(JdbcChatMemory): get query for MSSQL Server #2806

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

Closed

Conversation

xchopin
Copy link

@xchopin xchopin commented Apr 19, 2025

Fix the GET query for Microsoft SQL Server on JdbcChatMemory

I have tried to make the less changes, I was thinking at first to change with Impl classes and make a @OnConditionalClass("sql driver") but that would break too many things as it introduces the class a Component.

I hope the way I have fixed the issue fits the Spring standards, if not I will do the necessary.

Happy to contribute!

Related issue: #2807

@xchopin xchopin changed the title fix: get query for MSSQL Server fix(JdbcChatMemory): get query for MSSQL Server Apr 19, 2025
@xchopin xchopin force-pushed the hotfix/jdbcchatmemory-mssql branch from ec8c282 to 6ddaa46 Compare April 19, 2025 03:10
@xchopin
Copy link
Author

xchopin commented Apr 19, 2025

@leijendary @sobychacko the query was creating an error when using MSSQL Server. It is now fixed.

Can you get a look? I have tried making the least breaking changes so it doesn't break for existing projects using the class

@xchopin xchopin force-pushed the hotfix/jdbcchatmemory-mssql branch 6 times, most recently from 6b3840b to 2a23eca Compare April 19, 2025 16:07
Signed-off-by: Xavier Chopin <[email protected]>
@xchopin xchopin force-pushed the hotfix/jdbcchatmemory-mssql branch from 2a23eca to b4f95f2 Compare April 19, 2025 16:10
Copy link
Contributor

@leijendary leijendary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, I think using spring-data-jdbc would be better for a cleaner solution since more drivers with different query syntax needs to be supported.


import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Jonathan Leijendekker
*/
@Testcontainers
class JdbcChatMemoryAutoConfigurationIT {
class JdbcChatMemoryAutoConfigurationPostgreSQLIT {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be preferable to name it JdbcChatMemoryAutoConfigurationPostgresIT


import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Jonathan Leijendekker
*/
@Testcontainers
class JdbcChatMemoryDataSourceScriptDatabaseInitializerTests {
class JdbcChatMemoryDataSourceScriptDatabasePostgreSQLIT {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be preferable to name this JdbcChatMemoryDataSourceScriptDatabasePostgresIT

@@ -45,14 +45,29 @@ public class JdbcChatMemory implements ChatMemory {
INSERT INTO ai_chat_memory (conversation_id, content, type) VALUES (?, ?, ?)""";

private static final String QUERY_GET = """
SELECT content, type FROM ai_chat_memory WHERE conversation_id = ? ORDER BY "timestamp" DESC LIMIT ?""";
SELECT content, type \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this changed to multiline with a backslash? Also, utilise the proper alignment for closing the text blocks. Reference: Text Blocks

Copy link
Author

@xchopin xchopin Apr 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched it to multiline to keep it consistent with the new query.

My bad I thought without the backslash it would add extra spaces

LIMIT ?
""";

private static final String MSSQL_QUERY_GET = """
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Same as previous comment regarding utilising text block alignments; you can move the string content 1 tab to the right.
  2. ORDER BY should be DESC since we're querying lastN not the first n. Refer to Fixed message order for JDBC Chat Memory #2781 for the additional fix.

Copy link
Author

@xchopin xchopin Apr 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. ok, I will fix it
  2. putting DESC actually breaks the test and returns the list in a backward side, so either the one in Postgres is broken or there is something weird between the two behaviors

I am going to check the link thank you

chatMemory.add(conversationId, message);

var jdbcTemplate = context.getBean(JdbcTemplate.class);
var query = "SELECT conversation_id, content, type, \"timestamp\" FROM ai_chat_memory WHERE conversation_id = ?";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the timestamp column going to fail here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both "timestamp" [timestamp] works, the test succeeded when calling the method

Copy link
Author

@xchopin xchopin Apr 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could add an assert to verify it contains a value

chatMemory.add(conversationId, messages);

var jdbcTemplate = context.getBean(JdbcTemplate.class);
var query = "SELECT conversation_id, content, type, \"timestamp\" FROM ai_chat_memory WHERE conversation_id = ?";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the timestamp column going to fail here?

*/
@Testcontainers
class JdbcChatMemoryIT {
class JdbcChatMemoryPostgreSQLIT {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preferable to change name this to JdbcChatMemoryPostgresIT

<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use spring-data-jdbc instead of the starter.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will have to change org.springframework.boot.jdbc.DatabaseDriver then

Copy link
Contributor

@leijendary leijendary Apr 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xchopin btw, it is worth considering spring-data-jdbc repositories directly instead of manual query creations at this point. I added a comment to the PR.

Copy link
Author

@xchopin xchopin Apr 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leijendary is it still worth it to move to spring-data-jdbc with this incoming PR?

#2803

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xchopin Yes it is still worth it. The implementation in that PR is the same as the current implementation wherein it uses driver specific syntax. We should probably wait for that PR to be merged though as it is a conflict.

@ThomasVitale
Copy link
Contributor

@xchopin thanks so much for this improvement! We have just delivered some changes to the ChatMemory API which include the introduction of a ChatMemoryRepository API to separate the two different concerns: memory management strategy and storage mechanism. The JdbcChatMemory has now been superseded by JdbcChatMemoryRepository.

Upgrade Notes: https://docs.spring.io/spring-ai/reference/upgrade-notes.html#_chat_memory
New Chat Memory Docs: https://docs.spring.io/spring-ai/reference/api/chat-memory.html
PR with the change: #2890

@xchopin xchopin closed this Apr 26, 2025
@xchopin xchopin reopened this Apr 29, 2025
@xchopin
Copy link
Author

xchopin commented Apr 29, 2025

@ThomasVitale I have noticed you merged this PR #2781 today even tho the JdbcChatMemory is deprecated. Should I still continue my fix for MSSQL for this class or no?

cc @linarkou

@markpollack
Copy link
Member

Thoughts @ThomasVitale ?

@ThomasVitale
Copy link
Contributor

@xchopin thanks for your contribution! The deprecated JdbcChatMemory API has been removed in #3002, but we can add support for MSSQL to JdbcChatMemoryRepository.

Since MSSQL requires a different query (see https://github.com/spring-projects/spring-ai/pull/2806/files#diff-af27045980fb458706f33f2a0e23f6688b1f6c9ed46abb3d8cdb5f5c1cc6d234R76), I wonder if we should address the current problem of the JdbcChatMemoryRepository which doesn't allow customisations of the queries, as also pointed out in #2974 We might introduce some sort of QueryProvider interface to pass the SQL queries to JdbcChatMemoryRepository. And then we could have a MsSqlQueryProvider implementation for when we want to use MSSQL.

What do you think @markpollack?

@markpollack
Copy link
Member

markpollack commented May 8, 2025

The current state is certainly going to violate the principle of least surpise given the name JdbcChatMemoryRepository, so we should try to think of something to support other DB providers other than the postgres syntax.

I do like that things are simple now in terms of a few SQL statements to customize, but not sure how that works out in practice. Also, everyone wants control to name their own tables and rows, so there is a long tail to customization as well. The default table name also doesn't align with the default table name in vector stores which has spring_ai prefix.

not sure of what is a pragmatic way forward with a small time frame. will research a bit and post back.

@markpollack
Copy link
Member

I've made this PR that I hope will take into account all the various issues that have been raised around more flexible support for multiple databases.

#3055

closing this one now so we can concentrate on that PR. Your PR was very helpful! thanks @xchopin

@markpollack markpollack closed this May 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants