最近美国向全球加征关税,对全球经济贸易产生巨大影响,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已经集成支持目前主流的各种大模型还有模型实践框架技术。我们熟悉的RAG、MCP、prompts、语音、图片、视频、向量数据库、AI大模型基本都及时集成支持,方便大家应用到系统实践。

今天我们就通过一小段话,明确实现一个Springboot项目,提供一个在线AI聊天助手。具体内容如下:
【你是一个java研发人员,现在有一个Springboot项目需要你去完整实现,主要通过集成Spring ai 和deepseek,提供一个在线可视化聊天机器人系统。最终提供一个界面支持用户输入聊天内容,并响应展示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相关的两个参数配置进去。
ini
deepseek.api.key=your-deepseek-api-key
deepseek.api.url=https://api.deepseek.com/v1/chat/completions
然后 Spring Boot 应用程序,访问localhost:8080就可以访问。
五、最终demo实例
界面虽然很简陋,后端功能也没有实现没有上下文记忆能力。但是这种一键生成项目系统源码,0代码修改,只需要简单配置就可以直接运行的感觉,不得不佩服AI强大的能力。

六、总结和展望
除了尝试这种prompt方式去获得AI提供的系统源码能力,还尝试了其他几种agent方式。总体而言,针对一键生成UI设计、数据处理分析任务、完整系统项目源码生成、量化研究任务几个场景,陆续尝试过多个大模型,以及多个agent,但是目前总体感觉通用大模型还是不够智能,尤其是编程环境的复杂依赖、版本兼容冲突问题解决还不尽如意,然而智能IDE目前国内支持的还很少,值得期待。当然单纯的智能补齐、代码分析、单测编写已经非常成熟好用。
所以AI替换程序员的话题,个人觉得还有很大一段距离。而AI提升编程效率改变编程的时代,已经来临。
7.1 pom.xml
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
ini
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
kotlin
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
typescript
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
kotlin
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
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
xml
<!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/[email protected]/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/[email protected]/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>