AI大模型进阶系列(02)基于Spring AI实现AI chatbot助理|一句话让deepseek实现

简介: 本文介绍了通过DeepSeek生成一个基于Spring AI的在线AI聊天助手项目的全过程。项目采用JDK17+Spring AI+Thymeleaf+Spring Web技术栈,实现了一个简单的聊天界面,用户可输入内容并获得DeepSeek返回的结果。文章详细描述了从需求明确、项目结构设计到配置参数启动的步骤,并展示了核心代码片段如pom.xml、application.properties及主要Java类文件。尽管功能简单,但体现了AI在编程领域的高效应用,未来有望进一步优化上下文记忆等功能,提升开发体验与效率。

最近美国向全球加征关税,对全球经济贸易产生巨大影响,2025-04-07日,对全球来说都是黑色星期一,这两天相信大家都在刷各种金融资讯小作文。而AI作为本次技术革命先锋,最近各大金融公司也相继进行金融+AI的落地实践,积极拥抱新技术。我们也在积极探索尝试AI程序员、AI投资顾问落地应用。


一、前言背景

二、向deepseek明确具体需求

三、项目结构

四、配置参数启动

五、最终demo实例

六、总结和展望

七、项目源码


一、前言背景

      最近AI程序员非常火热,在AI coding rank上,国际大模型排名靠前的是claude 3.7 sonnet、gemini-2.5、还有deepseek v3。在编程领域,国内的混元、通义、豆包背后的金主也在积极布局AI coding 助手。未来万物皆可AI的局面将百花齐放,大幅提升各行各业的效率。

      IT人员已经开始尝试一键AI生成系统项目代码,或者对系统新功能直接一键生成。

      今天通过一句话让deepseek生成基于Spring A+DeepseekI实现的在线AI chatbot助手。大模型给出的代码0修改,只修改了pom,就直接启动可用。最终效果界面:

二、向deepseek明确具体需求

    Spring AI 1.0已经集成支持目前主流的各种大模型还有AI实践框架技术。我们熟悉的RAG、MCP、prompts、语音、图片、视频、向量数据库、AI大模型基本都及时集成支持,方便大家应用到系统实践。

     今天通过一小段话,明确实现一个Springboot项目,提供一个在线AI聊天助手。具体内容如下:

【你是一个java研发人员,现在有一个Springboot项目需要你去完整实现,主要通过集成Spring ai 和deepseek,提供一个在线可视化聊天机器人系统。最终提供一个界面支持用户输入聊天内容,并响应展示deepseek返回内容。】

    在prompt及其简略的前提下,deepseek依靠自身强大的推理能力依然可以给出超预期基本可直接运行的源码,并推荐使用Spring initialize去初始化项目。

三、项目结构

       deepseek最终给出的项目架构是JDK17+Spring AI+thymeleaf+Spring web来实现。

       具体项目源码内容有:

1、pom.xml详细配置(这里存在唯一一个bug)。deepseek 给的depenency用的是

spring-ai-ollama-spring-boot-starter,最后调整为spring-ai-bom才成功。

2、deepseek客户端,通过restClient调用deepseek api的bean,以及Service层的逻辑处理。

3、请求响应的model DeepSeekRequest.java+DeepSeekResponse.java+ChatMessage.java (模型)。

4、chat接口,支持前端界面录入聊天内容并返回。

5、前端界面实现templates/chat.html。

四、配置参数启动

      在deepseek提供源码application.properties基础上,deepseek的答案也完整提示,在application继续新增与deepseek api相关的两个参数配置进去。

      deepseek.api.key=your-deepseek-api-key

      deepseek.api.url=https://api.deepseek.com/v1/chat/completions

然后启动 Springboot 应用程序,访问localhost:8080就可以访问。

五、最终demo实例

      界面虽然很简陋,后端功能也没有实现上下文记忆能力。但是这种一键生成项目系统源码,0代码修改,只需要简单配置就可以直接运行的感觉,不得不佩服AI强大的能力。

