springboot、deepseek4j、bge-m3和milvus

news2025/3/1 9:47:45

1、pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lee</groupId>
    <artifactId>deepseektest</artifactId>
    <version>0.0.1</version>
    <name>deepseektest</name>
    <description>deepseektest</description>
    <properties>
        <java.version>23</java.version>
        <spring-ai.version>1.0.0-M5</spring-ai.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>io.github.pig-mesh.ai</groupId>
            <artifactId>deepseek-spring-boot-starter</artifactId>
            <version>1.4.5</version>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp-sse</artifactId>
            <version>4.12.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson</groupId>
            <artifactId>jackson-bom</artifactId>
            <version>2.12.4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83_noneautotype</version>
        </dependency>

        <!-- 链接 milvus SDK-->
        <dependency>
            <groupId>io.milvus</groupId>
            <artifactId>milvus-sdk-java</artifactId>
            <version>2.5.3</version>
        </dependency>

    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2、配置文件

# 推理模型链接信息
deepseek.api-key=sk-bedafbqsexpyunwgfawojwcachflvafxxksdgszvdsahwtlu
deepseek.model=deepseek-r1:32b
deepseek.base-url=http://172.16.50.25:11434/v1
# 向量模型链接信息
embedding.api-key=sk-bedafbqsexpyunwgfawojwcachflvafxxksdgszvdsahwtlu
embedding.base-url=http://172.16.50.25:11434/v1
embedding.model=bge-m3:latest

3、向量数据库 milvus代码

package com.lee.deepseektest.config;

import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MilvusConfig {


    @Bean
    public MilvusClientV2 MilvusClientV2() {

        ConnectConfig config = ConnectConfig.builder()
                .uri("http://xxx.xxx.xxx.xxx:19530")
                .build();
        MilvusClientV2 client = new MilvusClientV2(config);
        return client;
    }
}

4、向量数据库插入数据

package com.lee.deepseektest.controller;

import ch.qos.logback.core.util.FileUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.github.pigmesh.ai.deepseek.core.EmbeddingClient;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class MilvusController {


    @Autowired
    MilvusClientV2 milvusClientV2;

    @Autowired
    EmbeddingClient embeddingClient;

    @GetMapping("/milvus")
    public String insert() {
        // 这里以 2025最新的我司保密条例演示,可以换成你自己的
//        String law = FileUtil.readString("/Users/lengleng/Downloads/law.txt", Charset.defaultCharset());
//        String[] lawSplits = StrUtil.split(law, 400);
        String[] lawSplits = new String[]{"高速公路", "航运"};

        List<JsonObject> data = new ArrayList<>();
        for (String lawSplit : lawSplits) {
            List<Float> floatList = embeddingClient.embed(lawSplit);

            JsonObject jsonObject = new JsonObject();

            // 将 List<Float> 转换为 JsonArray
            JsonArray jsonArray = new JsonArray();
            for (Float value : floatList) {
                jsonArray.add(value);
            }
            jsonObject.add("vector", jsonArray);
            jsonObject.addProperty("text", lawSplit);

            data.add(jsonObject);
        }

        InsertReq insertReq = InsertReq.builder()
                .collectionName("deepseek4jtest")
                .data(data)
                .build();

        InsertResp insertResp =  milvusClientV2.insert(insertReq);
        System.out.println(insertResp.getInsertCnt());
        return "ok";
    }


}

5、deepseek模型使用

package com.lee.deepseektest.controller;

import io.github.pigmesh.ai.deepseek.core.DeepSeekClient;
import io.github.pigmesh.ai.deepseek.core.Json;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionChoice;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionRequest;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.HashMap;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
public class DeepSeekController {

    @Autowired
    private DeepSeekClient deepSeekClient;

    public final static HashMap<String, String> cache = new HashMap<>();

    Function<List<ChatCompletionChoice>, String> choicesProcess = list -> list.stream().map(e -> e.delta().content())
            .collect(Collectors.joining());

    Function<String, String> elt = s -> s.replaceAll("<think>[\\s\\S]*?</think>", "").replaceAll("\n", "");


    /**
     *  流式返回示例
     * @param prompt
     * @return
     */
    @GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatCompletionResponse> chat(String prompt) {
        return deepSeekClient.chatFluxCompletion(prompt);
    }

    @GetMapping(value = "/sync/chat")
    public ChatCompletionResponse syncChat(String prompt) {
        ChatCompletionRequest request = ChatCompletionRequest.builder()
                // 根据渠道模型名称动态修改这个参数
//                .model(deepSeekProperties.getModel())
                .addUserMessage(prompt).build();

        return deepSeekClient.chatCompletion(request).execute();
    }



