欢迎关注微信公众号 「思客潘」

Spring AI 整合 DeepSeek 聊天模型实战指南

前提条件

您需要使用 DeepSeek 创建一个 API 密钥才能访问 DeepSeek 语言模型。
在 DeepSeek 注册页面创建一个帐户,并在 API 密钥页面上生成Tokens。

一、环境准备与配置

1. 依赖引入

<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 http://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.5.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>SpringAIQuickStart</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringAIQuickStart</name>
    <description>SpringAIQuickStart</description>

    <properties>
        <java.version>17</java.version>
    </properties>

    <!-- 导入 Spring AI BOM,用于统一管理 Spring AI 依赖的版本,引用每个 Spring AI 模块时不用再写 <version>,只要依赖什么模块 Mavens 自动使用 BOM 推荐的版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- deepseek 依赖包-->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-deepseek</artifactId>
        </dependency>
    </dependencies>

    <!-- 声明仓库, 用于获取 Spring AI 以及相关预发布版本-->
    <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>
</project>

2. 基础配置

# application.yml
spring:
ai:
deepseek:
api-key: ${DEEPSEEK_API_KEY}# 推荐使用环境变量
base-url: https://api.deepseek.com
chat:
model: deepseek-chat# 默认模型
temperature: 0.7# 创意度
max-tokens: 2000# 最大输出长度

二、核心组件初始化

1. Java 配置类

@Configuration
public class DeepSeekConfig {

@Bean
public DeepSeekChatClient deepSeekChatClient(DeepSeekChatProperties properties) {
return new DeepSeekChatClient(properties);
}

@Bean
public PromptTemplate systemPromptTemplate() {
return new PromptTemplate("""
你是一个由DeepSeek模型驱动的AI助手,当前角色:{role}。
请根据以下要求回答问题:
{instruction}
用户输入:{input}
""");
}
}

三、基础聊天功能实现

1. 简单对话服务

@Service
public class ChatBotService {

private final DeepSeekChatClient chatClient;
private final PromptTemplate promptTemplate;

public ChatBotService(DeepSeekChatClient chatClient,
PromptTemplate promptTemplate) {
this.chatClient = chatClient;
this.promptTemplate = promptTemplate;
}

public String simpleChat(String message) {
Prompt prompt = new Prompt(message);
return chatClient.call(prompt)
.getResult()
.getOutput()
.getContent();
}

public String roleBasedChat(String role, String instruction, String input) {
Map<String, Object> params = Map.of(
"role", role,
"instruction", instruction,
"input", input
);
Prompt prompt = promptTemplate.create(params);
return chatClient.call(prompt).getResult().getOutput().getContent();
}
}

2. REST 接口暴露

@RestController
@RequestMapping("/api/chat")
public class ChatController {

@Autowired
private ChatBotService chatBotService;

@PostMapping("/simple")
public ResponseEntity<String> handleSimpleChat(@RequestBody String message) {
return ResponseEntity.ok(chatBotService.simpleChat(message));
}

@PostMapping("/role-play")
public ResponseEntity<String> rolePlayChat(
@RequestParam String role,
@RequestParam String instruction,
@RequestBody String input) {
return ResponseEntity.ok(
chatBotService.roleBasedChat(role, instruction, input)
);
}
}

四、高级功能实现

1. 带历史上下文的对话

@Service
public class ContextAwareChatService {

private final DeepSeekChatClient chatClient;
private final ChatHistoryRepository historyRepo;

public String chatWithContext(String sessionId, String userInput) {
// 获取历史对话
List<Message> history = historyRepo.findBySessionId(sessionId);

// 构建消息链
List<Message> messages = new ArrayList<>();
if (!history.isEmpty()) {
messages.add(new SystemMessage("历史对话上下文:"));
messages.addAll(history);
}
messages.add(new UserMessage(userInput));

// 调用API
ChatResponse response = chatClient.call(new Prompt(messages));
String aiResponse = response.getResult().getOutput().getContent();

// 保存对话历史(限制最大长度)
historyRepo.save(sessionId, userInput, aiResponse, 10);

return aiResponse;
}
}

2. 流式响应处理

@GetMapping("/stream")
public SseEmitter streamChat(@RequestParam String message) {
SseEmitter emitter = new SseEmitter(30_000L);

chatClient.stream(new Prompt(message))
.subscribe(
chunk -> {
try {
emitter.send(chunk.getResult()
.getOutput()
.getContent());
} catch (IOException e) {
emitter.completeWithError(e);
}
},
emitter::completeWithError,
emitter::complete
);

return emitter;
}

五、模型微调与定制

1. 自定义模型参数

