当前位置: 首页 > web >正文

Java大模型开发入门 (10/15):连接外部世界(下) - 端到端构建完整的RAG问答系统

前言

在过去的几篇文章中,我们已经完成了RAG系统所有的数据准备工作:

  1. 我们加载了私有文档并将其分割成了文本片段。
  2. 我们使用OpenAI的嵌入模型将这些片段向量化
  3. 我们把这些向量存储在了内存向量数据库中。
  4. 我们实现了语义搜索,能够根据用户问题找出最相关的文档片段。

我们已经成功地“开卷”并“找到了答案所在的页面”。但是,我们的search方法目前返回的,还只是原始的、未经加工的文本片段列表。这并不是一个用户友好的最终答案。

今天,我们的任务就是完成这最后一步:将检索到的这些“参考资料”与用户的原始问题一起,交给一个强大的语言模型(我们将使用最新的gpt-4o-mini),让它基于这些上下文,用自然、流畅的语言“总结”出最终答案。

第一部分:RAG的最后一公里 - 增强与生成

让我们回顾一下RAG的完整流程,并聚焦于最后两个步骤:

  • 检索 (Retrieve):根据用户问题,从向量数据库中找出最相关的文档片段。(我们已在上一篇实现)

  • 增强 (Augment):这是关键的一步。我们需要将检索到的片段(上下文)和用户的原始问题,组合成一个新的、信息更丰富的提示词。这个提示词的结构通常如下:

    请根据以下提供的上下文信息来回答问题。
    如果根据上下文无法回答,请说“根据我所掌握的资料,我无法回答这个问题”。[上下文信息]
    ---
    片段1:[检索到的第一个文本片段内容]
    ---
    片段2:[检索到的第二个文本片段内容]
    ---
    ...[问题]
    [用户的原始问题]
    
  • 生成 (Generate):将这个“增强版”的提示词发送给大语言模型,获取最终的、经过整合的答案。

手动完成这个“增强”步骤需要编写不少逻辑。幸运的是,LangChain4j为我们提供了极其优雅的高级抽象来自动化这个过程。

第二部分:LangChain4j的RAG核心组件
  1. ContentRetriever:

    • 职责:内容检索器。它的工作就是接收一个查询,然后从某个地方(比如我们的向量数据库)返回相关的内容。
    • 具体实现EmbeddingStoreContentRetriever。这是一个连接了EmbeddingStore(数据在哪)和EmbeddingModel(如何搜索)的检索器。
  2. RetrievalAugmentor:

    • 职责:检索增强器。这是整个RAG流程的“大脑”。它是一个中间件,位于我们的AI服务和最终的语言模型之间。
    • 工作流程:当你向一个配置了RetrievalAugmentor的AI服务提问时,它会:
      1. 使用内部的ContentRetriever去检索相关内容。
      2. 自动将检索到的内容按照预设的模板,与你的问题组合起来,形成我们上面看到的“增强版”提示词。
      3. 将这个新提示词传递给语言模型。
