后端接入DeepSeek全攻略:从本地部署到API调用全流程解析

1,856 阅读7分钟

一、引言:DeepSeek的性价比优势与开源生态

1. 成本对比:DeepSeek的百万tokens成本仅为OpenAI的1/280。

OpenAI的训练成本高昂,与其对算力的极端依赖直接相关。据披露,GPT-4o的训练成本高达1.1亿美元,主要源于其采用的百万级英伟达A100/H100 GPU集群 。这种“堆算力”的模式不仅消耗巨额资金,还受限于英伟达GPU的出口管制政策,进一步推高成本。

相比之下,DeepSeek通过算法架构创新将训练成本压缩至557.6万美元(仅为GPT-4o的5%),其核心突破在于绕开CUDA生态的硬件依赖

DeepSeek的案例证明,算法突破比硬件堆砌更具颠覆性。当行业还在争论“多少块H100才能训练大模型”时,DeepSeek已通过架构创新让算力需求“瘦身”90%。这种“用算法换算力”的思路,不仅为AI普惠铺平道路,更可能改写全球科技竞争的底层逻辑。

2.开源优势低成本+开源使得DeepSeek的全球用户用户爆炸式增长。开源策略使DeepSeek生态繁荣,并且支持本地化部署。DeepSeek-R1模型性能与OpenAI持平,但推理成本更低。

二、Ollama本地部署DeepSeek

Ollama是一款轻量级本地大语言模型运行框架,支持在CPU/GPU设备上离线运行DeepSeek、Llama等开源模型,无需依赖云端服务。

训练好的大模型(LLM),是要有自己的运行环境的,包括NLP(神经网络)和机器学习Transformers机制

我们来到ollama官网ollama.com/ ,把ollama下载下来。然后来到ollama官网的Models页面,这里有很多ollama支持本地部署的大模型,我们选择deepseek-r1

image.png 这里的1.5b,7b中的“b”表示模型的参数量(Parameter Count)​,单位是亿(Billion,简写为b)​,用于衡量模型的规模和复杂度。这里我就以1.5b为例,复制命令ollama run deepseek-r1:1.5b到cmd运行,电脑会自动下载deepseek1.5b版本的源代码。

image.png 下载成功是这样的,我们就完成了deepseek的本地部署。

三、后端接入DeepSeek

在后端接入deepseek前需要明白:

  • 本地运行的 deepseek,是可以被 ajax 通信的
  • 端口为11434
  • 接口路径为/api/chat
  • 发送post请求

向AI发post请求时要传的参数data要写成下面的样子, 这是openai 制定的行业标准

    // 当前 openai 制定的标准,行业标准
    const data = {
      model: 'deepseek-r1:1.5b', // 模型名称
      messages: [
        {
          role: 'user', // 角色
          content:'你好'
        }
      ],
      stream: false // 是否流式返回
    }

我们先用postman来测试一下朝http://localhost:11434/api/chat 发送post请求会得到什么(得先确保本地部署的deepseek在运行中)

{
    "model": "deepseek-r1:1.5b",
    "created_at": "2025-02-28T03:54:01.210382Z",
    "message": {
        "role": "assistant",
        "content": "<think>\n\n</think>\n\n你好!很高兴见到你,有什么我可以帮忙的吗?无论是学习、工作还是生活中的问题,都可以告诉我哦!😊"
    },
    "done_reason": "stop",
    "done": true,
    "total_duration": 2284946300,
    "load_duration": 16541100,
    "prompt_eval_count": 4,
    "prompt_eval_duration": 1405000000,
    "eval_count": 31,
    "eval_duration": 860000000
}

以上是朝http://localhost:11434/api/chat 发送post请求得到的结果。可以看到,message.content里面就是AI给我们返回的内容。

我们在后端把AI返回的内容打印出来看看。

const Koa = require('koa');
const app = new Koa();
const axios = require('axios');
const Router = require('koa-router'); // 路由
const router = new Router();
const bodyParser = require('koa-bodyparser');  // 解析请求体

app.use(async (ctx) => { // 中间件
  // 获取前端传过来的参数
  // 利用 ajax 将内容交给 deepseek 模型 (已经在本地部署了)
  // 模型返回结果
  // 返回给前端
  if (ctx.url === '/') {

    const message = '你好'
    // 当前 openai 制定的标准,行业标准
    const data = {
      model: 'deepseek-r1:1.5b', // 模型名称
      messages: [
        {
          role: 'user', // 角色
          content: message
        }
      ],
      stream: false // 是否流式返回
    }

    // 跟 deepseek 模型进行通信
    const response = await axios.post("http://localhost:11434/api/chat", data)
     console.log(response.data.message.content);

    ctx.body = {
      code: 200,
      content: response.data.message.content
    }
  }

})

app.use(bodyParser())

app.listen(3000, () => {
  console.log('server is running at port 3000');
});

在浏览器访问http://localhost:3000/, 可以看到后端打印出来了AI给我们返回的内容。

image.png

接下来我们用vue + koa + deepseek(离线调用)来写一个和AI聊天的网页。

在后端定义一个接口,当前端向该接口发请求时,把前端传来的提示语放入data的messages的content中,然后后端用axios向本地的deepseek发送post请求,传入data作为参数,再把后端得到的AI回复返回给前端。以下是后端代码:

