spring 的ai是一个应用框架,它可以帮助开发者快速构建智能应用。
模型(models)
一种算法,用于生成信息,常见模型有:
- LLM(Large Language Model)
- Embedding
- image generation
- text-to-voice / voice-to-text
提示符(prompt)
一种文本,用于指导模型生成信息
有多种文本输入,每种都被指派一个角色,例如:
- system:系统角色,用于指导模型的行为
- user:用户角色,来自用户的输入
token
AI模型处理的最小单位
在英文中,一个token相当于已给单词的75%
举个例子,莎士比亚的作品,大概90万个单词,大约需要120万个token
实践
接入deepseek聊天模型
环境准备
- 版本选择
Spring AI 支持 Spring Boot 3.4.x and 3.5.x.
jdk 17+ - API key
在deepseek官网注册账号,获取API key
添加依赖
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>
<!-- 引入webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
配置参数
配置参数详见:chat_properties
示例:
properties
spring.ai.deepseek.api-key=YOUR_API_KEY
spring.ai.deepseek.chat.options.model=deepseek-chat
spring.ai.deepseek.chat.options.temperature=0.8
编写代码
java
package com.example.demo.conroller;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.deepseek.DeepSeekAssistantMessage;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.ai.deepseek.DeepSeekChatOptions;
import org.springframework.ai.deepseek.api.DeepSeekApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@RestController
public class ChatController {
private final DeepSeekChatModel chatModel;
// 存储对话历史
private final Map<String, List<Message>> conversationMap = new ConcurrentHashMap<>();
@Autowired
public ChatController(DeepSeekChatModel chatModel) {
this.chatModel = chatModel;
}
// 单轮对话
@GetMapping("/ai/generate")
public Flux<String> generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return chatModel.stream(message);
}
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
var prompt = new Prompt(new UserMessage(message));
return chatModel.stream(prompt);
}
// 多轮对话
@GetMapping("/ai/generateMultiRoundStream")
public Flux<String> generateMultiRoundStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message,String conversationId) {
if(!StringUtils.hasText(conversationId)){
conversationId = System.currentTimeMillis()+"";
}
// 获取当前对话的历史对话
List<Message> messages = getMessage(conversationId);
// 添加用户消息
messages.add(new UserMessage(message));
// 设置模型类型 DEEPSEEK_REASONER 推导模型
DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder()
.model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER.getValue())
.build();
// 创建提示符
var prompt = new Prompt(messages, promptOptions);
StringBuffer sb = new StringBuffer();
return chatModel.stream(prompt).map(chatResponse -> {
// 获取响应中的文本
DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) chatResponse.getResult().getOutput();
String text = deepSeekAssistantMessage.getText();
if(StringUtils.hasText(text)){
sb.append(text);
}else{
text = "";
}
return text;
}).doAfterTerminate(() -> {
// 把返回的消息添加到对话历史中
messages.add(new AssistantMessage(sb.toString()));});
}
private List<Message> getMessage(String conversationId) {
List<Message> messages = conversationMap.get(conversationId);
if(CollectionUtils.isEmpty(messages)){
ArrayList<Message> list = new ArrayList<>();
conversationMap.put(conversationId, list);
return list;
}else{
return messages;
}
}
}