DeepSeek满血版JAVA接入指南(问答接入、流式接入双模式)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、必要信息准备
  • 二、HTTP问答接入
    • 1.配置文件
    • 2.创建实例类
    • 3.创建调用外部API接口
    • 4.创建调用服务service
    • 5.业务层service选择模型,并调用刚刚的服务
  • 三、WSS流式调用
    • 1.先写一个处理流式响应的方法
    • 2.业务层service调用
    • 3.WebSocket调用
  • 总结


前言

硅基流动推出了功能完备的DeepSeek满血版,然而众多用户在尝试接入大型模型时仍面临诸多挑战,特别是在流式接入方面。今天,我将引领大家通过Java实现双模式接入DeepSeek满血版,这涵盖了利用HTTP协议实现的问答模式,以及借助WSS协议实现的流式问答功能。话不多说,我们直接开始。


一、必要信息准备

在这里插入图片描述

接入满血版DeepSeek,肯定要有个硅基流动账号和秘钥啦,搜索一下硅基流动官网,打开硅基流动首页,注册账号,别忘了填邀请码wkzJFskh,注册后可以获取14元的赠送额度,嫌麻烦的同学可以直接复制https://cloud.siliconflow.cn/i/wkzJFskh,可以直接跳转到官网。
在这里插入图片描述
注册完成后,左侧菜单栏点击API秘钥,然后选择右上角的创建秘钥,输入必要信息后,秘钥创建完成,鼠标点击刚刚创建的秘钥,单击复制,这一步可以先把秘钥用个记事本记录一下,等会代码里会用到。
在这里插入图片描述

点击左侧模型广场,选取DeepSeekR1满血版模型,可以看到,广场里面有很多小模型是免费的,大家有空可以都尝试玩一下。
在这里插入图片描述

复制一下模型名称,写在记事本里,等会会用到。点击API文档,进入官方接入指南。
在这里插入图片描述

记住这边的路径,请求以及响应,下面要开始代码部分啦。

二、HTTP问答接入

我们先进行HTTP问答接入,这种接入方式需要等大模型完全回答完问题,将答案生成好之后,全部返回,这种方式的优点是前后端交互方便,缺点是在用户看来等待好长时间才返回答案。下面开始上代码

1.配置文件

代码如下(示例):

sili:
  apiKey: sk-xxxxxxxxx-your-api-key
  baseUrl: https://api.siliconflow.cn/v1/

2.创建实例类

会看第一节的官方API指南,根据官方的请求体和响应,构造实体类,我这边不展开篇幅

3.创建调用外部API接口

这里将普通调用和流模式均展示在了下面,流式调用需要用@Streaming注解。这里不使用openFeign是因为openFeign不支持流式响应的接收。

package com.example.awesome.feign.siliconflow;

import com.example.awesome.feign.siliconflow.req.ChatCompletionReq;
import com.example.awesome.feign.siliconflow.res.ChatCompletionRes;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.HeaderMap;
import retrofit2.http.POST;
import retrofit2.http.Streaming;

import java.util.Map;

/**
 * 定义与 SiliconFlow API 交互的 Retrofit 接口。
 */
public interface SiliconFlowApiService {

    /**
     * 发起同步的聊天完成请求。
     *
     * @param chatCompletionReq 请求体,包含聊天完成所需的参数。
     * @param headers           HTTP 请求头,包括授权信息等。
     * @return 返回一个 {@link Call} 对象,用于执行HTTP请求并获取 {@link ChatCompletionRes} 响应。
     */
    @POST("/chat/completions")
    Call<ChatCompletionRes> getChatCompletions(
        @Body ChatCompletionReq chatCompletionReq,
        @HeaderMap Map<String, String> headers
    );

    /**
     * 发起流式的聊天完成请求。
     *
     * @param chatCompletionReq 请求体,包含聊天完成所需的参数。
     * @param headers           HTTP 请求头,包括授权信息等。
     * @return 返回一个 {@link Call} 对象,用于执行HTTP请求并获取 {@link ResponseBody} 流式响应。
     * @see Streaming 表示该请求是流式的,不会将整个响应体加载到内存中。
     */
    @POST("/chat/completions")
    @Streaming
    Call<ResponseBody> getChatCompletionsStream(
        @Body ChatCompletionReq chatCompletionReq,
        @HeaderMap Map<String, String> headers
    );
}

