【Spring AI】Java实现类似langchain的向量数据库RAG_原理与具体实践

news2024/11/23 9:11:47

介绍一下RAG:

检索增强生成(RAG)是一种技术,它结合了检索模型和生成模型来提高文本生成的质量。通过从企业私有或专有的数据源中检索相关信息,并将这些信息与大型语言模型相结合,RAG能够显著减少模型产生幻觉的情况,同时使回答更加精确、相关。这解决了大模型在缺乏特定上下文或最新数据时提供的答案不够准确的问题。

向量数据库在Rag中的具体作用说明:

在检索增强生成(RAG)过程中,向量数据库起着核心作用。首先,原始文档或数据通过Embedding模型转化为高维向量,随后这些向量被存储于向量数据库中。当有新的查询请求时,系统将该查询也转换为相应的向量,并在向量数据库中查找最相似的向量以获取相关上下文信息。使用向量数据库的原因在于其能高效地处理大规模高维向量的存储与检索问题,支持快速精确匹配,这对于提高RAG系统的响应速度及准确性至关重要。此外,向量数据库还能够很好地支持非结构化数据的管理,使得从大量文本或其他类型的内容中提取有价值的信息成为可能。

Spring AI alibaba 是什么:

Spring AI Alibaba 是基于 Spring Boot 的应用框架,专为 Java 开发者设计,用于集成和利用阿里云的通义大模型等AI服务。其核心优势在于提供了标准化接口,使得开发者能够以一致的方式访问不同AI供应商(如OpenAI、Azure、阿里云)的服务,只需更改配置即可切换不同的AI实现。这极大简化了开发流程,减少了因适配不同API而带来的工作量。此外,Spring AI Alibaba 还支持多种生成式任务,如对话、文生图、语音合成,并且与 Flux 流输出兼容,方便构建复杂的AI应用。通过Spring Boot的自动装配机制,可以轻松地在现有项目中添加强大的AI能力。

详细实践:

检索增强的后端代码编写

为了实现基于检索增强生成 (RAG) 的功能,以读取阿里巴巴财务报表PDF并提供相应的服务,我们首先需要理解如何配置Spring AI Alibaba来支持RAG能力。根据提供的我了解的信息,这涉及到一系列的准备工作和具体的代码实现步骤。

1. 环境准备

  • JDK版本:确保你的开发环境使用的是JDK 17或更高版本。
  • Spring Boot版本:项目需基于Spring Boot 3.3.x及以上版本构建。
  • 阿里云账号与API Key获取
    • 登录阿里云百炼平台,开通“百炼大模型推理”服务。
    • 服务开通后,在用户中心创建一个新的API Key,并妥善保存用于后续配置。

2. 配置阿里云通义千问 API Key

在你的应用程序环境中设置AI_DASHSCOPE_API_KEY环境变量:

export AI_DASHSCOPE_API_KEY=您的实际API密钥

并在application.properties文件中添加如下配置项来引用这个环境变量:

spring.ai.dashscope.api-key: ${AI_DASHSCOPE_API_KEY}

3. 添加必要的依赖库

由于Spring AI Alibaba目前处于早期阶段,其Maven仓库尚未正式发布所有相关组件,因此我们需要指定额外的仓库地址以便能够下载所需的库。请将以下仓库配置加入到你的pom.xml文件内:

<repositories>
    <repository>
        <id>sonatype-snapshots</id>

        <url>https://oss.sonatype.org/content/repositories/snapshots</url>

        <snapshots>
            <enabled>true</enabled>

        </snapshots>

    </repository>

    <repository>
        <id>spring-milestones</id>

        <name>Spring Milestones</name>

        <url>https://repo.spring.io/milestone</url>

        <snapshots>
            <enabled>false</enabled>

        </snapshots>

    </repository>

    <repository>
        <id>spring-snapshots</id>

        <name>Spring Snapshots</name>

        <url>https://repo.spring.io/snapshot</url>

        <releases>
            <enabled>false</enabled>

        </releases>

    </repository>

</repositories>

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>

        <artifactId>spring-ai-alibaba-starter</artifactId>

        <version>1.0.0-M2</version>

    </dependency>

    <!-- 其他必要的依赖 -->
</dependencies>


4. RAG服务实现

接下来是核心的服务逻辑实现,包括向量存储、文档检索等关键组件的定义。我们将创建一个名为RagService的服务类,它负责处理从PDF提取内容、建立索引以及最终基于查询条件进行响应的过程。

