【ESP32接入国产大模型之Deepseek】

news2025/2/21 8:03:26

【ESP32接入国产大模型之Deepseek】

  • 1. Deepseek大模型
    • 1.1 了解Deepseek api
    • 1.2 Http接口鉴权
    • 1.3. 接口参数说明
    • 1.3.1 请求体(request)参数
    • 1.3.2 模型推理
  • 2. 先决条件
    • 2.1 环境配置
    • 2.2 所需零件
  • 3. 核心代码
    • 3.1 源码分享
    • 3.2 源码解析
    • 3.3 连续对话
      • 修改后的代码
      • 代码说明
      • 示例输出
      • 注意事项
  • 4. 上传验证
    • 4.1 对话测试
    • 4.2 报错
  • 5. 总结

1. Deepseek大模型

ESP32接入国产大模型之Deepseek

首先声明没有恰饭广告,源代码已经匿名处理,制作细节非常完善,方便大家复刻才会提供快捷的相关链接跳转!!!😘😘😘

在这里插入图片描述

DeepSeek 是一个先进的人工智能平台,旨在提供强大的对话和探索功能。它已经发布了性能更强的版本,并且已经开源,用户可以在网页端、APP 和 API 上注册使用。DeepSeek V3 是其最新的超级模型,用户可以免费与之对话,体验其强大的功能。

DeepSeek 的目标是探索未知的领域,提供创新的解决方案和工具。用户可以通过官方推出的手机 App 快速访问更多工具和资源。这个平台适合那些希望利用先进 AI 技术来增强其工作和生活体验的用户。。本文将重点介绍如何通过ESP32S3接入国产大模型之Deepseek api。
【ESP32接入国产大模型之腾讯混元】
上一篇博客已经分享了
【ESP32接入国产大模型之豆包】
【ESP32接入国产大模型之星火】
【ESP32接入国产大模型之MiniMax】
【ESP32接入语言大模型之智谱清言】
【ESP32接入国产大模型之文心一言】
【ESP32接入语言大模型之通义千问】
【ESP32接入国产大模型之kimi】
【ESP32接入国产大模型之Deepseek】
在这里插入图片描述

下面是不标准测评,参考而已

模型响应时间内容质量免费token次数地址
豆包2s9分50万https://www.volcengine.com/product/doubao
讯飞星火4s8分1亿https://www.xfyun.cn/doc/spark/HTTP%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3.html
MiniMax3s8分500万https://www.minimaxi.com/
智谱清言7s7分300万https://open.bigmodel.cn/
文心一言10s7分500万https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu
通义千问8s7分800万https://tongyi.aliyun.com/qianwen/
Kimi2s9分50万https://platform.moonshot.cn/docs/guide/start-using-kimi-api
混元6s8分50万https://cloud.tencent.com/document/product/1729/105701
Deepseek12s9分50万https://cloud.tencent.com/document/product/1729/105701

这一次还是采用Platformio编程就会轻松许多开发。这样就可以把大模型装进口袋啦🤣🤣🤣

1.1 了解Deepseek api

为方便用户使用,我们提供了 原生 HTTP 来实现模型 API 的调用。
Deepseek api

在这里插入图片描述

1.2 Http接口鉴权

Deepseek API 兼容了 OpenAI 的接口规范,这意味着您可以直接使用 OpenAI 官方提供的 SDK 来调用混元大模型。您仅需要将 base_url 和 api_key 替换成混元的相关配置,不需要对应用做额外修改,即可无缝将您的应用切换到混元大模型。详见鉴权认证方式。

  1. apikey
    进入 [API Key 管理]https://console.cloud.tencent.com/hunyuan/start)页面,在您有权限的项目下点击新建 API Key,即可生成长效 API Key。进入兼容OpenAI API KEY的创建页面,点击新建即可生成API KEY。
    点击创建api key
    在这里插入图片描述

API Key 签名鉴权方式要求在 HTTP 请求 header 中按如下方式添加 Authorization header:

