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

关于我对接了deepseek之后部署到本地将数据存储到mysql的过程

写在前面

今天写一下使用nodejs作为服务端,vue作为客户端,mysql的数据库,对接deepseek的全过程,要实现一个很简单的效果就是,可以自由的询问,然后可以将询问的过程存储到mysql的数据库中。

文档对接

deepseek对接文档

效果图

在这里插入图片描述

服务端代码
  • 这里避免你们看的时候费劲,所以这里不做任何封装,正常你们如果用代码,可以将连接数据、输出答案的过程封装起来。下面的代码为不封装的,仅供参考!别说我写代码不封装,最讨厌这种人。以下为nodejs代码
插件安装
npm i cors
npm i mysql2
npm i openai
var createError = require("http-errors");
var express = require("express");
var path = require("path");
var OpenAI = require("openai"); 
var cors = require("cors");

const mysql = require("mysql2/promise");

// 创建数据库连接池
const pool = mysql.createPool({
  host: "127.0.0.1", 
  port: 3306, 
  user: "root",
  password: "实际情况来!",
  database: "deepseek",
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
});
// 测试链接情况
pool
  .getConnection()
  .then((connection) => {
    console.log("数据库连接成功");
    connection.release();
  })
  .catch((err) => {
    console.error("数据库连接失败:", err);
  });

var app = express();
// 启用 CORS 避免本地调用出现的跨域问题
app.use(cors());
// 格式化返回数据为JSON格式
app.use(express.json());

// 初始化OpenAI客户端
const openai = new OpenAI({
  baseURL: "https://api.deepseek.com", // 官方固定的地址
  apiKey: "自己的key",
});

// 添加POST路由处理聊天请求
app.post("/chat", async (req, res) => {
  // console.log("收到请求:", req.body);
  // 添加这行来收集完整回答
  let fullAnswer = ""; 

  try {
    // 引入官方文档语法
    const completion = await openai.chat.completions.create(
      {
        messages: req.body.messages || [
          { role: "system", content: "You are a helpful assistant." },
        ],
        model: "deepseek-chat",
        stream: true,
      },
      { responseType: "stream" }
    );

    // 设置响应头
    res.setHeader("Content-Type", "text/event-stream");
    res.setHeader("Cache-Control", "no-cache");
    res.setHeader("Connection", "keep-alive");

    // 处理流式响应
    for await (const chunk of completion) {
      const content = chunk.choices[0]?.delta?.content || "";
      if (content) {
        fullAnswer += content; // 累积完整回答
        res.write(`data: ${JSON.stringify(chunk)}\n\n`);
      }
    }

    const connection = await pool.getConnection();
    try {
      console.log("准备存储到数据库:", {
        question: req.body.messages[0].content,
        answer: fullAnswer,
      });
      const [result] = await connection.execute(
        "INSERT INTO chat_history (question, answer) VALUES (?, ?)",
        [req.body.messages[0].content, fullAnswer]
      );
      console.log("数据库存储结果:", result);
    } catch (dbError) {
      console.error("数据库存储错误:", dbError);
    } finally {
      connection.release();
    }

    // 添加结束标记
    res.write("data: [DONE]\n\n"); 
    res.end();
  } catch (error) {
    console.error("Error:", error);
    if (!res.headersSent) {
      // 检查是否已经发送响应头
      res.status(500).json({ error: error.message });
    } else {
      res.write(`data: ${JSON.stringify({ error: error.message })}\n\n`);
      res.end();
    }
  }
});

// 添加服务启动监听
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`DeepSeek 服务已启动,监听端口: ${port}`);
});

module.exports = app;

客户端代码

这里为了简单,就没有对css进行scss处理,喜欢折腾的自己改一下样式也可以

插件安装
npm i axios
<template>
  <div class="chat-container">
    <div class="input-wrapper">
      <input
        class="ai-input"
        type="text"
        v-model="questionMsg"
        placeholder="请输入您的问题..."
        @keyup.enter="main"
      />
      <button class="ai-btn" @click="main">
        <span>询问</span>
      </button>
    </div>
    <textarea
      class="ai-area"
      v-model="answer"
      placeholder="AI 回答将显示在这里..."
      readonly
    ></textarea>
  </div>
</template>

<script setup>
import axios from 'axios';
import { ref } from "vue";

const questionMsg = ref("");
const answer = ref("");
const loading = ref(false);

