Use Double instead of Float for portable ChatOptions

This change updates the type of portable chat options from Float to
Double. Affected options include:
- frequencyPenalty
- presencePenalty
- temperature
- topP

The motivation for this change is to simplify coding. In Java, Float
values require an "f" suffix (e.g., 0.5f), while Double values don't
need any suffix. This makes Double easier to type and reduces
potential errors from forgetting the "f" suffix.

APIs, tests, and documentation have been updated to reflect this
change.

Fixes gh-712

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
This commit is contained in:
Thomas Vitale
2024-09-08 23:24:48 +02:00
committed by Mark Pollack
parent 40714c984d
commit 4b123a7516
146 changed files with 731 additions and 717 deletions

View File

@@ -134,7 +134,7 @@ public class OpenAiChatModel extends AbstractToolCallSupport implements ChatMode
*/
public OpenAiChatModel(OpenAiApi openAiApi) {
this(openAiApi,
OpenAiChatOptions.builder().withModel(OpenAiApi.DEFAULT_CHAT_MODEL).withTemperature(0.7f).build());
OpenAiChatOptions.builder().withModel(OpenAiApi.DEFAULT_CHAT_MODEL).withTemperature(0.7).build());
}
/**

View File

@@ -57,7 +57,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
* Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing
* frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.
*/
private @JsonProperty("frequency_penalty") Float frequencyPenalty;
private @JsonProperty("frequency_penalty") Double frequencyPenalty;
/**
* Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object
* that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100.
@@ -90,7 +90,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
* Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they
* appear in the text so far, increasing the model's likelihood to talk about new topics.
*/
private @JsonProperty("presence_penalty") Float presencePenalty;
private @JsonProperty("presence_penalty") Double presencePenalty;
/**
* An object specifying the format that the model must output. Setting to { "type":
* "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON.
@@ -117,13 +117,13 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
* more random, while lower values like 0.2 will make it more focused and deterministic. We generally recommend
* altering this or top_p but not both.
*/
private @JsonProperty("temperature") Float temperature;
private @JsonProperty("temperature") Double temperature;
/**
* An alternative to sampling with temperature, called nucleus sampling, where the model considers the
* results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10%
* probability mass are considered. We generally recommend altering this or temperature but not both.
*/
private @JsonProperty("top_p") Float topP;
private @JsonProperty("top_p") Double topP;
/**
* A list of tools the model may call. Currently, only functions are supported as a tool. Use this to
* provide a list of functions the model may generate JSON inputs for.
@@ -205,7 +205,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
return this;
}
public Builder withFrequencyPenalty(Float frequencyPenalty) {
public Builder withFrequencyPenalty(Double frequencyPenalty) {
this.options.frequencyPenalty = frequencyPenalty;
return this;
}
@@ -235,7 +235,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
return this;
}
public Builder withPresencePenalty(Float presencePenalty) {
public Builder withPresencePenalty(Double presencePenalty) {
this.options.presencePenalty = presencePenalty;
return this;
}
@@ -260,12 +260,12 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
return this;
}
public Builder withTemperature(Float temperature) {
public Builder withTemperature(Double temperature) {
this.options.temperature = temperature;
return this;
}
public Builder withTopP(Float topP) {
public Builder withTopP(Double topP) {
this.options.topP = topP;
return this;
}
@@ -337,11 +337,11 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
}
@Override
public Float getFrequencyPenalty() {
public Double getFrequencyPenalty() {
return this.frequencyPenalty;
}
public void setFrequencyPenalty(Float frequencyPenalty) {
public void setFrequencyPenalty(Double frequencyPenalty) {
this.frequencyPenalty = frequencyPenalty;
}
@@ -387,11 +387,11 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
}
@Override
public Float getPresencePenalty() {
public Double getPresencePenalty() {
return this.presencePenalty;
}
public void setPresencePenalty(Float presencePenalty) {
public void setPresencePenalty(Double presencePenalty) {
this.presencePenalty = presencePenalty;
}
@@ -439,20 +439,20 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions {
}
@Override
public Float getTemperature() {
public Double getTemperature() {
return this.temperature;
}
public void setTemperature(Float temperature) {
public void setTemperature(Double temperature) {
this.temperature = temperature;
}
@Override
public Float getTopP() {
public Double getTopP() {
return this.topP;
}
public void setTopP(Float topP) {
public void setTopP(Double topP) {
this.topP = topP;
}

View File

@@ -415,20 +415,20 @@ public class OpenAiApi {
public record ChatCompletionRequest(// @formatter:off
@JsonProperty("messages") List<ChatCompletionMessage> messages,
@JsonProperty("model") String model,
@JsonProperty("frequency_penalty") Float frequencyPenalty,
@JsonProperty("frequency_penalty") Double frequencyPenalty,
@JsonProperty("logit_bias") Map<String, Integer> logitBias,
@JsonProperty("logprobs") Boolean logprobs,
@JsonProperty("top_logprobs") Integer topLogprobs,
@JsonProperty("max_tokens") Integer maxTokens,
@JsonProperty("n") Integer n,
@JsonProperty("presence_penalty") Float presencePenalty,
@JsonProperty("presence_penalty") Double presencePenalty,
@JsonProperty("response_format") ResponseFormat responseFormat,
@JsonProperty("seed") Integer seed,
@JsonProperty("stop") List<String> stop,
@JsonProperty("stream") Boolean stream,
@JsonProperty("stream_options") StreamOptions streamOptions,
@JsonProperty("temperature") Float temperature,
@JsonProperty("top_p") Float topP,
@JsonProperty("temperature") Double temperature,
@JsonProperty("top_p") Double topP,
@JsonProperty("tools") List<FunctionTool> tools,
@JsonProperty("tool_choice") Object toolChoice,
@JsonProperty("parallel_tool_calls") Boolean parallelToolCalls,
@@ -441,7 +441,7 @@ public class OpenAiApi {
* @param model ID of the model to use.
* @param temperature What sampling temperature to use, between 0 and 1.
*/
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Float temperature) {
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Double temperature) {
this(messages, model, null, null, null, null, null, null, null,
null, null, null, false, null, temperature, null,
null, null, null, null);
@@ -456,7 +456,7 @@ public class OpenAiApi {
* @param stream If set, partial message deltas will be sent.Tokens will be sent as data-only server-sent events
* as they become available, with the stream terminated by a data: [DONE] message.
*/
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Float temperature, boolean stream) {
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model, Double temperature, boolean stream) {
this(messages, model, null, null, null, null, null, null, null,
null, null, null, stream, null, temperature, null,
null, null, null, null);
@@ -474,7 +474,7 @@ public class OpenAiApi {
public ChatCompletionRequest(List<ChatCompletionMessage> messages, String model,
List<FunctionTool> tools, Object toolChoice) {
this(messages, model, null, null, null, null, null, null, null,
null, null, null, false, null, 0.8f, null,
null, null, null, false, null, 0.8, null,
tools, toolChoice, null, null);
}

View File

@@ -35,7 +35,7 @@ public class ChatCompletionRequestTests {
public void createRequestWithChatOptions() {
var client = new OpenAiChatModel(new OpenAiApi("TEST"),
OpenAiChatOptions.builder().withModel("DEFAULT_MODEL").withTemperature(66.6f).build());
OpenAiChatOptions.builder().withModel("DEFAULT_MODEL").withTemperature(66.6).build());
var request = client.createRequest(new Prompt("Test message content"), false);
@@ -43,16 +43,16 @@ public class ChatCompletionRequestTests {
assertThat(request.stream()).isFalse();
assertThat(request.model()).isEqualTo("DEFAULT_MODEL");
assertThat(request.temperature()).isEqualTo(66.6f);
assertThat(request.temperature()).isEqualTo(66.6);
request = client.createRequest(new Prompt("Test message content",
OpenAiChatOptions.builder().withModel("PROMPT_MODEL").withTemperature(99.9f).build()), true);
OpenAiChatOptions.builder().withModel("PROMPT_MODEL").withTemperature(99.9).build()), true);
assertThat(request.messages()).hasSize(1);
assertThat(request.stream()).isTrue();
assertThat(request.model()).isEqualTo("PROMPT_MODEL");
assertThat(request.temperature()).isEqualTo(99.9f);
assertThat(request.temperature()).isEqualTo(99.9);
}
@Test

View File

@@ -44,7 +44,7 @@ public class OpenAiApiIT {
void chatCompletionEntity() {
ChatCompletionMessage chatCompletionMessage = new ChatCompletionMessage("Hello world", Role.USER);
ResponseEntity<ChatCompletion> response = openAiApi.chatCompletionEntity(
new ChatCompletionRequest(List.of(chatCompletionMessage), "gpt-3.5-turbo", 0.8f, false));
new ChatCompletionRequest(List.of(chatCompletionMessage), "gpt-3.5-turbo", 0.8, false));
assertThat(response).isNotNull();
assertThat(response.getBody()).isNotNull();
@@ -54,7 +54,7 @@ public class OpenAiApiIT {
void chatCompletionStream() {
ChatCompletionMessage chatCompletionMessage = new ChatCompletionMessage("Hello world", Role.USER);
Flux<ChatCompletionChunk> response = openAiApi.chatCompletionStream(
new ChatCompletionRequest(List.of(chatCompletionMessage), "gpt-3.5-turbo", 0.8f, true));
new ChatCompletionRequest(List.of(chatCompletionMessage), "gpt-3.5-turbo", 0.8, true));
assertThat(response).isNotNull();
assertThat(response.collectList().block()).isNotNull();

View File

@@ -124,7 +124,7 @@ public class OpenAiApiToolFunctionCallIT {
}
}
var functionResponseRequest = new ChatCompletionRequest(messages, "gpt-4o", 0.5f);
var functionResponseRequest = new ChatCompletionRequest(messages, "gpt-4o", 0.5);
ResponseEntity<ChatCompletion> chatCompletion2 = completionApi.chatCompletionEntity(functionResponseRequest);

View File

@@ -71,12 +71,12 @@ public class OpenAiChatModelObservationIT {
var options = OpenAiChatOptions.builder()
.withModel(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue())
.withFrequencyPenalty(0f)
.withFrequencyPenalty(0.0)
.withMaxTokens(2048)
.withPresencePenalty(0f)
.withPresencePenalty(0.0)
.withStop(List.of("this-is-the-end"))
.withTemperature(0.7f)
.withTopP(1f)
.withTemperature(0.7)
.withTopP(1.0)
.build();
Prompt prompt = new Prompt("Why does a raven look like a desk?", options);
@@ -94,12 +94,12 @@ public class OpenAiChatModelObservationIT {
void observationForStreamingChatOperation() {
var options = OpenAiChatOptions.builder()
.withModel(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue())
.withFrequencyPenalty(0f)
.withFrequencyPenalty(0.0)
.withMaxTokens(2048)
.withPresencePenalty(0f)
.withPresencePenalty(0.0)
.withStop(List.of("this-is-the-end"))
.withTemperature(0.7f)
.withTopP(1f)
.withTemperature(0.7)
.withTopP(1.0)
.withStreamUsage(true)
.build();

View File

@@ -203,7 +203,7 @@ public class OpenAiPaymentTransactionIT {
return new OpenAiChatModel(openAiApi,
OpenAiChatOptions.builder()
.withModel(ChatModel.GPT_4_O_MINI.getName())
.withTemperature(0.1f)
.withTemperature(0.1)
.build(),
functionCallbackContext, RetryUtils.DEFAULT_RETRY_TEMPLATE);
}