Authorization: Bearer $ARK_API_KEY

1.3. 接口参数说明

1.3.1 请求体(request)参数

curl https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <DeepSeek API Key>" \
  -d '{
        "model": "deepseek-chat",
        "messages": [
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "Hello!"}
        ],
        "stream": false
      }'

注意

model选默认就好
在这里插入图片描述

1.3.2 模型推理

在这里插入图片描述

上下文拼接
在每一轮对话过程中,模型会输出思维链内容(reasoning_content)和最终回答(content)。在下一轮对话中,之前轮输出的思维链内容不会被拼接到上下文中,如下图所示:

在这里插入图片描述

2. 先决条件

在继续此项目之前,请确保检查以下先决条件。

我们将使用 Arduino IDE 对 ESP32/ESP8266 开发板进行编程,因此在继续本教程之前,请确保已在 Arduino IDE 中安装这些开发板。

2.1 环境配置

  1. Arduino IDE:下载并安装 Arduino IDE;
  2. ESP32 开发板库:在 Arduino IDE 中添加 ESP32 支持;
    参考博客:【esp32c3配置arduino IDE教程】
    为安装过程留出一些时间,具体时间可能因您的互联网连接而异。

2.2 所需零件

要学习本教程,您需要1个 ESP32 开发板或者ESP32C3,建议使用后者,笔者发现同样的代码后者可以轻松调用,ESP32不行(可能板子坏了)

目前这是我使用的ESP32S3官方硬件👍👍👍(小小的身材有大大的力量)只需要35元加摄像头麦克风79元,后期我会整理相关专栏进行Arduino系统学习😘😘😘。有需要可以购买xiao开发板💕💕💕

  1. SeeedXIAO ESP32S3 Sense硬件购买地址:https://s.click.taobao.com/lekazrt
    在这里插入图片描述

  2. ESP32-S3-CAM 核心开发板 N16R8 wifi蓝牙模块 OV2640摄像头硬件购买地址:https://s.click.taobao.com/1PTagos

在这里插入图片描述

3. 核心代码

3.1 源码分享

esp32S3 Arduino代码如下

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>

// 替换为您的 WiFi 凭据
const char *ssid = "IQOO";
const char *password = "12345678";

// 替换为您的 DeepSeek API 密钥
const char* apiKey = "sk-ea62673968ca4a34a1a1f6a82e4";

// DeepSeek API 端点
const char* host = "api.deepseek.com";
const int httpsPort = 443;

// 创建 WiFiClientSecure 对象
WiFiClientSecure client;

// 设置超时时间 (单位:毫秒)
const unsigned long timeout = 10000;

// 函数声明
void connectToWiFi();
String askDeepSeek(String question);
void printResponse(String response);

void setup() {
  Serial.begin(115200);

  // 连接到 WiFi
  connectToWiFi();

  // 关闭证书鉴权
  client.setInsecure();

  Serial.println("初始化完成,请输入您的问题:");
}

void loop() {
  // 检查串口是否有输入
  if (Serial.available()) {
    String question = Serial.readStringUntil('\n');
    question.trim(); // 去除换行符和空格

    if (question.length() > 0) {
      Serial.println("正在向 DeepSeek 提问...");
      String response = askDeepSeek(question);
      printResponse(response);
      Serial.println("\n请输入下一个问题:");
    }
  }
}

// 连接到 WiFi
void connectToWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("正在连接到 WiFi...");
  }
  Serial.println("已连接到 WiFi");
}