第三部分:实战 - 构建端到端的RAG服务
  1. 更新application.properties以使用gpt-4o-mini
    gpt-4o-mini 是OpenAI最新推出的高性价比、高性能模型,非常适合RAG场景。

    # application.properties
    # ... 其他配置保持不变 ...# 将聊天模型更新为 gpt-4o-mini
    langchain4j.open-ai.chat-model.model-name=gpt-4o-mini
    
  2. LangChain4jConfig中组装RAG组件
    我们将在这里创建ContentRetrieverRetrievalAugmentor以及最终的RAG AI服务的Bean。

 package com.example.aidemoapp.config;import com.example.aidemoapp.service.KnowledgeBaseAssistant;import dev.langchain4j.data.segment.TextSegment;import dev.langchain4j.model.chat.ChatLanguageModel;import dev.langchain4j.model.embedding.EmbeddingModel;import dev.langchain4j.rag.DefaultRetrievalAugmentor;import dev.langchain4j.rag.RetrievalAugmentor;import dev.langchain4j.rag.content.retriever.ContentRetriever;import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;import dev.langchain4j.service.AiServices;import dev.langchain4j.store.embedding.EmbeddingStore;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class LangChain4jConfig {// ... 保留 chatLanguageModel, embeddingModel, embeddingStore 的Bean定义 ...// 步骤1: 创建ContentRetriever Bean@Beanpublic ContentRetriever contentRetriever(EmbeddingStore<TextSegment> embeddingStore, EmbeddingModel embeddingModel) {// 这个检索器知道如何从向量存储中根据语义相似度检索内容return EmbeddingStoreContentRetriever.builder().embeddingStore(embeddingStore).embeddingModel(embeddingModel).maxResults(3) // 每次检索最多返回3个最相关的片段.build();}// 步骤2: 创建RetrievalAugmentor Bean@Beanpublic RetrievalAugmentor retrievalAugmentor(ContentRetriever contentRetriever) {// 这是默认的检索增强器,它会使用提供的内容检索器return DefaultRetrievalAugmentor.builder().contentRetriever(contentRetriever).build();}// 步骤3: 创建最终的、具备RAG能力的AI服务Bean@Beanpublic KnowledgeBaseAssistant knowledgeBaseAssistant(ChatModel chatLanguageModel, RetrievalAugmentor retrievalAugmentor) {return AiServices.builder(KnowledgeBaseAssistant.class).chatModel(chatLanguageModel).retrievalAugmentor(retrievalAugmentor).build();}	}
  1. 定义KnowledgeBaseAssistant接口
    service包下创建一个新的接口,代表我们的知识库问答服务。

    package com.example.aidemoapp.service;public interface KnowledgeBaseAssistant {String chat(String userMessage);
    }
    
  2. 创建新的Controller来调用RAG服务
    controller包下创建KnowledgeBaseController.java

    package com.example.aidemoapp.controller;import com.example.aidemoapp.service.KnowledgeBaseAssistant;
    import lombok.RequiredArgsConstructor;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;@RestController
    @RequestMapping("/api/kb")
    @RequiredArgsConstructor
    public class KnowledgeBaseController {private final KnowledgeBaseAssistant knowledgeBaseAssistant;@GetMapping("/chat")public String chat(@RequestParam("query") String query) {return knowledgeBaseAssistant.chat(query);}
    }
    
第四步:运行并见证奇迹
  1. 确保你的OPENAI_API_KEY环境变量已设置。
  2. 启动Spring Boot应用。DocumentService 中的@PostConstruct方法会自动将文档加载并嵌入到内存向量库。
  3. 现在,向新的API端点发送请求:
    http://localhost:8080/api/kb/chat?query=What is the X-Wing AI Assistant?
    或者
    http://localhost:8080/api/kb/chat?query=What are the setup requirements?

发生了什么?
当你发送请求时,KnowledgeBaseAssistant的代理实例被调用。它内部的RetrievalAugmentor启动,使用ContentRetriever从向量库中找到了关于“X-Wing”或“setup requirements”的文本片段。然后,它构建了一个包含这些上下文的、增强版的提示词,并将其发送给gpt-4o-mini。最后,gpt-4o-mini基于这些精确的资料,生成了一个流畅、准确的回答,并返回给你。

如果你的文档中没有相关信息,它会告诉你它不知道,而不是胡乱猜测!

总结

恭喜你!我们已经成功地构建了一个完整的、端到端的RAG(检索增强生成)系统。这个系统能够:

  • 摄入私有文档。
  • 进行语义理解和检索。
  • 基于检索到的上下文生成准确的回答。

这是目前企业应用大模型最主流、最核心的技术之一。掌握了RAG,你就掌握了将通用大模型转变为领域专家的钥匙。

我们的AI应用现在既有“记忆”,又有“知识”。但它还只是一个被动的问答工具。如何让它更主动,能够像一个真正的助理一样,根据我们的指令去调用外部工具(比如查询天气、计算器、订票API)呢?


源码获取

本文中所有实战代码均已同步更新至Gitee仓库。建议您git pull拉取最新代码,对照本文进行学习。

  • Gitee仓库地址: https://gitee.com/chaocloud/springboot-langchain4j-demo.git

下一篇预告:
Java大模型开发入门 (11/15):让AI自主行动 - 初探LangChain4j中的智能体(Agents)》—— 我们将进入一个更激动人心的新领域:AI智能体(Agents)。我们将学习如何赋予AI使用工具的能力,让它从一个“问答机器人”进化成一个能执行任务的“智能助理”。

http://www.xdnf.cn/news/14274.html

相关文章:

  • 拓展:###单向循环链表###
  • 【MFC】编辑框、下拉框、列表控件
  • JavaScript基础-常用的鼠标事件
  • Bambu Studio 中的“回抽“与“装填回抽“的区别
  • Spark RDD 及性能调优
  • 案例:塔能科技智启某市光域,勾勒城市照明宏图
  • IEEE 802.16e 标准下的LDPC 码
  • 【知识图谱构建系列3】zero-shot的理念介绍
  • Vite 预构建机制深度解析(Vite缺点之一)
  • 深度理解 CLIP:连接图像与语言的桥梁
  • 从零开始的Conda环境配置
  • Java大模型开发入门 (11/15):让AI自主行动 - 初探LangChain4j中的智能体(Agents)
  • 【文献阅读】5%>100%: 打破视觉识别任务的完全微调的性能束缚
  • 20 - PPM模块
  • BKA-CNN-LSTM、CNN-LSTM、LSTM三模型光伏功率预测对比!(Matlab完整源码和数据)
  • 在docker中部署dify
  • 鸿蒙NEXT-HMRouter,在使用router后无法跳转问题解决
  • 人口贩卖暑期威胁消解:算法协同提升安全预警
  • SLAM文献之-LOAM: Lidar Odometry and Mapping in Real-time
  • 【一】零基础--分层强化学习概览
  • C# WinForms 实现打印监听组件
  • SAP学习笔记 - 开发33 - 前端Fiori开发 Accessibility(可访问性)
  • 10.OpenCV—联合QT界面显示
  • 【计算机网络】非阻塞IO——epoll 编程与ET模式详解——(easy)高并发网络服务器设计
  • 【python深度学习】Day53对抗生成网络
  • 安装laravel11和laravel12的一些报错问题解决
  • QDEC vs FlexPWM:RT1176编码器接口深度对比与工程实践指南
  • mysql查看表结构语句
  • 铸铁试验平台的重要性及应用前景
  • MVVM、MVP、MVC