4.创建调用服务service

package com.example.awesome.feign.siliconflow;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.example.awesome.feign.siliconflow.req.ChatCompletionReq;
import com.example.awesome.feign.siliconflow.res.ChatCompletionRes;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionResult;
import com.volcengine.ark.runtime.utils.ResponseBodyCallback;
import com.volcengine.ark.runtime.utils.SSE;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 实现与 SiliconFlow API 交互的服务类。
 */
@Service
@Slf4j
public class SiliconFlowApiServiceImpl {

    @Value("${sili.baseUrl}")
    private String SILI_API_URL;

    @Value("${sili.apiKey}")
    private String apiKey;

    private Retrofit retrofit;
    
    private SiliconFlowApiService apiService;
 
    /**
     * 初始化 Retrofit 客户端和 API 服务。
     */
    @PostConstruct
    public void init() {
        log.info("SiLiApiService init");
        retrofit = new Retrofit.Builder()
                .baseUrl(SILI_API_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .build();
        this.apiService = retrofit.create(SiliconFlowApiService.class);
    }


    /**
     * 发起同步的聊天完成请求,返回非流式的响应。
     *
     * @param req 请求体,包含聊天完成所需的参数。
     * @return 返回 {@link ChatCompletionRes} 对象,表示API的响应结果。
     */
    public ChatCompletionRes getChatCompletions(ChatCompletionReq req) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + apiKey);
        headers.put("Content-Type", "application/json");

        try {
            // 执行HTTP请求并获取响应
            Call<ChatCompletionRes> call = this.apiService.getChatCompletions(req, headers);
            return call.execute().body();
        } catch (Exception e) {
            // 记录错误日志并抛出运行时异常
            log.error("SiLiApiService error: {}", e.getMessage(), e);
            throw new RuntimeException("SiLiApiService error: " + e.getMessage(), e);
        }
    }

}

5.业务层service选择模型,并调用刚刚的服务

package com.example.awesome.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.example.awesome.feign.siliconflow.SiliconFlowApiServiceImpl;
import com.example.awesome.feign.siliconflow.req.ChatCompletionReq;
import com.example.awesome.feign.siliconflow.req.Message;
import com.example.awesome.feign.siliconflow.res.ChatCompletionRes;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.websocket.Session;
import java.util.ArrayList;
import java.util.List;

/**
 * 提供与 SiliconFlow API 交互的服务类。
 */
@Service
@Slf4j
public class SiliconFlowService {

    @Resource
    private SiliconFlowApiServiceImpl siliconFlowApiServiceImpl;

    /**
     * 发起同步的聊天完成请求,返回用户的回答内容。
     *
     * @param question 用户提出的聊天问题。
     * @return 返回用户的回答内容。
     * @throws RuntimeException 如果请求过程中发生异常,抛出运行时异常。
     */
    public String getChatCompletions(String question) {
        // 创建 ChatCompletionReq 对象
        ChatCompletionReq req = new ChatCompletionReq();

        // 设置模型名称
        req.setModel("deepseek-ai/DeepSeek-R1");

        // 创建消息列表
        List<Message> messages = new ArrayList<>();

        // 添加用户消息
        messages.add(Message.builder().role("user").content(question).build());

        // 设置请求的消息列表
        req.setMessages(messages);

        try {
            // 发起同步请求并获取响应
            ChatCompletionRes chatCompletions = siliconFlowApiServiceImpl.getChatCompletions(req);

            // 返回第一个选择的回答内容
            return chatCompletions.getChoices().get(0).getMessage().getContent();
        } catch (Exception e) {
            // 记录错误日志并抛出运行时异常
            log.error("siliconflow answer error: {}", e.getMessage(), e);
            throw new RuntimeException("网络异常请重试", e);
        }
    }

}

三、WSS流式调用

1.先写一个处理流式响应的方法

在官方指南中可以看到,流式调用需要将入参的stream设置为true