// 向 DeepSeek 提问
String askDeepSeek(String question) {
  String response = "";

  // 连接到 DeepSeek API
  if (!client.connect(host, httpsPort)) {
    Serial.println("连接失败");
    return "连接失败";
  }

  // 构建请求
  String request = "POST /v1/chat/completions HTTP/1.1\r\n";
  request += "Host: " + String(host) + "\r\n";
  request += "Authorization: Bearer " + String(apiKey) + "\r\n";
  request += "Content-Type: application/json\r\n";
  request += "Connection: close\r\n";

  // 构建请求体
  DynamicJsonDocument doc(1024);
  doc["model"] = "deepseek-chat";
  doc["messages"][0]["role"] = "user";
  doc["messages"][0]["content"] = question;
  doc["stream"] = true;

  String requestBody;
  serializeJson(doc, requestBody);

  request += "Content-Length: " + String(requestBody.length()) + "\r\n\r\n";
  request += requestBody;

  // 发送请求
  client.print(request);

  // 记录开始时间
  unsigned long startTime = millis();

  // 流式接收响应
  while (client.connected()) {
    // 检查超时
    if (millis() - startTime > timeout) {
      Serial.println("响应超时");
      break;
    }

    // 读取数据
    while (client.available()) {
      String line = client.readStringUntil('\n');
      if (line.startsWith("data: ")) {
        String jsonData = line.substring(6);
        DynamicJsonDocument doc(1024);
        deserializeJson(doc, jsonData);

        // 提取回复内容
        if (doc.containsKey("choices")) {
          String content = doc["choices"][0]["delta"]["content"];
          response += content;
        }
      }
    }
  }

  // 断开连接
  client.stop();
  return response;
}

// 打印回复内容
void printResponse(String response) {
  Serial.println("DeepSeek 回复:");
  Serial.println(response);
}

这段代码是一个基于Arduino平台(可能是ESP32或ESP8266)的示例,它通过WiFi连接到指定的无线网络,并利用HTTPClient库向智谱清言API发送POST请求以获取AI生成的回答。

3.2 源码解析

以下是详细的解释:

  1. 导入必要的库:
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

  1. 第一处修改定义Wi-Fi网络凭证:
// 1. Replace with your network credentials
const char *ssid = "IQOO";
const char *password = "12345678";
  1. 第二处修改定义要调用的APIkey:
// 2. Replace with your OpenAI API key
const char* apiKey = "sk-ea62673968ca4a34a1a1f6a82e4";

这段代码是一个用于ESP32微控制器的程序,旨在通过WiFi连接到DeepSeek API,并与之进行交互。以下是代码的主要功能概述:

  1. WiFi连接:代码首先连接到指定的WiFi网络(ssidpassword)。如果连接丢失,它会尝试重新连接。

  2. 用户输入处理:通过串口监视器,用户可以输入问题或消息。这些输入被发送到DeepSeek API进行处理。

  3. API请求:代码构建一个HTTP POST请求,包含用户输入的内容,并将其发送到DeepSeek API。请求使用JSON格式,并包含API密钥进行身份验证。

  4. 分块响应处理:由于API响应可能是分块的,代码实现了分块解析状态机来处理这些响应。它读取每个块的大小和数据,直到所有数据接收完毕。

  5. 响应解析:接收到的响应被解析为JSON格式,并提取出DeepSeek的回复内容。代码还提取并显示了使用的Token数量(输入、输出和总计)。

  6. 错误处理:代码包含了对连接失败、JSON解析错误和API错误的处理,确保在出现问题时能够提供有用的调试信息。

总体而言,这段代码展示了如何在ESP32上实现与远程API的交互,处理分块响应,并解析JSON数据。这对于需要与云服务进行通信的物联网(IoT)应用非常有用。

3.3 连续对话

为了实现上下文拼接功能,并让模型在每一轮对话中输出思维链内容,我们需要对代码进行以下改进:

  1. 维护对话历史:

    • 使用一个数组或列表来存储用户和模型的对话内容。
    • 每次对话时,将用户的问题和模型的回复添加到对话历史中。
  2. 拼接上下文:

    • 在每次请求时,将对话历史作为上下文传递给 DeepSeek API。
  3. 提取思维链内容:

    • 根据 DeepSeek API 的响应,提取模型输出的思维链内容(通常是一个字段,如 reasoningchain_of_thought)。

以下是修改后的代码:


修改后的代码

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>

// 替换为您的 WiFi 凭据
const char *ssid = "IQOO";
const char *password = "12345678";

