当前位置: 首页 > article >正文

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 主页…...

LINUX网络基础 [一] - 初识网络,理解网络协议

目录 前言 一. 计算机网络背景 1.1 发展历程 1.1.1 独立模式 1.1.2 网络互联 1.1.3 局域网LAN 1.1.4 广域网WAN 1.2 总结 二. "协议" 2.1 什么是协议 2.2 网络协议的理解 2.3 网络协议的分层结构 三. OSI七层模型&#xff08;理论标准&#xff09; …...

由麻省理工学院计算机科学与人工智能实验室等机构创建低成本、高效率的物理驱动数据生成框架,助力接触丰富的机器人操作任务

2025-02-28&#xff0c;由麻省理工学院计算机科学与人工智能实验室&#xff08;CSAIL&#xff09;和机器人与人工智能研究所的研究团队创建了一种低成本的数据生成框架&#xff0c;通过结合物理模拟、人类演示和基于模型的规划&#xff0c;高效生成大规模、高质量的接触丰富型机…...

【RAG从入门到精通系列】【RAG From Scratch 系列教程2:Query Transformations】

目录 前言一、概述1-1、RAG概念1-2、前置知识1-2-1、ModelScopeEmbeddings 词嵌入模型1-2-2、FAISS介绍&安装 (向量相似性搜索)1-2-3、Tiktoken 分词工具 二、Rag From Scratch&#xff1a;Query Transformations2-1、前置环境安装2-2、多查询检索器2-2-1、加载网页内容2-2…...

通过RK3588的cc-linaro-7.5.0交叉编译器搭建QT交叉编译环境QtCreator(无需编译QT源码)

当我们需要给新的电脑上部署RK3588的QT交叉编译环境时&#xff0c;我们可以将旧电脑上的编译好的qmake直接拷贝到新电脑上并配置好环境。 一、开发环境 1、ubuntu20.04 2、qt5.14.2 3、交叉编译器gcc-linaro-7.5.0 4、已编译好的qt交叉编译器 二、资料下载 链接: https:…...

前端基础之消息订阅与发布

需要下载npm I pubsub-js 在Student.vue中发送数据 <template> <div class"demo"> <h2 class"title">学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <button click"sendStudentName">将学生名给…...

51c自动驾驶~合集53

我自己的原文哦~ https://blog.51cto.com/whaosoft/13431196 #DriveTransformer 上交提出&#xff1a;以Decoder为核心的大一统架构写在前面 & 笔者的个人理解 当前端到端自动驾驶架构的串行设计导致训练稳定性问题&#xff0c;而且高度依赖于BEV&#xff0c;严重限…...

CS144 Lab Checkpoint 0: networking warm up

Set up GNU/Linux on your computer 我用的是Ubuntu&#xff0c;按照指导书上写的输入如下命令安装所需的软件包&#xff1a; sudo apt update && sudo apt install git cmake gdb build-essential clang \ clang-tidy clang-format gcc-doc pkg-config glibc-doc tc…...

Spring WebFlux 中 WebSocket 使用 DataBuffer 的注意事项

以下是修改后的完整文档&#xff0c;包含在多个多线程环境中使用 retain() 和 release() 方法的示例&#xff0c;且确保在 finally 块中调用 release()&#xff1a; 在 Spring WebFlux 中&#xff0c;WebSocketMessage 主要用于表示 WebSocket 的消息载体&#xff0c;其中 getP…...

Android ChatOn-v1.66.536-598-[构建于ChatGPT和GPT-4o之上]

ChatOn 链接&#xff1a;https://pan.xunlei.com/s/VOKYnq-i3C83CK-HJ1gfLf4gA1?pwdwzwc# 添加了最大无限积分 删除了所有调试信息 语言&#xff1a;全语言支持...

游戏树搜索与优化策略:Alpha-Beta剪枝及其实例分析

1.Alpha-Beta搜索 Alpha-Beta 搜索是一种用于对抗性游戏&#xff08;比如象棋、围棋&#xff09;的智能算法&#xff0c;目的是帮助计算机快速找到“最优走法”&#xff0c;同时避免不必要的计算。它的核心思想是&#xff1a;通过剪掉明显糟糕的分支&#xff0c;大幅减少需要计…...