创建RagService类
public class RagService {
    // ...省略了构造器和其他成员变量声明...
    
    public String buildIndex() {
        String filePath = "阿里巴巴财报.pdf";
        DocumentReader reader = new DashScopeDocumentCloudReader(filePath, dashscopeApi, null);
        List<Document> documentList = reader.get();
        vectorStore.add(documentList);
        return "索引构建完成";
    }
    
    public StreamResponseSpec queryWithDocumentRetrieval(String message) {
        StreamResponseSpec response = chatClient.prompt().user(message)
                .advisors(new DocumentRetrievalAdvisor(retriever, DEFAULT_USER_TEXT_ADVISE)).stream();
        return response;
    }
}
提供REST接口

最后一步是在Controller层暴露两个端点,一个是用来初始化索引的/buildIndex,另一个则是实际对外提供查询服务的/ragChat

@RestController
@RequestMapping("/ai")
public class RagController {
    @Autowired
    private RagService ragService;

    @GetMapping("/buildIndex")
    public String buildIndex() {
        return ragService.buildIndex();
    }

    @GetMapping("/ragChat")
    public Flux<String> generate(@RequestParam("input") String input, HttpServletResponse httpResponse) {
        StreamResponseSpec chatResponse = ragService.queryWithDocumentRetrieval(input);
        httpResponse.setCharacterEncoding("UTF-8");
        return chatResponse.content();
    }
}

以上就是通过检索增强技术实现读取PDF文件并提供问答服务的整体流程。此方案利用了Spring AI Alibaba提供的RAG框架,并结合阿里云的大规模语言模型能力,实现了高效的知识检索与自然语言处理。在实际部署前,请确保所有依赖均已被正确添加至项目,并且已按照要求设置了正确的环境变量及属性配置。

检索增强的前端代码编写

检索增强的前端代码编写

根据我了解的信息中提供的关于基于React构建支持流输出的前端项目的内容,我们可以按照类似的步骤来构建一个能够与后端http://localhost:8080/ai/ragChat?input=…接口交互,并处理返回的flux<String>数据流的前端应用。下面将具体阐述如何搭建这样的项目。

构建项目并填写代码

首先,我们需要创建一个新的React应用,并确保安装所有必需的依赖项。这可以通过运行以下命令实现:

npx create-react-app ragchat-frontend
cd ragchat-frontend
npm install

接下来,我们将依次设置或修改几个关键文件以满足项目需求。

public/index.html

无需特别改动此文件,保持默认内容即可。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>RAG Chat App</title>

</head>

<body>
  <div id="root"></div>

</body>

</html>
src/index.js

同样地,这个文件基本可以保持原样,仅用于渲染应用入口组件App

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
src/App.js

这里是主应用程序组件,我们将其简单指向我们的聊天组件RAGChatComponent

import React from 'react';
import RAGChatComponent from './components/RAGChatComponent';

function App() {
  return (
    <div className="App">
      <RAGChatComponent />
    </div>

  );
}

export default App;
src/components/RAGChatComponent.js

这是核心功能所在的地方。我们需要在此处添加逻辑来发送请求到指定的URL,并且处理从服务器接收到的数据流。

import React, { useState } from 'react';

function RAGChatComponent() {
  const [input, setInput] = useState('');
  const [messages, setMessages] = useState('');

  const handleInputChange = (event) => {
    setInput(event.target.value);
  };

  const handleSendMessage = async () => {
    try {
      const response = await fetch(`http://localhost:8080/ai/ragChat?input=${input}`);
      if (!response.ok) throw new Error("Network response was not ok");
      
      const reader = response.body.getReader();
      const decoder = new TextDecoder('utf-8');
      let done = false;

      while (!done) {
        const { value, done: readerDone } = await reader.read();
        done = readerDone;
        const chunk = decoder.decode(value, { stream: true });
        setMessages((prevMessages) => prevMessages + chunk);
      }

      // 请求完成后添加换行符
      setMessages((prevMessages) => prevMessages + '\n\n=============================\n\n');
    } catch (error) {
      console.error('Failed to fetch', error);
    }
  };

  const handleClearMessages = () => {
    setMessages('');
  };

  return (
    <div>
      <input
        type="text"
        value={input}
        onChange={handleInputChange}
        placeholder="Enter your message"
      />
      <button onClick={handleSendMessage}>Send</button>

      <button onClick={handleClearMessages}>Clear</button>

      <div>
        <h3>Messages:</h3>

        <pre>{messages}</pre>

      </div>

    </div>

  );
}