// 替换为您的 DeepSeek API 密钥
const char* apiKey = "sk-ea62673968ca4a34a1a1f6a82e4";

// DeepSeek API 端点
const char* host = "api.deepseek.com";
const int httpsPort = 443;

// 创建 WiFiClientSecure 对象
WiFiClientSecure client;

// 设置超时时间 (单位:毫秒)
const unsigned long timeout = 10000;

// 对话历史
const int maxHistory = 10; // 最大对话轮次
String conversationHistory[maxHistory]; // 存储对话历史
int historyIndex = 0; // 当前对话历史索引

// 函数声明
void connectToWiFi();
String askDeepSeek(String question);
void printResponse(String response);
void addToHistory(String role, String content);
void printHistory();

void setup() {
  Serial.begin(115200);

  // 连接到 WiFi
  connectToWiFi();

  // 关闭证书鉴权
  client.setInsecure();

  Serial.println("初始化完成,请输入您的问题:");
}

void loop() {
  // 检查串口是否有输入
  if (Serial.available()) {
    String question = Serial.readStringUntil('\n');
    question.trim(); // 去除换行符和空格

    if (question.length() > 0) {
      // 将用户问题添加到对话历史
      addToHistory("user", question);

      Serial.println("正在向 DeepSeek 提问...");
      String response = askDeepSeek(question);
      printResponse(response);

      // 将模型回复添加到对话历史
      addToHistory("assistant", response);

      // 打印当前对话历史
      printHistory();

      Serial.println("\n请输入下一个问题:");
    }
  }
}

// 连接到 WiFi
void connectToWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("正在连接到 WiFi...");
  }
  Serial.println("已连接到 WiFi");
}

// 向 DeepSeek 提问
String askDeepSeek(String question) {
  String response = "";

  // 连接到 DeepSeek API
  if (!client.connect(host, httpsPort)) {
    Serial.println("连接失败");
    return "连接失败";
  }

  // 构建请求
  String request = "POST /v1/chat/completions HTTP/1.1\r\n";
  request += "Host: " + String(host) + "\r\n";
  request += "Authorization: Bearer " + String(apiKey) + "\r\n";
  request += "Content-Type: application/json\r\n";
  request += "Connection: close\r\n";

  // 构建请求体
  DynamicJsonDocument doc(1024);
  doc["model"] = "deepseek-chat";
  doc["stream"] = true;

  // 添加对话历史
  JsonArray messages = doc.createNestedArray("messages");
  for (int i = 0; i < historyIndex; i++) {
    JsonObject message = messages.createNestedObject();
    message["role"] = i % 2 == 0 ? "user" : "assistant"; // 交替用户和助手角色
    message["content"] = conversationHistory[i];
  }

  // 添加当前问题
  JsonObject newMessage = messages.createNestedObject();
  newMessage["role"] = "user";
  newMessage["content"] = question;

  String requestBody;
  serializeJson(doc, requestBody);

  request += "Content-Length: " + String(requestBody.length()) + "\r\n\r\n";
  request += requestBody;

  // 发送请求
  client.print(request);

  // 记录开始时间
  unsigned long startTime = millis();

  // 流式接收响应
  while (client.connected()) {
    // 检查超时
    if (millis() - startTime > timeout) {
      Serial.println("响应超时");
      break;
    }

    // 读取数据
    while (client.available()) {
      String line = client.readStringUntil('\n');
      if (line.startsWith("data: ")) {
        String jsonData = line.substring(6);
        DynamicJsonDocument doc(1024);
        deserializeJson(doc, jsonData);

        // 提取回复内容
        if (doc.containsKey("choices")) {
          String content = doc["choices"][0]["delta"]["content"];
          response += content;
        }

        // 提取思维链内容(假设字段为 "reasoning")
        if (doc.containsKey("choices") && doc["choices"][0].containsKey("delta") && doc["choices"][0]["delta"].containsKey("reasoning")) {
          String reasoning = doc["choices"][0]["delta"]["reasoning"];
          Serial.println("思维链: " + reasoning);
        }
      }
    }
  }

  // 断开连接
  client.stop();
  return response;
}

