跳到主要内容

DeepSeek Chat

Deepseek 3.2 中英对照 DeepSeek DeepSeek Chat

Spring AI 支持来自 DeepSeek 的各种 AI 语言模型。您可以与 DeepSeek 语言模型交互,并基于 DeepSeek 模型创建多语言对话助手。

先决条件

你需要创建一个 DeepSeek API 密钥来访问 DeepSeek 语言模型。

DeepSeek 注册页面创建账户,并在API 密钥页面生成令牌。

Spring AI项目定义了一个名为 spring.ai.deepseek.api-key 的配置属性,您应将其设置为从API密钥页面获取的 API Key 的值。

您可以在 application.properties 文件中设置此配置属性:

spring.ai.deepseek.api-key=<your-deepseek-api-key>

为了在处理敏感信息(如API密钥)时增强安全性,您可以使用Spring表达式语言(SpEL)来引用自定义环境变量:

# In application.yml
spring:
ai:
deepseek:
api-key: ${DEEPSEEK_API_KEY}
# In your environment or .env file
export DEEPSEEK_API_KEY=<your-deepseek-api-key>

您也可以在应用程序代码中通过编程方式设置此配置:

// Retrieve API key from a secure source or environment variable
String apiKey = System.getenv("DEEPSEEK_API_KEY");

添加仓库和物料清单

Spring AI 构件发布在 Spring Milestone 和 Snapshot 仓库中。请参考 Artifact Repositories 部分,将这些仓库添加到您的构建系统中。

为了帮助进行依赖管理,Spring AI 提供了一个 BOM(物料清单)来确保在整个项目中统一使用 Spring AI 的版本。请参考依赖管理部分,将 Spring AI BOM 添加到您的构建系统中。

自动配置

Spring AI 为 DeepSeek Chat 模型提供了 Spring Boot 自动配置。要启用此功能,请将以下依赖项添加到项目的 Maven pom.xml 文件中:

<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>

或将其添加到你的 Gradle build.gradle 文件中。

dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-deepseek'
}
提示

请参考 依赖管理 部分,将 Spring AI BOM 添加到您的构建文件中。

聊天属性

重试属性

前缀 spring.ai.retry 用作属性前缀,用于配置 DeepSeek Chat 模型的重试机制。

属性描述默认值
spring.ai.retry.max-attempts最大重试尝试次数。10
spring.ai.retry.backoff.initial-interval指数退避策略的初始休眠时长。2 秒
spring.ai.retry.backoff.multiplier退避间隔乘数。5
spring.ai.retry.backoff.max-interval最大退避时长。3 分钟
spring.ai.retry.on-client-errors如果为 false,对于 4xx 客户端错误代码,将抛出 NonTransientAiException 且不尝试重试。false
spring.ai.retry.exclude-on-http-codes不应触发重试的 HTTP 状态码列表(例如,抛出 NonTransientAiException)。
spring.ai.retry.on-http-codes应触发重试的 HTTP 状态码列表(例如,抛出 TransientAiException)。

连接属性

前缀 spring.ai.deepseek 被用作属性前缀,使你能够连接到 DeepSeek。

属性描述默认值
spring.ai.deepseek.base-url连接使用的 URLhttps://api.deepseek.com
spring.ai.deepseek.api-keyAPI 密钥-

配置属性

spring.ai.deepseek.chat 是用于配置 DeepSeek 聊天模型实现的属性前缀。