    @GetMapping(value = "/chat/advanced", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatCompletionResponse> chatAdvanced(String prompt, String cacheCode) {
        ChatCompletionRequest request = ChatCompletionRequest.builder()
//                .model(deepSeekProperties.getModel())
                .addUserMessage(prompt).addAssistantMessage(elt.apply(cache.getOrDefault(cacheCode, "")))
                .addSystemMessage("你是一个专业的助手").maxCompletionTokens(5000).build();
        // 只保留上一次回答内容
        cache.remove(cacheCode);
        return deepSeekClient.chatFluxCompletion(request).doOnNext(i -> {
            String content = choicesProcess.apply(i.choices());
            // 其他ELT流程
            cache.merge(cacheCode, content, String::concat);
        }).doOnError(e -> System.out.println(e.getMessage()));
    }

}

6、deepseek4j官方文档

deepseek4j简介 - 零基础入门Java AI

7、测试推理过程

deepseek 调试

8、向量数据库中的collections在使用时必须要先加载

判断和加载向量数据库milvus中的collection

package com.lee.deepseektest.service;

import io.milvus.param.R;
import io.milvus.param.collection.LoadCollectionParam;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.GetLoadStateReq;
import io.milvus.v2.service.collection.request.HasCollectionReq;
import io.milvus.v2.service.collection.request.LoadCollectionReq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MilvusService {

    @Autowired
    MilvusClientV2 milvusClientV2;

    public boolean loadCollection(String collectionName) {

        //先判断是否有 collection
        HasCollectionReq hasCollectionReq = HasCollectionReq.builder()
                .collectionName(collectionName).build();
        boolean hasCollection = milvusClientV2.hasCollection(hasCollectionReq);

        //在判断是否已加载 collection
        GetLoadStateReq getLoadStateReq = GetLoadStateReq.builder()
                .collectionName(collectionName).build();
        boolean hasLoad = milvusClientV2.getLoadState(getLoadStateReq);

        // 加载集合到内存
        LoadCollectionReq loadCollectionReq = LoadCollectionReq.builder()
                .collectionName(collectionName).build();
        milvusClientV2.loadCollection(loadCollectionReq);
        hasCollection = milvusClientV2.hasCollection(hasCollectionReq);
        return hasCollection;

    }
}

9、RAG接口

package com.lee.deepseektest.controller;

import io.github.pigmesh.ai.deepseek.core.DeepSeekClient;
import io.github.pigmesh.ai.deepseek.core.EmbeddingClient;
import io.github.pigmesh.ai.deepseek.core.Json;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionChoice;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionRequest;
import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionResponse;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.SearchResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
public class DeepSeekController {

    @Autowired
    private DeepSeekClient deepSeekClient;


    @Autowired
    MilvusClientV2 milvusClientV2;

    @Autowired
    EmbeddingClient embeddingClient;

    public final static HashMap<String, String> cache = new HashMap<>();

    Function<List<ChatCompletionChoice>, String> choicesProcess = list -> list.stream().map(e -> e.delta().content())
            .collect(Collectors.joining());

    Function<String, String> elt = s -> s.replaceAll("<think>[\\s\\S]*?</think>", "").replaceAll("\n", "");


    /**
     *  流式返回示例
     * @param prompt
     * @return
     */
    @GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatCompletionResponse> chat(String prompt) {
        return deepSeekClient.chatFluxCompletion(prompt);
    }

    @GetMapping(value = "/sync/chat")
    public ChatCompletionResponse syncChat(String prompt) {
        ChatCompletionRequest request = ChatCompletionRequest.builder()
                // 根据渠道模型名称动态修改这个参数
//                .model(deepSeekProperties.getModel())
                .addUserMessage(prompt).build();

        return deepSeekClient.chatCompletion(request).execute();
    }


