Skip to content

Commit 4a32968

Browse files
committed
Add deterministic seeds
1 parent 2f2a50b commit 4a32968

File tree

5 files changed

+92
-5
lines changed

5 files changed

+92
-5
lines changed

OpenAI_API/Chat/ChatRequest.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ internal Dictionary<string, string> ResponseFormatRaw
145145
}
146146
}
147147

148+
/// <summary>
149+
/// If specified, OpenAI will make a best effort to sample deterministically, such that repeated requests with the same seed and parameters should return the same result. Determinism is not guaranteed, and you should refer to the <see cref="ChatResult.SystemFingerprint"/> response parameter to monitor changes in the backend.
150+
/// </summary>
151+
[JsonProperty("seed", DefaultValueHandling=DefaultValueHandling.Ignore)]
152+
public int? Seed { get; set; }
153+
148154
/// <summary>
149155
/// Creates a new, empty <see cref="ChatRequest"/>
150156
/// </summary>

OpenAI_API/Chat/ChatResult.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ public override string ToString()
3939
else
4040
return null;
4141
}
42+
43+
/// <summary>
44+
/// This fingerprint represents the backend configuration that the model runs with. It can be used in conjunction with the seed request parameter to understand when backend changes have been made that might impact determinism.This is the indicator on whether users should expect "almost always the same result".
45+
/// </summary>
46+
[JsonProperty("system_fingerprint")]
47+
public string SystemFingerprint { get; set; }
4248
}
4349

4450
/// <summary>

OpenAI_API/Completions/CompletionRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public string StopSequence
162162
public string user { get; set; }
163163

164164
/// <summary>
165-
/// Cretes a new, empty <see cref="CompletionRequest"/>
165+
/// Creates a new, empty <see cref="CompletionRequest"/>
166166
/// </summary>
167167
public CompletionRequest()
168168
{

OpenAI_API/Model/Model.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,16 +144,21 @@ public async Task<Model> RetrieveModelDetailsAsync(OpenAI_API.OpenAIAPI api)
144144
/// The latest GPT-4 model with improved instruction following, JSON mode, reproducible outputs, parallel function calling, and more. Returns a maximum of 4,096 output tokens. This preview model is not yet suited for production traffic.
145145
/// </summary>
146146
public static Model GPT4_Turbo => new Model("gpt-4-1106-preview") { OwnedBy = "openai" };
147-
#endregion
147+
#endregion
148148

149-
#region GPT-3.5
149+
#region GPT-3.5
150150
/// <summary>
151-
/// Most capable GPT-3.5 model and optimized for chat at 1/10th the cost of text-davinci-003. Will be updated with the latest model iteration.
151+
/// GPT-3.5 Turbo model which regularly updates with the latest model iteration.
152152
/// </summary>
153153
public static Model ChatGPTTurbo => new Model("gpt-3.5-turbo") { OwnedBy = "openai" };
154154

155155
/// <summary>
156-
/// The latest GPT-3.5 Turbo model with 16k context window, improved instruction following, JSON mode, reproducible outputs, parallel function calling, and more. Returns a maximum of 4,096 output tokens.
156+
/// The latest GPT-3.5 Turbo model with improved instruction following, JSON mode, reproducible outputs, parallel function calling, and more. Returns a maximum of 4,096 output tokens.
157+
/// </summary>
158+
public static Model ChatGPTTurbo_1106 => new Model("gpt-3.5-turbo-1106") { OwnedBy = "openai" };
159+
160+
/// <summary>
161+
/// GPT-3.5 Turbo model with 16k context window, improved instruction following.
157162
/// </summary>
158163
public static Model ChatGPTTurbo_16k => new Model("gpt-3.5-turbo-16k") { OwnedBy = "openai" };
159164

OpenAI_Tests/ChatEndpointTests.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,5 +496,75 @@ public void ChatJsonFormat(string model)
496496
}
497497

498498
}
499+
500+
[Test]
501+
public async Task SameSeedShouldBeSameOutput() {
502+
var api = new OpenAI_API.OpenAIAPI();
503+
ChatRequest chatRequest = new ChatRequest()
504+
{
505+
Model = Model.ChatGPTTurbo_1106,
506+
Temperature = 0,
507+
MaxTokens = 100,
508+
Seed = 5,
509+
Messages = new ChatMessage[] {
510+
new ChatMessage(ChatMessageRole.System, "You are a very creative comedian."),
511+
new ChatMessage(ChatMessageRole.User, "Tell me a joke.")
512+
}
513+
};
514+
var resultA = await api.Chat.CreateChatCompletionAsync(chatRequest);
515+
string jokeA = resultA.ToString();
516+
string systemFingerprintA = resultA.SystemFingerprint;
517+
Assert.IsNotNull(systemFingerprintA);
518+
Assert.IsNotEmpty(systemFingerprintA);
519+
Assert.IsNotEmpty(jokeA);
520+
521+
var resultB = await api.Chat.CreateChatCompletionAsync(chatRequest);
522+
string jokeB = resultB.ToString();
523+
string systemFingerprintB = resultB.SystemFingerprint;
524+
Assert.IsNotNull(systemFingerprintB);
525+
Assert.IsNotEmpty(systemFingerprintB);
526+
Assert.IsNotEmpty(jokeB);
527+
528+
if (systemFingerprintA == systemFingerprintB)
529+
{
530+
Assert.AreEqual(jokeA, jokeB);
531+
}
532+
}
533+
534+
[Test]
535+
public async Task DifferentSeedShouldBeDifferentOutput()
536+
{
537+
var api = new OpenAI_API.OpenAIAPI();
538+
ChatRequest chatRequest = new ChatRequest()
539+
{
540+
Model = Model.ChatGPTTurbo_1106,
541+
Temperature = 0,
542+
MaxTokens = 100,
543+
Seed = 5,
544+
Messages = new ChatMessage[] {
545+
new ChatMessage(ChatMessageRole.System, "You are a very creative comedian."),
546+
new ChatMessage(ChatMessageRole.User, "Tell me a joke.")
547+
}
548+
};
549+
var resultA = await api.Chat.CreateChatCompletionAsync(chatRequest);
550+
string jokeA = resultA.ToString();
551+
string systemFingerprintA = resultA.SystemFingerprint;
552+
Assert.IsNotNull(systemFingerprintA);
553+
Assert.IsNotEmpty(systemFingerprintA);
554+
Assert.IsNotEmpty(jokeA);
555+
556+
chatRequest.Seed = 99;
557+
var resultB = await api.Chat.CreateChatCompletionAsync(chatRequest);
558+
string jokeB = resultB.ToString();
559+
string systemFingerprintB = resultB.SystemFingerprint;
560+
Assert.IsNotNull(systemFingerprintB);
561+
Assert.IsNotEmpty(systemFingerprintB);
562+
Assert.IsNotEmpty(jokeB);
563+
564+
if (systemFingerprintA == systemFingerprintB)
565+
{
566+
Assert.AreNotEqual(jokeA, jokeB);
567+
}
568+
}
499569
}
500570
}

0 commit comments

Comments
 (0)