nbmade-boot调用deepseek的api过程与显示

news2025/2/9 6:35:38

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

下面简单介绍调用最近大红的AI :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

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

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接口类

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实现类

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();
        }
    }
}

二、前端代码如下:

<!-- 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返回显示样式调整

显示返回效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2295118.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux:安装 node 及 nvm node 版本管理工具(ubuntu )

目录 方法一&#xff1a;手动下载安装文件安装方法二&#xff1a;curl安装 方法一&#xff1a;手动下载安装文件安装 git clone 远程镜像 git clone https://gitee.com/mirrors/nvm安装 nvm bash install.sh刷新配置&#xff0c;使配置在终端生效 // 方法 1 source /root/.…

【多线程-第三天-NSOperation和GCD的区别 Objective-C语言】

一、我们来看NSOperation和GCD的区别 1.我们来对比一下,NSOperation和GCD, 那这个代码,我们都写过了, 我们来看一下它们的特点啊,首先来看GCD, 1)GCD是C语言的框架,是iOS4.0之后推出的,并且它的特点是,针对多核做了优化,可以充分利用CPU的多核,OK,这是GCD, 2…

【医院运营统计专题】2.运营统计:医院管理的“智慧大脑”

医院成本核算、绩效管理、运营统计、内部控制、管理会计专题索引 引言 在当今医疗行业快速发展的背景下,医院运营管理的科学性和有效性成为了决定医院竞争力和可持续发展能力的关键因素。运营统计作为医院管理的重要工具,通过对医院各类数据的收集、整理、分析和解读,为医…

Ollama 部署 DeepSeek-R1 及Open-WebUI

Ollama 部署 DeepSeek-R1 及Open-WebUI 文章目录 Ollama 部署 DeepSeek-R1 及Open-WebUI〇、说明为什么使用本方案 一、 安装Ollama1、主要特点&#xff1a;2、安装3、验证 二、Ollama 部署 DeepSeek1、部署2、模型选用3、Ollama 常用命令4、Ollama模型默认存储路径 安装open-w…

Vite 打包原理

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【大模型】Ubuntu下安装ollama,DeepSseek-R1:32b的本地部署和运行

1 ollama 的安装与设置 ollama官网链接&#xff1a;https://ollama.com/ 在左上角的【Models】中展示了ollama支持的模型在正中间的【Download】中课可以下载支持平台中的安装包。   其安装和模型路径配置操作流程如下&#xff1a; ollama的安装 这里选择命令安装curl -fsSL …

蓝桥杯---力扣题库第38题目解析

文章目录 1.题目重述2.外观数列举例说明3.思路分析&#xff08;双指针模拟&#xff09;4.代码说明 1.题目重述 外观数列实际上就是给你一串数字&#xff0c;我们需要对于这个数据进行一个简单的描述罢了&#xff1b; 2.外观数列举例说明 外观数列都是从1开始的&#xff0c;也…

oCam:免费且强大的录屏软件

今天给大家推荐一个非常好的录屏软件。几乎可以满足你日常工作的需求。而且软件完全免费&#xff0c;没有任何的广告。 oCam&#xff1a;免费且强大的录屏软件 oCam是一款功能强大的免费录屏软件&#xff0c;支持屏幕录制、游戏录制和音频录制等多种模式&#xff0c;能够满足不…

【GitLab CI/CD 实践】从 0 到 1 搭建高效自动化部署流程

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

Django开发入门 – 1.搭建基于Python Web框架Django的IDE开发环境

Django开发入门 – 1.搭建基于Python Web框架Django的IDE开发环境 Build A Integrated Development Environment(IDE) for Python Web Framework - django By JacksonML 1. 获取及安装最新版Python 打开Chrome浏览器&#xff0c;访问Python官网链接&#xff1a;https://www…

【Java基础】序列化、反序列化和不可变类

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;Java基础面经 &#x1f4da;本系列文章为个…

USB子系统学习(四)使用libusb读取鼠标数据

文章目录 1、声明2、HID协议2.1、描述符2.2、鼠标数据格式 3、应用程序4、编译应用程序5、测试 1、声明 本文是在学习韦东山《驱动大全》USB子系统时&#xff0c;为梳理知识点和自己回看而记录&#xff0c;全部内容高度复制粘贴。 韦老师的《驱动大全》&#xff1a;商品详情 …

深度剖析 Redisson 分布式锁:原理、实现与应用实践

文章目录 写在文章开头详解Redisson 分布式锁使用和实现前置准备工作分布式锁的基本使用公平锁的使用联锁的使用读写锁基本使用常见问题Redisson和Jedis有什么区别redisson如何实现分布式锁redisson如何实现分布式锁的可重入redisson如何实现公平锁Redisson的watchdog机制是什么…

基于微信小程序的医院预约挂号系统的设计与实现

hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生…

仅128个token达到ImageNet生成SOTA性能!MAETok:有效的扩散模型的关键是什么?(卡内基梅隆港大等)

论文链接&#xff1a;https://arxiv.org/pdf/2502.03444 项目链接&#xff1a;https://github.com/Hhhhhhao/continuous_tokenizer 亮点直击 理论与实验分析&#xff1a;通过实验和理论分析建立了潜空间结构与扩散模型性能之间的联系。揭示了具有更少高斯混合模型&#xff08;G…

示例:JAVA调用deepseek

近日&#xff0c;国产AI DeepSeek在中国、美国的科技圈受到广泛关注&#xff0c;甚至被认为是大模型行业的最大“黑马”。在外网&#xff0c;DeepSeek被不少人称为“神秘的东方力量”。1月27日&#xff0c;DeepSeek应用登顶苹果美国地区应用商店免费APP下载排行榜&#xff0c;在…

Linux系统命令无法使用(glib库相关问题)

1.背景描述 Yum强制安装了一些软件&#xff0c;安装软件成功无报错&#xff0c;完成后不久突然发现系统出问题了&#xff0c;所有的命令无法使用了&#xff0c;如ls、mv、cat等基本命令报错。 relocation error&#xff1a; /lib64/libpthread.so.0: symbol_libc_dl_error_tsd …

电脑黑屏按什么键恢复?电脑黑屏的解决办法

电脑黑屏的原因有很多&#xff0c;可能是硬件、软件、系统或者病毒等方面造成的。那么&#xff0c;当我们遇到电脑黑屏时&#xff0c;应该怎么做呢&#xff1f;有没有什么快捷的方法可以恢复正常呢&#xff1f;本文将为您介绍一些常见的电脑黑屏情况及其解决办法。 一、电脑开机…

思翼遥控器疑问?

1.地面端与遥控端对频&#xff0c;地面端选择数传2为串口&#xff0c;天空端的UART2通过USB转TTL模块连接电脑&#xff0c;通过串口助手观察得有1Hz输出帧&#xff08;开启遥控器APP时间段为10Hz&#xff09;&#xff0c;共21字节&#xff0c;请问&#xff0c;这个是什么含义&a…

anaconda中可以import cv2,但是notebook中cv2 module not found

一、问题 anaconda中成功import cv2 但是jupyter notebook中却无法导入cv2 二、排查 anaconda中使用python路径如下&#xff1a; jupyter notebook中使用python路径如下&#xff1a; 可以发现路径不一致。 三、解决 ①查看可用的kernel ②选中想要修改的kernel&#xff0c;打…