一、对话记忆(多轮对话)
1. 目标
让智能助手在自然对话的基础上,结合知识库进行问答,全面提升用户体验。
2. 提示词优化
- 明确角色定位:知识库助手
- 约束答案范围:仅基于参考资料作答
- 处理无答案情况:无法回答时,明确告知用户
3. RAG客户端配置
(1)记忆持久化方式
支持三种记忆持久化方式:
- InMemory:默认,数据存于内存,重启后丢失
- Redis:数据存入Redis,支持分布式部署
- JDBC:数据持久化到数据库,最为可靠
配置:
具体配置可参考第三章:4、对话记忆与会话管理
(2)InMemoryChatMemory 职责分离重构
Spring AI 2.0 对 ChatMemory 进行了职责分离重构:
- ChatMemoryRepository:存储和检索消息(支持InMemory/Redis/JDBC)
- MessageWindowChatMemory:管理记忆窗口(保留最近N条消息)
- MessageChatMemoryAdvisor:将记忆注入Prompt
(3)闲聊感知
- 判断用户输入是闲聊还是知识性问题
- 闲聊内容直接对话,不走RAG流程
详细实现请参见第三章:5、RAG进阶优化中的"闲聊感知查询改写"章节
(4)查询增强
- ContextualQueryAugmenter:负责将检索到的文档与用户查询拼装为完整Prompt
详细配置请参见第三章:5、RAG进阶优化中的"查询增强与空上下文处理"章节
4. RAG + 记忆完整配置
java
@Configuration
public class RagWithMemoryConfig {
@Bean("ragMemoryChatClient")
public ChatClient ragMemoryChatClient(
ChatClient.Builder chatClientBuilder,
VectorStore vectorStore,
ChatMemoryRepository chatMemoryRepository) {
// 设置记忆窗口:保留最近20条消息
ChatMemory chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(20)
.build();
RetrievalAugmentationAdvisor ragAdvisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.topK(5)
.build())
.build();
return chatClientBuilder
.defaultAdvisors(ragAdvisor, MessageChatMemoryAdvisor.builder()
.chatMemory(chatMemory)
.build())
.build();
}
}
二、多轮对话接口
java
@RestController
@RequestMapping("/ai")
public class ChatController {
@Resource(name = "ragMemoryChatClient")
private ChatClient chatClient;
@GetMapping("/chat")
public Flux<String> chat(
@RequestParam String message,
@RequestParam(defaultValue = "default") String conversationId) {
return chatClient.prompt()
.user(message)
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, conversationId))
.stream().content();
}
}
三、引用标注
引用标注的核心思路:在返回答案的同时,附带答案来源的文档信息(citations)。
java
@GetMapping("/ask-citation")
public Map<String, Object> askWithCitation(
@RequestParam String message,
@RequestParam(defaultValue = "default") String conversationId) {
ChatResponse response = chatClient.prompt()
.user(message)
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, conversationId))
.call().chatResponse();
Map<String, Object> result = new HashMap<>();
result.put("answer", response.getResult().getOutput().getText());
result.put("citations", extractCitations(response));
return result;
}
四、总结
- 对话记忆:赋予助手多轮对话能力
- 引用标注:让答案来源可追溯
- 结合RAG检索增强:打造专业、可信赖的知识库问答系统