package com.example.awesome.feign.siliconflow;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.example.awesome.feign.siliconflow.req.ChatCompletionReq;
import com.example.awesome.feign.siliconflow.res.ChatCompletionRes;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionResult;
import com.volcengine.ark.runtime.utils.ResponseBodyCallback;
import com.volcengine.ark.runtime.utils.SSE;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 实现与 SiliconFlow API 交互的服务类。
 */
@Service
@Slf4j
public class SiliconFlowApiServiceImpl {

    @Value("${sili.baseUrl}")
    private String SILI_API_URL;

    @Value("${sili.apiKey}")
    private String apiKey;

    private Retrofit retrofit;
    private SiliconFlowApiService apiService;
    private static final ObjectMapper mapper = defaultObjectMapper();


    /**
     * 创建并配置 ObjectMapper 实例。
     *
     * @return 配置好的 ObjectMapper 实例。
     */
    public static ObjectMapper defaultObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        return mapper;
    }

    /**
     * 初始化 Retrofit 客户端和 API 服务。
     */
    @PostConstruct
    public void init() {
        log.info("SiLiApiService init");
        retrofit = new Retrofit.Builder()
                .baseUrl(SILI_API_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .build();
        this.apiService = retrofit.create(SiliconFlowApiService.class);
    }

    /**
     * 将 Call<ResponseBody> 转换为 Flowable<T>,并进行数据映射。
     *
     * @param apiCall API 调用对象。
     * @param cl      目标类类型。
     * @param <T>     泛型类型。
     * @return Flowable<T> 对象。
     */
    public static <T> Flowable<T> stream(Call<ResponseBody> apiCall, Class<T> cl) {
        return stream(apiCall).map((sse) -> {
//            log.info("SiLiApiService stream: {}", sse.getData());
            return mapper.readValue(sse.getData(), cl);
        });
    }

    /**
     * 将 Call<ResponseBody> 转换为 Flowable<SSE>,并处理响应。
     *
     * @param apiCall  API 调用对象。
     * @param emitDone 是否在流结束时发送完成信号。
     * @return Flowable<SSE> 对象。
     */
    public static Flowable<SSE> stream(Call<ResponseBody> apiCall, boolean emitDone) {
        return Flowable.create((emitter) -> {
            apiCall.enqueue(new ResponseBodyCallback(emitter, emitDone));
        }, BackpressureStrategy.BUFFER);
    }

    /**
     * 将 Call<ResponseBody> 转换为 Flowable<SSE>,默认不发送完成信号。
     *
     * @param apiCall API 调用对象。
     * @return Flowable<SSE> 对象。
     */
    public static Flowable<SSE> stream(Call<ResponseBody> apiCall) {
        return stream(apiCall, false);
    }

    /**
     * 发起流式的聊天完成请求,返回流式的响应。
     *
     * @param request 请求体,包含聊天完成所需的参数。
     * @return 返回 {@link Flowable<ChatCompletionResult>} 对象,表示流式的API响应结果。
     */
    public Flowable<ChatCompletionResult> streamChatCompletion(ChatCompletionReq request) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + apiKey);
        headers.put("Content-Type", "application/json");
        request.setStream(Boolean.TRUE);
        return stream(this.apiService.getChatCompletionsStream(request, headers), ChatCompletionResult.class);
    }
}

2.业务层service调用


package com.example.awesome.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.example.awesome.feign.siliconflow.SiliconFlowApiServiceImpl;
import com.example.awesome.feign.siliconflow.req.ChatCompletionReq;
import com.example.awesome.feign.siliconflow.req.Message;
import com.example.awesome.feign.siliconflow.res.ChatCompletionRes;
import com.volcengine.ark.runtime.model.completion.chat.ChatCompletionResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.websocket.Session;
import java.util.ArrayList;
import java.util.List;

/**
 * 提供与 SiliconFlow API 交互的服务类。
 */
@Service
@Slf4j
public class SiliconFlowService {

    @Resource
    private SiliconFlowApiServiceImpl siliconFlowApiServiceImpl;

