Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ public class DeepSeekChatProperties extends DeepSeekParentProperties {

private @Nullable ReasoningEffort reasoningEffort;

private @Nullable Boolean echo;

private @Nullable String suffix;

public boolean isEnabled() {
return this.enabled;
}
Expand Down Expand Up @@ -196,6 +200,22 @@ public void setReasoningEffort(@Nullable ReasoningEffort reasoningEffort) {
this.reasoningEffort = reasoningEffort;
}

public @Nullable Boolean getEcho() {
return this.echo;
}

public void setEcho(@Nullable Boolean echo) {
this.echo = echo;
}

public @Nullable String getSuffix() {
return this.suffix;
}

public void setSuffix(@Nullable String suffix) {
this.suffix = suffix;
}

public DeepSeekChatOptions toOptions() {
return DeepSeekChatOptions.builder()
.model(this.model)
Expand All @@ -210,6 +230,8 @@ public DeepSeekChatOptions toOptions() {
.topLogprobs(this.topLogprobs)
.thinking(this.thinking)
.reasoningEffort(this.reasoningEffort)
.echo(this.echo)
.suffix(this.suffix)
.build();
}

Expand Down Expand Up @@ -347,6 +369,26 @@ public void setReasoningEffort(@Nullable ReasoningEffort reasoningEffort) {
DeepSeekChatProperties.this.setReasoningEffort(reasoningEffort);
}

@DeprecatedConfigurationProperty(replacement = "spring.ai.deepseek.chat.echo")
@Deprecated(since = "2.0.0", forRemoval = true)
public @Nullable Boolean getEcho() {
return DeepSeekChatProperties.this.getEcho();
}

public void setEcho(@Nullable Boolean echo) {
DeepSeekChatProperties.this.setEcho(echo);
}

@DeprecatedConfigurationProperty(replacement = "spring.ai.deepseek.chat.suffix")
@Deprecated(since = "2.0.0", forRemoval = true)
public @Nullable String getSuffix() {
return DeepSeekChatProperties.this.getSuffix();
}

public void setSuffix(@Nullable String suffix) {
DeepSeekChatProperties.this.setSuffix(suffix);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ public void chatOptionsTest() {
"spring.ai.deepseek.chat.top-p=0.56",
"spring.ai.deepseek.chat.user=userXYZ",
"spring.ai.deepseek.chat.thinking.type=disabled",
"spring.ai.deepseek.chat.reasoning-effort=max"
"spring.ai.deepseek.chat.reasoning-effort=max",
"spring.ai.deepseek.chat.echo=true",
"spring.ai.deepseek.chat.suffix=return x"
)
// @formatter:on
.withConfiguration(AutoConfigurations.of(DeepSeekChatAutoConfiguration.class,
Expand All @@ -141,6 +143,13 @@ public void chatOptionsTest() {
assertThat(chatProperties.getTopP()).isEqualTo(0.56);
assertThat(chatProperties.getThinking()).isEqualTo(Thinking.DISABLED);
assertThat(chatProperties.getReasoningEffort()).isEqualTo(ReasoningEffort.MAX);

assertThat(chatProperties.getEcho()).isTrue();
assertThat(chatProperties.getSuffix()).isEqualTo("return x");

var chatOptions = chatProperties.toOptions();
assertThat(chatOptions.getEcho()).isTrue();
assertThat(chatOptions.getSuffix()).isEqualTo("return x");
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,12 @@ else if (message.getMessageType() == MessageType.TOOL) {
if (options.getReasoningEffort() != null) {
requestBuilder.reasoningEffort(options.getReasoningEffort());
}
if (options.getEcho() != null) {
requestBuilder.echo(options.getEcho());
}
if (options.getSuffix() != null) {
requestBuilder.suffix(options.getSuffix());
}

// Add the tool definitions to the request's tools parameter.
List<ToolDefinition> toolDefinitions = this.toolCallingManager.resolveToolDefinitions(options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ public class DeepSeekChatOptions implements ToolCallingChatOptions {
*/
private final @Nullable ReasoningEffort reasoningEffort;

/**
* Echo back the prompt in addition to the completion.
*/
private final @Nullable Boolean echo;

/**
* The suffix that comes after a completion of inserted text.
*/
private final @Nullable String suffix;

/**
* Tool Function Callbacks to register with the ChatModel.
* For Prompt Options the toolCallbacks are automatically enabled for the duration of the prompt execution.
Expand All @@ -158,7 +168,8 @@ protected DeepSeekChatOptions(@Nullable String model, @Nullable Double frequency
@Nullable List<String> stop, @Nullable Double temperature, @Nullable Double topP,
@Nullable Boolean logprobs, @Nullable Integer topLogprobs, @Nullable List<DeepSeekApi.FunctionTool> tools,
@Nullable Object toolChoice, @Nullable Thinking thinking, @Nullable ReasoningEffort reasoningEffort,
@Nullable List<ToolCallback> toolCallbacks, @Nullable Map<String, Object> toolContext) {
@Nullable Boolean echo, @Nullable String suffix, @Nullable List<ToolCallback> toolCallbacks,
@Nullable Map<String, Object> toolContext) {
this.model = model != null ? model : DeepSeekApi.DEFAULT_CHAT_MODEL.getValue();
this.frequencyPenalty = frequencyPenalty;
this.maxTokens = maxTokens;
Expand All @@ -173,6 +184,8 @@ protected DeepSeekChatOptions(@Nullable String model, @Nullable Double frequency
this.toolChoice = toolChoice;
this.thinking = thinking;
this.reasoningEffort = reasoningEffort;
this.echo = echo;
this.suffix = suffix;
this.toolCallbacks = toolCallbacks != null ? List.copyOf(toolCallbacks) : null;
this.toolContext = toolContext != null ? Map.copyOf(toolContext) : null;
}
Expand Down Expand Up @@ -253,6 +266,14 @@ public String getModel() {
return this.topLogprobs;
}

public @Nullable Boolean getEcho() {
return this.echo;
}

public @Nullable String getSuffix() {
return this.suffix;
}

@Override
public @Nullable Integer getTopK() {
return null;
Expand Down Expand Up @@ -285,14 +306,17 @@ public Builder mutate() {
.tools(this.tools)
.toolChoice(this.toolChoice)
.thinking(this.thinking)
.reasoningEffort(this.reasoningEffort);
.reasoningEffort(this.reasoningEffort)
.echo(this.echo)
.suffix(this.suffix);
}

@Override
public int hashCode() {
return Objects.hash(this.model, this.frequencyPenalty, this.logprobs, this.topLogprobs, this.maxTokens,
this.presencePenalty, this.responseFormat, this.stop, this.temperature, this.topP, this.tools,
this.toolChoice, this.thinking, this.reasoningEffort, this.toolCallbacks, this.toolContext);
this.toolChoice, this.thinking, this.reasoningEffort, this.echo, this.suffix, this.toolCallbacks,
this.toolContext);
}

@Override
Expand All @@ -312,8 +336,8 @@ public boolean equals(@Nullable Object o) {
&& Objects.equals(this.temperature, other.temperature) && Objects.equals(this.topP, other.topP)
&& Objects.equals(this.tools, other.tools) && Objects.equals(this.toolChoice, other.toolChoice)
&& Objects.equals(this.thinking, other.thinking)
&& Objects.equals(this.reasoningEffort, other.reasoningEffort)
&& Objects.equals(this.toolCallbacks, other.toolCallbacks)
&& Objects.equals(this.reasoningEffort, other.reasoningEffort) && Objects.equals(this.echo, other.echo)
&& Objects.equals(this.suffix, other.suffix) && Objects.equals(this.toolCallbacks, other.toolCallbacks)
&& Objects.equals(this.toolContext, other.toolContext);
}

Expand Down Expand Up @@ -347,6 +371,10 @@ public B clone() {

protected @Nullable ReasoningEffort reasoningEffort;

protected @Nullable Boolean echo;

protected @Nullable String suffix;

public B model(DeepSeekApi.@Nullable ChatModel deepseekAiChatModel) {
if (deepseekAiChatModel == null) {
this.model = null;
Expand Down Expand Up @@ -416,6 +444,16 @@ public B reasoningEffortMax() {
return self();
}

public B echo(@Nullable Boolean echo) {
this.echo = echo;
return self();
}

public B suffix(@Nullable String suffix) {
this.suffix = suffix;
return self();
}

public B combineWith(ChatOptions.Builder<?> other) {
super.combineWith(other);
if (other instanceof AbstractBuilder<?> that) {
Expand Down Expand Up @@ -447,6 +485,12 @@ public B combineWith(ChatOptions.Builder<?> other) {
if (that.reasoningEffort != null) {
this.reasoningEffort = that.reasoningEffort;
}
if (that.echo != null) {
this.echo = that.echo;
}
if (that.suffix != null) {
this.suffix = that.suffix;
}
}
return self();
}
Expand All @@ -455,8 +499,8 @@ public B combineWith(ChatOptions.Builder<?> other) {
public DeepSeekChatOptions build() {
return new DeepSeekChatOptions(this.model, this.frequencyPenalty, this.maxTokens, this.presencePenalty,
this.responseFormat, this.stopSequences, this.temperature, this.topP, this.logprobs,
this.topLogprobs, this.tools, this.toolChoice, this.thinking, this.reasoningEffort,
this.toolCallbacks, this.toolContext);
this.topLogprobs, this.tools, this.toolChoice, this.thinking, this.reasoningEffort, this.echo,
this.suffix, this.toolCallbacks, this.toolContext);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
Expand Down Expand Up @@ -218,7 +219,7 @@ private String getEndpoint(ChatCompletionRequest request) {
.map(ChatCompletionMessage::prefix)
.filter(Objects::nonNull)
.anyMatch(prefix -> prefix);
String endpointPrefix = isPrefix ? this.betaPrefixPath : "";
String endpointPrefix = isPrefix || StringUtils.hasText(request.suffix) ? this.betaPrefixPath : "";
return endpointPrefix + this.completionsPath;
}

Expand Down Expand Up @@ -517,7 +518,9 @@ public record ChatCompletionRequest(// @formatter:off
@JsonProperty("tools") @Nullable List<FunctionTool> tools,
@JsonProperty("tool_choice") @Nullable Object toolChoice,
@JsonProperty("thinking") @Nullable Thinking thinking,
@JsonProperty("reasoning_effort") @Nullable ReasoningEffort reasoningEffort) {
@JsonProperty("reasoning_effort") @Nullable ReasoningEffort reasoningEffort,
@JsonProperty("echo") @Nullable Boolean echo,
@JsonProperty("suffix") @Nullable String suffix) {

/**
* Create a new {@link ChatCompletionRequest} builder.
Expand All @@ -537,7 +540,7 @@ public static Builder builder() {
public ChatCompletionRequest(List<ChatCompletionMessage> messages, Boolean stream) {
this(messages, null, null, null, null, null,
null, stream, null, null, null, null, null,
null, null, null);
null, null, null, null, null);
}

/**
Expand All @@ -550,7 +553,7 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, Boolean strea
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Double temperature) {
this(messages, model, null,
null, null, null, null, false, temperature, null,
null, null, null, null, null, null);
null, null, null, null, null, null, null, null);
}

/**
Expand All @@ -565,7 +568,7 @@ public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Double temperature, boolean stream) {
this(messages, model, null,
null, null, null, null, stream, temperature, null,
null, null, null, null, null, null);
null, null, null, null, null, null, null, null);
}

/**
Expand Down Expand Up @@ -683,6 +686,10 @@ public static class Builder {

private @Nullable Thinking thinking;

private @Nullable Boolean echo;

private @Nullable String suffix;

/**
* Set the messages comprising the conversation so far.
* @param messages the messages.
Expand Down Expand Up @@ -843,6 +850,26 @@ public Builder thinking(@Nullable Thinking thinking) {
return this;
}

/**
* Set whether to echo the prompt.
* @param echo whether to echo the prompt.
* @return this builder.
*/
public Builder echo(@Nullable Boolean echo) {
this.echo = echo;
return this;
}

/**
* Set the suffix.
* @param suffix the suffix.
* @return this builder.
*/
public Builder suffix(@Nullable String suffix) {
this.suffix = suffix;
return this;
}

/**
* Build the {@link ChatCompletionRequest}.
* @return a new {@link ChatCompletionRequest}.
Expand All @@ -852,7 +879,7 @@ public ChatCompletionRequest build() {
return new ChatCompletionRequest(this.messages, this.model, this.frequencyPenalty, this.maxTokens,
this.presencePenalty, this.responseFormat, this.stop, this.stream, this.temperature, this.topP,
this.logprobs, this.topLogprobs, this.tools, this.toolChoice, this.thinking,
this.reasoningEffort);
this.reasoningEffort, this.echo, this.suffix);
}

}
Expand Down
Loading
Loading