属性描述默认值
spring.ai.deepseek.chat.enabled启用 DeepSeek 聊天模型。true
spring.ai.deepseek.chat.base-url可选地覆盖 spring.ai.deepseek.base-url 以提供聊天专用的 URLhttps://api.deepseek.com/
spring.ai.deepseek.chat.api-key可选地覆盖 spring.ai.deepseek.api-key 以提供聊天专用的 API 密钥-
spring.ai.deepseek.chat.completions-path聊天补全端点的路径/chat/completions
spring.ai.deepseek.chat.beta-prefix-pathBeta 功能端点的前缀路径/beta
spring.ai.deepseek.chat.options.model要使用的模型 ID。您可以使用 deepseek-reasoner 或 deepseek-chat。deepseek-chat
spring.ai.deepseek.chat.options.frequencyPenalty介于 -2.0 和 2.0 之间的数字。正值会根据标记在文本中已有的频率对新标记进行惩罚,从而降低模型逐字重复相同内容的可能性。0.0f
spring.ai.deepseek.chat.options.maxTokens聊天补全中生成的最大标记数。输入标记和生成标记的总长度受模型上下文长度限制。-
spring.ai.deepseek.chat.options.presencePenalty介于 -2.0 和 2.0 之间的数字。正值会根据新标记是否已在文本中出现对其进行惩罚,从而增加模型谈论新话题的可能性。0.0f
spring.ai.deepseek.chat.options.stop最多 4 个序列,API 将在这些序列处停止生成更多标记。-
spring.ai.deepseek.chat.options.temperature使用的采样温度,介于 0 和 2 之间。较高的值(如 0.8)会使输出更加随机,而较低的值(如 0.2)会使其更加集中和确定。我们通常建议调整此参数或 top_p,但不要同时调整两者。1.0F
spring.ai.deepseek.chat.options.topP温度采样的替代方法,称为核采样,模型考虑 top_p 概率质量的标记结果。因此,0.1 意味着只考虑构成前 10% 概率质量的标记。我们通常建议调整此参数或温度,但不要同时调整两者。1.0F
spring.ai.deepseek.chat.options.logprobs是否返回输出标记的对数概率。如果为 true,则返回消息内容中每个返回的输出标记的对数概率。-
spring.ai.deepseek.chat.options.topLogprobs介于 0 和 20 之间的整数,指定在每个标记位置返回的最可能标记的数量,每个标记都有相关的对数概率。如果使用此参数,则必须将 logprobs 设置为 true。-
spring.ai.deepseek.chat.options.tool-names工具名称列表,用于在单个提示请求中启用函数调用。具有这些名称的工具必须存在于 ToolCallback 注册表中。-
spring.ai.deepseek.chat.options.tool-callbacks要注册到 ChatModel 的 Tool Callback。-
spring.ai.deepseek.chat.options.internal-tool-execution-enabled如果为 false,Spring AI 将不会在内部处理工具调用,而是将其代理给客户端。然后客户端负责处理工具调用、将其分派给适当的函数并返回结果。如果为 true(默认值),Spring AI 将在内部处理函数调用。仅适用于支持函数调用的聊天模型true
备注

你可以为 ChatModel 实现覆盖通用的 spring.ai.deepseek.base-urlspring.ai.deepseek.api-key。如果设置了 spring.ai.deepseek.chat.base-urlspring.ai.deepseek.chat.api-key 属性,它们将优先于通用属性。如果你希望为不同模型和不同的模型端点使用不同的 DeepSeek 账户,这将非常有用。

:::提示
所有以 spring.ai.deepseek.chat.options 为前缀的属性,都可以在运行时通过在 Prompt 调用中添加特定于请求的运行时选项来覆盖。
:::

运行时选项

DeepSeekChatOptions.java 提供了模型配置选项,例如使用的模型、温度参数、频率惩罚等。

在启动时,可以通过 DeepSeekChatModel(api, options) 构造函数或 spring.ai.deepseek.chat.options.* 属性来配置默认选项。

在运行时,你可以通过向Prompt调用添加新的、特定于请求的选项来覆盖默认选项。例如,要覆盖特定请求的默认模型和温度:

ChatResponse response = chatModel.call(
new Prompt(
"Generate the names of 5 famous pirates. Please provide the JSON response without any code block markers such as ```json```.",
DeepSeekChatOptions.builder()
.withModel(DeepSeekApi.ChatModel.DEEPSEEK_CHAT.getValue())
.withTemperature(0.8f)
.build()
));
提示

