An option to use a generic JdbcChatMemory
with a starter for users that want to use SQL as chat memory.
Comment From: ogbozoyan
Is it will be usable with VectorStoreChayMemoryAdvisor? Or what is the point ?
Comment From: leijendary
@ogbozoyan VectorStoreChatMemoryAdvisor
is optional if we have this change. PgVectorChatMemory
is an implementation of ChatMemory
and the postgres version of CassandraChatMemory
which is specialized just for the chat memory/history.
Comment From: ogbozoyan
@leijendary which advisor you should use with that ChatMemory to process saving ?
Comment From: leijendary
@ogbozoyan You can use MessageChatMemoryAdvisor
and pass in the instance of the PgVectorChatMemory
. Then for RAG, you can use RetrievalAugmentationAdvisor
. This is what I did for my chatClient
bean:
@Bean
fun chatClient(builder: ChatClient.Builder, vectorStore: VectorStore, chatMemory: ChatMemory): ChatClient {
val memoryAdvisor = MessageChatMemoryAdvisor(chatMemory)
val documentRetriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.build()
val ragAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(documentRetriever)
.build()
return builder
.defaultAdvisors(memoryAdvisor, ragAdvisor)
.build()
}
Comment From: ogbozoyan
@ogbozoyan You can use
MessageChatMemoryAdvisor
and pass in the instance of thePgVectorChatMemory
. Then for RAG, you can useRetrievalAugmentationAdvisor
. This is what I did for mychatClient
bean:```kotlin @Bean fun chatClient(builder: ChatClient.Builder, vectorStore: VectorStore, chatMemory: ChatMemory): ChatClient { val memoryAdvisor = MessageChatMemoryAdvisor(chatMemory) val documentRetriever = VectorStoreDocumentRetriever.builder() .vectorStore(vectorStore) .build() val ragAdvisor = RetrievalAugmentationAdvisor.builder() .documentRetriever(documentRetriever) .build()
return builder .defaultAdvisors(memoryAdvisor, ragAdvisor) .build()
} ```
in this example you passing VectorStore, may be you meant ?
fun chatClient(builder: ChatClient.Builder, **pgVectorChatMemory: PgVectorChatMemory**, chatMemory: ChatMemory): ChatClient {
val memoryAdvisor = MessageChatMemoryAdvisor(**pgVectorChatMemory**)
val documentRetriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.build()
val ragAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(documentRetriever)
.build()
return builder
.defaultAdvisors(memoryAdvisor, ragAdvisor)
.build()
}
Comment From: leijendary
@ogbozoyan
@ogbozoyan You can use
MessageChatMemoryAdvisor
and pass in the instance of thePgVectorChatMemory
. Then for RAG, you can useRetrievalAugmentationAdvisor
. This is what I did for mychatClient
bean: ```kotlin @Bean fun chatClient(builder: ChatClient.Builder, vectorStore: VectorStore, chatMemory: ChatMemory): ChatClient { val memoryAdvisor = MessageChatMemoryAdvisor(chatMemory) val documentRetriever = VectorStoreDocumentRetriever.builder() .vectorStore(vectorStore) .build() val ragAdvisor = RetrievalAugmentationAdvisor.builder() .documentRetriever(documentRetriever) .build()return builder .defaultAdvisors(memoryAdvisor, ragAdvisor) .build()
} ```
in this example you passing VectorStore, may be you meant ?
```kotlin fun chatClient(builder: ChatClient.Builder, pgVectorChatMemory: PgVectorChatMemory, chatMemory: ChatMemory): ChatClient { val memoryAdvisor = MessageChatMemoryAdvisor(pgVectorChatMemory) val documentRetriever = VectorStoreDocumentRetriever.builder() .vectorStore(vectorStore) .build() val ragAdvisor = RetrievalAugmentationAdvisor.builder() .documentRetriever(documentRetriever) .build()
return builder .defaultAdvisors(memoryAdvisor, ragAdvisor) .build()
} ```
The code I provided is correct. I am using it right now. The ChatMemory
instance is automatically picked up by spring as PgVectorChatMemory
because of PgVectorChatMemoryAutoConfiguration
Comment From: eddumelendez
I wonder if this should be more generic and instead providing a JdbcChatMemory
instead. I would be also nice to provide the proper scripts to create the tables, similar to what spring security and spring session does.
Comment From: leijendary
@eddumelendez I agree. I also originally designed it to be the same as the existing CassandraChatMemory
and just used the same columns. I thought of changing the columns to the following:
CREATE TABLE ai_chat_memory (
session_id character varying(36) NOT NULL,
content text NOT NULL,
type character varying(10) NOT NULL, -- USER/ASSISTANT
"timestamp" timestamp without time zone NOT NULL DEFAULT NOW()
);
Do you also mean that the table should not be automatically created and instead be created manually by the developer?
Comment From: eddumelendez
Do you also mean that the table should not be automatically created and instead be created manually by the developer?
it should be created automatically by detecting the database. I meant having something like https://github.com/spring-projects/spring-session/blob/main/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-postgresql.sql that spring ai can execute, so, if new database should be supported then adding a script should be enough
Comment From: ogbozoyan
sql type character varying(10) NOT NULL, -- USER/ASSISTANT
maybe add check ?
CREATE TABLE ai_chat_memory (
session_id character varying(36) NOT NULL,
content text NOT NULL,
type character varying(10) NOT NULL CHECK (type IN ('USER', 'ASSISTANT')), -- USER/ASSISTANT
"timestamp" timestamp without time zone NOT NULL DEFAULT NOW()
);