async function main() {
  if (!questionMsg.value.trim()) return;
  loading.value = true;
  answer.value = "";

  try {
    const response = await axios({
      method: 'post',
      url: 'http://localhost:3000/chat',
      data: {
        messages: [
          {
            role: "system",
            content: questionMsg.value,
          },
        ],
        model: "deepseek-chat",
        stream: true
      },
      headers: {
        'Authorization': 'Bearer 自己的key',
        'Content-Type': 'application/json',
      },
      responseType: 'text', // 改为 text 类型
    });

    // 处理返回的文本数据
    const lines = response.data.split('\n').filter(line => line.trim() !== '');
    for (const line of lines) {
      if (line.startsWith('data: ')) {
        try {
          const data = JSON.parse(line.slice(6));
          const content = data.choices[0]?.delta?.content || '';
          answer.value += content;
        } catch (e) {
          console.error('Parse error:', e);
        }
      }
    }
  } catch (error) {
    console.error("Error:", error);
    answer.value = "抱歉,发生了错误,请稍后重试。";
  } finally {
    loading.value = false;
  }
}
</script>

<style>
.chat-container {
  max-width: 800px;
  margin: 40px auto;
  padding: 20px;
  border-radius: 12px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  background-color: #ffffff;
}

.input-wrapper {
  display: flex;
  gap: 15px;
  margin-bottom: 20px;
}

.ai-input {
  flex: 1;
  height: 45px;
  padding: 0 15px;
  border: 2px solid #e8e8e8;
  border-radius: 8px;
  font-size: 16px;
  transition: all 0.3s ease;
}

.ai-input:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}

.ai-btn {
  min-width: 100px;
  height: 45px;
  border: none;
  border-radius: 8px;
  background-color: #409eff;
  color: #fff;
  font-size: 16px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
}

.ai-btn:hover {
  background-color: #66b1ff;
  transform: translateY(-1px);
}

.ai-btn:active {
  transform: translateY(1px);
}

.ai-area {
  width: 100%;
  min-height: 200px;
  padding: 15px;
  border: 2px solid #e8e8e8;
  border-radius: 8px;
  font-size: 15px;
  line-height: 1.6;
  resize: vertical;
  transition: all 0.3s ease;
}

.ai-area:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}
</style>

数据库设计

因为我主要是搞前端的,所以对数据库设计这块无法整的很好,后端的大佬看到就不要笑我了,这里我只是简单的演示一下整个处理的过程,所以表设计也是非常简单的。我用的数据库客户端也是DBeaver,非常简单的一个客户端。

CREATE DATABASE IF NOT EXISTS deepseek;
USE deepseek;

CREATE TABLE IF NOT EXISTS chat_history (
    id INT AUTO_INCREMENT PRIMARY KEY,
    question TEXT NOT NULL,
    answer TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
存储之后的效果

在这里插入图片描述

服务端拦截到的日志

在这里插入图片描述

总结

整体对接下来,因为我对接的是最基础的,你们可以看到这里我甚至没有做连续对话和长链接的形式对接,虽然用了stream的形式处理的,但是其实并没有达到这种效果,你们对接的时候可以看文档自己多做几步处理,今天的文章就先这样吧,感觉不错的可以关注一下哦!


http://www.kler.cn/a/612154.html

相关文章:

  • Selenium基本使用(三)隐藏框、获取文本、断言、切换窗口
  • 【数据可视化艺术·进阶篇】热力图探秘:用色彩演绎场馆和景区的人流奥秘
  • Xcode 打开报错 / 解決 Could not open workspace file at xxx 问题
  • vue2自定义指令实现滚动动画-使用IntersectionObserver观察器
  • 从零构建大语言模型全栈开发指南:第三部分:训练与优化技术-3.1.3分布式数据加载与并行处理(PyTorch DataLoader优化)
  • nestjs 连接redis
  • 数据可视化(matplotlib)-------图表样式美化
  • 蓝桥杯第十届 数的分解
  • Linux——进程信号(1)(signal与sigaction)
  • java程序员实用英语学习总结
  • linux scp复制多层级文件夹到另一服务器免密及脚本配置
  • 【深度学习与实战】2.1、线性回归模型与梯度下降法先导
  • [250324] Kafka 4.0.0 版本发布:告别 ZooKeeper,拥抱 KRaft!| Wine 10.4 发布!
  • Apache Shiro 全面指南:从入门到高级应用
  • 网络安全可以去哪些单位工作
  • Windows 图形显示驱动开发-WDDM 2.7功能-MCDM KM 驱动程序实现指南(三)
  • Anaconda 安装NCL (Linux系统)
  • ArcGIS字段计算器的详细使用案例
  • 机器学习核心评估指标解析:AUC-ROC、RMSE、轮廓系数与PR AUC详解
  • 深度解析 | Android 12系统级禁用SIM卡功能实现与Framework层定制