六、总结和展望

      除了尝试这种prompt方式去获得AI提供的系统源码能力,还尝试了其他几种agent方式。总体而言,针对一键生成UI设计、数据处理分析任务、完整系统项目源码生成、量化研究任务几种场景,近期尝试过多个大模型,以及多个agent。但是总体感觉通用大模型还是不够智能,尤其是编程环境的复杂依赖、版本兼容冲突问题解决还不尽如意,然而智能IDE目前国内支持的还很少,值得期待。当然单纯的智能补齐、代码分析、单测编写已经非常成熟好用。

     所以AI替换程序员的话题,个人觉得还有很大一段距离。而AI提升编程效率改变编程的时代,已经来临。

七、项目源码

7.1 pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>ai-chatbot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ai-chatbot</name>
    <description>Demo project for Spring Boot with DeepSeek AI</description>
    <properties>
        <java.version>17</java.version>
        <spring-ai.version>0.8.1</spring-ai.version>
    </properties>
    <dependencies>
        <!-- Spring Boot Starters -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- Other dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
        <repository>
            <name>Central Portal Snapshots</name>
            <id>central-portal-snapshots</id>
            <url>https://central.sonatype.com/repository/maven-snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

7.2 application.properties

spring.application.name=ai-chatbot
# Server port
server.port=8080
# Spring AI - DeepSeek configuration
# Note: As of my knowledge cutoff, Spring AI doesn't have direct DeepSeek support
# We'll implement a custom client for DeepSeek API
# Thymeleaf configuration
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
deepseek.api.key=你的deepseek api key替换
deepseek.api.url=https://api.deepseek.com/v1/chat/completions

7.3 DeepSeekConfig.java

package com.example.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestClient;
@Configuration
public class DeepSeekConfig {
    @Value("${deepseek.api.key}")
    private String apiKey;
    @Value("${deepseek.api.url}")
    private String apiUrl;
    @Bean
    public RestClient deepSeekRestClient() {
        return RestClient.builder()
                .baseUrl(apiUrl)
                .defaultHeader("Authorization", "Bearer " + apiKey)
                .defaultHeader("Content-Type", "application/json")
                .build();
    }
}

7.4 model 模型

ChatMessage.java、DeepSeekRequest.java 、DeepSeekResponse.java

package com.example.model;
import java.util.List;
public class DeepSeekResponse {
    private String id;
    private String object;
    private long created;
    private String model;
    private List<Choice> choices;
    private Usage usage;
    // Getters and setters
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getObject() {
        return object;
    }
    public void setObject(String object) {
        this.object = object;
    }
    public long getCreated() {
        return created;
    }
    public void setCreated(long created) {
        this.created = created;
    }
    public String getModel() {
        return model;
    }
    public void setModel(String model) {
        this.model = model;
    }
    public List<Choice> getChoices() {
        return choices;
    }
    public void setChoices(List<Choice> choices) {
        this.choices = choices;
    }
    public Usage getUsage() {
        return usage;
    }
    public void setUsage(Usage usage) {
        this.usage = usage;
    }
    public static class Choice {
        private int index;
        private Message message;
        private String finish_reason;
        // Getters and setters
        public int getIndex() {
            return index;
        }
        public void setIndex(int index) {
            this.index = index;
        }
        public Message getMessage() {
            return message;
        }
        public void setMessage(Message message) {
            this.message = message;
        }
        public String getFinish_reason() {
            return finish_reason;
        }
        public void setFinish_reason(String finish_reason) {
            this.finish_reason = finish_reason;
        }
    }
    public static class Message {
        private String role;
        private String content;
        // Getters and setters
        public String getRole() {
            return role;
        }
        public void setRole(String role) {
            this.role = role;
        }
        public String getContent() {
            return content;
        }
        public void setContent(String content) {
            this.content = content;
        }
    }
    public static class Usage {
        private int prompt_tokens;
        private int completion_tokens;
        private int total_tokens;
        // Getters and setters
        public int getPrompt_tokens() {
            return prompt_tokens;
        }
        public void setPrompt_tokens(int prompt_tokens) {
            this.prompt_tokens = prompt_tokens;
        }
        public int getCompletion_tokens() {
            return completion_tokens;
        }
        public void setCompletion_tokens(int completion_tokens) {
            this.completion_tokens = completion_tokens;
        }
        public int getTotal_tokens() {
            return total_tokens;
        }
        public void setTotal_tokens(int total_tokens) {
            this.total_tokens = total_tokens;
        }
    }
}



