SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(SSE连接模式)

06-01 1408阅读

文章目录

  • 前言
  • 正文
    • 一、项目环境
    • 二、项目代码
      • 2.1 pom.xml
      • 2.2 DeepSeekController.java
      • 2.3 启动类
      • 2.4 logback-spring.xml
      • 2.5 application.yaml
      • 2.6 index.html
      • 三、页面调试
        • 3.1 参数提示
        • 3.2 开始请求
        • 3.3 手动断开

          前言

          作为一个Java程序员,了解前沿科技技术,也算是份内的事了。

          DeepSeek 大模型,从开源到现在,一直在🔥。各个公司也基本都部署了自己的所谓满血版DeepSeek。

          虽然官方是免费使用的,但是它太忙了。因此,很多能直接使用的,不太忙的DeepSeek应运而生。

          我今天使用的就是“硅基流动版”DeepSeek!

          本文的主旨是,使用SpringBoot接入DeepSeek,并提供一个调试页面,用来请求,和展示结果。

          硅基流动DeepSeek页面:

          https://m.siliconflow.cn/playground/chat

          硅基流动推理模型接口文档:

          https://docs.siliconflow.cn/cn/userguide/capabilities/reasoning

          所谓SSE 是使用js中的EventSource对象。

          它 是 JavaScript 中用于实现 服务器发送事件(Server-Sent Events, SSE) 的接口。它允许服务器向浏览器推送实时更新,而不需要客户端频繁地轮询服务器。SSE 提供了一种单向的通信机制,即服务器可以主动向客户端推送数据,但客户端不能通过 EventSource 向服务器发送数据。

          另见 WebSocket连接方式的实现:SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(WebSocket连接模式)

          正文

          一、项目环境

          • Java版本:Java1.8
          • SpringBoot版本:2.7.7
          • deepseek-spring-boot-starter:1.1.0

            项目结构如下:

            SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(SSE连接模式)

            二、项目代码

            2.1 pom.xml

              4.0.0
              org.pine.ai
              pine-ai
              1.0-SNAPSHOT
              jar
              pine-ai-demo
              http://maven.apache.org
              
                1.8
                UTF-8
                UTF-8
                2.7.7
              
              
                
                  org.projectlombok
                  lombok
                  1.18.34
                  provided
                  true
                
                
                  io.github.pig-mesh.ai
                  deepseek-spring-boot-starter
                  1.1.0
                
                
                  org.springframework.boot
                  spring-boot-starter-web
                  2.7.7
                
                
                  ch.qos.logback
                  logback-classic
                  1.2.11
                
              
              
                
                  
                    org.apache.maven.plugins
                    maven-compiler-plugin
                    3.8.1
                    
                      1.8
                      1.8
                      UTF-8
                    
                  
                  
                    org.springframework.boot
                    spring-boot-maven-plugin
                    2.7.7
                    
                      org.pine.ai.BootDemoApplication
                      true
                    
                    
                      
                        repackage
                        
                          repackage
                        
                      
                    
                  
                
              
            
            

            2.2 DeepSeekController.java

            package org.pine.ai.controller;
            import io.github.pigmesh.ai.deepseek.core.DeepSeekClient;
            import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionRequest;
            import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionResponse;
            import io.github.pigmesh.ai.deepseek.core.chat.ResponseFormatType;
            import lombok.extern.slf4j.Slf4j;
            import org.springframework.http.MediaType;
            import org.springframework.stereotype.Controller;
            import org.springframework.util.StringUtils;
            import org.springframework.web.bind.annotation.GetMapping;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RequestParam;
            import reactor.core.publisher.Flux;
            import javax.annotation.Resource;
            import java.util.List;
            @Controller
            @Slf4j
            @RequestMapping("/deepseek")
            public class DeepSeekController {
                @Resource
                private DeepSeekClient deepSeekClient;
                @GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
                public Flux chat(@RequestParam("prompt") String prompt,
                                                         @RequestParam(value = "model", defaultValue = "deepseek-ai/DeepSeek-R1") String model,
                                                         @RequestParam(value = "temperature", defaultValue = "0.7") Double temperature,
                                                         @RequestParam(value = "frequencyPenalty", defaultValue = "0.5") Double frequencyPenalty,
                                                         @RequestParam(value = "user", defaultValue = "user") String user,
                                                         @RequestParam(value = "topP", defaultValue = "0.7") Double topP,
                                                         @RequestParam(value = "maxCompletionTokens", defaultValue = "1024") Integer maxCompletionTokens) {
                    log.info("prompt: {}", prompt);
                    log.info("model: {}, temperature: {}, frequencyPenalty: {}, user: {}, topP: {}, maxCompletionTokens: {}", model, temperature, frequencyPenalty, user, topP, maxCompletionTokens);
                    if (!StringUtils.hasText(prompt)) {
                        throw new IllegalArgumentException("prompt is empty");
                    }
                    ChatCompletionRequest request = ChatCompletionRequest.builder()
                            // 添加用户输入的提示词(prompt),即模型生成文本的起点。告诉模型基于什么内容生成文本。
                            .addUserMessage(prompt)
                            // 指定使用的模型名称。不同模型可能有不同的能力和训练数据,选择合适的模型会影响生成结果。
                            .model(model)
                            // 是否以流式(streaming)方式返回结果。
                            .stream(true)
                            // 控制生成文本的随机性。0.0:生成结果非常确定,倾向于选择概率最高的词。1.0:生成结果更具随机性和创造性。
                            .temperature(temperature)
                            // 控制生成文本中重复内容的惩罚程度。0.0:不惩罚重复内容。1.0 或更高:减少重复内容,增加多样性。
                            .frequencyPenalty(frequencyPenalty)
                            // 标识请求的用户。用于跟踪和日志记录,通常用于区分不同用户的请求。
                            .user(user)
                            // 控制生成文本时选择词的范围。0.7:从概率最高的 70% 的词中选择。1.0:不限制选择范围。
                            .topP(topP)
                            // 控制模型生成的文本的最大长度。这对于防止生成过长的文本或确保响应在预期的范围内非常有用。
                            .maxCompletionTokens(maxCompletionTokens)
                            // 响应结果的格式。
                            .responseFormat(ResponseFormatType.TEXT)
                            .build();
                    return deepSeekClient.chatFluxCompletion(request);
                }
            }
            

            2.3 启动类

            package org.pine.ai;
            import org.springframework.boot.SpringApplication;
            import org.springframework.boot.autoconfigure.SpringBootApplication;
            import org.springframework.web.bind.annotation.CrossOrigin;
            @SpringBootApplication
            @CrossOrigin(
                    origins = "*",
                    allowedHeaders = "*",
                    exposedHeaders = {"Cache-Control", "Connection"}  // 暴露必要头
            )
            public class BootDemoApplication {
                public static void main(String[] args) {
                    SpringApplication.run(BootDemoApplication.class, args);
                }
            }
            

            2.4 logback-spring.xml

            
                
                
                    
                        
                        %d{yyyy-MM-dd HH:mm:ss.SSS}[%thread] %-5level %logger{50} - %msg%n
                    
                
                
                
                    
                
            
            

            2.5 application.yaml

            deepseek:
              # 硅基流动的url
              base-url: https://api.siliconflow.cn/v1
              # 秘钥(自己注册硅基的账号,并申请即可)
              api-key: sk-ezcxadqecocxixxxxxxx
            spring:
              main:
                allow-bean-definition-overriding: true
            server:
              tomcat:
                keep-alive-timeout: 30000  # 30秒空闲超时
                max-connections: 100       # 最大连接数
                uri-encoding: UTF-8
              servlet:
                encoding:
                  charset: UTF-8
                  force: true
                  enabled: true
              compression:
                enabled: false  # 禁用压缩(否则流式数据可能被缓冲)
            

            2.6 index.html

            
            
              
              调用演示
              
                body {
                  padding: 20px;
                  font-family: Arial, sans-serif;
                }
                #output {
                  height: 400px;
                  width: 900px;
                  border: 2px solid #c7c1c1;
                  padding: 10px;
                  overflow-y: auto;
                  margin: 20px 0;
                  white-space: pre-wrap;
                  box-shadow: 0 4px 6px rgba(13, 118, 231, 0.25);
                }
                button {
                  padding: 10px 20px;
                  background: #007bff;
                  color: white;
                  border: none;
                  border-radius: 4px;
                  cursor: pointer;
                }
                .danger-button {
                  background-color: #ec1b1b;
                }
                .form-group {
                  margin: 20px 0;
                  max-width: 900px;
                }
                label[for="promptInput"] {
                  display: block;
                  margin-bottom: 12px;
                  font-size: 1.1em;
                  color: #2c3e50;
                  font-weight: 600;
                  letter-spacing: 0.5px;
                }
                label[for="paramInput"] {
                  display: block;
                  margin-bottom: 12px;
                  font-size: 1.1em;
                  color: #2c3e50;
                  font-weight: 600;
                  letter-spacing: 0.5px;
                }
                #promptInput, #paramInput {
                  /* 尺寸调整 */
                  width: 100%;
                  padding: 14px 20px;
                  /* 样式美化 */
                  border: 2px solid #007bff;
                  border-radius: 8px;
                  font-size: 1.1rem;
                  background-color: #f8f9fa;
                  transition: all 0.3s ease-in-out;
                  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
                  color: #44878c;
                  font-style: italic;
                }
                #promptInput, #paramInput:focus {
                  outline: none;
                  border-color: #0056b3;
                  box-shadow: 0 4px 6px rgba(0,123,255,0.25);
                  background-color: white;
                }
                /* 暗色模式适配 */
                @media (prefers-color-scheme: dark) {
                  #promptInput, #paramInput {
                    background-color: #2d3436;
                    border-color: #4a90e2;
                    color: #ecf0f1;
                  }
                  #promptInput, #paramInput:focus {
                    background-color: #34495e;
                  }
                }
                /* 输入提示动画 */
                @keyframes pulse-shadow {
                  0% { box-shadow: 0 0 0 0 rgba(0,123,255,0.4) }
                  100% { box-shadow: 0 0 0 10px rgba(0,123,255,0) }
                }
                .input-highlight {
                  animation: pulse-shadow 1.5s infinite;
                }
              
            
            
            
            URL + Prompt 提示词:
            参数串:
            开始请求 断开连接 参数提示
            let eventSource; function connectAiServer(url) { eventSource = new EventSource(url); } function disconnectAiServer() { if (eventSource) { eventSource.close() } } function start() { const output = document.getElementById('output') const promptInput = document.getElementById('promptInput') const paramInput = document.getElementById('paramInput') output.textContent = '' // 清空内容 try { // 创建 EventSource 连接 connectAiServer(promptInput.value + "&" + paramInput.value) // 监听默认事件(无事件名的消息) eventSource.onmessage = (event) => { const value = event.data; const data = JSON.parse(value); if (data.choices[0].delta.reasoning_content === '') { output.textContent += '开始思考:\n\t' } if (data.choices[0].delta.content === '\n\n') { output.textContent += '思考结束!!\n\n\n\n' output.textContent += '以下是正式回答:\n\n' } if(data.choices[0].finish_reason === "stop" || data.choices[0].delta.content === "[DONE]") { output.textContent += '\r\n\r\n回答结束!!' disconnectAiServer() } // 拼接思考内容 if (data.choices[0].delta.reasoning_content) { output.textContent += data.choices[0].delta.reasoning_content } // 拼接回答内容 if (data.choices[0].delta.content) { output.textContent += data.choices[0].delta.content; } // 自动滚动到底部 output.scrollTop = output.scrollHeight }; } catch (error) { console.error('请求失败:', error) output.textContent = '请求失败: ' + error.message disconnectAiServer() } } /* 回车触发请求 */ document.querySelector('#promptInput').addEventListener('keypress', (e) => { if(e.key === 'Enter') { start() } }) function tips() { const output = document.getElementById('output') output.textContent = ` 参数说明: prompt:添加用户输入的提示词(prompt),即模型生成文本的起点。告诉模型基于什么内容生成文本。默认为:空\n model:不同模型可能有不同的能力和训练数据,选择合适的模型会影响生成结果。默认为:deepseek-ai/DeepSeek-R1\n temperature:控制生成文本的随机性。0.0:生成结果非常确定,倾向于选择概率最高的词。1.0:生成结果更具随机性和创造性。默认为:0.7\n frequencyPenalty:控制生成文本中重复内容的惩罚程度。0.0:不惩罚重复内容。1.0 或更高:减少重复内容,增加多样性。默认为:0.5\n user:标识请求的用户。用于跟踪和日志记录,通常用于区分不同用户的请求。默认为:user\n topP:控制生成文本时选择词的范围。0.7:从概率最高的 70% 的词中选择。1.0:不限制选择范围。默认为:0.7\n maxCompletionTokens:控制模型生成的文本的最大长度。这对于防止生成过长的文本或确保响应在预期的范围内非常有用。默认为:1024\n` }

            三、页面调试

            启动项目后,访问:http://localhost:8080/

            3.1 参数提示

            点击参数提示

            SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(SSE连接模式)

            3.2 开始请求

            在【URL + Prompt参数提示】的输入框中,追加你要问的问题。然后点击【开始请求】或直接【回车】。

            SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(SSE连接模式)

            3.3 手动断开

            点击【断开连接】。将会停止回答。

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码