dot Redis 8 来了——而且它是开源的

了解更多

使用 Redis 和 Spring AI 构建 RAG 应用

引言

向量数据库经常充当 AI 应用的内存。对于那些由大型语言模型(LLM)驱动的应用来说尤其如此。向量数据库允许您执行语义搜索,这为提示 LLM 提供了相关的上下文。 

直到最近,使用 Spring 和 Redis 构建 AI 应用的选择还不多。现在,Redis 作为高性能向量数据库越来越受欢迎。而 Spring 社区推出了一个名为 Spring AI 的新项目,旨在简化 AI 驱动应用(包括那些利用向量数据库的应用)的开发。 

让我们看看如何构建一个使用 Redis 作为其向量数据库的 Spring AI 应用,重点是实现检索增强生成(RAG)工作流程。

检索增强生成

检索增强生成(RAG)是一种用于将数据与 AI 模型集成起来的技术。在 RAG 工作流程中,第一步是将数据加载到向量数据库(例如 Redis)中。当接收到用户查询时,向量数据库检索一组与查询相似的文档。然后,这些文档作为用户问题的上下文,并与用户查询结合使用,通常通过 AI 模型生成响应。

在此示例中,我们将使用一个包含啤酒信息的数据集,其中包括每种啤酒的名称、酒精度(ABV)、国际苦度单位(IBU)以及描述等属性。该数据集将加载到 Redis 中以演示 RAG 工作流程。

代码和依赖项

您可以在 Github 上找到 Spring AI 和 Redis 演示的所有代码

本项目使用了 Web 应用常用的 Spring Boot starter 依赖项,以及 Azure OpenAI 和 Spring AI Redis

数据加载

我们将用于应用的数据由提供啤酒信息的 JSON 文档组成。每个文档具有以下结构

{
  "id": "00gkb9",
  "name": "Smoked Porter Ale",
  "description": "The Porter Pounder Smoked Porter is a dark rich flavored ale that is made with 5 malts that include smoked and chocolate roasted malts. It has coffee and mocha notes that create a long finish that ends clean with the use of just a bit of dry hopping",
  "abv": 8,
  "ibu": 36
}

要将此啤酒数据集加载到 Redis 中,我们将使用 RagDataLoader 类。此类包含一个在应用启动时执行的 run 方法。在该方法中,我们使用 JsonReader 解析数据集,然后使用自动注入的 VectorStore 将文档插入到 Redis 中。

// Create a JSON reader with fields relevant to our use case
JsonReader loader = new JsonReader(file, "name", "abv", "ibu", "description");
// Use the autowired VectorStore to insert the documents into Redis
vectorStore.add(loader.get());

此时,我们拥有大约 22,000 种啤酒及其对应嵌入的数据集。

RAG 服务

RagService 类实现了 RAG 工作流程。当收到用户提示时,会调用 retrieve 方法,该方法执行以下步骤

  • 计算用户提示的向量
  • 查询 Redis 数据库以检索最相关的文档
  • 使用检索到的文档和用户提示构建提示
  • 使用提示调用 ChatClient 生成响应
public Generation retrieve(String message) {
    SearchRequest request = SearchRequest.query(message).withTopK(topK);
    // Query Redis for the top K documents most relevant to the input message
    List<Document> docs = store.similaritySearch(request);
    Message systemMessage = getSystemMessage(docs);
    UserMessage userMessage = new UserMessage(message);
    // Assemble the complete prompt using a template
    Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
    // Call the autowired chat client with the prompt
    ChatResponse response = client.call(prompt);
    return response.getResult();
}

控制器

现在我们已经实现了 RAG 服务,我们可以将其封装在一个 HTTP 端点中。

RagController 类将服务暴露为 POST 端点

@PostMapping("/chat/{chatId}")
@ResponseBody
public Message chatMessage(@PathVariable("chatId") String chatId, @RequestBody Prompt prompt) {
    // Extract the user prompt from the body and pass it to the autowired RagService
    Generation generation = ragService.retrieve(prompt.getPrompt());
    // Reply with the generated message
    return Message.of(generation.getOutput().getContent());
}

用户界面

对于用户界面,我们创建了一个简单的 React 前端,允许用户询问有关啤酒的问题。前端通过向 /chat/{chatId} 端点发送 HTTP 请求并显示响应来与 Spring 后端交互。

spring ai redis screenshot

就这样——只需几个类,我们就使用 Spring AI 和 Redis 实现了一个 RAG 应用。

下一步,我们鼓励您查看 Github 上的示例代码。如果您有任何问题或疑问,请随时提交工单。将 Redis 的速度和易用性与 Spring AI 提供的便捷抽象相结合,使得 Java 开发人员更容易使用 Spring 构建响应式 AI 应用。我们迫不及待地想看看您会构建出什么。

相关资源

  • 本文介绍的代码可在 GitHub 上获取。
  • Spring AI Redis 的文档可在此获取。
  • 有关 Spring AI 的更多信息,请访问项目主页
  • Redis 向量文档中了解更多关于 Redis 向量搜索 API 的信息。