export default RAGChatComponent;

通过以上步骤,你已经成功配置了一个简单的React应用,该应用能够向给定的后端服务发送请求,并实时显示返回的文本流。请确保你的后端服务正在本地运行于http://localhost:8080,并且允许来自前端的跨域请求(CORS)。如果需要进一步定制样式或其他功能,可以根据实际需求调整上述代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2209512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何建立高质量的谷歌外链?

想做谷歌seo&#xff0c;外链是绝对绕不开的一个门槛&#xff0c;外链对网站的流量和SEO表现有很大帮助&#xff0c;正常途径想建立高质量外链需要策略和技巧&#xff0c;内容平台和博客是获取外链的好地方。在这些平台上发布文章并嵌入外链&#xff0c;不仅可以展示你的专业能…

删除链表的倒数第 N 个结点 | LeetCode-19 | 双指针 | 递归 | 栈 | 四种方法

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 这道题还可以用递归法&#xff0c;你想到了吗&#xff1f;毛毛张介绍四种方法 LeetCode链接&#xff1a;19. 删除链表的倒数第 N 个结点 1.题目描述 给你一个链表&a…

《Linux从小白到高手》综合应用篇:深入理解Linux进程调优

本篇深入介绍Linux进程调优. 1. Linux系统进程类型&#xff1a; Linux的进程可能有成千上万个&#xff1a; ‌新建状态‌&#xff1a;进程刚刚被创建&#xff0c;但尚未运行。 ‌就绪状态‌&#xff1a;进程已经准备好运行&#xff0c;等待CPU分配。 ‌运行状态‌&#xff1…

解读 AI 获客关键要素,开启营销新未来

​在当今数字化浪潮席卷的时代&#xff0c;企业获客的难度与日俱增&#xff0c;传统方式逐渐力不从心。而 AI 获客宛如一颗璀璨的新星&#xff0c;为企业带来全新的机遇。 AI 获客凭借人工智能强大的数据分析能力&#xff0c;能从海量数据中精准挖掘出目标客户。其优势显著&…

C语言题目练习2

前面我们知道了单链表的结构及其一些数据操作&#xff0c;今天我们来看看有关于单链表的题目~ 移除链表元素 移除链表元素&#xff1a; https://leetcode.cn/problems/remove-linked-list-elements/description/ 这个题目要求我们删除链表中是指定数据的结点&#xff0c;最终返…

虹科应用 | 15分钟部署CAN记录仪,节省95%成本的秘诀是什么?

欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 导读 虹科CSS的CANedge数据记录仪专为汽车和工业领域的工程师设计&#xff0c;旨在通过监控现场资产来支持研发、诊断和预测性维护。为了将这些数据转化为直观的可视化信息&#xff0c;工程师们通常依赖于Grafana仪表板…

MuMu模拟器12 KitsumeMask安装教程

这里是引用"> 在MuMu模拟器上安装KitsumeMask的时候遇到安装失败的情况。 一、下载APK安装包 如果你没有apk安装包可以通过下面的百度网盘进行下载 通过网盘分享的文件:KitsumeMask 链接: https://pan.baidu.com/s/1yeq3I6BsUD7J6uI-bnk-Vw?pwd=7n3v 提取码: 7n3v 二…

【LeetCode】动态规划—123. 买卖股票的最佳时机 III(附完整Python/C++代码)

动态规划—123. 买卖股票的最佳时机 III 题目描述前言基本思路1. 问题定义2. 理解问题和递推关系状态定义&#xff1a;状态转移公式&#xff1a;初始条件&#xff1a; 3. 解决方法动态规划方法伪代码&#xff1a; 4. 进一步优化5. 小总结 Python代码Python代码解释 C代码C代码解…

『网络游戏』代码操作数据库增删改查【22】

创建一个新的Vistual Studio案例工程 命名为SqlTest 导入MySql.dll (官网安装即可) 导入到新建工程创建Libs文件夹放里即可 浏览找到位置添加引用即可 1.增加数据 编写脚本&#xff1a;Program 运行工程 - 添加/插入完成 打开navicat查看数据库表信息 在增加数据中可以获取主…

如何安装Tensorflow GPU版本

