利用Qt开发自己的DeepSeek终端

前言:

        2025年开年大作应该可以有DeepSeek的一席之地了,而且现在可以说是日活跃度非常高的一个大模型,所以说了解并掌握他的API是一个必要的开发过程。博主通过之前的百度AI开发心路写了一下关于DeepSeek的一个简单demo,以供大家参考学习。

正文:

一、构思

        其实这个项目对于我来说已经不陌生了,参考我之前的项目文章就可以略知一二。利用Qt制作基于百度Ai的智能语音聊天机器人_基于qt的智能机器人-优快云博客文章浏览阅读2.8k次,点赞9次,收藏41次。在学习和使用Qt框架制作ui的过程中,渐渐发现自己可以搞一个智能机器人的ui界面用于聊天和前端控制底层的Ros框架,于是就开始了断断续续长达5day的项目开发周期。技术栈:在这个项目里,首先就是要用到Qt的设计框架,用到了一个类作为聊天窗口,一个QlineEdit作为聊天输入框,还有一些作为控制交互单元,一些QLabel作为显示单元,当然还有布局器等等...最后就是用到http请求和js解析。语音录入->语音识别转文字->文字内容上传得到Ai回答->Ai回答内容转语音。_基于qt的智能机器人https://blog.youkuaiyun.com/qq_60640693/article/details/131167764?spm=1001.2014.3001.5502其实,原理都是差不多的,利用JSON数据的填充、发送、接收和解析来完成对API的调用。

二、了解API

        这一步其实是很重要的,需要我们到对应的官网找到API的一些相关文档,了解数据结构和CURL已经创建自己的Key。

通过DeepSeek来创建自己的API的key,进入后,选择API开放平台,进入后该注册注册,该登录登录

           

OK,当你去到接口文档中,就可以看到我下面绿色框内的信息,这其实就是我们发送的JSON数据的填充方式,也就是我所说的数据结构,而且他也提供了CURL,现在只是差一个key了,你只需要回到上一个页面去申请一个,并复制就好了。

三、开始开发

        提示: 由于DeepSeek是在是太火爆了服务器经常挺不住,博主针对上面的文档开发完了也不能正常使用,于是我就换了另一个支持DeepSeek的服务商硅基流动统一登录,注册API会送14元余额,够学习使用了。

        和DeepSeek一样,注册登录后直接去API秘钥(创建自己的key)和文档中心(查看API的调用方式)。

文档中心中点击API手册就可以看到类似DeepSeek文档的东西了那么最关键的就是这个字符串

curl --request POST \
  --url https://api.siliconflow.cn/v1/chat/completions \
  --header 'Authorization: Bearer <我们申请的KEY token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "deepseek-ai/DeepSeek-V3",
  "messages": [
    {
      "role": "user",
      "content": "中国大模型行业2025年将会迎来哪些机遇和挑战?"
    }
  ],
  "stream": false,
  "max_tokens": 512,
  "stop": [
    "null"
  ],
  "temperature": 0.7,
  "top_p": 0.7,
  "top_k": 50,
  "frequency_penalty": 0.5,
  "n": 1,
  "response_format": {
    "type": "text"
  },
  "tools": [
    {
      "type": "function",
      "function": {
        "description": "<string>",
        "name": "<string>",
        "parameters": {},
        "strict": false
      }
    }
  ]
}'

我们就只需要将我们申请的KEY填入再用Qt的NetWork模块相关功能来填充和发送出去就好了。

代码:

main.cpp
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
widget.cpp(界面相关的代码)
#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(&n,&Net::Answer,this,&Widget::getAnswer);
    //this->setWindowState(Qt::WindowMaximized);//界面最大化
    ui->label->setWordWrap(true);
    n.init();
}

Widget::~Widget()
{
    delete ui;

}

void Widget::on_pushButton_clicked()
{
    ui->label->setText("让我找找^_^ 看怎么回答你...");
    QString word =ui->textEdit->toPlainText();
    ui->textEdit->clear();
    n.send(word);
}

void Widget::getAnswer(QString word)
{
    ui->label->setText(word);
}
net.cpp(Json请求和数据解析的相关代码)
#include "net.h"

Net::Net()
{

}

void Net::init()
{

    _manager = new QNetworkAccessManager();
    _request.setUrl(QUrl(_curl_https));

    // 头部信息
    _request.setRawHeader("Authorization", ("Bearer " + _api_key).toUtf8());
    _request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

//    qDebug() << "QSslSocket=" << QSslSocket::sslLibraryBuildVersionString();
//    qDebug() << "OpenSSL支持情况:" << QSslSocket::supportsSsl();
}

int Net::send(QString word)
{

    //qDebug() << word;

    // messages部分
    QJsonArray messages;
    QJsonObject text1;
    text1["role"] = "user";
    text1["content"] = word;
    messages.append(text1);

    QJsonObject data;
    data["model"] = _model;
    data["messages"] = messages;
    data["stream"] = false;

    data["max_tokens"] = 512;
    data["stop"] = QJsonArray({"null"});
    data["temperature"] = 0.7;
    data["top_p"] = 0.7;
    data["top_k"] = 50;
    data["frequency_penalty"] = 0.5;
    data["n"] = 1;
    data["response_format"] = QJsonObject{{"type", "text"}};


    QJsonArray tools;
    QJsonObject tool;
    tool["type"] = "function";
    QJsonObject function;
    function["description"] = ""; //Fill in if needed
    function["name"] = "";       //Fill in if needed
    function["parameters"] = QJsonObject{};
    function["strict"] = false;
    tool["function"] = function;
    tools.append(tool);
    data["tools"] = tools;

    QJsonDocument doc(data);
    QByteArray postData = doc.toJson();

    QSslConfiguration config = QSslConfiguration::defaultConfiguration();
    config.setProtocol(QSsl::AnyProtocol);
    config.setPeerVerifyMode(QSslSocket::VerifyNone);
    _request.setSslConfiguration(config);

    //发送post请求
    _reply = _manager->post(_request, postData);

    // 链接槽函数
    // 连接信号槽处理响应
    connect(_reply, &QNetworkReply::finished,this,&Net::getAnswer);
    return true;
}

