feat: RAG
This commit is contained in:
parent
f5b0e16c94
commit
bf47df6ac6
19
pom.xml
19
pom.xml
|
|
@ -77,12 +77,25 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!--mysql驱动-->
|
<!-- PostgreSQL:聊天记忆 JDBC + pgvector 共用同一数据源 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysql</groupId>
|
<groupId>org.postgresql</groupId>
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
|
||||||
|
<version>1.1.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 向量数据库 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-advisors-vector-store</artifactId>
|
||||||
|
<version>1.1.2</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
package com.baoshi.conf;
|
package com.baoshi.conf;
|
||||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
||||||
|
import com.alibaba.cloud.ai.dashscope.spec.DashScopeModel;
|
||||||
import org.springframework.ai.chat.client.ChatClient;
|
import org.springframework.ai.chat.client.ChatClient;
|
||||||
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
|
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
|
||||||
import org.springframework.ai.chat.memory.ChatMemory;
|
import org.springframework.ai.chat.memory.ChatMemory;
|
||||||
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
|
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
|
||||||
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
|
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
|
||||||
|
import org.springframework.ai.embedding.EmbeddingModel;
|
||||||
import org.springframework.ai.model.ollama.autoconfigure.OllamaChatProperties;
|
import org.springframework.ai.model.ollama.autoconfigure.OllamaChatProperties;
|
||||||
import org.springframework.ai.ollama.OllamaChatModel;
|
import org.springframework.ai.ollama.OllamaChatModel;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class AiConfig {
|
public class AiConfig {
|
||||||
|
|
@ -16,7 +21,7 @@ public class AiConfig {
|
||||||
@Bean
|
@Bean
|
||||||
public ChatMemory chatMemory(JdbcChatMemoryRepository chatMemoryRepository) {
|
public ChatMemory chatMemory(JdbcChatMemoryRepository chatMemoryRepository) {
|
||||||
return MessageWindowChatMemory.builder()
|
return MessageWindowChatMemory.builder()
|
||||||
.maxMessages(1)
|
.maxMessages(3)
|
||||||
.chatMemoryRepository(chatMemoryRepository)
|
.chatMemoryRepository(chatMemoryRepository)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -37,4 +42,10 @@ public class AiConfig {
|
||||||
.defaultAdvisors(PromptChatMemoryAdvisor.builder(chatMemory).build())
|
.defaultAdvisors(PromptChatMemoryAdvisor.builder(chatMemory).build())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Primary
|
||||||
|
@Bean
|
||||||
|
public EmbeddingModel embeddingModel(@Autowired @Qualifier("ollamaEmbeddingModel") EmbeddingModel embeddingModel) {
|
||||||
|
return embeddingModel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ spring:
|
||||||
base-url: http://100.121.13.117:11434
|
base-url: http://100.121.13.117:11434
|
||||||
chat:
|
chat:
|
||||||
model: qwen2.5:7b
|
model: qwen2.5:7b
|
||||||
|
embedding:
|
||||||
|
model: bge-m3
|
||||||
dashscope:
|
dashscope:
|
||||||
api-key: sk-36a57382b9ae4db696ecd07eb7150a88
|
api-key: sk-36a57382b9ae4db696ecd07eb7150a88
|
||||||
chat:
|
chat:
|
||||||
|
|
@ -14,11 +16,18 @@ spring:
|
||||||
repository:
|
repository:
|
||||||
jdbc:
|
jdbc:
|
||||||
initialize-schema: always
|
initialize-schema: always
|
||||||
|
vectorstore:
|
||||||
|
pgvector:
|
||||||
|
initialize-schema: true
|
||||||
|
index-type: HNSW
|
||||||
|
distance-type: COSINE_DISTANCE
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
username: root
|
username: postgres
|
||||||
password: 123456
|
password: postgres
|
||||||
url: jdbc:mysql://localhost:3306/springai?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&
|
url: jdbc:postgresql://localhost:5432/springai
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: org.postgresql.Driver
|
||||||
|
|
||||||
|
|
||||||
server:
|
server:
|
||||||
port: 8080
|
port: 8080
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import org.springframework.ai.chat.client.ChatClient;
|
||||||
import org.springframework.ai.chat.memory.ChatMemory;
|
import org.springframework.ai.chat.memory.ChatMemory;
|
||||||
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
|
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
|
|
@ -23,14 +24,12 @@ class JDBCMemoryTest {
|
||||||
private static final String CONVERSATION_ID = "1";
|
private static final String CONVERSATION_ID = "1";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ChatClient ollama;
|
@Qualifier("ollama")
|
||||||
|
private ChatClient chatClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ChatMemory chatMemory;
|
private ChatMemory chatMemory;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private JdbcChatMemoryRepository chatMemoryRepository;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private JdbcTemplate jdbcTemplate;
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
|
@ -41,20 +40,23 @@ class JDBCMemoryTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldPersistMessagesIntoJdbcRepositoryByChatModelConversation() {
|
void shouldPersistMessagesIntoJdbcRepositoryByChatModelConversation() {
|
||||||
ollama.prompt()
|
chatClient.prompt()
|
||||||
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, CONVERSATION_ID))
|
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, CONVERSATION_ID))
|
||||||
.user("我叫邹志文")
|
.user("我叫邹志文")
|
||||||
.call()
|
.call()
|
||||||
.content();
|
.content();
|
||||||
|
chatClient.prompt()
|
||||||
String secondResponse = ollama.prompt()
|
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, CONVERSATION_ID))
|
||||||
|
.user("她叫冬马和纱")
|
||||||
|
.call()
|
||||||
|
.content();
|
||||||
|
String secondResponse = chatClient.prompt()
|
||||||
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, CONVERSATION_ID))
|
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, CONVERSATION_ID))
|
||||||
.user("我叫什么")
|
.user("我叫什么")
|
||||||
.call()
|
.call()
|
||||||
.content();
|
.content();
|
||||||
|
|
||||||
assertThat(secondResponse).isNotBlank();
|
System.out.println(secondResponse);
|
||||||
assertThat(chatMemoryRepository.findByConversationId(CONVERSATION_ID)).isNotEmpty();
|
|
||||||
Integer rowCount = jdbcTemplate.queryForObject(
|
Integer rowCount = jdbcTemplate.queryForObject(
|
||||||
"SELECT COUNT(*) FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ?",
|
"SELECT COUNT(*) FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ?",
|
||||||
Integer.class,
|
Integer.class,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.baoshi;
|
||||||
|
|
||||||
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.ai.chat.client.ChatClient;
|
||||||
|
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
|
||||||
|
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
|
||||||
|
import org.springframework.ai.document.Document;
|
||||||
|
import org.springframework.ai.vectorstore.SearchRequest;
|
||||||
|
import org.springframework.ai.vectorstore.VectorStore;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
public class SimpleVectorStoreTest {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void init( @Autowired
|
||||||
|
VectorStore vectorStore) {
|
||||||
|
// 1. 声明内容文档
|
||||||
|
Document doc = Document.builder()
|
||||||
|
.text("""
|
||||||
|
预订航班:
|
||||||
|
- 通过我们的网站或移动应用程序预订。
|
||||||
|
- 预订时需要全额付款。
|
||||||
|
- 确保个人信息(姓名、ID 等)的准确性,因为更正可能会产生 25 的费用。
|
||||||
|
""")
|
||||||
|
.build();
|
||||||
|
Document doc2 = Document.builder()
|
||||||
|
.text("""
|
||||||
|
取消预订:
|
||||||
|
- 最晚在航班起飞前 48 小时取消。
|
||||||
|
- 取消费用:经济舱 75 美元,豪华经济舱 50 美元,商务舱 25 美元。
|
||||||
|
- 退款将在 7 个工作日内处理。
|
||||||
|
""")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
// 2. 将文本进行向量化,并且存入向量数据库(无需再手动向量化)
|
||||||
|
vectorStore.add(Arrays.asList(doc,doc2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void chatRagTest(
|
||||||
|
@Autowired
|
||||||
|
VectorStore vectorStore,
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("ollama")
|
||||||
|
ChatClient chatClient
|
||||||
|
) {
|
||||||
|
|
||||||
|
|
||||||
|
String message="退费需要多少费用?";
|
||||||
|
String content = chatClient.prompt().user(message)
|
||||||
|
.advisors(
|
||||||
|
new SimpleLoggerAdvisor(),
|
||||||
|
QuestionAnswerAdvisor.builder(vectorStore)
|
||||||
|
.searchRequest(
|
||||||
|
SearchRequest
|
||||||
|
.builder().query(message)
|
||||||
|
.topK(5)
|
||||||
|
.similarityThreshold(0.3)
|
||||||
|
.build())
|
||||||
|
.build()
|
||||||
|
).call().content();
|
||||||
|
|
||||||
|
System.out.println(content);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue