基于若依的ruoyi-vue-plus的nbmade-boot调用deepseek的api过程与显示

希望大家一起能参与我的新开源项目nbmade-boot: 宁波智能制造低代码实训平台

下面简单介绍调用最近大红的AI :基于若依的ruoyi-vue-plus的deepseek的api过程与显示,包括前后端代码与效果图

一、后端代码

1、几个基础的java类

DeepSeekRequest .java

复制代码
package com.nbcio.demo.domain;

import java.util.List;

import lombok.Data;

@Data
public class DeepSeekRequest {
    private String model;
    private List<Message> messages;
    
    @Data
    public static class Message {
        private String role;
        private String content;
    }
}

DeepSeekResponse.java

java 复制代码
package com.nbcio.demo.domain;

import java.util.List;

import com.nbcio.demo.domain.DeepSeekRequest.Message;

import lombok.Data;

@Data
public class DeepSeekResponse {
    private List<Choice> choices;
    
    @Data
    public static class Choice {
        private Message message;
    }
}

HttpClientSingleton.java

java 复制代码
package com.nbcio.demo.utils;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;

public class HttpClientSingleton {
    private static OkHttpClient client;

    public static OkHttpClient getClient() {
        if (client == null) {
            client = new OkHttpClient.Builder()
                    .connectTimeout(300, TimeUnit.SECONDS)
                    .writeTimeout(300, TimeUnit.SECONDS)
                    .readTimeout(300, TimeUnit.SECONDS)
                    .build();
        }
        return client;
    }
}

2、DeepSeekController.java接口类

java 复制代码
package com.nbcio.demo.controller;

import lombok.RequiredArgsConstructor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.nbcio.common.core.domain.R;
import com.nbcio.demo.domain.DeepSeekRequest;
import com.nbcio.demo.service.IDeepSeekService;

/**
 * deepseek api 演示案例
 *
 * @author nbacheng
 */

@RequiredArgsConstructor
@RestController
@RequestMapping("/demo/deepseek")
public class DeepSeekController {

	private final IDeepSeekService deepSeekService;

    @PostMapping("/chat")
    public R<?> chat(@RequestBody DeepSeekRequest request) {
        try {
            String response = deepSeekService.callDeepSeekAPI(request);
            return R.ok(response);
        } catch (Exception e) {
            return R.fail("API调用失败: " + e.getMessage());
        }
    }
}

3、DeepSeekServiceImpl.java实现类

java 复制代码
package com.nbcio.demo.service.impl;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.nbcio.demo.domain.DeepSeekRequest;
import com.nbcio.demo.service.IDeepSeekService;
import com.nbcio.demo.utils.HttpClientSingleton;

import lombok.RequiredArgsConstructor;
import okhttp3.*;
import java.io.IOException;

@Service
@RequiredArgsConstructor
public class DeepSeekServiceImpl implements IDeepSeekService {
	@Value("${deepseek.api.key}")
    private String apiKey;

    @Value("${deepseek.api.url}")
    private String apiUrl;

    public String callDeepSeekAPI(DeepSeekRequest request) throws IOException {
    	OkHttpClient client = HttpClientSingleton.getClient();
        
        MediaType mediaType = MediaType.parse("application/json;charset=utf-8");
        RequestBody body = RequestBody.create(mediaType, new Gson().toJson(request));
        
        Request httpRequest = new Request.Builder()
                .url(apiUrl)
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
    			.addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + apiKey)
                .build();

        try (Response response = client.newCall(httpRequest).execute()) {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
            return response.body().string();
        }
    }
}

二、前端代码如下:

javascript 复制代码
<!-- views/ai/DeepSeekChat.vue -->
<template>
  <div class="chat-container">
    <div class="chat-history">
      <div v-for="(msg, index) in messages" :key="index" :class="['message', msg.role]">
        <div class="message-content" v-html="msg.htmlContent"></div>
      </div>
    </div>

    <div class="input-area">
      <el-input
        v-model="inputMessage"
        type="textarea"
        :rows="4"
        placeholder="输入您的问题..."
        @keydown.enter.exact.prevent="sendMessage"
      />
      <el-button
        type="primary"
        :loading="loading"
        @click="sendMessage"
        class="send-button"
      >
        发送
      </el-button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { deepSeekChat } from '@/api/demo/deepseek'
import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
import 'highlight.js/styles/github-dark.css'

const md = new MarkdownIt({
  html: true,
  linkify: true,
  highlight: (str, lang) => {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return `<pre class="hljs"><code>${hljs.highlight(str, {
          language: lang,
          ignoreIllegals: true
        }).value}</code></pre>`
      } catch (__) {}
    }
    return `<pre class="hljs"><code>${md.utils.escapeHtml(str)}</code></pre>`
  }
})

const messages = ref([])
const inputMessage = ref('')
const loading = ref(false)

const formatContent = (content) => {
  return md.render(content)
}

const sendMessage = async () => {
  if (!inputMessage.value.trim()) return

  const userMessage = {
    role: 'user',
    content: inputMessage.value,
    htmlContent: formatContent(inputMessage.value)
  }

  messages.value.push(userMessage)
  loading.value = true

  try {
    const response = await deepSeekChat({
      model: 'deepseek-chat',
      messages: [...messages.value.map(m => ({ role: m.role, content: m.content }))]
    })
    const content = JSON.parse(response.msg)
    const aiMessage = {
      role: 'assistant',
      content: content.choices[0].message.content,
      htmlContent: formatContent(content.choices[0].message.content)
    }
    messages.value.push(aiMessage)
  } catch (error) {
    ElMessage.error('请求失败:' + error.message)
  } finally {
    inputMessage.value = ''
    loading.value = false
  }
}
</script>

<style scoped>
.chat-container {
  max-width: 800px;
  margin: 20px auto;
  height: 70vh;
  display: flex;
  flex-direction: column;
}

.chat-history {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  margin-bottom: 20px;
  background: #f9fafb;
}

.message {
  margin: 10px 0;
  padding: 15px 20px;
  border-radius: 8px;
  line-height: 1.6;
}

.message.user {
  background-color: #fff;
  margin-left: 20%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.message.assistant {
  background-color: #ffffff;
  margin-right: 20%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
  border: 1px solid #e5e7eb;
}

.input-area {
  position: relative;
}

.send-button {
  margin-top: 10px;
  float: right;
}

/* Markdown内容样式 */
.message-content ::v-deep() {
  h1, h2, h3 {
    margin: 1em 0 0.5em;
    font-weight: 600;
  }

  p {
    margin: 0.8em 0;
  }

  pre {
    background: #1f2937;
    color: #fff;
    padding: 1em;
    border-radius: 6px;
    overflow-x: auto;
    margin: 1em 0;
  }

  code {
    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
    background: #f3f4f6;
    padding: 0.2em 0.4em;
    border-radius: 4px;
    font-size: 0.9em;
  }

  blockquote {
    border-left: 4px solid #e5e7eb;
    padding: 0 1em;
    color: #6b7280;
    margin: 1em 0;
  }

  ul, ol {
    padding-left: 2em;
    margin: 1em 0;
  }

  li {
    margin: 0.3em 0;
  }
}
</style>

三、效果图

在发送提问里输入:测试deepseek的api返回显示样式调整

显示返回效果如下:

相关推荐
wang_yb6 分钟前
同样的数据,更强的效果:如何让模型学会‘互补思维’?
ai·databook
视觉&物联智能2 小时前
【杂谈】-AI 重塑体育营销:从内容管理到创意释放的全面变革
人工智能·ai·aigc·agi·营销
伊织code8 小时前
PyTorch API 5 - 全分片数据并行、流水线并行、概率分布
pytorch·python·ai·api·-·5
jc_hook11 小时前
Python 接入DeepSeek
python·大模型·deepseek
想要成为计算机高手14 小时前
OpenVLA:开源的视觉-语言-动作模型
ai·自然语言处理·开源·大模型·视觉处理·openvla
选型宝16 小时前
腾讯怎样基于DeepSeek搭建企业应用?怎样私有化部署满血版DS?直播:腾讯云X DeepSeek!
人工智能·ai·云计算·腾讯云·选型宝
码码哈哈爱分享16 小时前
开源Heygem本地跑AI数字人视频教程
ai
伊织code17 小时前
PyTorch API 7 - TorchScript、hub、矩阵、打包、profile
人工智能·pytorch·python·ai·矩阵·api
AI不止绘画17 小时前
分享一个可以用GPT打标的傻瓜式SD图片打标工具——辣椒炒肉图片打标助手
人工智能·ai·aigc·图片打标·图片模型训练·lora训练打标·sd打标
RebekahHQ19 小时前
Deepseek+Xmind:秒速生成思维导图与流程图
流程图·xmind·思维导图·deepseek