RAG:融合检索与生成的文本精准生成技术
检索增强生成(RAG)是一种技术,它通过结合检索模型和生成模型来提高文本生成的准确性。具体来说,RAG首先利用检索模型从私有或专有的数据源中搜索相关信息,然后将这些信息提供给生成模型,如大型语言模型(LLM),以生成更加准确、基于上下文的回复。这种方法有助于减少大模型在生成过程中可能出现的“幻觉”现象,并且能够使模型的回答更贴合企业的特定数据,从而提高了回答的精确度与相关性。这样,在使用大模型时,即使面对企业特有的知识或数据,也能获得更为精准的答案。
Spring AI:提升Java AI开发效率与灵活性的解决方案
我们使用了Spring AI来做这个检索增强。
之所以选择Spring AI,是因为在过去用Java编写AI应用时面临的一个主要困境是没有非常标准的Java封装。
现在,Spring项目推出了一套可以兼容市面上主要各类生成任务的接口——Spring AI,极大地解决了这一问题。
Spring AI通过标准化不同AI提供者的接口实现,使得开发者能够一次编写代码,仅通过修改配置即可轻松切换不同的AI实现。
同时,它直接兼容Flux流输出,简化了与基于流的机器人模型的集成。通过良好的抽象设计,Spring AI显著减少了程序员在对接不同类型接口时查阅文档和迁移实现的工作量,为基于Java的AI开发带来了极大的便利性和效率提升。因此,采用Spring AI不仅提高了开发效率,还增强了项目的可维护性与灵活性。
Spring生态AI框架:Spring AI Alibaba,赋能Java开发者高效对接多AI服务商
Spring AI Alibaba 是基于 Spring 生态系统设计的用于AI工程的应用框架,特别适合 Java 和 Spring Boot 开发者。它通过提供一套统一的抽象接口,标准化了不同AI服务提供商(如阿里云、OpenAI等)的接入方式,使得开发者能够轻松切换AI服务而无需大幅改动代码。此外,Spring AI Alibaba 集成了阿里云百炼系列的多个模型,支持对话、文本生成图像等功能,并提供了诸如Prompt Template等实用工具来简化开发过程。其核心优势在于极大提高了AI应用开发的效率与灵活性,同时保持了与现有Java Spring Boot项目的良好兼容性。
增强检索:打造PDF财务报表查询后端代码
为了通过检索增强的方式读取一个阿里巴巴的财务报表PDF并提供对外服务,我们需要按照以下步骤进行:
1. 确保前置条件
- JDK版本:确保你的JDK版本在17及以上。
 
- Spring Boot版本:确认使用的Spring Boot版本为3.3.x或更高。
 
- API Key申请:访问阿里云百炼页面,登录账号后开通“百炼大模型推理”服务,并创建一个新的API Key。将此Key配置到环境变量中:
 
export AI_DASHSCOPE_API_KEY=YOUR_VALID_API_KEY 
并且,在application.properties文件里添加:
spring.ai.dashscope.api-key: ${AI_DASHSCOPE_API_KEY} 
2. 添加仓库与依赖
由于spring-ai-alibaba-starter尚未发布到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>
 
3. 编写RAG服务相关代码
首先定义RagService类用于处理索引构建和查询逻辑。这包括向量存储、文档检索器以及如何使用这些组件来处理来自客户端的请求。
public class RagService {
    private final ChatClient chatClient;
    private final VectorStore vectorStore;
    private final DashScopeApi dashscopeApi = new DashScopeApi("您的API密钥");
    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 = "/path/to/your/financial_report.pdf";
        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;
    }
} 
4. 创建Controller以暴露REST API
最后,我们需要创建一个控制器类来接收HTTP请求,并调用之前定义的服务方法。
@RestController
@RequestMapping("/ai")
public class RagController {
    private final RagService ragService;
    public RagController(RagService ragService) {
        this.ragService = ragService;
    }
    @GetMapping("/steamChat")
    public Flux<String> generate(@RequestParam(value = "input", defaultValue = "2024年6月止,云智能集团的营收是多少?") String input, HttpServletResponse httpResponse) {
        StreamResponseSpec chatResponse = ragService.queryWithDocumentRetrieval(input);
        httpResponse.setCharacterEncoding("UTF-8");
        return chatResponse.content();
    }
    @GetMapping("/buildIndex")
    public String buildIndex() {
        return ragService.buildIndex();
    }
} 
通过上述步骤,我们实现了基于Spring Cloud Alibaba框架下的检索增强功能,能够从指定的PDF文件中提取信息并通过HTTP接口返回给用户。需要注意的是,在实际部署前,请确保已经完成了所有必要的环境配置,特别是关于API密钥的安全管理和正确配置。
构建React流式聊天应用:从零开始的实现攻略
 基于提供的知识,我们可以分析出构建一个支持流式输出的前端项目需要遵循一定的步骤。这里的项目将使用React框架来创建,并与后端服务进行交互以处理用户输入并显示响应。后端接口返回的是flux<String>数据类型,这意味着客户端能够以渐进的方式接收和展示信息,而非等待全部数据加载完毕后再一次性展示。
分析
从给出的知识来看,我们已经有了关于如何设置基础React环境、以及如何处理流式数据请求的具体示例。这些例子非常适合用来作为本问题解决方案的基础。接下来将详细介绍如何根据要求实现这样一个前端应用。
实现步骤
首先,确保你已经安装了Node.js和npm(或yarn),然后按照以下步骤操作:
- 初始化一个新的React应用
 
npx create-react-app rag-chat-frontend
cd rag-chat-frontend
npm install 
- 修改
public/index.html文件(如果需要自定义HTML头部等信息):不过在这个案例中,我们可以直接使用默认生成的内容。 
- 更新
src/index.js以引入应用程序入口点: 
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: 
import React from 'react';
import ChatComponent from './components/ChatComponent';
function App() {
  return (
    <div className="App">
      <ChatComponent />
    </div>
  );
}
export default App; 
- 创建聊天组件
src/components/ChatComponent.js来处理用户输入及流式数据接收: 
import React, { useState } from 'react';
function ChatComponent() {
  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/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: 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);
    }
  };
  return (
    <div>
      <input
        type="text"
        value={input}
        onChange={handleInputChange}
        placeholder="Enter your message"
      />
      <button onClick={handleSendMessage}>Send</button>
      <div>
        <h3>Messages:</h3>
        <pre>{messages}</pre>
      </div>
    </div>
  );
}
export default ChatComponent; 
- 启动你的React应用:
 
npm start 
这将打开浏览器并自动导航到 http://localhost:3000/ ,你可以在这里测试你的聊天界面。
小结
通过上述步骤,我们建立了一个基本的聊天应用程序界面,它可以通过发送GET请求至指定URL (http://localhost:8080/ai/steamChat) 来与后端通信。该请求会携带用户的输入文本参数。当后端开始流式地返回数据时,前端应用程序会逐步解析这些数据片段,并即时更新显示给用户。这种方式非常适合于实时性较强的场景,如在线聊天或实时问答系统。