基于Qwen-VL的手机智能体开发

先上Demo&#xff1a; vl_agent_demo 代码如下&#xff1a; 0 设置工作目录&#xff1a; 你的工作目录需要如下&#xff1a; 其中utils文件夹和qwenvl_agent.py均参考自 GitHub - QwenLM/Qwen2.5-VL: Qwen2.5-VL is the multimodal large language model series developed by …...

记录一次Spring事务失效导致的生产问题

一、背景介绍 公司做的是“聚合支付”业务&#xff0c;对接了微信、和包、数字人民币等等多家支付机构&#xff0c;我们提供统一的支付、退款、自动扣款签约、解约等能力给全国的省公司、机构、商户等。 同时&#xff0c;需要做对账功能&#xff0c;即支付机构将对账文件给到…...

深度学习实战:用TensorFlow构建高效CNN的完整指南

一、为什么每个开发者都要掌握CNN&#xff1f; 在自动驾驶汽车识别路标的0.1秒里&#xff0c;在医疗AI诊断肺部CT片的精准分析中&#xff0c;甚至在手机相册自动分类宠物的日常场景里&#xff0c;卷积神经网络&#xff08;CNN&#xff09;正悄然改变着我们的世界。本文将以工业…...

算法 之 贪心思维训练!

文章目录 从最大/最小开始贪心2279.装满石头的背包的最大数量2971.找到最大周长的多边形 从最左、最右开始贪心2712.使所有字符相等的最小成本 划分型贪心1221.分割平衡字符串 贪心策略在处理一些题目的时候能够带来意想不到的效果 从最小/最大开始贪心&#xff0c;优先考虑最小…...

从0到1构建AI深度学习视频分析系统--基于YOLO 目标检测的动作序列检查系统:(1)视频信息的获取与转发

文章大纲 基于YOLO的动作序列检查系统架构设计系统架构图实时视频传输协议技术对比视频流 常见协议对比表三、WebSocket内网传输设计方案四、样例程序(Python + JavaScript)五、性能优化建议新兴技术预警参考文献提示词参考基于YOLO的动作序列检查系统架构设计 系统架构图 #…...

大语言模型学习--LangChain

LangChain基本概念 ReAct学习资料 https://zhuanlan.zhihu.com/p/660951271 LangChain官网地址 Introduction | &#x1f99c;️&#x1f517; LangChain LangChain是一个基于语言模型开发应用程序的框架。它可以实现以下应用程序&#xff1a; 数据感知&#xff1a;将语言模型…...

【PCIe 总线及设备入门学习专栏 4.5 -- PCIe 中断 MSI 与 MSI-X 机制介绍】

文章目录 PCI 设备中断机制PCIe 设备中断机制PCIe MSI 中断机制MSI CapabilityMSI-X 中断机制MSI-X capabilityMSI-X TablePBAMSI-X capability 解析MSI/MSI-X 操作流程扫描设备配置设备MSI 配置MSI-X 配置中断触发与处理PCI 设备中断机制 以前的PCI 设备是支持 物理上的 INTA…...

wxWidgets GUI 跨平台 入门学习笔记

准备 参考 https://wiki.wxwidgets.org/Microsoft_Visual_C_NuGethttps://wiki.wxwidgets.org/Tools#Rapid_Application_Development_.2F_GUI_Buildershttps://docs.wxwidgets.org/3.2/https://docs.wxwidgets.org/latest/overview_helloworld.htmlhttps://wizardforcel.gitb…...

valgrind 检测多线程 bug,检测 并发 bug concurrent bug parallel bug

valgrind --toolhelgrind ./your_program 如果检测的对象是大型程序&#xff0c;可以设定仅在某些函数中开启 valgrind 的检测&#xff1a; Valgrind 提供了一些客户请求&#xff08;client requests&#xff09;&#xff0c;可以在代码中插入特定的宏来控制 Valgrind 的行为。…...

OpenMCU(一):STM32F407 FreeRTOS移植

