Java 读取word , 作为私有知识库做RAG答疑

发布于:2024-10-18 ⋅ 阅读:(27) ⋅ 点赞:(0)

检索与生成的技术(RAG),可以提升文本精准度与企业数据相关性

检索增强生成 (RAG) 是一种技术,它结合了检索模型和生成模型,旨在通过私有或专有的数据源来辅助文本生成。在使用大模型时,一个常见问题是模型可能会产生“幻觉”,即生成的信息可能与事实不符;此外,由于模型通常不包含企业的特定数据,其回答往往缺乏针对性和精确性。RAG 通过引入企业知识库中的信息作为上下文,使得生成的回答更加准确、相关且基于最新的企业数据,从而有效缓解了这些问题。

Spring AI  Alibaba :类似Spring cloud alibaba的Spring AI最佳实践

Spring AI Alibaba 是一个专为 Java 和 Spring Boot 生态系统设计的应用框架,旨在将 Spring 的设计理念应用到人工智能领域。

Spring ai 由 Spring 官方团队维护,确保了高质量和稳定性。

其核心优势在于提供了统一的接口来标准化不同AI提供商(如OpenAI、阿里云等)的服务接入方式,使开发者能够通过简单的配置切换不同的AI实现。

此外,Spring AI Alibaba 结合了阿里云的最佳实践,特别是与百炼平台的深度集成,支持多种生成式AI能力,包括对话、文生图、文生语音等功能,极大地简化了在Spring Boot项目中引入和使用AI功能的过程。

构建RAG后端服务:从PDF到智能对话

检索增强的后端代码编写

根据提供的我了解的信息,为了通过检索增强(RAG)的方式读取一个名为专家答疑文档.pdf的PDF文件、构建向量索引,并对外提供服务,我们需要遵循一定的步骤来完成环境准备与编码实现。首先确保你的开发环境满足以下要求:

  1. JDK版本:需在JDK 17或以上。
  1. Spring Boot版本:需要3.3.x或更高版本。
  1. 阿里云API Key获取:按照我了解的信息中的指引,在阿里云申请并记录下通义千问的API Key。

环境配置

配置仓库

由于Spring AI Alibaba当前使用的某些组件尚未正式发布到Maven中央仓库,你需要添加Spring官方维护的仓库到你的项目中:

<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>
添加依赖

接下来,添加必要的依赖项以支持RAG功能以及与阿里云大模型的交互:

<parent>
    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>3.3.4</version>

</parent>

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

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

        <version>1.0.0-M2</version>

    </dependency>

    <!-- 其他所需依赖 -->
</dependencies>

API Key配置

将从阿里云获得的API Key设置为环境变量或者直接在application.properties里指定:

spring.ai.dashscope.api-key=这里填写你的API Key

RAG服务实现

创建一个名为RagService的服务类,用于处理RAG相关的逻辑,包括初始化向量存储和文档检索器等:

public class RagService {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;
    private final DashScopeApi dashscopeApi = new DashScopeApi("这里填写你的API Key");
    DocumentRetriever retriever;

    public RagService(ChatClient chatClient, EmbeddingModel embeddingModel) {
        this.chatClient = chatClient;
        vectorStore = new DashScopeCloudStore(dashscopeApi, new DashScopeStoreOptions("专家答疑库"));
        retriever = new DashScopeDocumentRetriever(dashscopeApi, 
            DashScopeDocumentRetrieverOptions.builder().withIndexName("专家答疑库").build());
    }

    public String buildIndex() {
        String filePath = "专家答疑文档.doc";
        DocumentReader reader = new DashScopeDocumentCloudReader(filePath, dashscopeApi, null);
        List<Document> documentList = reader.get();
        vectorStore.add(documentList);
        return "SUCCESS";
    }

    public StreamResponseSpec queryWithDocumentRetrieval(String message) {
        StreamResponseSpec response = chatClient.prompt()
            .user(message)
            .advisors(new DocumentRetrievalAdvisor(retriever, DEFAULT_USER_TEXT_ADVISE))
            .stream();
        return response;
    }
}