除了特定于模型的 DeepSeekChatOptions 外,你也可以使用一个可移植的 ChatOptions 实例,该实例可以通过 ChatOptions#builder() 创建。

示例控制器(自动配置)

创建一个新的Spring Boot项目,并将spring-ai-starter-model-deepseek添加到您的pom(或gradle)依赖项中。

src/main/resources 目录下添加一个 application.properties 文件来启用并配置 DeepSeek Chat 模型:

spring.ai.deepseek.api-key=YOUR_API_KEY
spring.ai.deepseek.chat.options.model=deepseek-chat
spring.ai.deepseek.chat.options.temperature=0.8

:::提示
请将 api-key 替换为你的 DeepSeek 凭证。
:::

这将创建一个 DeepSeekChatModel 实现,你可以将其注入到你的类中。以下是一个使用该聊天模型进行文本生成的简单 @Controller 类示例。

@RestController
public class ChatController {

private final DeepSeekChatModel chatModel;

@Autowired
public ChatController(DeepSeekChatModel chatModel) {
this.chatModel = chatModel;
}

@GetMapping("/ai/generate")
public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
return Map.of("generation", chatModel.call(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);
}
}

聊天前缀补全

聊天前缀补全遵循聊天补全 API 的规范,用户提供助手的初始消息前缀,模型将基于此前缀完成剩余的消息内容。

当使用前缀补全功能时,用户必须确保消息列表中的最后一条消息是DeepSeekAssistantMessage。

以下是一个完整的聊天前缀补全Java代码示例。在此示例中,我们将助手的消息前缀设置为 "```python\n" 以强制模型输出 Python 代码,并设置停止参数为 [‘`’] 以防止模型输出额外的解释。

@RestController
public class CodeGenerateController {

private final DeepSeekChatModel chatModel;

@Autowired
public ChatController(DeepSeekChatModel chatModel) {
this.chatModel = chatModel;
}

@GetMapping("/ai/generatePythonCode")
public String generate(@RequestParam(value = "message", defaultValue = "Please write quick sort code") String message) {
UserMessage userMessage = new UserMessage(message);
Message assistantMessage = DeepSeekAssistantMessage.prefixAssistantMessage("```python\\n");
Prompt prompt = new Prompt(List.of(userMessage, assistantMessage), ChatOptions.builder().stopSequences(List.of("```")).build());
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getText();
}
}

Reasoning Model (deepseek-reasoner)

deepseek-reasoner 是 DeepSeek 开发的一款推理模型。在给出最终答案之前,该模型会先生成思维链(Chain of Thought, CoT),以提高其回答的准确性。我们的 API 向用户提供了访问 deepseek-reasoner 生成的 CoT 内容的能力,使他们能够查看、展示并提炼这些信息。

您可以使用 DeepSeekAssistantMessage 来获取由 deepseek-reasoner 生成的思维链(CoT)内容。

public void deepSeekReasonerExample() {
DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder()
.model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER.getValue())
.build();
Prompt prompt = new Prompt("9.11 and 9.8, which is greater?", promptOptions);
ChatResponse response = chatModel.call(prompt);

// Get the CoT content generated by deepseek-reasoner, only available when using deepseek-reasoner model
DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) response.getResult().getOutput();
String reasoningContent = deepSeekAssistantMessage.getReasoningContent();
String text = deepSeekAssistantMessage.getText();
}

推理模型多轮对话

在每一轮对话中,模型输出推理内容(CoT)和最终答案(content)。在下一轮对话中,前几轮的推理内容不会被拼接到上下文里,如下图所示:

多模态测试图像

请注意,如果输入消息序列中包含 reasoning_content 字段,API 将返回 400 错误。因此,在发起 API 请求之前,您应从 API 响应中移除 reasoning_content 字段,如 API 示例所示。