    /**
     * 发起流式的聊天完成请求,并将结果通过 WebSocket 会话发送给客户端。
     *
     * @param question 用户提出的聊天问题。
     * @param session  WebSocket 会话对象。
     * @throws RuntimeException 如果请求过程中发生异常,抛出运行时异常。
     */
    public void getChatCompletionsStream(String question, Session session) {
        // 创建 ChatCompletionReq 对象
        ChatCompletionReq req = new ChatCompletionReq();

        // 设置模型名称
        req.setModel("deepseek-ai/DeepSeek-R1");

        // 创建消息列表
        List<Message> messages = new ArrayList<>();

        // 添加用户消息
        messages.add(Message.builder().role("user").content(question).build());

        // 设置请求的消息列表
        req.setMessages(messages);

        try {
            // 发起流式请求并处理响应
            siliconFlowApiServiceImpl.streamChatCompletion(req)
                    .doOnError(e -> log.error("Error in streamChatCompletion: ", e))
                    .blockingForEach(chunk -> {
                        if (!chunk.getChoices().isEmpty()) {
                            chunk.getChoices().forEach(choice -> {
                                // 如果完成原因为空或不是 "stop",则继续处理
                                if (StrUtil.isNotEmpty(choice.getFinishReason()) && StrUtil.equals(choice.getFinishReason(), "stop")) {
                                    // 发送 "answer-stop" 信号
                                    session.getAsyncRemote().sendText("answer-stop");
                                    return;
                                }
                                // 如果消息内容为空,则跳过
                                if (ObjectUtil.isEmpty(choice.getMessage().getContent())) {
                                    return;
                                }
                                // 同步发送消息内容
                                synchronized (session) {
                                    try {
                                        session.getBasicRemote().sendText(choice.getMessage().getContent());
                                    } catch (Exception e) {
                                        // 记录错误日志并抛出运行时异常
                                        log.error("answerByStream error: {}", e.getMessage(), e);
                                        throw new RuntimeException(e);
                                    }
                                }
                            });
                        }
                    });
        } catch (Exception e) {
            // 记录错误日志并抛出运行时异常
            log.error("siliconflow answer error: {}", e.getMessage(), e);
            throw new RuntimeException("网络异常请重试", e);
        }
    }
}

3.WebSocket调用

在onMessage方法中,在session中写入流式调用的响应,即可实现wss流式接入,输出就类似于官方的一字一字输出。在用户看来减少了等待时间,十分友好。


package com.example.awesome.controller.webSocket;

import cn.hutool.core.util.ObjectUtil;
import com.example.awesome.service.SiliconFlowService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

/**
 * WebSocket 服务器端点,处理与客户端的 WebSocket 连接。
 */
@Slf4j
@ServerEndpoint(value = "/websocket/test")
@Component
public class TestSocketServer {

    private static SiliconFlowService siliconFlowService;

    /**
     * 注入 SiliconFlowService 实例。
     *
     * @param siliconFlowService SiliconFlowService 实例。
     */
    @Autowired
    public void setSiliconFlowService(SiliconFlowService siliconFlowService) {
        this.siliconFlowService = siliconFlowService;
    }

    /**
     * 处理 WebSocket 连接打开事件。
     *
     * @param session 当前 WebSocket 会话。
     */
    @OnOpen
    public void onOpen(Session session) {
        log.info("新连接: {}", session.getId());
    }

    /**
     * 处理接收到的 WebSocket 消息。
     *
     * @param message 接收到的消息内容。
     * @param session 当前 WebSocket 会话。
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        // 调用 SiliconFlowService 处理流式聊天完成请求
        siliconFlowService.getChatCompletionsStream(message, session);
    }

    /**
     * 处理 WebSocket 连接关闭事件。
     *
     * @param session 当前 WebSocket 会话。
     */
    @OnClose
    public void onClose(Session session) {
        log.info("连接关闭: {}", session.getId());
    }

    /**
     * 处理 WebSocket 连接中的错误事件。
     *
     * @param session 当前 WebSocket 会话。
     * @param throwable 发生的异常。
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        log.error("Error on session: {}", session.getId(), throwable);
    }
}

总结

上面就是双模式的接入全过程啦!~~~~~~
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值