其中,DEFAULT_USER_TEXT_ADVISE应定义为包含{documents}占位符的字符串模板,以便后续替换实际文档内容。

控制器实现

最后,创建一个控制器类,公开/buildIndex/steamChat两个接口,分别对应索引构建和服务请求:

@RestController
@RequestMapping("/ai")
public class RagController {

    private final RagService ragService;

    public RagController(RagService ragService) {
        this.ragService = ragService;
    }

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

    @GetMapping("/steamChat")
    public Flux<String> steamChat(@RequestParam(value = "input", required = true) String input,
                                  HttpServletResponse httpResponse) {
        httpResponse.setCharacterEncoding("UTF-8");
        return ragService.queryWithDocumentRetrieval(input).content();
    }
}

通过上述步骤,你已经成功搭建了一个基于Spring AI Alibaba框架的应用程序,它能够利用RAG技术从给定的PDF文件中提取信息,并通过指定的URL对外提供智能对话服务。记得首次启动应用时先访问http://localhost:8080/ai/buildIndex来构建索引,之后就可以正常调用聊天接口了。

流式数据处理:React构建实时聊天应用教程

检索增强的前端代码编写

分析问题的原因

要基于React构建一个简单的支持流输出(如flux<String>)的项目,首先需要确保后端接口能够以流的形式返回数据。本案例中给定的后端接口为http://localhost:8080/ai/steamChat?input=…,它应该已经配置好能够处理请求并返回流式响应。

在React前端部分,关键在于如何正确地读取这个流,并将获取到的信息实时展示给用户。根据我了解的信息中的内容,我们可以了解到如何创建基础的React应用框架以及如何通过Fetch API与后端交互来实现这一目标。特别地,对于流式响应,我们需要使用ReadableStream相关API来逐块接收数据,并即时更新UI。

构建并运行项目的步骤

由于我了解的信息提供了构建基本React项目的方法和所需代码,这里直接给出基于上述要求的具体实现步骤:

  1. 初始化新的React应用:
npx create-react-app frontend
cd frontend
npm install
  1. 编辑公共HTML文件 (public/index.html) 和入口JavaScript文件 (src/index.js),这部分保持默认或按需修改即可。
  1. 开发主要组件 (src/App.js 和 src/components/ChatComponent.js) 用于显示聊天界面及处理逻辑:
    • App.js 主要是容器作用。
    • ChatComponent.js 实现了输入消息、发送消息、清除消息的功能,特别是从服务器异步获取流数据的部分。
  1. 在 ChatComponent.js 中实现对流的支持,参考如下代码片段:
// ... 其他import语句
function ChatComponent() {
  const [input, setInput] = useState('');
  const [messages, setMessages] = useState('');

  const handleSendMessage = async () => {
    try {
      const response = await fetch(`http://localhost:8080/ai/steamChat?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: isDone } = await reader.read();
        done = isDone;
        const chunk = decoder.decode(value, { stream: true });
        setMessages(prev => prev + chunk);
      }
    } catch (error) {
      console.error('Failed to fetch', error);
    }
  };

  // ...其他函数定义

  return (
    <div>
      {/* 输入框、按钮等元素 */}
      <pre>{messages}</pre>  {/* 显示消息区域 */}
    </div>

  );
}

export default ChatComponent;
  1. 启动应用程序:
npm start
对步骤的解释
  • 步骤1至2是标准的新React项目搭建流程。
  • 步骤3和4专注于聊天功能的实际实现。特别是,在处理来自服务器的流时,我们使用了fetch发起HTTP请求,然后利用ReadableStreamgetReader()方法读取流中的数据块,并通过TextDecoder将其转换成可读文本格式。每当收到新的数据块时,就更新状态变量messages,从而触发组件重新渲染,让用户看到最新的消息。
  • 最后一步启动本地开发服务器,使你可以在浏览器中查看你的工作成果。