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

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

【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大模型交互功能。

相关文章:

  • 2.5 模块化迁移策略:从传统项目到模块化系统
  • 算法——结合实例了解启发式搜索
  • 网络安全的现状如何?
  • LabVIEW 中dde.llbDDE 通信功能
  • linux中top命令详解
  • linux 释放9090端口
  • 多模态识别和自然语言处理有什么区别
  • 100N10-ASEMI小家电专用MOS管100N10
  • 51单片机俄罗斯方块开机动画
  • TypeScript装饰器 ------- 学习笔记分享
  • 数据结构 双链表的模拟实现
  • 32单片机学习记录4之串口通信
  • Word写论文常用操作的参考文章
  • DeepSeek应用——与PyCharm的配套使用
  • Java实现HTTPS双向认证的终极指南:从原理到实战
  • DeepSeek R1打造本地化RAG知识库
  • 腾讯发布混元-3D 2.0: 首个开源高质3D-DiT生成大模型
  • CentOS-Stream 9安装
  • 【开源免费】基于SpringBoot+Vue.JS商品秒杀系统(JAVA毕业设计)
  • DeepSeek应用——与word的配套使用
  • 盐城网站定制/电商大数据查询平台免费
  • 常州微信网站建设流程/网络工程师培训一般多少钱
  • 建站之星如何建网站/自己怎么优化网站排名
  • 怎么创建个网站/it培训机构哪家好
  • 小程序询价表/seo百度点击软件
  • 德州网站优化/徐州seo外包平台