public class CustomDeepSeekClient {

private final DeepSeekChatClient client;

public CustomDeepSeekClient(DeepSeekChatProperties properties) {
DeepSeekChatOptions options = DeepSeekChatOptions.builder()
.withModel("deepseek-custom-model")
.withTemperature(0.3)
.withTopP(0.9)
.withMaxTokens(1000)
.build();

this.client = new DeepSeekChatClient(properties, options);
}

public String generateStrictResponse(String prompt) {
return client.call(new Prompt(prompt))
.getResult()
.getOutput()
.getContent();
}
}

2. 结构化输出生成

public JSONObject getStructuredResponse(String query) {
String prompt = """
请将以下信息转为JSON格式:
问题:{query}
要求包含字段:answer, confidence, related_entities
""".replace("{query}", query);

String jsonStr = chatClient.call(new Prompt(prompt))
.getResult()
.getOutput()
.getContent();

return new JSONObject(jsonStr);// 需处理解析异常
}

六、生产环境最佳实践

1. 重试与熔断机制

@Bean
public DeepSeekChatClient resilientClient(DeepSeekChatProperties properties) {
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setRetryPolicy(new SimpleRetryPolicy(3));
retryTemplate.setBackOffPolicy(new ExponentialBackOffPolicy());

CircuitBreakerFactory cbFactory = new DefaultCircuitBreakerFactory();

return new DeepSeekChatClient(properties) {
@Override
public ChatResponse call(Prompt prompt) {
return cbFactory.create("deepseek-cb").run(
() -> retryTemplate.execute(
context -> super.call(prompt)
),
throwable -> new ChatResponse(List.of(
new Generation("服务暂时不可用,请稍后重试")
))
);
}
};
}

2. 监控与指标收集

@Aspect
@Component
public class DeepSeekMonitor {

private final MeterRegistry meterRegistry;

@Around("execution(* com..DeepSeekChatClient.*(..))")
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
String method = pjp.getSignature().getName();
Timer.Sample sample = Timer.start(meterRegistry);

try {
Object result = pjp.proceed();
sample.stop(meterRegistry.timer("deepseek.calls", "method", method));
return result;
} catch (Exception ex) {
meterRegistry.counter("deepseek.errors",
"method", method,
"exception", ex.getClass().getSimpleName()).increment();
throw ex;
}
}
}

七、典型应用案例

1. 智能客服集成

@Service
public class CustomerSupportService {

private final DeepSeekChatClient chatClient;
private final ProductRepository productRepo;

public String handleSupportTicket(Ticket ticket) {
String productInfo = productRepo.findById(ticket.getProductId())
.orElseThrow().getDescription();

String prompt = """
客服工单#{id} - 产品:{product}
用户问题:{question}
历史记录:{history}
请以专业客服身份回复:
""".replace("{id}", ticket.getId())
.replace("{product}", productInfo)
.replace("{question}", ticket.getQuestion())
.replace("{history}", ticket.getHistory());

return chatClient.call(new Prompt(prompt))
.getResult()
.getOutput()
.getContent();
}
}

2. 技术文档助手

@RestController
@RequestMapping("/api/docs")
public class DocAssistantController {

@PostMapping("/explain")
public ResponseEntity<String> explainConcept(
@RequestBody DocQuery query) {

String prompt = """
你是一个{tech}技术专家,请用{level}级别难度解释以下概念:
概念:{concept}
要求:{requirements}
""".replace("{tech}", query.getTechnology())
.replace("{level}", query.getDifficulty())
.replace("{concept}", query.getConcept())
.replace("{requirements}", query.getRequirements());

String explanation = chatClient.call(new Prompt(prompt))
.getResult()
.getOutput()
.getContent();

return ResponseEntity.ok(
MarkdownUtils.formatAsHtml(explanation)// 转换Markdown为HTML
);
}
}

八、故障排查指南

常见问题与解决方案

问题现象 可能原因 解决方案
401 Unauthorized API密钥无效或过期 检查密钥配置,确认账户状态
响应速度慢 网络延迟或模型负载高 增加超时设置,实现客户端缓存
输出不符合预期 提示词设计不合理 使用System Message明确角色要求
上下文丢失 未正确维护对话历史 实现Session级别的历史记录管理

九、扩展阅读

推荐配置组合

spring:
ai:
deepseek:
connection:
connect-timeout: 5s
read-timeout: 30s
chat:
frequency-penalty: 0.5# 降低重复内容
presence-penalty: 0.3# 提高话题新鲜度

性能优化建议

  1. 对高频查询实现本地缓存
  2. 批量处理多个请求(需DeepSeek API支持)
  3. 使用CDN加速API访问
  4. 对长文本采用分块处理策略

完整示例项目结构

src/
├── main/
│├── java/
││└── com/
││└── example/
││├── config/
││├── controller/
││├── service/
││└── Application.java
│└── resources/
│└── application.yml
└── test/
└── java/
└── com/example/service/
└── ChatServiceTest.java

通过本指南,开发者可以快速将DeepSeek强大的聊天模型能力集成到Spring应用中,构建智能对话功能。建议根据实际业务需求调整提示词工程和异常处理策略。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