// 打印回复内容
void printResponse(String response) {
  Serial.println("DeepSeek 回复:");
  Serial.println(response);
}

// 添加对话历史
void addToHistory(String role, String content) {
  if (historyIndex < maxHistory) {
    conversationHistory[historyIndex] = content;
    historyIndex++;
  } else {
    // 如果历史记录已满,移除最早的记录
    for (int i = 0; i < maxHistory - 1; i++) {
      conversationHistory[i] = conversationHistory[i + 1];
    }
    conversationHistory[maxHistory - 1] = content;
  }
}

// 打印对话历史
void printHistory() {
  Serial.println("\n当前对话历史:");
  for (int i = 0; i < historyIndex; i++) {
    Serial.println((i % 2 == 0 ? "用户: " : "助手: ") + conversationHistory[i]);
  }
}

代码说明

  1. 对话历史管理:

    • 使用 conversationHistory 数组存储对话内容。
    • 通过 addToHistory 函数将用户问题和模型回复添加到历史中。
    • 如果历史记录已满,移除最早的记录以保持最大轮次。
  2. 上下文拼接:

    • 在每次请求时,将对话历史作为 messages 数组传递给 DeepSeek API。
  3. 思维链提取:

    • 假设 DeepSeek API 返回的思维链内容字段为 reasoning,在流式接收时提取并打印。
  4. 对话历史打印:

    • 使用 printHistory 函数打印当前对话历史,方便调试和观察上下文。

示例输出

初始化完成,请输入您的问题:
你好,DeepSeek!
正在向 DeepSeek 提问...
思维链: 用户打招呼,我需要回应问候。
DeepSeek 回复:
你好!我是 DeepSeek,很高兴为您服务。请问有什么可以帮您的?

当前对话历史:
用户: 你好,DeepSeek!
助手: 你好!我是 DeepSeek,很高兴为您服务。请问有什么可以帮您的?

请输入下一个问题:

注意事项

  1. API 字段名称:

    • 确保 reasoning 字段与 DeepSeek API 返回的思维链字段名称一致。如果不一致,请根据 API 文档修改。
  2. 历史记录长度:

    • 根据 ESP32 的内存限制,调整 maxHistory 的大小,避免内存不足。
  3. 流式数据解析:

    • 确保解析逻辑能够正确处理流式数据的分块传输。

希望这段代码能满足您的需求!如果有其他问题,请随时告诉我。

4. 上传验证

下面给出下载配置,请严格配置
platformio.ini文件

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32s3-cam]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
board_upload.flash_size = 16MB
board_build.partitions = default_16MB.csv
board_build.mcu = esp32s3
monitor_speed = 115200
upload_speed = 921600
lib_deps = 
	bblanchon/ArduinoJson@^7.3.0

4.1 对话测试

打开串口监视器,注意右下角选择回车符,选择115200波特率,输入你想问的问题,他就可以回答你

在这里插入图片描述

个人感觉混元比其他国内大模型响应有点快啦,大约10s返回,太爽啦!😘😘😘

4.2 报错

如果返回error ,大家对照列表查询错误代码,结合提示排查解决

在这里插入图片描述

5. 总结

🥳🥳🥳现在,我们在本教程中,您学习了如何使用ESP32接入语言大模型之Deepseek。🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境,后期会持续分享esp32跑freertos实用案列🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣

如果你有任何问题,可以通过q group(945348278)加入鹏鹏小分队,期待与你思维的碰撞😘😘😘

鸣谢B站UP星汇极客
参考文献:ESP32对接DeepSeek API,实现AI大模型交互功能。

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

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

相关文章

C语言蓝桥杯1003: [编程入门]密码破译