概述 本文主要描述了STM32F407移植FreeRTOS的简要步骤。移植描述过程中&#xff0c;忽略了Keil软件的部分使用技巧。默认读者熟练使用Keil软件。本文的描述是基于OpenMCU_FreeRTOS这个工程&#xff0c;该工程已经下载放好了移植stm32f407 FreeRTOS的所有文件 OpenMCU_FreeRTOS工…...

割平面法的理解

割平面法的理解 1. 简介 割平面法&#xff08;Cutting Plane Method&#xff09;用于求解整数规划问题&#xff0c;通过逐步添加线性约束&#xff08;割平面&#xff09;逼近整数解。本文以Gomory割平面法为例&#xff0c;结合简单示例拆解核心步骤。 2. 示例详解 问题描述 …...

[自动驾驶-传感器融合] 多激光雷达的外参标定

文章目录 引言外参标定原理ICP匹配示例参考文献 引言 多激光雷达系统通常用于自动驾驶或机器人&#xff0c;每个雷达的位置和姿态不同&#xff0c;需要将它们的数据统一到同一个坐标系下。多激光雷达外参标定的核心目标是通过计算不同雷达坐标系之间的刚性变换关系&#xff08…...

C++ 学习(八)(模板,可变参数模板,模板专业化(完整模板专业化,部分模板专业化),类型 Traits,SFINAE(替换失败不是错误),)

C 模板 C 中的模板是一项强大的功能&#xff0c;允许您编写通用代码&#xff0c;这意味着您可以编写可以处理不同数据类型的单个函数或类。这意味着您无需为要使用的每种数据类型编写单独的函数或类。 模板函数 要创建模板函数&#xff0c;请使用 关键字&#xff0c;后跟类型…...

AI---DevOps常备工具(‌AI-Integrated DevOps Essential Tools)

AI---DevOps常备工具 技术领域正在迅速发展&#xff0c;随着我们步入 2025 年&#xff0c;有一点是明确的&#xff1a;人工智能&#xff08;AI&#xff09;不再只是一个流行词&#xff0c;它是每个 DevOps 工程师都需要掌握的工具。随着云环境的复杂性增加、对更快部署的需求以…...

题目梳理2025[长期更新]

题目梳理 组合类题目(2025年3月5日) 组合总数1&#xff0c;组合总数2&#xff0c;组合总数3 -> 递归回溯的思想 组合总数4 -> 爬楼的思想&#xff0c;动态规划&#xff0c;确定递归边界&#xff0c;确定递归入口&#xff0c;最后一步怎么走的思想...

Maven 中 SNAPSHOT 版本与 RELEASE 版本的区别

Maven 仓库分为 Snapshot 快照仓库和 Release 发行仓库两种类型的仓库。Snapshot 快照仓库用于保存 SNAPSHOT 版本&#xff0c;Release 发行仓库用于保存 RELEASE 版本。 SNAPSHOT 是一种特殊的版本标识&#xff0c;主要用于表示项目的不稳定、正在开发中的版本&#xff0c;而…...

JavaScript 知识点整理

1. 什么是AST&#xff1f;它在前端有哪些应用场景&#xff1f; AST Abstract Syntax Tree抽象语法树&#xff0c;用于表达源码的树形结构 应用&#xff1a; Babel&#xff1a;一个广泛使用的 JS 编译器&#xff0c;将ES6 或 JSX 等现代语法转换为兼容性较好的 ES5 代码。Esl…...

迷你世界脚本出生点接口:Spawnport

出生点接口&#xff1a;Spawnport 彼得兔 更新时间: 2023-04-26 10:19:56 具体函数名及描述如下: 序号 函数名 函数描述 1 getSpawnPoint(...) 获取默认出生点 2 setSpawnPoint(...) 设置出生点位置 3 getChunkValidSpawnPos(...) 获取区块有效刷新点…...

鸿蒙与DeepSeek深度整合:构建下一代智能操作系统生态

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/north 目录 技术融合背景与价值鸿蒙分布式架构解析DeepSeek技术体系剖析核心整合架构设计智能调度系统实现…...