package com.ard.agent.service; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.PromptTemplate; import org.springframework.ai.document.Document; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import java.util.List; import java.util.stream.Collectors; @Slf4j @Service public class RagChatService { @Resource private ChatClient chatClient; @Resource private VectorStore vectorStore; /** * RAG问答流式方法(推荐使用) */ public Flux chatStream(String question) { log.info("收到RAG流式请求,question={}", question); // 1. 向量检索:召回Top3相关文档(同步执行) List similarDocs = vectorStore.similaritySearch( SearchRequest.builder() .query(question) .topK(3) .build() ); // 2. 拼接上下文 String context = similarDocs.stream() .map(doc -> "【参考内容】:" + doc.getText()) .collect(Collectors.joining("\n\n")); log.info("检索到{}条相关文档,开始流式生成回答", similarDocs.size()); // 3. 构建Prompt模板 String promptText = """ 你是专业知识库助手,基于以下参考内容回答用户问题,禁止编造,答案必须准确: {context} 用户问题:{question} """; PromptTemplate promptTemplate = new PromptTemplate(promptText); promptTemplate.add("context", context); promptTemplate.add("question", question); Prompt prompt = promptTemplate.create(); // 4. 流式调用大模型 return chatClient.prompt(prompt) .stream() .content() .doOnNext(chunk -> log.debug("输出数据块: {}", chunk)) .doOnComplete(() -> log.info("流式输出完成")) .doOnError(error -> log.error("流式输出出错: {}", error.getMessage())); } }