SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(WebSocket连接模式)
文章目录
- 前言
- 正文
- 一、项目环境
- 二、项目代码
- 2.1 pom.xml
- 2.2 DeepSeekController.java
- 2.3 启动类
- 2.4 logback-spring.xml
- 2.5 application.yaml
- 2.6 WebsocketConfig.java
- 2.7 AiChatWebSocketHandler.java
- 2.8 SaveChatSessionParamRequest.java
- 2.9 index.html
- 三、页面调试
- 3.1 主页
- 3.2 参数调整
- 3.3 问问题(看下效果)
- 四、遗留问题
前言
本文使用SpringBoot提供 WebSocket 对话功能。通过模拟对话的方式,来和DeepSeek进行交互。包含Java后端和一个简单的前端页面。
另见SSE模式的实现: SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(SSE连接模式)
硅基流动DeepSeek页面:
https://m.siliconflow.cn/playground/chat
硅基流动推理模型接口文档:
https://docs.siliconflow.cn/cn/userguide/capabilities/reasoning
正文
一、项目环境
- Java版本:Java1.8
- SpringBoot版本:2.7.7
- deepseek-spring-boot-starter:1.1.0
- spring-boot-starter-websocket:2.7.7
项目结构如下:
二、项目代码
2.1 pom.xml
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.pine.ai</groupId><artifactId>pine-ai</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>pine-ai-demo</name><url>http://maven.apache.org</url><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.7</spring-boot.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version><scope>provided</scope><optional>true</optional></dependency><dependency><groupId>io.github.pig-mesh.ai</groupId><artifactId>deepseek-spring-boot-starter</artifactId><version>1.1.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.7</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.7</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.7.7</version><configuration><mainClass>org.pine.ai.BootDemoApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
</project>
2.2 DeepSeekController.java
package org.pine.ai.controller;import lombok.extern.slf4j.Slf4j;
import org.pine.ai.client.request.SaveChatSessionParamRequest;
import org.pine.ai.config.AiChatWebSocketHandler;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@Slf4j
@RequestMapping("/deepseek")
public class DeepSeekController {/*** 保存会话参数*/@PostMapping(value = "/saveSessionParam")public ResponseEntity<Void> saveSessionParam(@RequestBody SaveChatSessionParamRequest request) {String sessionId = request.getSessionId();if (!StringUtils.hasText(sessionId)) {throw new IllegalArgumentException("sessionId is empty");}AiChatWebSocketHandler.putSessionParam(sessionId, "model", request.getModel());AiChatWebSocketHandler.putSessionParam(sessionId, "temperature", request.getTemperature());AiChatWebSocketHandler.putSessionParam(sessionId, "frequencyPenalty", request.getFrequencyPenalty());AiChatWebSocketHandler.putSessionParam(sessionId, "user", request.getUser());AiChatWebSocketHandler.putSessionParam(sessionId, "topP", request.getTopP());AiChatWebSocketHandler.putSessionParam(sessionId, "maxCompletionTokens", request.getMaxCompletionTokens());return new ResponseEntity<>(null, null, HttpStatus.OK);}
}
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
<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="false"><!-- 配置控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!-- 格式化输出: %d表示日期, %thread表示线程名, %-5level: 级别从左显示5个字符宽度 %msg:日志消息, %n是换行符 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}[%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!-- 日志输出级别 --><root level="INFO"><appender-ref ref="STDOUT"/></root>
</configuration>
2.5 application.yaml
deepseek:# 硅基流动的urlbase-url: https://api.siliconflow.cn/v1# 秘钥(你自己申请的)api-key: sk-ezcxadqecocxisaspring:main:allow-bean-definition-overriding: trueserver:tomcat:keep-alive-timeout: 30000 # 30秒空闲超时max-connections: 100 # 最大连接数uri-encoding: UTF-8servlet:encoding:charset: UTF-8force: trueenabled: truecompression:enabled: false # 禁用压缩(否则流式数据可能被缓冲)
2.6 WebsocketConfig.java
package org.pine.ai.config;import io.github.pigmesh.ai.deepseek.core.DeepSeekClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import javax.annotation.Resource;@Configuration
@EnableWebSocket
public class WebsocketConfig implements WebSocketConfigurer {@Resourceprivate DeepSeekClient deepSeekClient;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(aiChatWebSocketHandler(), "/ws/chat").setAllowedOrigins("*");}@Beanpublic WebSocketHandler aiChatWebSocketHandler() {return new AiChatWebSocketHandler(deepSeekClient);}
}
2.7 AiChatWebSocketHandler.java
package org.pine.ai.config;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.ResponseFormatType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Slf4j
public class AiChatWebSocketHandler extends TextWebSocketHandler {private static final Map<String, WebSocketSession> WEB_SOCKET_SESSION_MAP = new ConcurrentHashMap<>();private final DeepSeekClient deepSeekClient;public AiChatWebSocketHandler(DeepSeekClient deepSeekClient) {this.deepSeekClient = deepSeekClient;}public static void putSessionParam(String sessionId, String key, Object value) {WebSocketSession webSocketSession = WEB_SOCKET_SESSION_MAP.get(sessionId);if (webSocketSession == null) {throw new IllegalArgumentException("sessionId is not exist");}Map<String, Object> attributes = webSocketSession.getAttributes();attributes.put(key, value);}@Overridepublic void afterConnectionEstablished(WebSocketSession session) {WEB_SOCKET_SESSION_MAP.put(session.getId(), session);log.info("新连接: {}", session.getId());try {session.sendMessage(new TextMessage("sysLog=连接成功!"));session.sendMessage(new TextMessage("sysLog=sessionId:" + session.getId()));} catch (IOException e) {e.printStackTrace();}}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) {String payload = message.getPayload();log.info("收到消息: {}", payload);Map<String, Object> attributes = session.getAttributes();String model = attributes.getOrDefault("model", "deepseek-ai/DeepSeek-R1").toString();Double temperature = (Double) attributes.getOrDefault("temperature", 0.7);Double frequencyPenalty = (Double) attributes.getOrDefault("frequencyPenalty", 0.5);String user = attributes.getOrDefault("user", "user").toString();Double topP = (Double) attributes.getOrDefault("topP", 0.7);Integer maxCompletionTokens = (Integer) attributes.getOrDefault("maxCompletionTokens", 1024);log.info("model: {}, temperature: {}, frequencyPenalty: {}, user: {}, topP: {}, maxCompletionTokens: {}", model, temperature, frequencyPenalty, user, topP, maxCompletionTokens);ChatCompletionRequest request = buildRequest(payload, model, temperature, frequencyPenalty, user, topP, maxCompletionTokens);deepSeekClient.chatFluxCompletion(request).doOnNext(responseContent -> {// 发送消息给客户端try {String content = responseContent.choices().get(0).delta().content();String reasoningContent = responseContent.choices().get(0).delta().reasoningContent();if (StringUtils.hasText(reasoningContent) || (reasoningContent != null && reasoningContent.contains("\n"))) {session.sendMessage(new TextMessage("reasonContent=" + reasoningContent));} else if (StringUtils.hasText(content) || (content != null && content.contains("\n"))) {session.sendMessage(new TextMessage("content=" + content));}if ("stop".equals(responseContent.choices().get(0).finishReason())) {session.sendMessage(new TextMessage("\n\n回答结束!"));}} catch (IOException e) {e.printStackTrace();}}).subscribe();}private ChatCompletionRequest buildRequest(String prompt,String model,Double temperature,Double frequencyPenalty,String user,Double topP,Integer maxCompletionTokens) {return 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).maxTokens(maxCompletionTokens)// 响应结果的格式。.responseFormat(ResponseFormatType.TEXT).build();}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) {WEB_SOCKET_SESSION_MAP.remove(session.getId());log.info("连接关闭: {}", session.getId());}
}
2.8 SaveChatSessionParamRequest.java
package org.pine.ai.client.request;import lombok.Data;import java.io.Serializable;@Data
public class SaveChatSessionParamRequest implements Serializable {private String sessionId;private String model;private Double temperature;private Double frequencyPenalty;private String user;private Double topP;private Integer maxCompletionTokens;
}
2.9 index.html
<!DOCTYPE html>
<html>
<head><title>WebSocket DeepSeek Chat</title><style>body {font-family: Arial, sans-serif;background-color: #f4f4f9;margin: 0;padding: 20px;display: flex;flex-direction: column;align-items: center;}.input-button-container {display: flex;align-items: center;margin-bottom: 20px;width: 1060px;}#messageInput {width: 900px;padding: 10px;margin-right: 10px;border: 1px solid #ccc;border-radius: 5px;}button {padding: 10px 20px;border: none;border-radius: 5px;background-color: #007bff;color: white;cursor: pointer;margin-right: 10px;}button:hover {background-color: #0056b3;}.message-container {width: 500px;margin-top: 20px;border: 1px solid #ccc;border-radius: 5px;background-color: white;padding: 10px;overflow-y: auto;height: 200px;}.message-container p {margin: 5px 0;}#messages {border-color: #ccc;}#reasonMessages {border-color: #e89c10;}#sysLog {border-color: #ec1b1b;}.section-title {font-weight: bold;margin-top: 20px;}#paramConfigForm input[type = "text"] {width: 100%;padding: 10px;margin-left: 10px;border: 1px solid #ccc;border-radius: 5px;margin-top: 8px;}#paramConfigForm label {font-weight: bold;margin-top: 20px;}</style>
</head>
<body>
<div class="input-button-container"><input type="text" id="messageInput" placeholder="输入消息"/><button onclick="sendMessage()">发送</button>
</div><div style="display: flex;justify-content: flex-start;width: 1060px;align-items: center;"><button onclick="connectWebSocket()">连接</button><button style="background-color: #ec1b1b" onclick="disconnectWebSocket()">断开连接</button>
</div><div style="display: flex; width: 1100px;"><div style="width: 520px"><div class="section-title">思考过程:</div><div id="reasonMessages" class="message-container"></div></div><div style="width: 520px; margin-left: 20px;"><div class="section-title">正式回答:</div><div id="messages" class="message-container"></div></div>
</div><div style="width: 1100px;margin-top: 40px;"><div class="section-title">系统日志记录:</div><div id="sysLog" class="message-container" style="height: 100px;width: 1040px;"></div>
</div><div style="width: 1000px;margin-top: 40px;border: 1px solid #aba8a8;"><div class="section-title">参数配置:</div><div style="height: 700px;width: 900px;"><form id="paramConfigForm"><div style="margin-top: 20px;"><label for="sessionId">sessionId:</label><input type="text" id="sessionId" name="sessionId" required></div><div style="margin-top: 20px;"><label for="model">model:</label><input type="text" id="model" name="model" value="deepseek-ai/DeepSeek-R1"></div><div style="margin-top: 20px;"><label for="temperature">temperature:</label><input type="text" id="temperature" name="temperature" value="0.7"></div><div style="margin-top: 20px;"><label for="frequencyPenalty">frequencyPenalty:</label><input type="text" id="frequencyPenalty" name="frequencyPenalty" value="0.5"></div><div style="margin-top: 20px;"><label for="user">user:</label><input type="text" id="user" name="user" value="user"></div><div style="margin-top: 20px;"><label for="topP">topP:</label><input type="text" id="topP" name="topP" value="0.7"></div><div style="margin-top: 20px;"><label for="maxCompletionTokens">maxCompletionTokens:</label><input type="text" id="maxCompletionTokens" name="maxCompletionTokens" value="1024"></div><div style="margin-top: 20px;"><button type="button" onclick="submitParamConfigForm()">提交</button></div></form></div>
</div>
<script>let socket;/*** 连接websocket*/function connectWebSocket() {if (socket) {disconnectWebSocket()}// 根据实际服务地址修改const wsUri = "ws://localhost:8080/ws/chat";socket = new WebSocket(wsUri);socket.onopen = function (event) {appendMessage("系统: 连接已建立", "sysLog");};socket.onmessage = function (event) {let message = event.data.toString();console.log("收到消息:" + message);if (message.startsWith("content=")) {appendInlineMessage("messages", "" + message.substring(8))} else if (message.startsWith("reasonContent=")) {appendInlineMessage("reasonMessages", "" + message.substring(14))} else if (message.startsWith("sysLog=")) {appendMessage("系统: " + message.substring(7), "sysLog");}if (message.startsWith("sysLog=sessionId:")) {document.getElementById("sessionId").value = message.substring(17);}};socket.onclose = function (event) {appendMessage("系统: 连接已断开", "sysLog");};socket.onerror = function (error) {console.error("WebSocket错误:", error);appendMessage("系统: 连接发生错误", "sysLog");};}/*** 断开连接*/function disconnectWebSocket() {if (socket) {socket.close();}}/*** 发送消息*/function sendMessage() {const input = document.getElementById("messageInput");if (socket.readyState === WebSocket.OPEN) {socket.send(input.value);appendMessage("我: " + input.value, "sysLog");input.value = "";document.getElementById("reasonMessages").textContent = "";document.getElementById("messages").textContent = "";} else {alert("连接尚未建立");}}function appendMessage(message, divId) {const messagesDiv = document.getElementById(divId);const p = document.createElement("p");p.textContent = message;messagesDiv.appendChild(p);messagesDiv.scrollTop = messagesDiv.scrollHeight;}function appendInlineMessage(divId, messages) {const messagesDiv = document.getElementById(divId);messagesDiv.textContent += messages;messagesDiv.scrollTop = messagesDiv.scrollHeight;}// 初始化连接window.onload = connectWebSocket;/*** 提交参数配置表单*/function submitParamConfigForm() {// 获取表单元素const form = document.getElementById('paramConfigForm');const formData = new FormData(form);// 创建一个对象来存储表单数据const data = {};formData.forEach((value, key) => {data[key] = value;});// 将对象转换为 JSON 字符串const jsonData = JSON.stringify(data);// 使用 fetch API 发送 POST 请求fetch('http://localhost:8080/deepseek/saveSessionParam', {method: 'POST',headers: {'Content-Type': 'application/json'},body: jsonData}).then(response => {if (!response.ok) {throw new Error('Network response was not ok ' + response.statusText);}}).then(data => {console.log('Success:', data);// 处理成功响应alert("参数配置成功")}).catch((error) => {console.error('Error:', error);// 处理错误alert(error)});}</script>
</body>
</html>
三、页面调试
3.1 主页
启动SpringBoot项目后,访问页面:
http://localhost:8080/
3.2 参数调整
可以在主页的下方,进行基本参数的调整,一次调整对应的是当前的session。默认参数是输入框中显示的内容,【提交】表单后,调用deepseek时的基本参数就是你刚刚修改的内容了。
3.3 问问题(看下效果)
问:如何学习Java
四、遗留问题
页面中对换行、markdown的渲染还有些问题,但是这个页面的初衷只是为了调试deepseek的文本对话接口。因此后续可能不会继续完善了!!
相关文章:

SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(WebSocket连接模式)
文章目录 前言正文一、项目环境二、项目代码2.1 pom.xml2.2 DeepSeekController.java2.3 启动类2.4 logback-spring.xml2.5 application.yaml2.6 WebsocketConfig.java2.7 AiChatWebSocketHandler.java2.8 SaveChatSessionParamRequest.java2.9 index.html 三、页面调试3.1 主页…...

idea实现热部署
1.在pom.xml文件添加依赖 java <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency> 更新可见配置成功: 2.在appli…...

记一次误禁用USB导致键盘鼠标失灵的修复过程
背景说明 在电脑上插入了一个USB hub,然后弹窗提示:“集线器端口上出现电涌”,点开让选择“重置”或者“关闭”,不小心点了关闭,结果这个usb口就被关了,再插任何东西都没反应,找了很多办法都恢…...

0x03 http协议和分层架构
HTTP协议 简介 Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则 http协议基于TCP协议:面向连接,安全基于请求-响应模型:一次请求对应一次响应HTTP协议是无状态的协议ÿ…...

【leetcode hot 100 189】轮转数组
错误解法一:申请一个数组,第i个数放在新数组的ik或ik-nums.length上 class Solution {public void rotate(int[] nums, int k) {int[] resultsnew int[nums.length];for(int i0; i<nums.length; i){if(ik<nums.length){results[ik] nums[i];}els…...

医药行业哪些招聘管理系统有AI功能?
随着医药行业竞争加剧,企业对高端研发、临床、市场人才的需求日益迫切。传统招聘模式因效率低、成本高、匹配度不足等问题,已难以满足行业需求。2025年,以AI为核心的招聘管理系统成为解决痛点的关键工具。 一、医药行业招聘的痛点与AI解决方案…...

.net8 使用 license 证书授权案例解析
创建 webapi 项目 使用 .NET CLI 创建一个 ASP.NET Core Web API 应用,并添加指定的 NuGet 包,可以按照以下步骤操作: 创建 ASP.NET Core Web API 项目: dotnet new webapi -n WebAppLicense cd WebAppLicense添加 Standard.Li…...
golang的io
https://www.bilibili.com/video/BV1gx4y1r7xb 1. 原生io包 io包是Go语言标准库中底层的I/O接口层,定义了通用的读写规则和错误处理逻辑。每次读写都是直接调用底层系统 I/O,每次读取1字节,系统调用次数多。适用于小数据量、实时性要求高。i…...

全向广播扬声器在油气田中的关键应用 全方位守护安全
油气田作为高风险作业场所,安全生产始终是重中之重。在紧急情况下,如何快速、有效地传达信息,确保人员安全撤离,是油气田安全管理的关键环节。全向广播扬声器凭借其全方位覆盖、高音质输出和强大的环境适应性,成为油气…...
76.读取计时器运行时间 C#例子 WPF例子
TimerManager:一个增强的定时器类,带时间管理功能 在使用定时器时,我们常常需要知道定时器的运行状态,比如它已经运行了多久,或者还剩下多少时间。然而,.NET 的 System.Timers.Timer 类本身并没有直接提供…...

嵌入式开发:傅里叶变换(5):基于STM32,实现CMSIS中的DSP库
目录 步骤 1:准备工作 步骤 2:创建 Keil 项目,并配置工程 步骤 3:在MDK工程上添加 CMSIS-DSP 库 步骤 5:编写代码 步骤 6:配置时钟和优化 步骤 7:调试与验证 步骤 8:优化和调…...

探秘基带算法:从原理到5G时代的通信变革【六】CRC 校验
文章目录 2.5 CRC 校验2.5.1 前言2.5.2 CRC算法简介2.5.3 CRC计算的详细过程2.5.4 CRC校验的两种方法详解**分离比较法****整体运算法****不同位出错与余数的关系****总结** 2.5.5 CRC计算的C实现及工具介绍**C实现CRC计算****CRC计算工具推荐** **2.5.6 总结:CRC校…...

MySQL——DQL、多表设计
目录 一、DQL 1.基本查询 2.条件查询 3.分组查询 4.排序查询 5.分页查询 二、多表设计 1.一对多 2.一对一 3.多对多 一、DQL 1.基本查询 注意: *号代表查询所有字段,在实际开发中尽量少用(不直观、影响效率) 2.条件查询…...
XML 编辑器:全面指南与最佳实践
XML 编辑器:全面指南与最佳实践 引言 XML(可扩展标记语言)编辑器是处理XML文件的关键工具,对于开发人员、系统管理员以及任何需要处理XML数据的人来说至关重要。本文将全面介绍XML编辑器的概念、功能、选择标准以及最佳实践,旨在帮助读者了解如何选择和使用合适的XML编辑…...

【USRP】NVIDIA Sionna:用于 6G 物理层研究的开源库
目录 Sionna:用于 6G 物理层研究的开源库主要特点实现6G研究的民主化支持 5G、6G 等模块化、可扩展、可伸缩快速启动您的研究 好处原生人工智能支持综合研究平台开放生态系统 安装笔记使用 pip 安装基于Docker的安装从源代码安装“你好世界!”探索锡奥纳…...

DeepSeek开源周Day6:DeepSeek V3、R1 推理系统深度解析,技术突破与行业启示
DeepSeek 在开源周第六天再次发文,中文原文、官方号在知乎 DeepSeek - 知乎DeepSeek-V3 / R1 推理系统概览 - 知乎deepseek-ai/open-infra-index: Production-tested AI infrastructure tools for efficient AGI development and community-driven innovation 引言 …...

intra-mart实现logicDesigner与forma联动
一、前言 有一个需求,想实现从页面上传一个excel文件,点击提交,就转发给forma模块,然后用户在forma模块里,确认下自动填写的信息是否正确,正确的话就点击保存,存入数据库;不正确的话…...
《大语言模型的原理发展与应用》:此文为AI自动生成
《大语言模型的原理发展与应用》:此文为AI自动生成 一、引言:大语言模型,AI 时代的 “新引擎” 在当今数字化浪潮中,大语言模型宛如一颗璀璨的明星,照亮了人工智能发展的道路,成为推动各领域变革的核心驱…...
生态安全相关
概念:生态安全指一个国家具有支撑国家生存发展的较为完整、不受威胁的生态系统,以及应对内外重大生态问题的能力。 (1)国外生态安全的研究进展 国际上对生态安全的研究是从“环境”与“安全”之间的关系展开的。开始的阶段&#x…...

DeepSeek-R1国产化系统gpu驱动+cuda+ollama+webui可视化离线私有化部署
1.概述 网上大部分教程都是在线部署,完全离线私有化部署的文章不多,本文介绍从GPU驱动、cuda、ollama、deepseek模型和open webui等完全离线安装几个方面,让小白0基础也可以私有化部署大模型deepseek-R1。 我使用的设备是银河麒麟V10操作系统…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...