const Koa = require('koa');
const app = new Koa();
const axios = require('axios');
const Router = require('koa-router'); // 路由
const router = new Router();
const bodyParser = require('koa-bodyparser');  // 解析请求体

app.use(async(ctx, next) => {  // 处理跨域
  ctx.set('Access-Control-Allow-Origin', '*');  // 允许所有域名访问我这个后端
  ctx.set('Access-Control-Allow-Methods', 'OPTIONS, GET, PUT, POST, DELETE'); // 允许的请求方法
  ctx.set('Access-Control-Allow-Headers', 'x-requested-with, accept, origin, content-type'); // 允许的请求头
  // 请求预检(http协议规定每一个 http 请求发送前都会自动发送一个预检请求)
  if (ctx.method === 'OPTIONS') {
    ctx.status = 204
    return;
  }
  await next();
})

app.use(bodyParser())

router.post('/deepseek/chat', async (ctx) => {
  console.log(ctx.request.body)
  const message = ctx.request.body.content // 前端传过来的消息
  const data = {
    model: 'deepseek-r1:1.5b', // 模型名称
    messages: [
      {
        role: 'user', // 角色
        content: message
      }
    ],
    stream: false // 是否流式返回
  }
  // 跟 deepseek 模型进行通信

  await axios.post("http://localhost:11434/api/chat", data).then(response => {
    console.log(response.data.message.content);
    ctx.body = {
      code: 200,
      content: response.data.message.content
    }
  })
  
  
})

app.use(router.routes()) // 启动路由

app.listen(3000, () => {
  console.log('server is running at port 3000');
});

接下来看前端代码

定义一个响应式数组conversation,里面存储用户与AI的交互内容,数组里有一个个对象,每个对象包含role:user/assistant 和 content:存储具体对话内容,以此来区分哪些话是用户说的,哪些话是AI说的。

const conversation = ref([
  {
    role: "user",
    content: "你好"
  },
  {
    role: "assistant",
    content: "您好!我是您的 AI 智能助手。"
  }
])

当用户输入内容点击发送按钮时,把用户输入的内容添加到conversation数组中去 然后给后端发请求并把用户输入的内容传给后端,后端返回AI输出的内容给前端,然后再把AI的回复添加到conversation数组中去。在html用v-for中遍历conversation数组就可以将对话展示在页面上了。

const send = async() => {
  if(question.value.trim() === ""){
    return
  }
  conversation.value.push({
    role: "user",
    content: question.value
  })

  // 发送请求
  const msg = {
    role: "user",
    content: question.value
  }
  const res = await axios.post('http://localhost:3000/deepseek/chat', msg)

  conversation.value.push({
    role: "assistant",
    content: res.data.content
  })

以下是完整的前端代码:


<template>
  <div>
    <div class="hd">deepseek 智能助手</div>

    <div class="bd">
      <div class="bot answer">
        ai: 
        <span>您好!我是您的 AI 智能助手。我可以帮助您解答问题、编写代码、进行创作等。请问有什么我可以帮您的吗?</span>
      </div>

      <div class="chat" v-for="item in conversation">
        <div class="user question"  v-if="item.role === 'user'">
          me: 
          <span>{{item.content}}</span>
        </div>
        <div class="bot answer" v-if="item.role === 'assistant'">
          ai:
          <span v-html="item.content"></span>
        </div>
      </div>

    </div>

    <div class="ft">
      <div class="input">
        <input type="text" placeholder="请输入您的问题" v-model="question">
        <button @click="send">发送</button>
      </div>
    </div>
  </div>
</template>

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

const conversation = ref([])
const question = ref("")
const send = async() => {
  if(question.value.trim() === ""){
    return
  }
  conversation.value.push({
    role: "user",
    content: question.value
  })

  // 发送请求
  const msg = {
    role: "user",
    content: question.value
  }
  const res = await axios.post('http://localhost:3000/deepseek/chat', msg)

  conversation.value.push({
    role: "assistant",
    content: res.data.content
  })
  
}
</script>

<style lang="css" scoped>
.hd{
  height: 60px;
  background: #FFFFFF;
  border-radius: 0px 0px 0px 0px;
  border: 1px solid #E5E7EB;
  line-height: 60px;
  padding: 0 30px;
}
.bd{
  height: calc(100vh - 140px);
  background: #F9FAFB;
  overflow-y: auto;
  padding: 30px 20%;
  box-sizing: border-box;
}
.bot{
  padding: 10px 20px;
  background: #F3F4F6;
  border-radius: 16px 16px 16px 16px;
  margin-bottom: 20px;
}
.user{
  padding: 10px 20px;
  background: #8E6FF7;
  border-radius: 16px 16px 16px 16px;
  color: #fff;
  margin-bottom: 20px;
}
.ft{
  height: 80px;
  background: #FFFFFF;
  border-radius: 0px 0px 0px 0px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px 0;
  box-sizing: border-box;
}
.input{
  width: 700px;
  height: 100%;
  display: flex;
}
.input input{
  flex: 1;
  padding: 0 20px;
  font-size: 16px;
}
.input button{
  width: 80px;
  margin-left: 20px;
}
</style>

这样就完成了一个简易的AI聊天页面,效果如下:

image.png