方式一:基于HttpClient
步骤 1:准备工作
获取 DeepSeek API 密钥:访问 DeepSeek 的开发者平台,注册并获取 API 密钥。
步骤 2:引入依赖
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
步骤 3:配置 DeepSeek API
**配置参数:**在 application.yml 文件里,把 DeepSeek 的 API 端点和密钥写进去:
在 application.properties
或 application.yml
中配置 DeepSeek 的 API 密钥和端点:
XML
deepseek.api.key=sk-xxxxxxxxxx
deepseek.api.url=https://api.deepseek.com/v1/chat/completions
步骤 4:自定义 DeepSeek Client Service
(1)自定义请求头
java
public record DeepSeekRequest(
String model,
List<Message> messages,
double temperature,
int max_tokens
) {
public record Message(String role, String content) {}
}
(2)自定义响应体
java
public record DeepSeekResponse(
String id,
String object,
long created,
String model,
List<Choice> choices
) {
public record Choice(
int index,
Message message,
String finish_reason
) {
public record Message(String role, String content) {}
}
}
(3)service
java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Service
public class DeepSeekService {
@Value("${deepseek.api.url}")
private String apiUrl;
@Value("${deepseek.api.key}")
private String apiKey;
private final RestTemplate restTemplate;
public DeepSeekService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
public String getChatResponse(String userMessage) {
// 构造请求体
DeepSeekRequest request = new DeepSeekRequest(
"deepseek-chat",
List.of(new DeepSeekRequest.Message("user", userMessage)),
0.7,
1000
);
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(apiKey);
HttpEntity<DeepSeekRequest> entity = new HttpEntity<>(request, headers);
// 发送请求
ResponseEntity<DeepSeekResponse> response = restTemplate.exchange(
apiUrl,
HttpMethod.POST,
entity,
DeepSeekResponse.class
);
// 处理响应
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
return response.getBody().choices().get(0).message().content();
}
throw new RuntimeException("API请求失败: " + response.getStatusCode());
}
}
请求体中可以指定:调整模型、温度、最大 token 数等
什么是温度(Temperature)?
温度是控制模型生成文本的"创造力"或"随机性"的一个参数。你可以把它想象成调节模型的"脑洞大小"。
- 温度低(比如 0.1):
模型会变得非常保守,倾向于选择最确定、最安全的答案。
适合需要准确性和一致性的任务,比如回答事实性问题。
例子:问"1+1等于几?",模型会回答"2",不会瞎编。
- 温度高(比如 1.0 或更高):
模型会变得更有创造力,可能会给出一些意想不到的回答。
适合需要创意或多样性的任务,比如写故事、生成诗歌。
例子:问"写一首关于秋天的诗",模型可能会生成一些充满想象力的句子。
- 温度适中(比如 0.7):
模型会在保守和创意之间找到一个平衡点。
适合大多数任务,既能保证一定的准确性,又能有一些变化。
总结:
-
温度低 → 模型像"学霸",回答严谨但可能无聊。
-
温度高 → 模型像"艺术家",回答有趣但可能不靠谱。
-
温度适中 → 模型像"聪明人",回答既靠谱又有趣。
最大 token 数(Max Tokens)
token 是模型处理文本的基本单位,可以理解为一个词或一部分词。
比如:
-
英文单词"hello"是一个 token。
-
中文"你好"可能是两个 token(每个字一个 token)。
-
长单词或复杂字符可能会被拆成多个 token。
最大 token 数就是限制模型生成的文本长度。可以把它想象成给模型一个"字数限制"。
- 设置较小的最大 token 数(比如 50):
模型生成的文本会非常短,可能只回答问题的核心部分。
例子:问"介绍一下太阳系",模型可能只回答"太阳系包括太阳和八大行星"。
- 设置较大的最大 token 数(比如 500):
模型生成的文本会更长,可能会包含更多细节。
例子:问"介绍一下太阳系",模型可能会详细描述每颗行星的特点。
- 不设置最大 token 数:
模型可能会一直生成文本,直到达到它的内部限制(通常是几千个 token)。
这可能会导致生成的文本过长,甚至跑题。
总结:
-
最大 token 数小 → 模型像"话少的人",回答简短。
-
最大 token 数大 → 模型像"话多的人",回答详细。
-
不设置最大 token 数 → 模型像"话痨",可能会一直说个不停。
步骤 5:创建控制器
java
@RestController
@RequestMapping("/deepseek/chat")
public class DeepSeekController {
private final DeepSeekService deepSeekService;
public DeepSeekController(DeepSeekService deepSeekService) {
this.deepSeekService = deepSeekService;
}
@PostMapping
public ResponseEntity<?> chat(@RequestBody Map<String, String> request) {
try {
String response = deepSeekService.getChatResponse(request.get("message"));
return ResponseEntity.ok(Collections.singletonMap("response", response));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Collections.singletonMap("error", e.getMessage()));
}
}
}
方式二:基于spring-ai-openai
步骤基本一致,这里罗列几处实现代码
依赖:
java
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-M5</spring-ai.version>
</properties>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
DeepSeekConfig:
java
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DeepSeekConfig {
@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
return ChatClient.builder(openAiChatModel).build();
}
}
DeepSeekController:
java
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.openai.OpenAiChatModel;
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 org.springframework.ai.chat.model.ChatResponse;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/api")
public class ChatController {
@Resource
private OpenAiChatModel chatModel;
private final List<Message> chatHistoryList = new ArrayList<>();
@PostConstruct
public void init() {
chatHistoryList.add(new SystemMessage("You are a helpful assistant."));
}
@PostMapping("/chat")
public ChatResponse test(@RequestBody String message) {
chatHistoryList.add(new UserMessage(message));
Prompt prompt = new Prompt(chatHistoryList);
ChatResponse chatResponse = chatModel.call(prompt);
if (chatResponse.getResult() != null && chatResponse.getResult().getOutput() != null) {
chatHistoryList.add(chatResponse.getResult().getOutput());
}
return chatResponse;
}
}