可以安装对应版本的cudatoolkit cudnn 我这次需要安装tensorflow-gpu1.15.0 经查看 对应的cuda 10 所以&#xff1a; conda install cudatoolkit10.0.130它对应的是cudnn 7.4 但是没安装成功 然后我直接输入 conda install cudnn 它根据cuda10 找到了对应的cudnn 7.6.…

13.JVM内存模型深度剖析

一、JDK体系结构 JDK代表Java Development Kit(Java开发工具包)&#xff0c;是用于开发和编译Java应用程序的软件包。JDK是由Oracle提供的Java平台的官方实现&#xff0c;包含了开发和运行Java程序所需的工具、库和JRE(Java Runtime Environment)。 二、JAVA语言跨平台特性 Ja…

控制模型执行 | AnyLogic帮助

控制模型执行 | AnyLogic帮助 当运行AnyLogic模型时&#xff0c;您可以使用控制面板来控制模型的执行&#xff0c;控制面板显示在AnyLogic模型窗口的底部。 控制面板包含用于控制启动模型执行的按钮&#xff1a; 按钮命令描述运行[仅当模型当前未运行时可见]从当前状态运行模…

无人机之交互系统篇

一、系统构成 无人机交互系统通常由多个子系统组成&#xff0c;包括但不限于&#xff1a; 多模式人机交互装置&#xff1a;这是人机交互系统的基础层&#xff0c;通常包括计算机、局域网、传感器等设备&#xff0c;用于实现操作员与无人机之间的数据交互和指令传递。例如&…

MATLAB实现AM调制解调

1.基本概念 1.1 AM调制原理 调幅就是使载波的振幅随调制信号的变化规律而变化。基带信号m(t)与直流分量A0相加&#xff0c;然后和高频载波相乘实现AM信号的调制&#xff0c;如图1所示。 1.2 AM解调原理 AM信号经过信道传输&#xff0c;引入噪声后&#xff0c;再和载波相乘&…

jenkins 插件Publish Over SSH (sskey) 同步文件夹

一、安装插件 Publish Over SSH SSH Pipeline Steps 二、添加sshkey 将ssh免密登录的私钥新建到 二、准备目录 源&#xff1a;images 目标&#xff1a;/root/images2 流水线脚本 pipeline {agent anystages {stage(Dest) {steps {script{def remote [:]remote.name tstr…

【中短文--深度学习笔记】Batchsize的选择、批量归一化、loss是否已经收敛(更新中-ing)

一、如何选择合适的Batchsize&#xff1f; 如果你没有任何参考&#xff0c;那么选择2的n次方&#xff08;即64、128、256、512、1024等&#xff09;可以会更加直接和易于管理。而对于上限来说&#xff0c;batchsize大小最好<数据集样本数*0.1。 why? 梯度下降算法 在更新模…

盈利路上的关键一步:掌握五大交易离场技巧

近期&#xff0c;股市节后短暂的牛市成为了众人瞩目的焦点。有人收获颇丰&#xff0c;也有人因此亏了不少&#xff0c;时机没抓对&#xff0c;倒是被割了一波韭菜。市场起伏已是常态&#xff0c;但依旧会有很多人中招。围观近况&#xff0c;忽然深刻体会到&#xff0c;适时离场…

二值形态学基本运算的几何解释

Rafael Gonzalez和Richard Woods所著的《数字图像处理》&#xff0c;从集合角度定义膨胀和腐蚀&#xff0c;不易理解。本书从空域滤波角度对二值图像形态学中膨胀和腐蚀的定义和过程进行描述&#xff0c;并给出了动画演示过程。使用结构元素对图像的形态学处理与滤波模板的空域…

HIVE beeline连接报错Operation category READ is not supported in state standby

问题&#xff1a;hive连接报错Operation category READ is not supported in state standby 这个可能是因为hive配置的hdfs连接地址指定的是具体的namenode地址&#xff0c;但是hadoop集群配置的是HA,所以会发生主备切换&#xff0c;那么我们hive元数据配置就需要使用NameNode…

JavaEE-进程与线程

1.进程 1.1什么是进程 每个应⽤程序运⾏于现代操作系统之上时&#xff0c;操作系统会提供⼀种抽象&#xff0c;好像系统上只有这个程序在运 ⾏&#xff0c;所有的硬件资源都被这个程序在使⽤。这种假象是通过抽象了⼀个进程的概念来完成的&#xff0c;进程可 以说是计算机科学…