Skip to content

Commit

Permalink
Fix deserialization of Run Steps when using File Search
Browse files Browse the repository at this point in the history
  • Loading branch information
joseharriaga committed Sep 1, 2024
1 parent 78f3f96 commit 46f31a5
Show file tree
Hide file tree
Showing 17 changed files with 253 additions and 122 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
- Updated fine-tuning pagination methods `GetJobs`, `GetEvents`, and `GetJobCheckpoints` to return `IEnumerable<ClientResult>` instead of `ClientResult`. (commit_hash)
- Updated the batching pagination method `GetBatches` to return `IEnumerable<ClientResult>` instead of `ClientResult`. (commit_hash)
- Changed `GeneratedSpeechVoice` from an enum to an "extensible enum". (commit_hash)
- Changed `GeneratedSpeechFormat` from an enum to an "extensible enum". (commit_hash)
- Renamed `SpeechGenerationOptions`'s `Speed` property to `SpeedRatio`. (commit_hash)

### Bugs Fixed

- Corrected an internal deserialization issue that caused recent updates to Assistants `file_search` to fail when streaming a run. Strongly typed support for `ranking_options` is not included but will arrive soon. (commit_hash)

### Other Changes

- Reverted the removal of the version path parameter "v1" from the default endpoint URL. (commit_hash)
Expand Down
28 changes: 20 additions & 8 deletions api/OpenAI.netstandard2.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1084,13 +1084,25 @@ public class AudioTranslationOptions : IJsonModel<AudioTranslationOptions>, IPer
string IPersistableModel<AudioTranslationOptions>.GetFormatFromOptions(ModelReaderWriterOptions options);
BinaryData IPersistableModel<AudioTranslationOptions>.Write(ModelReaderWriterOptions options);
}
public enum GeneratedSpeechFormat {
Mp3 = 0,
Opus = 1,
Aac = 2,
Flac = 3,
Wav = 4,
Pcm = 5
public readonly partial struct GeneratedSpeechFormat : IEquatable<GeneratedSpeechFormat> {
private readonly object _dummy;
private readonly int _dummyPrimitive;
public GeneratedSpeechFormat(string value);
public static GeneratedSpeechFormat Aac { get; }
public static GeneratedSpeechFormat Flac { get; }
public static GeneratedSpeechFormat Mp3 { get; }
public static GeneratedSpeechFormat Opus { get; }
public static GeneratedSpeechFormat Pcm { get; }
public static GeneratedSpeechFormat Wav { get; }
public readonly bool Equals(GeneratedSpeechFormat other);
[EditorBrowsable(EditorBrowsableState.Never)]
public override readonly bool Equals(object obj);
[EditorBrowsable(EditorBrowsableState.Never)]
public override readonly int GetHashCode();
public static bool operator ==(GeneratedSpeechFormat left, GeneratedSpeechFormat right);
public static implicit operator GeneratedSpeechFormat(string value);
public static bool operator !=(GeneratedSpeechFormat left, GeneratedSpeechFormat right);
public override readonly string ToString();
}
public readonly partial struct GeneratedSpeechVoice : IEquatable<GeneratedSpeechVoice> {
private readonly object _dummy;
Expand Down Expand Up @@ -1120,7 +1132,7 @@ public static class OpenAIAudioModelFactory {
}
public class SpeechGenerationOptions : IJsonModel<SpeechGenerationOptions>, IPersistableModel<SpeechGenerationOptions> {
public GeneratedSpeechFormat? ResponseFormat { get; set; }
public float? Speed { get; set; }
public float? SpeedRatio { get; set; }
SpeechGenerationOptions IJsonModel<SpeechGenerationOptions>.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options);
void IJsonModel<SpeechGenerationOptions>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options);
SpeechGenerationOptions IPersistableModel<SpeechGenerationOptions>.Create(BinaryData data, ModelReaderWriterOptions options);
Expand Down
6 changes: 3 additions & 3 deletions examples/CombinationExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void AlpacaArtAssessor()
GeneratedSpeechVoice.Fable,
new SpeechGenerationOptions()
{
Speed = 0.9f,
SpeedRatio = 0.9f,
ResponseFormat = GeneratedSpeechFormat.Opus,
});
FileInfo ttsFileInfo = new($"{chatCompletion.Id}.opus");
Expand Down Expand Up @@ -89,7 +89,7 @@ public async Task CuriousCreatureCreator()
GeneratedSpeechVoice.Onyx,
new SpeechGenerationOptions()
{
Speed = 1.1f,
SpeedRatio = 1.1f,
ResponseFormat = GeneratedSpeechFormat.Opus,
});
_ = Task.Run(async () =>
Expand Down Expand Up @@ -136,7 +136,7 @@ public async Task CuriousCreatureCreator()
GeneratedSpeechVoice.Fable,
new SpeechGenerationOptions()
{
Speed = 0.9f,
SpeedRatio = 0.9f,
ResponseFormat = GeneratedSpeechFormat.Opus,
});
FileInfo criticAudioFileInfo = new($"{criticalAppraisalResult.Value.Id}-appraisal.opus");
Expand Down
29 changes: 2 additions & 27 deletions src/Custom/Audio/GeneratedSpeechFormat.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,7 @@
namespace OpenAI.Audio;