public String deepSeekReasonerMultiRoundExample() {
List<Message> messages = new ArrayList<>();
messages.add(new UserMessage("9.11 and 9.8, which is greater?"));
DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder()
.model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER.getValue())
.build();

Prompt prompt = new Prompt(messages, promptOptions);
ChatResponse response = chatModel.call(prompt);

DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) response.getResult().getOutput();
String reasoningContent = deepSeekAssistantMessage.getReasoningContent();
String text = deepSeekAssistantMessage.getText();

messages.add(AssistantMessage.builder().content(Objects.requireNonNull(text)).build());
messages.add(new UserMessage("How many Rs are there in the word 'strawberry'?"));
Prompt prompt2 = new Prompt(messages, promptOptions);
ChatResponse response2 = chatModel.call(prompt2);

DeepSeekAssistantMessage deepSeekAssistantMessage2 = (DeepSeekAssistantMessage) response2.getResult().getOutput();
String reasoningContent2 = deepSeekAssistantMessage2.getReasoningContent();
return deepSeekAssistantMessage2.getText();
}

手动配置

DeepSeekChatModel 实现了 ChatModelStreamingChatModel 接口,并使用 DeepSeek 低级 API 客户端 连接到 DeepSeek 服务。

spring-ai-deepseek 依赖添加到项目的 Maven pom.xml 文件中:

<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-deepseek</artifactId>
</dependency>

或添加到您的Gradle build.gradle文件中。

dependencies {
implementation 'org.springframework.ai:spring-ai-deepseek'
}
提示

请参考依赖管理部分,将 Spring AI BOM 添加到您的构建文件中。

接下来,创建一个 DeepSeekChatModel 并使用它进行文本生成:

DeepSeekApi deepSeekApi = DeepSeekApi.builder()
.apiKey(System.getenv("DEEPSEEK_API_KEY"))
.build();
DeepSeekChatOptions options = DeepSeekChatOptions.builder()
.model(DeepSeekApi.ChatModel.DEEPSEEK_CHAT.getValue())
.temperature(0.4)
.maxTokens(200)
.build();
DeepSeekChatModel chatModel = DeepSeekChatModel.builder()
.deepSeekApi(deepSeekApi)
.defaultOptions(options)
.build();
ChatResponse response = chatModel.call(
new Prompt("Generate the names of 5 famous pirates."));

// Or with streaming responses
Flux<ChatResponse> streamResponse = chatModel.stream(
new Prompt("Generate the names of 5 famous pirates."));

DeepSeekChatOptions 提供聊天请求的配置信息。DeepSeekChatOptions.Builder 是一个流畅的选项构建器。

底层 DeepSeekApi 客户端

DeepSeekApi 是一个用于 DeepSeek API 的轻量级 Java 客户端。

以下是一个简单的代码片段,展示了如何以编程方式使用该 API:

DeepSeekApi deepSeekApi =
new DeepSeekApi(System.getenv("DEEPSEEK_API_KEY"));

ChatCompletionMessage chatCompletionMessage =
new ChatCompletionMessage("Hello world", Role.USER);

// Sync request
ResponseEntity<ChatCompletion> response = deepSeekApi.chatCompletionEntity(
new ChatCompletionRequest(List.of(chatCompletionMessage), DeepSeekApi.ChatModel.DEEPSEEK_CHAT.getValue(), 0.7, false));

// Streaming request
Flux<ChatCompletionChunk> streamResponse = deepSeekApi.chatCompletionStream(
new ChatCompletionRequest(List.of(chatCompletionMessage), DeepSeekApi.ChatModel.DEEPSEEK_CHAT.getValue(), 0.7, true));

有关更多信息,请参阅 DeepSeekApi.java 的 JavaDoc。

DeepSeekApi 示例

  • DeepSeekApiIT.java 测试提供了一些关于如何使用该轻量级库的通用示例。