目录
- 前言
- 一、必要信息准备
- 二、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.fei编程客栈gn.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 rjsetrofit2.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);python 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.volcen编程gine.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, ThrowablNMsxkMVQCe throwable) { log.error("Error on session: {}", session.getId(), throwable); } }
总结
到此这篇关于JAVA接入DeepSeek满血版的详细指南(问答接入、流式接入双模式)的文章就介绍到这了,更多相关JAVA接入DeepSeek满血版内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论