暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

使用HetuVDB和DeepSeek构建高质量RAG

蓬莱智数 2025-02-13
21


合存向量数据库 (HetuVDB) 是由蓬莱智数团队自主研发的一款支持向量检索、向量存取的高性能向量数据库,专为提升人工智能模型数据训练效率而设计。它能够高效地存储和检索向量数据,支持相似性搜索和复杂查询,为企业在AI大模型训练加速、图像识别、自然语言处理、推荐系统、问答系统等场景赋能。
DeepSeek使开发人员能够利用高性能语言模型构建和扩展人工智能应用。它提供高效的推理、灵活的应用程序接口(API)和先进的专家混合物(MoE)架构,适用于强大的推理和检索任务。
在本教程中,我们将向您展示如何使用HetuVDB 和 DeepSeek 构建检索增强生成(RAG)管道。

1 准备工作

1.1 依赖和环境

  1. ubuntu22.04

  2. JDK8

  3. maven 3.6.3

  4. ollama

1.2 数据准备

我们使用HetuKV术语和常见问题作为 RAG 中的私有知识,这对于简单的 RAG 管道来说是一个很好的数据源。
数据源如下如所示:
对于该文档,我们只需简单地使用 "#"来分隔文件中的内容,这样就能大致分隔出 markdown 文件中每个主要部分的内容。
            // 1获取HetuKV私有知识文档
    String filePath = "/VDB/HetuKV_RAG_Test.md";
    StringBuilder content = new StringBuilder();
    try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
    String line;
    while ((line = reader.readLine()) != null) {
    content.append(line).append("\n");
    }
    } catch (IOException e) {
    e.printStackTrace();
    return;
    }


    // 获取整个文件内容并按#分割
    String text = content.toString();
    String[] segments = text.split("#");

    1.3 准备 LLM 和 Embeddings 模型

    参考DeepSeek官方API文档,HetuVDB已经封装好了对应的API接口类。你可以登录其官方网站获取DeepSeek API Key。

              // 实例化工具类
      DeepSeekClient apiClient = new DeepSeekClient(
      "Your DeepSeek API Key");


      // 构建请求体
      List<String> messages = new ArrayList<>();
      messages.add("你好");


      JSONObject requestBody = apiClient.chat("deepseek-chat", messages,false);


      // 发送请求并获取响应
      try {
      String response = apiClient.sendRequest(requestBody);
      // 解析响应
      DeepSeekResponse parsedResponse = apiClient.parseResponse(response);
      System.out.println("Parsed Response: " + parsedResponse.content);
      } catch (IOException e) {
      e.printStackTrace();
              }



      使用ollama部署一个nomic-embed-text
      嵌入模型生成文本嵌入。HetuVDB提供了对ollama接口API的封装类。
               // 输入参数示例
        String ip = "your IP";
        int port = 11434;
        String model = "nomic-embed-text";
        String input = "这是一个测试句子";


        try {
        EmbedResponse embedResponse = new OllamaEmbeddingUtils().embed(ip, port, model, input);
        System.out.println(embedResponse);


        float[] floats = embedResponse.getEmbeddings().get(0);
        System.out.println(Arrays.toString(floats));
        } catch (IOException e) {
        e.printStackTrace();
        }

        生成一个测试嵌入,并打印其维度和嵌入向量(只截取了一部分)。

          768
          [0.008433551, 0.060538568, -0.15399724, 0.018865598, 0.0091602765, 0.016291345, 0.05111419, -0.018628616, -0.038147576, -0.033492282, -0.098604344, 0.0067264084, 0.023402072, -0.0049559334, -0.007166973, -0.07849371, -0.031152047, -0.038216475, -0.068336934, 0.095721535, 0.0046433937, 0.031166036, -0.032429334, -0.00805019, 0.1079416, -0.0011236112, 0.038522687, 0.061783068, -0.012630016, -0.0059412066, 0.020410854, -0.018237721, -0.014239253, 0.0013444505, 0.019328492, -0.014417462, 0.04224368, 0.011871055, 0.054475706, 0.031483572, -0.013881395, 0.030970223, 0.033263147, -0.015748387, 0.05927272, -0.01088858, 0.042979363, 0.040499695,



          2 将数据载入HetuVDB

          2.1 创建Hetu对象、创建并定义向量索引。

           
                    int flags = Hetu.HE_O_CREATE | Hetu.HE_O_TRUNCATE | Hetu.HE_O_VOLUME_CREATE | Hetu.HE_O_VOLUME_TRUNCATE;
            Hetu he = new Hetu("he://.//dev/nvme2n1", "testRAG", flags);
            if (!he.checkVectorIndexExists()) {
            he.IndexCreate(1000000, 32, 128, 20, 768, SimilarityMetric.EUCLIDEAN, false);
            }

            Hetu对象的参数依次为:

            • DEVICE_URL -String类型,分为两部分:服务器地址+实际路径。

            • DB_NAME  -String类型,表示数据库的名字。

            • 标志位 -用户创建数据库时的操作。

            IndexCreate函数的参数依次为:

            • initialItemSize -int类型,用于确定索引的初始大小,会自动扩容。

            • m  -int类型,节点在层次结构的每个层级所能拥有的最大边数或连接数。

            • efConstruction -int类型,索引构建过程中考虑的候选节点数量。

            • ef -int类型,搜索过程中评估的邻居数量。

            • dimensions -int类型,向量的维度,即每个向量的特征数量。

            • distanceName -String类型,距离度量的名称,用于计算向量之间的相似性或距离,常见的有l2
              (欧几里得距离)、cosine
              (余弦相似度)、ip
              (内积)等。

            • useGpu -布尔类型,是否使用GPU加速。如果设置为true
              ,则在构建和搜索过程中利用GPU资源以提高性能。

            2.2 插入数据

            遍历文本segment,创建 Embeddings,然后将数据插入 HetuVDB。

                      String ip = "your ip";
              int port = 11434;
              String model = "nomic-embed-text";
              for (String segment : segments) {
              if (!segment.isEmpty()) {
              OllamaEmbeddingUtils.EmbedResponse embedResponse = new OllamaEmbeddingUtils().embed(ip, port, model, segment);
              float[] vector = embedResponse.getEmbeddings().get(0);
              he.Vadd(segment, vector);
              }
              }

              3 构建RAG

              3.1 为查询检索数据

              让我们指定一个关于 HetuVDB 的常见问题。

                 String question = "我想要了解HetuKV卷的概念以及在使用过程中出现的-102代码code错误";

                在HetuVDB中搜索该问题,并检索语义前4个匹配项。

                          float[] questionVector = new OllamaEmbeddingUtils().embed(ip, port, model, question).getEmbeddings().get(0);
                  Map<String, float[]> nearestSegment = he.VfindNearest(questionVector, 4);
                  for (Map.Entry<String, float[]> entry : nearestSegment.entrySet()) {
                  System.out.println(entry.getKey());
                  }

                  让我们看看查询的搜索结果:

                     **HetuKV 库**
                    HetuKV有专门的嵌入式库,提供了一系列的函数及其相关的类型、结构和常量。




                    **HetuKV 键/值项(item)**
                    一个item包含一个键、一个值,以及键和值数据块的关联长度。HetuKV假定键和值是数据的二进制块。




                    **HetuKV 事务 (Transaction)**
                    一个隔离的操作序列,可以被丢弃或原子性地与数据存储合并。




                    **HetuKV 卷 (Volume)**
                    一个或多个块设备或固定大小文件捆绑成单个卷(由HetuKV管理),为数据存储提供单个大型存储结构。不允许创建包含一个或多个HetuKV目录的卷。

                    3.2 使用DeepSeek获取RAG响应

                    将检索到的文档直接加入到用户问题的集合里面。

                    使用 DeepSeek 提供的deepseek-chat 模型,根据提示生成响应。

                             DeepSeekClient apiClient = new DeepSeekClient(
                      "Your DeepSeek API Key");
                      List<String> messages = new ArrayList<>();
                      messages.add(question);
                      for (Map.Entry<String, float[]> entry : nearestSegment.entrySet()) {
                      messages.add(entry.getKey());
                      }
                      JSONObject requestBody = apiClient.chat("deepseek-chat", messages, false);
                      try {
                      String response = apiClient.sendRequest(requestBody);


                      DeepSeekClient.DeepSeekResponse parsedResponse = apiClient.parseResponse(response);
                      System.out.println("Parsed Response: " + parsedResponse.getContent());
                      } catch (IOException e) {
                      e.printStackTrace();
                      }

                      查看DeepSeek的返回信息:

                        ### HetuKV 卷的概念


                        在 HetuKV 中,**卷(Volume)** 是一个或多个块设备或固定大小文件的集合,这些设备或文件被捆绑在一起,形成一个单一的存储结构。HetuKV 使用卷来管理数据存储,卷为数据存储提供了一个大型的、连续的存储空间。卷的设计允许 HetuKV 在多个设备或文件之间进行数据分布和管理,从而提高存储的灵活性和性能。


                        #### 关键点:
                        1. **卷的组成**:卷可以由一个或多个块设备(如硬盘分区)或固定大小的文件组成。这些设备或文件被 HetuKV 视为一个整体,形成一个逻辑上的存储单元。
                        2. **存储结构**:卷为 HetuKV 提供了一个大型的存储结构,HetuKV 可以在卷中存储键/值对、事务日志等数据。
                        3. **卷的管理**:HetuKV 负责管理卷中的数据分布、读写操作以及数据的持久化。卷的管理是透明的,用户只需要通过 HetuKV 提供的 API 来操作数据,而不需要直接管理底层的存储设备或文件。
                        4. **卷的限制**:HetuKV 不允许创建包含一个或多个 HetuKV 目录的卷。这意味着卷是独立的存储单元,不能嵌套或包含其他 HetuKV 管理的目录结构。


                        ### 错误代码 -102


                        在使用 HetuKV 的过程中,可能会遇到错误代码 **-102**。这个错误代码通常表示某种与卷相关的操作失败。具体的错误原因可能包括以下几种情况:


                        1. **卷初始化失败**:在创建或打开卷时,HetuKV 可能无法正确初始化卷。这可能是由于底层存储设备或文件不可用、权限不足、文件损坏等原因导致的。
                        2. **卷空间不足**:如果卷的存储空间不足,HetuKV 可能无法继续写入数据,从而导致操作失败并返回错误代码 -102。
                        3. **卷损坏**:如果卷的底层存储设备或文件损坏,HetuKV 可能无法正确读取或写入数据,从而导致操作失败。
                        4. **卷配置错误**:如果卷的配置参数不正确(例如,卷的大小设置错误),HetuKV 可能无法正确管理卷,从而导致操作失败。


                        ### 解决方法


                        当遇到错误代码 -102 时,可以尝试以下步骤来排查和解决问题:


                        1. **检查卷的存储设备或文件**:确保卷所使用的块设备或文件是可用的,并且具有正确的权限。如果使用的是文件作为卷,确保文件没有被损坏或删除。
                        2. **检查卷的空间**:使用 HetuKV 提供的工具或 API 检查卷的剩余空间。如果空间不足,可以考虑扩展卷的大小或清理不必要的数据。
                        3. **检查卷的配置**:确保卷的配置参数(如大小、路径等)是正确的。如果配置错误,可以尝试重新创建卷或调整配置。
                        4. **查看日志**:HetuKV 通常会记录详细的日志信息。查看日志可以帮助你更准确地定位问题的根源。
                        5. **联系支持**:如果问题无法通过上述步骤解决,可以联系 HetuKV 的支持团队,提供详细的错误信息和日志,以便进一步排查问题。


                        ### 总结


                        HetuKV 的卷是一个重要的存储管理单元,它通过将多个块设备或文件捆绑在一起,提供了一个大型的存储结构。错误代码 -102 通常与卷的操作失败有关,可能由卷初始化失败、空间不足、卷损坏或配置错误等原因引起。通过检查存储设备、卷空间、配置参数以及查看日志,可以帮助你解决这个问题。


                        至此,我们成功地利用 HetuVDB 和 DeepSeek 搭建了一条 RAG 管道!

                        3.3 DeepSeek未构建RAG对比

                        我们还是使用同一个问题:"我想要了解HetuKV卷的概念以及在使用过程中出现的-102代码code错误"

                        DeepSeek的回答如下:

                          HetuKV 卷的概念
                          HetuKV 是一种分布式键值存储系统,通常用于大规模数据存储和高并发访问场景。卷(Volume) 在 HetuKV 中指的是存储数据的逻辑单元,类似于传统文件系统中的分区或卷。每个卷可以独立管理,具有自己的存储空间和数据分布策略。


                          主要特点:


                          分布式存储:数据分布在多个节点上,支持高可用性和扩展性。


                          高并发访问:支持大量并发读写操作。


                          数据分片:通过分片(Sharding)将数据分散到不同节点,提升性能。


                          副本机制:通过数据副本提高容错能力。


                          -102 代码错误
                          在使用 HetuKV 时,-102 错误代码 通常表示某种类型的操作失败,具体含义需参考 HetuKV 的官方文档或源码。常见原因包括:


                          网络问题:节点间通信失败。


                          资源不足:如内存或磁盘空间不足。


                          配置错误:配置文件参数设置不当。


                          数据不一致:副本间数据不一致导致操作失败。


                          权限问题:操作权限不足。


                          解决方法
                          检查网络:确保节点间网络通畅。


                          查看日志:通过日志定位具体错误。


                          资源监控:检查系统资源使用情况,必要时释放资源。


                          验证配置:确保配置文件正确。


                          数据一致性检查:使用工具检查并修复数据不一致问题。


                          权限检查:确认操作权限是否足够。


                          总结
                          HetuKV 的卷是逻辑存储单元,支持分布式存储和高并发访问。-102 错误通常表示操作失败,可能由网络、资源、配置、数据一致性或权限问题引起。通过检查网络、日志、资源、配置、数据一致性和权限,可以逐步解决问题。

                          总结:通过以上对比可以明显看到,使用HetuVDB与DeepSeek构建RAG生成内容的质量得到显著提升,而且更加准确、全面和可信。这种技术组合为构建高质量的私有知识库提供了强大的支持。

                          在后续的文章我们将陆续展示如何在蓬莱硬件环境中部署DeepSeek R1。




                          网址:https://www.penglaitech.cn/

                          邮箱:business@penglaitech.cn

                          地址:广东省深圳市宝安区宝兴路6号海纳百川总部大厦A座1501

                          电话:0755-26406747 (工作日 9:00-18:30)


                          最后修改时间:2025-02-21 18:03:58
                          文章转载自蓬莱智数,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                          评论