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

news2025/3/6 11:53:37

文章目录

  • 前言
  • 正文
    • 一、项目环境
    • 二、项目代码
      • 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:
  # 硅基流动的url
  base-url: https://api.siliconflow.cn/v1
  # 秘钥(你自己申请的)
  api-key: sk-ezcxadqecocxisa

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 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 {

    @Resource
    private DeepSeekClient deepSeekClient;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(aiChatWebSocketHandler(), "/ws/chat")
                .setAllowedOrigins("*");
    }

    @Bean
    public 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);
    }

    @Override
    public 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();
        }
    }

    @Override
    protected 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();
    }

    @Override
    public 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的文本对话接口。因此后续可能不会继续完善了!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2310521.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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:…

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…

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;即支付机构将对账文件给到…

算法 之 贪心思维训练!

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

大语言模型学习--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…

OpenMCU(一):STM32F407 FreeRTOS移植

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

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

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

JavaScript 知识点整理

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

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

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

利用行波展开法测量横观各向同性生物组织的生物力学特性|文献速递-医学影像人工智能进展

Title 题目 Measurement of biomechanical properties of transversely isotropic biological tissue using traveling wave expansion 利用行波展开法测量横观各向同性生物组织的生物力学特性 01 文献速递介绍 纤维嵌入结构在自然界中普遍存在。从脑白质&#xff08;罗曼…

AR配置静态IP双链路负载分担示例

AR配置静态IP双链路负载分担示例 适用于大部分企业网络出口 业务需求&#xff1a; 运营商1分配的接口IP为100.100.1.2&#xff0c;子网掩码为255.255.255.252&#xff0c;网关IP为100.100.1.1。 运营商2分配的接口IP为200.200.1.2&#xff0c;子网掩码为255.255.255.248&am…