要将"China"译成密码&#xff0c;译码规律是&#xff1a;用原来字母后面的第4个字母代替原来的字母&#xff0e; 例如&#xff0c;字母"A"后面第4个字母是"E"&#xff0e;"E"代替"A"。因此&#xff0c;"China"应译…

SolidWorks速成教程P3-3【零件 | 第三节】——草图绘制面实线与构造线的区别

经过了前面的特征学习后,是不是感觉对 SolidWorks越来越熟悉了?不过发现, SolidWorks速成这套教程,对于一些基础问题,还是需要解释得更详细一些,所以在这节再补充一下草图绘制面&实线与构造线的区别。 目录 1.草图绘制面 2.实线与构造线的区别 1.草图绘制面 之前…

win10中mstsc远程Centos-Stream 9图形化界面

文章目录 1 前置状态2 安装配置XRDP3 关闭SELinux3.1 查看selinux状态3.2 关闭selinux 4 启动XRDP5 Win10远程连接测试 1 前置状态 已安装CentOS9桌面版&#xff1b;Windows10。 2 安装配置XRDP sudo yum install epel-release sudo yum install xrdp sudo yum install tige…

中国AI“拥抱开源”给世界的启示——Anko

事实证明&#xff0c;中国AI企业“拥抱开源”&#xff0c;不仅为自身发展开拓了新路径&#xff0c;也带动AI企业跨国合作的需求&#xff0c;并推动全球AI生态向“开源普惠”转型。Anko通过免费开放部分模型功能&#xff0c;将AI时代的数字红利公平地派发到每一位网民手中&#…

DeepSeek处理自有业务的案例:让AI给你写一份小众编辑器(EverEdit)的语法着色文件

1 DeepSeek处理自有业务的案例&#xff1a;让AI给你写一份小众编辑器(EverEdit)的语法着色文件 1.1 背景 AI能力再强&#xff0c;如果不能在企业的自有业务上产生助益&#xff0c;那基本也是一无是处。将企业的自有业务上传到线上训练&#xff0c;那是脑子进水的做法&#xff…

Jenkins 配置 Git Parameter 四

Jenkins 配置 Git Parameter 四 一、开启 项目参数设置 勾选 This project is parameterised 二、添加 Git Parameter 如果此处不显示 Git Parameter 说明 Jenkins 还没有安装 Git Parameter plugin 插件&#xff0c;请先安装插件 Jenkins 安装插件 三、设置基本参数 点击…

网络工程师 (38)流量和差错控制

一、流量控制 流量控制是一种协调发送站和接收站工作步调的技术。它的主要目的是防止发送端发送数据过快&#xff0c;导致接收端缓冲区溢出&#xff0c;从而造成数据丢失。流量控制机制通过调整发送速率来匹配接收端的处理能力。 基本原理 发送站每发出一帧数据&#xff0c;就进…

从零开始:Django初学者的实战之旅

一、概念引入 要基于编程开发一个完整的企业项目不管什么样的项目&#xff0c;基本都有3种不同的开发模式&#xff0c;这几种开发模式&#xff0c;如果把项目类比成建造房子则有如下&#xff1a; 1.原生开发&#xff1a;类似从0开始造房子&#xff0c;从0开始构建项目&#xf…

青果教务系统逆向(js逆向)

首先我们打开f12检查以下登录函数 可以看到登录函数在checkrand中&#xff0c;直接去全局搜索函数 在这里&#xff0c;打个断点直接跳进去 可以看到参数在这里形成 这是我们发起请求需要的参数&#xff0c;把这几个参数加进去直接登录就行 那就一个一个看呗&#xff0c;第一…

在Linux中Redis不支持lua脚本的处理方法

redis安装在IP为x.x.x.x的服务器上 redis安装 第一步&#xff0c;安装前&#xff0c;检测系统是否安装了redis。若安装了redis&#xff0c;则需要删除redis&#xff1b;若没有安装redis&#xff0c;则需要安装2.6版本以上的redis。 # 确保Redis版本支持Lua脚本。从Redis 2.6…