/// <summary>
/// Represents an audio data format available as either input or output into an audio operation.
/// </summary>
/// <summary> The audio format in which to generate the speech. </summary>
[CodeGenModel("CreateSpeechRequestResponseFormat")]
public enum GeneratedSpeechFormat
public readonly partial struct GeneratedSpeechFormat
{
/// <summary> MP3. /// </summary>
[CodeGenMember("Mp3")]
Mp3,

/// <summary> Opus. /// </summary>
[CodeGenMember("Opus")]
Opus,

/// <summary> AAC (advanced audio coding). /// </summary>
[CodeGenMember("Aac")]
Aac,

/// <summary> FLAC (free lossless audio codec). /// </summary>
[CodeGenMember("Flac")]
Flac,

/// <summary> WAV. /// </summary>
[CodeGenMember("Wav")]
Wav,

/// <summary> PCM (pulse-code modulation). /// </summary>
[CodeGenMember("Pcm")]
Pcm,
}
22 changes: 12 additions & 10 deletions src/Custom/Audio/SpeechGenerationOptions.cs
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
namespace OpenAI.Audio;

/// <summary>
/// A representation of additional options available to control the behavior of a text-to-speech audio generation
/// operation.
/// </summary>
/// <summary> The options to configure text-to-speech audio generation. </summary>
[CodeGenModel("CreateSpeechRequest")]
[CodeGenSuppress("SpeechGenerationOptions", typeof(InternalCreateSpeechRequestModel), typeof(string), typeof(GeneratedSpeechVoice))]
public partial class SpeechGenerationOptions
{
// CUSTOM:
// - Made internal. The model is specified by the client.
// - Added setter.
/// <summary> One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. </summary>
[CodeGenMember("Model")]
internal InternalCreateSpeechRequestModel Model { get; set; }

// CUSTOM:
// - Made internal. This value comes from a parameter on the client method.
// - Added setter.
/// <summary> The text to generate audio for. The maximum length is 4096 characters. </summary>
[CodeGenMember("Input")]
internal string Input { get; set; }

// CUSTOM:
// - Made internal. This value comes from a parameter on the client method.
// - Added setter.
/// <summary>
/// The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`,
/// `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the
/// [Text to speech guide](/docs/guides/text-to-speech/voice-options).
/// </summary>
[CodeGenMember("Voice")]
internal GeneratedSpeechVoice Voice { get; set; }

// CUSTOM: Made public now that there are no required properties.
/// <summary> Initializes a new instance of <see cref="SpeechGenerationOptions"/>. </summary>
public SpeechGenerationOptions()
{
}

// CUSTOM: Renamed.
/// <summary>
/// The speed of the generated audio expressed as a ratio between 0.5 and 2.0. The default is 1.0.
/// </summary>
[CodeGenMember("Speed")]

public float? SpeedRatio { get; set; }
}
33 changes: 0 additions & 33 deletions src/Generated/Models/GeneratedSpeechFormat.Serialization.cs