    /**
     * 多轮会话
     * @param prompt
     * @param cacheCode
     * @return
     */
    @GetMapping(value = "/chat/advanced", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatCompletionResponse> chatAdvanced(String prompt, String cacheCode) {
        ChatCompletionRequest request = ChatCompletionRequest.builder()
//                .model(deepSeekProperties.getModel())
                .addUserMessage(prompt).addAssistantMessage(elt.apply(cache.getOrDefault(cacheCode, "")))
                .addSystemMessage("你是一个专业的助手").maxCompletionTokens(5000).build();
        // 只保留上一次回答内容
        cache.remove(cacheCode);
        return deepSeekClient.chatFluxCompletion(request).doOnNext(i -> {
            String content = choicesProcess.apply(i.choices());
            // 其他ELT流程
            cache.merge(cacheCode, content, String::concat);
        }).doOnError(e -> System.out.println(e.getMessage()));
    }


    /**
     * RAG知识库接口
     * @param prompt
     * @return
     */
    @GetMapping(value = "/rag/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ChatCompletionResponse> ragchat(String prompt) {

        List<Float> floatList = embeddingClient.embed(prompt);

        SearchReq searchReq = SearchReq.builder()
                .collectionName("test1")
                .data(Collections.singletonList(new FloatVec(floatList)))
                .outputFields(Collections.singletonList("text"))
                .topK(3)
                .build();

        SearchResp searchResp = milvusClientV2.search(searchReq);

        List<String> resultList = new ArrayList<>();
        List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
        for (List<SearchResp.SearchResult> results : searchResults) {
            System.out.println("TopK results:");
            for (SearchResp.SearchResult result : results) {
                resultList.add(result.getEntity().get("text").toString());
            }
        }


        ChatCompletionRequest request = ChatCompletionRequest.builder()
                // 根据渠道模型名称动态修改这个参数
                .model("deepseek-r1:32b")
                .addUserMessage(String.format("你要根据用户输入的问题:%s \n \n 参考如下内容: %s  \n\n 整理处理最终结果", prompt, resultList)).build();

        return deepSeekClient.chatFluxCompletion(request);
    }
}

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

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

相关文章

会话与会话管理:Cookie与Session的深度解析

一、什么是会话&#xff1f; 二、Cookie&#xff1a;客户端存储技术 1. Cookie的工作原理 2、在后端设置cookie 3、在前端设置cookie 三、浏览器开启了cookie禁用怎么办&#xff1f; 一、什么是会话&#xff1f; 会话&#xff08;Session&#xff09;是指一个用户与服务器之间…

MAVlink链路环境搭建并解决“ModuleNotFoundError: No module named ‘xxx’”问题

MAVlink链路常用于云台相机与飞控以及地面站之间的数据传输&#xff0c;搭建MAVlink链路环境需要安装Python、Future、MAVLink、pymavlink四样工具用于生成mavlink代码。 Python 直接从官网下载默认安装即可https://www.python.org/downloads/ 在电脑命令行进行安装验证&#x…

java后端开发day23--面向对象进阶(四)--抽象类、接口、内部类

&#xff08;以下内容全部来自上述课程&#xff09; 1.抽象类 父类定义抽象方法后&#xff0c;子类的方法就必须重写&#xff0c;抽象方法在的类就是抽象类。 1.定义 抽象方法 将共性的行为&#xff08;方法&#xff09;抽取到父类之后。由于每一个子类执行的内容是不一样…

Go - 泛型的使用

泛型的语法 泛型为Go语言添加了三个新的重要特性: 函数和类型的类型参数。将接口类型定义为类型集&#xff0c;包括没有方法的类型。类型推断&#xff0c;它允许在调用函数时在许多情况下省略类型参数。 类型参数 类型参数的使用 除了函数中支持类型参数列表外&#xff0c…

蓝桥杯刷题-dp-线性dp(守望者的逃离,摆花,线段)

[NOIP 2007 普及组] 守望者的逃离 题目描述 恶魔猎手尤迪安野心勃勃&#xff0c;他背叛了暗夜精灵&#xff0c;率领深藏在海底的娜迦族企图叛变。 守望者在与尤迪安的交锋中遭遇了围杀&#xff0c;被困在一个荒芜的大岛上。 为了杀死守望者&#xff0c;尤迪安开始对这个荒岛…

内容中台的企业CMS架构是什么?

企业CMS模块化架构 现代企业内容管理系统的核心在于模块化架构设计&#xff0c;通过解耦内容生产、存储、发布等环节构建灵活的技术栈。动态/静态发布引擎整合技术使系统既能处理实时更新的产品文档&#xff0c;也能生成高并发的营销落地页&#xff0c;配合版本控制机制确保内…

算法题(81):询问学号

审题&#xff1a; 需要我们根据给出的n值确定录入数据个数&#xff0c;然后根据给出的数据存储学号。再根据m值确定需要输出的学号个数&#xff0c;然后根据数组内容输出学号 思路: 我们可以利用数组进行数据顺序存储&#xff0c;以及随机读取完成本题 由于学号最大为1e9&#…

React antd的datePicker自定义,封装成组件

一、antd的datePicker自定义 需求&#xff1a;用户需要为日期选择器的每个日期单元格添加一个Tooltip&#xff0c;当鼠标悬停时显示日期、可兑换流量余额和本公会可兑流量。这些数据需要从接口获取。我需要结合之前的代码&#xff0c;确保Tooltip正确显示&#xff0c;并且数据…

C++ AVL树详解(含模拟实现)

目录 AVL树的概念 AVL树节点的定义 AVL树的插入 AVL树的旋转&#xff08;难点&#xff09; AVL树的验证 AVL树的删除(本文不做具体的模拟实现) AVL树的性能 AVL树的模拟实现 AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索…

Spring Boot 3.x 系列【3】Spring Initializr快速创建Spring Boot项目

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot版本3.0.3 源码地址&#xff1a;https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言安装JDK 17创建Spring Boot 项目 方式1&#xff1a;网页在线生成方式2&#…

Elasticsearch:过滤 HNSW 搜索,快速模式

作者&#xff1a;来自 Elastic Benjamin Trent 通过我们的 ACORN-1 算法实现&#xff0c;探索我们对 Apache Lucene 中的 HNSW 向量搜索所做的改进。 多年来&#xff0c;Apache Lucene 和 Elasticsearch 一直支持使用 kNN 查询的过滤搜索&#xff0c;允许用户检索符合指定元数据…

【AI测试学习】AnythingLLM+Ollama+DeepSeek部署私人知识库

1.搭建DeepSeek大语言模型 1.1Ollama大预言模型部署 Ollama简化了大型语言模型的运行,让每个人都能在本地轻松体验AI的强大,打开浏览器-下载Ollama-输入命令-搞定,这是本地部署大语言模型的全新方式。 这里我们借助Ollama大预言模型部署工具进行搭建 官网如下:Ollama …

通义灵码插件安装入门教学 - IDEA(安装篇)

在开发过程中&#xff0c;使用合适的工具和插件可以极大地提高我们的工作效率。今天&#xff0c;我们将详细介绍如何在 IntelliJ IDEA 中安装并配置通义灵码插件&#xff0c;这是一款旨在提升开发者效率的实用工具。无论你是新手还是有经验的开发者&#xff0c;本文都将为你提供…

ES、OAS、ERP、电子政务、企业信息化(高软35)

系列文章目录 ES、OAS、ERP、电子政务、企业信息化 文章目录 系列文章目录前言一、专家系统&#xff08;ES&#xff09;二、办公自动化系统&#xff08;OAS&#xff09;三、企业资源规划&#xff08;ERP&#xff09;四、典型信息系统架构模型1.政府信息化和电子政务2.企业信息…

python-leetcode-删除并获得点数

740. 删除并获得点数 - 力扣&#xff08;LeetCode&#xff09; 解法 1&#xff1a;动态规划&#xff08;O(n) 时间&#xff0c;O(n) 空间&#xff09; class Solution:def deleteAndEarn(self, nums: List[int]) -> int:if not nums:return 0# 统计每个数的贡献points Cou…

助力DeepSeek私有化部署服务:让企业AI落地更简单、更安全

在数字化转型的浪潮中&#xff0c;越来越多的企业选择私有化部署AI技术&#xff0c;以保障数据安全、提升业务效率并实现自主可控。DeepSeek作为行业领先的AI开源技术&#xff0c;其技术可以支持企业私有化部署&#xff0c;企业需要一站式服务私有化部署&#xff0c;涵盖硬件采…

【每天认识一个漏洞】url重定向

&#x1f31d;博客主页&#xff1a;菜鸟小羊 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 常见应用场景 主要是业务逻辑中需要进行跳转的地方。比如登录处、注册处、访问用户信息、订单信息、加入购物车、分享、收…

纯代码实战--用Deepseek+SQLite+Ollama搭建数据库助手

如何用Python调用本地模型实现DeepSeek提示词模板&#xff1a;一步步教你高效解决13种应用场景 从零到一&#xff1a;纯代码联合PyQt5、Ollama、Deepseek打造简易版智能聊天助手 用外接知识库武装大模型&#xff1a;基于Deepseek、Ollama、LangChain的RAG实战解析 纯代码实战–…

2025 最新版鸿蒙 HarmonyOS 开发工具安装使用指南

为保证 DevEco Studio 正常运行&#xff0c;建议电脑配置满足如下要求&#xff1a; Windows 系统 操作系统&#xff1a;Windows10 64 位、Windows11 64 位内存&#xff1a;16GB 及以上硬盘&#xff1a;100GB 及以上分辨率&#xff1a;1280*800 像素及以上 macOS 系统 操作系统…

AI数字人开发,引领科技新潮流

引言 随着人工智能技术的迅猛发展&#xff0c;AI 数字人在影视娱乐、客户服务、教育及医疗等多个领域展现出巨大的潜力。本文旨在为开发者提供一份详细的 AI 数字人系统开发指南&#xff0c;涵盖从基础架构到实现细节的各个方面&#xff0c;包括人物建模、动作生成、语音交互、…