void Net::getAnswer()
{
    if(_reply != nullptr && _reply->error() == QNetworkReply::NoError)
    {
        //得到返回的数据
        QByteArray read_data = (_reply->readAll());

        //对返回的json数据进行解析
        QJsonObject obj = QJsonDocument::fromJson(read_data).object();

        QJsonArray choicesarray = obj.value("choices").toArray();
        if (!choicesarray.isEmpty())
        {
            QJsonObject choiceobj = choicesarray[0].toObject();
            if (choiceobj.contains("message") && choiceobj["message"].isObject())
            {
                QJsonObject messageobj = choiceobj["message"].toObject();
                if (messageobj.contains("content") && messageobj["content"].isString())
                {
                    QString rawContent = messageobj["content"].toString();
                    QRegularExpression regex("```json\\n(.*?)\\n```");
                    QRegularExpressionMatch match = regex.match(rawContent);
                    if (match.hasMatch())
                    {
                        QString innerJsonStr = match.captured(1);
                        QJsonDocument innerDoc = QJsonDocument::fromJson(innerJsonStr.toUtf8());
                        if (!innerDoc.isNull() && innerDoc.isObject())
                        {
                            QJsonObject innerObj = innerDoc.object();
                           if(innerObj["key"].toString().isEmpty())
                           {
                                emit Answer("你让我怎么回答你嘛...@_@");
                           }
                           else
                           {
                              emit Answer(innerObj["key"].toString());
                           }
                        }
                    }
                    else
                    {
                        emit Answer(messageobj["content"].toString());
                    }

                }
            }
        }
    }
    else
    {

      emit Answer( "https request error:"+_reply->errorString());
    }
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H

#define LB_HEIGHT 30
#define LB_WIDTH 100

#include <QWidget>
#include "net.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public slots:
    void getAnswer(QString word);

private slots:
    void on_pushButton_clicked();


private:
    Ui::Widget *ui;
    Net n;
};
#endif // WIDGET_H
net.h
#ifndef NET_H
#define NET_H

#include <QObject>
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QString>

class Net:public QObject
{
    Q_OBJECT //对信号和槽至关重要
public:
    Net();
    void init();
    int send(QString word);

private slots:
       void getAnswer();

private:

    QNetworkRequest _request; // 封装网络请求信息
    QNetworkAccessManager *_manager; // 管理网络请求和响应
    QNetworkReply *_reply; // 网络请求响应

    QString _curl_https = "https://api.siliconflow.cn/v1/chat/completions";
    QString _model = "deepseek-ai/DeepSeek-V3";
    QString _api_key = "你的秘钥";
    QString _read_text;

signals:
       void Answer(QString word);
};

#endif // NET_H
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>819</width>
    <height>580</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="minimumSize">
   <size>
    <width>0</width>
    <height>0</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
  <property name="styleSheet">
   <string notr="true"/>
  </property>
  <layout class="QGridLayout" name="gridLayout_3">
   <item row="1" column="0">
    <widget class="QFrame" name="frame">
     <property name="frameShape">
      <enum>QFrame::StyledPanel</enum>
     </property>
     <property name="frameShadow">
      <enum>QFrame::Raised</enum>
     </property>
     <layout class="QGridLayout" name="gridLayout">
      <item row="0" column="0" colspan="2">
       <widget class="QLabel" name="label">
        <property name="styleSheet">
         <string notr="true">background-color: rgb(85, 87, 83);
color: rgb(138, 226, 52);</string>
        </property>
        <property name="text">
         <string/>
        </property>
       </widget>
      </item>
      <item row="1" column="0">
       <widget class="QTextEdit" name="textEdit">
        <property name="maximumSize">
         <size>
          <width>16777215</width>
          <height>60</height>
         </size>
        </property>
       </widget>
      </item>
      <item row="1" column="1">
       <widget class="QPushButton" name="pushButton">
        <property name="text">
         <string>问你</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
CMakeLista.txt
cmake_minimum_required(VERSION 2.8)

project(deepSeek)

find_package(Qt5 COMPONENTS Widgets Core Gui REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

set(SOURCES
    src/main.cpp
    src/widget.cpp
    src/net.cpp
    src/widget.ui
)

set(HEADS
    include/widget.h
    include/net.h
    )
#加载头文件到环境中
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/include/
    ${Qt_INCLUDE_DIRS}
)

add_executable(deepSeek ${SOURCES} ${HEADS})
#链接所有动态链接库
target_link_libraries(deepSeek Qt5::Widgets Qt5::Core Qt5::Gui)

项目链接

        git地址icon-default.png?t=O83Ahttps://github.com/xs-sam/DeepSeek.git

        百度网盘链接icon-default.png?t=O83Ahttps://pan.baidu.com/s/1HBJUmR-HZiif05e1KNyYDg?pwd=xs66

四、实现效果

点击 问你......等待一会儿。

      

完成啦...

结语:

        该说不说,这个DeepSeek确实可以称得上国产大语言模型的骄傲,用更低的成本达到了同等水平的GPT性能,为这些科研人员点赞;关键是这东西还开源,我感觉这能被玩出花样了,以后把他本地部署在自己的机器人上,甚至可以用来处理一些逻辑性强的问题,不过就是现在的服务器压力太大了,还是给他点时间我相信会发展的更好 哈哈哈 ,完结 撒花...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值