This file was deleted.

44 changes: 44 additions & 0 deletions src/Generated/Models/GeneratedSpeechFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <auto-generated/>

#nullable disable

using System;
using System.ComponentModel;

namespace OpenAI.Audio
{
public readonly partial struct GeneratedSpeechFormat : IEquatable<GeneratedSpeechFormat>
{
private readonly string _value;

public GeneratedSpeechFormat(string value)
{
_value = value ?? throw new ArgumentNullException(nameof(value));
}

private const string Mp3Value = "mp3";
private const string OpusValue = "opus";
private const string AacValue = "aac";
private const string FlacValue = "flac";
private const string WavValue = "wav";
private const string PcmValue = "pcm";

public static GeneratedSpeechFormat Mp3 { get; } = new GeneratedSpeechFormat(Mp3Value);
public static GeneratedSpeechFormat Opus { get; } = new GeneratedSpeechFormat(OpusValue);
public static GeneratedSpeechFormat Aac { get; } = new GeneratedSpeechFormat(AacValue);
public static GeneratedSpeechFormat Flac { get; } = new GeneratedSpeechFormat(FlacValue);
public static GeneratedSpeechFormat Wav { get; } = new GeneratedSpeechFormat(WavValue);
public static GeneratedSpeechFormat Pcm { get; } = new GeneratedSpeechFormat(PcmValue);
public static bool operator ==(GeneratedSpeechFormat left, GeneratedSpeechFormat right) => left.Equals(right);
public static bool operator !=(GeneratedSpeechFormat left, GeneratedSpeechFormat right) => !left.Equals(right);
public static implicit operator GeneratedSpeechFormat(string value) => new GeneratedSpeechFormat(value);

[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj) => obj is GeneratedSpeechFormat other && Equals(other);
public bool Equals(GeneratedSpeechFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase);

[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => _value != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_value) : 0;
public override string ToString() => _value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,19 @@ void IJsonModel<InternalBatchRequestOutputResponse>.Write(Utf8JsonWriter writer,
foreach (var item in Body)
{
writer.WritePropertyName(item.Key);
writer.WriteStringValue(item.Value);
if (item.Value == null)
{
writer.WriteNullValue();
continue;
}
#if NET6_0_OR_GREATER
writer.WriteRawValue(item.Value);
#else
using (JsonDocument document = JsonDocument.Parse(item.Value))
{
JsonSerializer.Serialize(writer, document.RootElement);
}
#endif
}
writer.WriteEndObject();
}
Expand Down Expand Up @@ -86,7 +98,7 @@ internal static InternalBatchRequestOutputResponse DeserializeInternalBatchReque
}
int? statusCode = default;
string requestId = default;
IReadOnlyDictionary<string, string> body = default;
IReadOnlyDictionary<string, BinaryData> body = default;
IDictionary<string, BinaryData> serializedAdditionalRawData = default;
Dictionary<string, BinaryData> rawDataDictionary = new Dictionary<string, BinaryData>();
foreach (var property in element.EnumerateObject())
Expand All @@ -111,10 +123,17 @@ internal static InternalBatchRequestOutputResponse DeserializeInternalBatchReque
{
continue;
}
Dictionary<string, string> dictionary = new Dictionary<string, string>();
Dictionary<string, BinaryData> dictionary = new Dictionary<string, BinaryData>();
foreach (var property0 in property.Value.EnumerateObject())
{
dictionary.Add(property0.Name, property0.Value.GetString());
if (property0.Value.ValueKind == JsonValueKind.Null)
{
dictionary.Add(property0.Name, null);
}
else
{
dictionary.Add(property0.Name, BinaryData.FromString(property0.Value.GetRawText()));
}
}
body = dictionary;
continue;
Expand All @@ -126,7 +145,7 @@ internal static InternalBatchRequestOutputResponse DeserializeInternalBatchReque
}
}
serializedAdditionalRawData = rawDataDictionary;
return new InternalBatchRequestOutputResponse(statusCode, requestId, body ?? new ChangeTrackingDictionary<string, string>(), serializedAdditionalRawData);
return new InternalBatchRequestOutputResponse(statusCode, requestId, body ?? new ChangeTrackingDictionary<string, BinaryData>(), serializedAdditionalRawData);
}