package com.example.model;
import java.util.ArrayList;
import java.util.List;
public class DeepSeekRequest {
    private String model = "deepseek-chat";
    private List<Message> messages;
    private double temperature = 0.7;
    private int max_tokens = 2000;
    public DeepSeekRequest(String prompt) {
        this.messages = new ArrayList<>();
        this.messages.add(new Message("user", prompt));
    }
    // Getters and setters
    public String getModel() {
        return model;
    }
    public void setModel(String model) {
        this.model = model;
    }
    public List<Message> getMessages() {
        return messages;
    }
    public void setMessages(List<Message> messages) {
        this.messages = messages;
    }
    public double getTemperature() {
        return temperature;
    }
    public void setTemperature(double temperature) {
        this.temperature = temperature;
    }
    public int getMax_tokens() {
        return max_tokens;
    }
    public void setMax_tokens(int max_tokens) {
        this.max_tokens = max_tokens;
    }
    public static class Message {
        private String role;
        private String content;
        public Message(String role, String content) {
            this.role = role;
            this.content = content;
        }
        // Getters and setters
        public String getRole() {
            return role;
        }
        public void setRole(String role) {
            this.role = role;
        }
        public String getContent() {
            return content;
        }
        public void setContent(String content) {
            this.content = content;
        }
    }
}


package com.example.model;
public class ChatMessage {
    private String role; // "user" or "ai"
    private String content;
    public ChatMessage() {
    }
    public ChatMessage(String role, String content) {
        this.role = role;
        this.content = content;
    }
    // Getters and setters
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}

7.5 DeepSeekService.java


package com.example.service;
import com.example.model.DeepSeekRequest;
import com.example.model.DeepSeekResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
@Service
public class DeepSeekService {
    private final RestClient deepSeekRestClient;
    @Autowired
    public DeepSeekService(RestClient deepSeekRestClient) {
        this.deepSeekRestClient = deepSeekRestClient;
    }
    public String generateResponse(String prompt) {
        DeepSeekRequest request = new DeepSeekRequest(prompt);
        DeepSeekResponse response = deepSeekRestClient.post()
                .body(request)
                .retrieve()
                .body(DeepSeekResponse.class);
        return response != null ? response.getChoices().get(0).getMessage().getContent() : "No response from DeepSeek";
    }
}

7.6 ChatController.java


package com.example.controller;
import com.example.model.ChatMessage;
import com.example.service.DeepSeekService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.ArrayList;
import java.util.List;
@Controller
public class ChatController {
    private final DeepSeekService deepSeekService;
    private List<ChatMessage> chatHistory = new ArrayList<>();
    public ChatController(DeepSeekService deepSeekService) {
        this.deepSeekService = deepSeekService;
    }
    @GetMapping("/")
    public String chat(Model model) {
        model.addAttribute("chatMessage", new ChatMessage());
        model.addAttribute("chatHistory", chatHistory);
        return "chat";
    }
    @PostMapping("/send")
    public String sendMessage(@ModelAttribute ChatMessage chatMessage, Model model) {
        // Add user message to chat history
        chatHistory.add(new ChatMessage("user", chatMessage.getContent()));
        // Get response from DeepSeek
        String response = deepSeekService.generateResponse(chatMessage.getContent());
        // Add AI response to chat history
        chatHistory.add(new ChatMessage("ai", response));
        model.addAttribute("chatMessage", new ChatMessage());
        model.addAttribute("chatHistory", chatHistory);
        return "chat";
    }
}

7.7 前端实现templates/chat.html


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DeepSeek Chatbot</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .chat-container {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        .chat-history {
            height: 500px;
            overflow-y: auto;
            margin-bottom: 20px;
            padding: 10px;
            border: 1px solid #eee;
            border-radius: 5px;
        }
        .user-message {
            background-color: #e3f2fd;
            padding: 10px;
            border-radius: 10px;
            margin-bottom: 10px;
            max-width: 80%;
            margin-left: auto;
        }
        .ai-message {
            background-color: #f5f5f5;
            padding: 10px;
            border-radius: 10px;
            margin-bottom: 10px;
            max-width: 80%;
        }
        .message-time {
            font-size: 0.8em;
            color: #666;
            margin-top: 5px;
        }
    </style>
</head>
<body>
<div class="container mt-5">
    <div class="chat-container">
        <h2 class="text-center mb-4">DeepSeek Chatbot</h2>
        <div class="chat-history" id="chatHistory">
            <div th:each="message : ${chatHistory}">
                <div th:class="${message.role == 'user' ? 'user-message' : 'ai-message'}">
                    <strong th:text="${message.role == 'user' ? 'You:' : 'AI:'}"></strong>
                    <div th:text="${message.content}"></div>
                    <div class="message-time" th:text="${#temporals.format(#temporals.createNow(), 'HH:mm')}"></div>
                </div>
            </div>
        </div>
        <form th:action="@{/send}" th:object="${chatMessage}" method="post">
            <div class="input-group mb-3">
                <input type="text" class="form-control" th:field="*{content}"
                       placeholder="Type your message here..." autocomplete="off">
                <button class="btn btn-primary" type="submit">Send</button>
            </div>
        </form>
    </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
    // Scroll to bottom of chat history
    window.onload = function() {
        var chatHistory = document.getElementById('chatHistory');
        chatHistory.scrollTop = chatHistory.scrollHeight;
    };
</script>
</body>
</html>
相关文章
|
5月前
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
4304 85
|
5月前
|
人工智能 测试技术 API
构建AI智能体:二、DeepSeek的Ollama部署FastAPI封装调用
本文介绍如何通过Ollama本地部署DeepSeek大模型,结合FastAPI实现API接口调用。涵盖Ollama安装、路径迁移、模型下载运行及REST API封装全过程,助力快速构建可扩展的AI应用服务。
1651 6
|
5月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
6582 91
|
5月前
|
机器学习/深度学习 人工智能 人机交互
当AI学会“看”和“听”:多模态大模型如何重塑人机交互
当AI学会“看”和“听”:多模态大模型如何重塑人机交互
499 121
|
5月前
|
人工智能 人机交互 知识图谱
当AI学会“融会贯通”:多模态大模型如何重塑未来
当AI学会“融会贯通”:多模态大模型如何重塑未来
393 114
|
5月前
|
人工智能 API 开发工具
构建AI智能体:一、初识AI大模型与API调用
本文介绍大模型基础知识及API调用方法,涵盖阿里云百炼平台密钥申请、DashScope SDK使用、Python调用示例(如文本情感分析、图像文字识别),助力开发者快速上手大模型应用开发。
2133 17
构建AI智能体:一、初识AI大模型与API调用
|
5月前
|
消息中间件 人工智能 安全
云原生进化论:加速构建 AI 应用
本文将和大家分享过去一年在支持企业构建 AI 应用过程的一些实践和思考。
1355 54
|
5月前
|
人工智能 运维 Kubernetes
Serverless 应用引擎 SAE:为传统应用托底,为 AI 创新加速
在容器技术持续演进与 AI 全面爆发的当下,企业既要稳健托管传统业务,又要高效落地 AI 创新,如何在复杂的基础设施与频繁的版本变化中保持敏捷、稳定与低成本,成了所有技术团队的共同挑战。阿里云 Serverless 应用引擎(SAE)正是为应对这一时代挑战而生的破局者,SAE 以“免运维、强稳定、极致降本”为核心,通过一站式的应用级托管能力,同时支撑传统应用与 AI 应用,让企业把更多精力投入到业务创新。
655 30

热门文章

最新文章