微信扫码
添加专属顾问
我要投稿
掌握RAG技术,构建智能文档检索系统。 核心内容: 1. RAG技术原理与核心设计理念 2. RAG四大核心步骤解析 3. Spring AI实现RAG流程与代码示例
RAG 简介
Cloud Native
RAG(Retrieval Augmented Generation,检索增强生成)是一种结合信息检索和文本生成的技术范式。
RAG 技术就像给 AI 装上了「实时百科大脑」,通过先查资料后回答的机制,让 AI 摆脱传统模型的“知识遗忘”困境。
应答触发流程:
应答构建过程:
? 输出示例:
“根据《产品手册v2.3》第5章内容:该设备续航时间为...”
Spring AI 实现基本 RAG 流程
Cloud Native
@Configuration
public class RagConfig {
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
return builder.defaultSystem("你将作为一名机器人产品的专家,对于用户的使用需求作出解答")
.build();
}
@Bean
VectorStore vectorStore(EmbeddingModel embeddingModel) {
SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(embeddingModel)
.build();
// 生成一个机器人产品说明书的文档
List<Document> documents = List.of(
new Document("产品说明书:产品名称:智能机器人\n" +
"产品描述:智能机器人是一个智能设备,能够自动完成各种任务。\n" +
"功能:\n" +
"1. 自动导航:机器人能够自动导航到指定位置。\n" +
"2. 自动抓取:机器人能够自动抓取物品。\n" +
"3. 自动放置:机器人能够自动放置物品。\n"));
simpleVectorStore.add(documents);
return simpleVectorStore;
}
}
通过这个配置类,完成以下内容:
1、配置 ChatClient 作为 Bean,其中设置系统默认角色为机器人产品专家, 负责处理用户查询并生成回答向量存储配置。
SimpleVectorStore 是将向量保存在内存 ConcurrentHashmap 中,Spring AI 提供了多种存储方式,如 Redis、MongoDB 等,可以根据实际情况选择适合的存储方式。
@RestController
@RequestMapping("/ai")
public class RagController {
@Autowired
private ChatClient chatClient;
@Autowired
private VectorStore vectorStore;
@PostMapping(value = "/chat", produces = "text/plain; charset=UTF-8")
public String generation(String userInput) {
// 发起聊天请求并处理响应
return chatClient.prompt()
.user(userInput)
.advisors(new QuestionAnswerAdvisor(vectorStore))
.call()
.content();
}
}
POST http://localhost:8080/spring-ai/ai/chat?userInput=机器人有哪些功能?
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
根据您提供的智能机器人产品说明书,该机器人的主要功能包括:
1. 自动导航:机器人可以自动导航到指定的位置。
2. 自动抓取:机器人能够自动抓取物品。
3. 自动放置:机器人能够自动放置物品。
如果您需要更详细的信息或者关于其他功能的问题,请提供具体的需求,我会尽力帮助您。
Spring AI 模块化 RAG 增强
Cloud Native
// 创建聊天客户端实例
// 设置系统提示信息,定义AI助手作为专业的室内设计顾问角色
ChatClient chatClient = builder
.defaultSystem("你是一位专业的室内设计顾问,精通各种装修风格、材料选择和空间布局。请基于提供的参考资料,为用户提供专业、详细且实用的建议。在回答时,请注意:\n" +
"1. 准确理解用户的具体需求\n" +
"2. 结合参考资料中的实际案例\n" +
"3. 提供专业的设计理念和原理解释\n" +
"4. 考虑实用性、美观性和成本效益\n" +
"5. 如有需要,可以提供替代方案")
.build();
// 构建查询扩展器
// 用于生成多个相关的查询变体,以获得更全面的搜索结果
MultiQueryExpander queryExpander = MultiQueryExpander.builder()
.chatClientBuilder(builder)
.includeOriginal(false) // 不包含原始查询
.numberOfQueries(3) // 生成3个查询变体
.build();
// 执行查询扩展
// 将原始问题"请提供几种推荐的装修风格?"扩展成多个相关查询
List<Query> queries = queryExpander.expand(
new Query("请提供几种推荐的装修风格?"));
在这个过程中,系统会自动生成多个相关的查询变体,例如当用户查询“请提供几种推荐的装修风格?”时,系统会生成多个不同角度的查询。这种方式不仅提高了检索的全面性,还能捕获用户潜在的查询意图。
扩展后的查询内容:1. 哪些装修风格最受欢迎?请推荐一些。2. 能否推荐一些流行的家居装修风格?3. 想了解不同的装修风格,有哪些是值得推荐的?
多查询扩展的主要优势:
// 创建一个模拟用户学习AI的查询场景
Query query = new Query("我正在学习人工智能,什么是大语言模型?");
// 创建查询重写转换器
QueryTransformer queryTransformer = RewriteQueryTransformer.builder()
.chatClientBuilder(builder)
.build();
// 执行查询重写
Query transformedQuery = queryTransformer.transform(query);
// 输出重写后的查询
System.out.println(transformedQuery.text());
重写后的查询可能会变成:
什么是大语言模型?
查询重写的主要优势:查询明确化:将模糊的问题转换为具体的查询点
// 创建一个英文查询
Query query = new Query("What is LLM?");
// 创建查询翻译转换器,设置目标语言为中文
QueryTransformer queryTransformer = TranslationQueryTransformer.builder()
.chatClientBuilder(builder)
.targetLanguage("chinese")// 设置目标语言为中文
.build();
// 执行查询翻译
Query transformedQuery = queryTransformer.transform(query);
// 输出翻译后的查询
System.out.println(transformedQuery.text());
翻译后的查询结果:
什么是大语言模型?
查询翻译的主要优势:
// 构建带有历史上下文的查询// 这个例子模拟了一个房地产咨询场景,用户先问小区位置,再问房价Query query = Query.builder().text("那这个小区的二手房均价是多少?")// 当前用户的提问.history(new UserMessage("深圳市南山区的碧海湾小区在哪里?"),// 历史对话中用户的问题new AssistantMessage("碧海湾小区位于深圳市南山区后海中心区,临近后海地铁站。"))// AI的回答.build();
在这个例子中:
如果不考虑上下文,系统将无法理解“这个小区”具体指的是哪个小区。为了解决这个问题,我们使用 CompressionQueryTransformer 来处理上下文信息:
// 创建查询转换器
// QueryTransformer用于将带有上下文的查询转换为完整的独立查询
QueryTransformer queryTransformer = CompressionQueryTransformer.builder()
.chatClientBuilder(builder)
.build();
// 执行查询转换
// 将模糊的代词引用("这个小区")转换为明确的实体名称("碧海湾小区")
Query transformedQuery = queryTransformer.transform(query);
转换后的查询会变成更明确的形式,比如:“深圳市南山区碧海湾小区的二手房均价是多少?”。这种转换有以下优势:
提高准确性:使系统能够更精确地检索相关信息
输出结果:深圳市南山区碧海湾小区的二手房均价是多少?
以下是一个使用示例:
// 从多个查询或数据源获取的文档集合
Map<Query, List<List<Document>>> documentsForQuery = ...
// 创建文档合并器实例
DocumentJoiner documentJoiner = new ConcatenationDocumentJoiner();
// 执行文档合并
List<Document> documents = documentJoiner.join(documentsForQuery);
这种合并机制在以下场景特别有用:
增量更新:在现有文档集合中添加新的检索结果
// 1. 初始化向量存储
SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel)
.build();
// 2. 添加文档到向量存储
List<Document> documents = List.of(
new Document("产品说明书:产品名称:智能机器人\n" +
"产品描述:智能机器人是一个智能设备,能够自动完成各种任务。\n" +
"功能:\n" +
"1. 自动导航:机器人能够自动导航到指定位置。\n" +
"2. 自动抓取:机器人能够自动抓取物品。\n" +
"3. 自动放置:机器人能够自动放置物品。\n"));
vectorStore.add(documents);
// 3. 创建检索增强顾问
Advisor advisor = RetrievalAugmentationAdvisor.builder()
.documentRetriever(VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.build())
.build();
// 4. 在聊天客户端中使用顾问
String response = chatClient.prompt()
.user("机器人有哪些功能?")
.advisors(advisor)// 添加检索增强顾问
.call()
.content();
这个基础实现提供了以下功能:
Advisor advisor = RetrievalAugmentationAdvisor.builder()// 配置查询增强器.queryAugmenter(ContextualQueryAugmenter.builder().allowEmptyContext(true)// 允许空上下文查询.maxTokens(300) // 限制查询长度.temperature(0.7) // 控制查询扩展的创造性.build())// 配置文档检索器.documentRetriever(VectorStoreDocumentRetriever.builder().vectorStore(vectorStore).similarityThreshold(0.5) // 相似度阈值.topK(3)// 返回文档数量.minScore(0.1)// 最小匹配分数.maxDistance(0.8) // 最大向量距离.build()) .build();
主要配置选项包括:
// 生成室内设计案例文档
List<Document> documents = new ArrayList<>();
// 现代简约风格客厅案例
documents.add(new Document(
"案例编号:LR-2023-001\n" +
"项目概述:180平米大平层现代简约风格客厅改造\n" +
"设计要点:\n" +
"1. 采用5.2米挑高的落地窗,最大化自然采光\n" +
"2. 主色调:云雾白(哑光,NCS S0500-N)配合莫兰迪灰\n" +
"3. 家具选择:意大利B&B品牌真皮沙发,北欧白橡木茶几\n" +
"4. 照明设计:嵌入式筒灯搭配意大利Flos吊灯\n" +
"5. 软装配饰:进口黑胡桃木电视墙,几何图案地毯\n" +
"空间效果:通透大气,适合商务接待和家庭日常起居",
Map.of(
"type", "interior",// 文档类型
"year", "2023",// 年份
"month", "06", // 月份
"location", "indoor", // 位置类型
"style", "modern",// 装修风格
"room", "living_room" // 房间类型
)));
每个文档包含两个主要部分:
// 1. 初始化向量存储
SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel)
.build();
// 2. 配置AI助手角色
ChatClient chatClient = builder
.defaultSystem("你是一位专业的室内设计顾问,精通各种装修风格、材料选择和空间布局。请基于提供的参考资料,为用户提供专业、详细且实用的建议。在回答时,请注意:\n" +
"1. 准确理解用户的具体需求\n" +
"2. 结合参考资料中的实际案例\n" +
"3. 提供专业的设计理念和原理解释\n" +
"4. 考虑实用性、美观性和成本效益\n" +
"5. 如有需要,可以提供替代方案")
.build();
// 3. 构建复杂的文档过滤条件
var b = new FilterExpressionBuilder();
var filterExpression = b.and(
b.and(
b.eq("year", "2023"), // 筛选2023年的案例
b.eq("location", "indoor")), // 仅选择室内案例
b.and(
b.eq("type", "interior"),// 类型为室内设计
b.in("room", "living_room", "study", "kitchen")// 指定房间类型
));
// 4. 配置文档检索器
DocumentRetriever retriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.similarityThreshold(0.5)// 设置相似度阈值
.topK(3) // 返回前3个最相关的文档
.filterExpression(filterExpression.build())
.build();
// 5. 创建上下文感知的查询增强器
Advisor advisor = RetrievalAugmentationAdvisor.builder()
.queryAugmenter(ContextualQueryAugmenter.builder()
.allowEmptyContext(true)
.build())
.documentRetriever(retriever)
.build();
// 6. 执行查询并获取响应
String userQuestion = "根据已经提供的资料,请描述所有相关的场景风格,输出案例编号,尽可能详细地描述其内容。";
String response = chatClient.prompt()
.user(userQuestion)
.advisors(advisor)
.call()
.content();
这个实现包含以下关键特性:
通过这种多层次的文档选择机制,系统能够:
// 1. 构建检索增强顾问
Advisor advisor = RetrievalAugmentationAdvisor.builder()
.queryAugmenter(ContextualQueryAugmenter.builder()
.allowEmptyContext(true)// 允许空上下文,避免NPE
.build())
.documentRetriever(retriever)
.build();
// 2. 执行查询并处理可能的异常
return chatClient.prompt()
.user(query)
.advisors(advisor)
.call()
.getContent();
运行效果对比:
AI回答:I'm sorry, but it appears that the specific details or references you mentioned for your interior design query are not included in my current knowledge base. To provide you with the best possible advice, I would need more information about your project, such as the style you're aiming for, the size of the space, your budget, and any specific elements you want to include or avoid. If you can provide more details, I would be more than happy to offer tailored advice on interior design, space planning, material selection, and more.
修改后的结果展示:
AI回答:很抱歉,您没有提供具体的参考资料或案例编号。为了能够提供详细的场景风格描述,我需要您提供具体的案例编号或者相关资料。一旦您提供了这些信息,我将能够准确地描述相关的场景风格,包括以下内容:
1. 设计风格和主题
2. 空间布局和功能规划
3. 材料选择和色彩搭配
4. 灯光设计和氛围营造
5. 家具配置和软装搭配
通过使用 ContextualQueryAugmenter,我们实现了以下改进:
结构化 RAG 最佳实践
Cloud Native
Map.of("type", "interior",// 文档类型"year", "2023",// 年份"style", "modern"// 风格类型)
SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel).build();
选择合适的向量存储方案
DocumentRetriever retriever = VectorStoreDocumentRetriever.builder().vectorStore(vectorStore).similarityThreshold(0.5)// 相似度阈值.topK(3) // 返回文档数量.build();
设置合理的相似度阈值
ContextualQueryAugmenter.builder().allowEmptyContext(true).build()
处理文档未找到情况
ChatClient chatClient = builder.defaultSystem("你是一位专业的顾问,请注意:\n" +"1. 准确理解用户需求\n" +"2. 结合参考资料\n" +"3. 提供专业解释\n" +"4. 考虑实用性\n" +"5. 提供替代方案").build();
设定清晰的角色定位
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-10-27
2024-09-04
2024-07-18
2024-05-05
2024-06-20
2024-06-13
2024-07-09
2024-07-09
2024-05-19
2024-07-07
2025-04-01
2025-04-01
2025-03-30
2025-03-28
2025-03-27
2025-03-27
2025-03-25
2025-03-19