BinaryData IPersistableModel<InternalBatchRequestOutputResponse>.Write(ModelReaderWriterOptions options)
Expand Down
6 changes: 3 additions & 3 deletions src/Generated/Models/InternalBatchRequestOutputResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ internal partial class InternalBatchRequestOutputResponse
internal IDictionary<string, BinaryData> SerializedAdditionalRawData { get; set; }
internal InternalBatchRequestOutputResponse()
{
Body = new ChangeTrackingDictionary<string, string>();
Body = new ChangeTrackingDictionary<string, BinaryData>();
}

internal InternalBatchRequestOutputResponse(int? statusCode, string requestId, IReadOnlyDictionary<string, string> body, IDictionary<string, BinaryData> serializedAdditionalRawData)
internal InternalBatchRequestOutputResponse(int? statusCode, string requestId, IReadOnlyDictionary<string, BinaryData> body, IDictionary<string, BinaryData> serializedAdditionalRawData)
{
StatusCode = statusCode;
RequestId = requestId;
Expand All @@ -25,6 +25,6 @@ internal InternalBatchRequestOutputResponse(int? statusCode, string requestId, I

public int? StatusCode { get; }
public string RequestId { get; }
public IReadOnlyDictionary<string, string> Body { get; }
public IReadOnlyDictionary<string, BinaryData> Body { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,19 @@ void IJsonModel<InternalRunStepDeltaStepDetailsToolCallsFileSearchObject>.Write(
foreach (var item in FileSearch)
{
writer.WritePropertyName(item.Key);
writer.WriteStringValue(item.Value);
if (item.Value == null)
{
writer.WriteNullValue();
continue;
}
#if NET6_0_OR_GREATER
writer.WriteRawValue(item.Value);
#else
using (JsonDocument document = JsonDocument.Parse(item.Value))
{
JsonSerializer.Serialize(writer, document.RootElement);
}
#endif
}
writer.WriteEndObject();
}
Expand Down Expand Up @@ -91,7 +103,7 @@ internal static InternalRunStepDeltaStepDetailsToolCallsFileSearchObject Deseria
}
int index = default;
string id = default;
IReadOnlyDictionary<string, string> fileSearch = default;
IReadOnlyDictionary<string, BinaryData> fileSearch = default;
string type = default;
IDictionary<string, BinaryData> serializedAdditionalRawData = default;
Dictionary<string, BinaryData> rawDataDictionary = new Dictionary<string, BinaryData>();
Expand All @@ -109,10 +121,17 @@ internal static InternalRunStepDeltaStepDetailsToolCallsFileSearchObject Deseria
}
if (property.NameEquals("file_search"u8))
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
Dictionary<string, BinaryData> dictionary = new Dictionary<string, BinaryData>();
foreach (var property0 in property.Value.EnumerateObject())
{
dictionary.Add(property0.Name, property0.Value.GetString());
if (property0.Value.ValueKind == JsonValueKind.Null)
{
dictionary.Add(property0.Name, null);
}
else
{
dictionary.Add(property0.Name, BinaryData.FromString(property0.Value.GetRawText()));
}
}
fileSearch = dictionary;
continue;
Expand Down
Loading

0 comments on commit 46f31a5

Please sign in to comment.