WPF进阶 | 深入 WPF 依赖项属性:理解其强大功能与应用场景

WPF进阶 | 深入 WPF 依赖项属性&#xff1a;理解其强大功能与应用场景 前言一、依赖项属性基础概念1.1 什么是依赖项属性1.2 依赖项属性与 CLR 属性的区别1.3 依赖项属性的定义与注册 二、依赖项属性的原理深入剖析2.1 依赖项属性系统的工作机制2.2 元数据&#xff08;Metadata…

关于 IoT DC3 中设备(Device)的理解

在物联网系统中&#xff0c;设备&#xff08;Device&#xff09;是一个非常宽泛的概念&#xff0c;它可以指代任何能够接入系统并进行数据交互的实体。包括但不限于手机、电脑、服务器、网关、硬件设备甚至是某些软件程序等所有能接入到该平台的媒介。 内容 定义 目的 示例 …

从 0 开始本地部署 DeepSeek:详细步骤 + 避坑指南 + 构建可视化(安装在D盘)

个人主页&#xff1a;chian-ocean 前言&#xff1a; 随着人工智能技术的迅速发展&#xff0c;大语言模型在各个行业中得到了广泛应用。DeepSeek 作为一个新兴的 AI 公司&#xff0c;凭借其高效的 AI 模型和开源的优势&#xff0c;吸引了越来越多的开发者和企业关注。为了更好地…

Uniapp 获取定位详解:从申请Key到实现定位功能

文章目录 前言一、申请定位所需的 Key1.1 注册高德开发者账号1.2 创建应用1.3 添加 Key 二、在 Uniapp 中配置定位功能2.1 引入高德地图 SDK2.2 获取定位权限 三、实现定位功能3.1 使用 uni.getLocation 获取位置3.2 处理定位失败的情况3.3 持续定位3.4 停止持续定位 四、总结 …

Spring系统学习——持续更新

spring概述 1.轻量级的开源的JAVAEE框架 2.解决企业应用开发的复杂性 3.两大核心 &#xff1a;IOC&#xff08;控制反转&#xff09;和AOP&#xff08;面向切面&#xff09; 4.Spring特点&#xff1a; 1.方便解耦&#xff0c;简化开发。2.Aop编程支持3.方便程序测试4.方便和其…

QT笔记——QRadioButton

文章目录 1、概要2、实际的应用2.1、创建多个QRadioButton,只可同时选中其中一个&#xff0c;点击后实现对应的槽函数 1、概要 实现QRadioButton相关的应用&#xff1b;2、实际的应用 2.1、创建多个QRadioButton,只可同时选中其中一个&#xff0c;点击后实现对应的槽函数 创建…

微服务面试题:远程调用

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

C++17 中的 std::reduce:详细教程

文章目录 1. 简介2. 函数签名3. 使用场景3.1 简单的累加操作3.2 自定义归并操作3.3 并行计算的性能优势 4. 注意事项4.1 归并操作的结合律和交换律4.2 默认值的使用 5. 总结 1. 简介 std::reduce 是 C17 标准库中引入的一个算法&#xff0c;用于对范围内的元素进行归并操作。它…

Navicat导入海量Excel数据到数据库(简易介绍)

目录 前言正文 前言 此处主要作为科普帖进行记录 原先Java处理海量数据的导入时&#xff0c;由于接口超时&#xff0c;数据处理不过来&#xff0c;后续转为Navicat Navicat 是一款功能强大的数据库管理工具&#xff0c;支持多种数据库系统&#xff08;如 MySQL、PostgreSQL、…

【Map vs Set】:Java数据存储的“双子星”对决

个人主页&#xff1a;♡喜欢做梦 欢迎 &#x1f44d;点赞 ➕关注 ❤️收藏 &#x1f4ac;评论 目录 &#x1f370;一、搜索 &#x1f36e;1.概念 &#x1f36e;2.模型 &#x1f370;二、Map &#x1f368;1.什么是Map&#xff1f; &#x1f368;2.Map的实例化 &…