Skip to content

Commit

Permalink
com.openai.unity 7.1.0 (#146)
Browse files Browse the repository at this point in the history
- Refactor ImagesEndpoint
  - Changed all endpoint signatures to `IReadOnlyList<ImageResult>`
- Fix Text To Speech generation for webgl
- Updated Chat sample with image generation capabilities
  • Loading branch information
StephenHodgson authored Dec 14, 2023
1 parent a446783 commit 562bf5c
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 316 deletions.
36 changes: 14 additions & 22 deletions Documentation~/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1107,12 +1107,10 @@ var api = new OpenAIClient();
var request = new ImageGenerationRequest("A house riding a velociraptor", Models.Model.DallE_3);
var imageResults = await api.ImagesEndPoint.GenerateImageAsync(request);

foreach (var (path, texture) in results)
foreach (var result in imageResults)
{
Debug.Log(path);
// path == file://path/to/image.png
Assert.IsNotNull(texture);
// texture == The preloaded Texture2D
Debug.Log(result.ToString());
Assert.IsNotNull(result.Texture);
}
```

Expand All @@ -1125,12 +1123,10 @@ var api = new OpenAIClient();
var request = new ImageEditRequest(Path.GetFullPath(imageAssetPath), Path.GetFullPath(maskAssetPath), "A sunlit indoor lounge area with a pool containing a flamingo", size: ImageSize.Small);
var imageResults = await api.ImagesEndPoint.CreateImageEditAsync(request);

foreach (var (path, texture) in imageResults)
foreach (var result in imageResults)
{
Debug.Log(path);
// path == file://path/to/image.png
Assert.IsNotNull(texture);
// texture == The preloaded Texture2D
Debug.Log(result.ToString());
Assert.IsNotNull(result.Texture);
}
```

Expand All @@ -1143,12 +1139,10 @@ var api = new OpenAIClient();
var request = new ImageVariationRequest(imageTexture, size: ImageSize.Small);
var imageResults = await api.ImagesEndPoint.CreateImageVariationAsync(request);

foreach (var (path, texture) in imageResults)
foreach (var result in imageResults)
{
Debug.Log(path);
// path == file://path/to/image.png
Assert.IsNotNull(texture);
// texture == The preloaded Texture2D
Debug.Log(result.ToString());
Assert.IsNotNull(result.Texture);
}
```

Expand All @@ -1157,14 +1151,12 @@ Alternatively, the endpoint can directly take a Texture2D with Read/Write enable
```csharp
var api = new OpenAIClient();
var request = new ImageVariationRequest(imageTexture, size: ImageSize.Small);
var results = await api.ImagesEndPoint.CreateImageVariationAsync(request);
// imageTexture is of type Texture2D
foreach (var (path, texture) in results)
var imageResults = await api.ImagesEndPoint.CreateImageVariationAsync(request);

foreach (var result in imageResults)
{
Debug.Log(path);
// path == file://path/to/image.png
Assert.IsNotNull(texture);
// texture == The preloaded Texture2D
Debug.Log(result.ToString());
Assert.IsNotNull(result.Texture);
}
```

Expand Down
18 changes: 12 additions & 6 deletions Runtime/Audio/AudioEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Scripting;
using Utilities.WebRequestRest;

Expand Down Expand Up @@ -56,12 +57,17 @@ public async Task<Tuple<string, AudioClip>> CreateSpeechAsync(SpeechRequest requ
_ => throw new NotSupportedException(request.ResponseFormat.ToString())
};
var payload = JsonConvert.SerializeObject(request, OpenAIClient.JsonSerializationOptions);
var response = await Rest.PostAsync(GetUrl("/speech"), payload, new RestParameters(client.DefaultRequestHeaders), cancellationToken);
response.Validate(EnableDebug);
await Rest.ValidateCacheDirectoryAsync();
var cachedPath = Path.Combine(Rest.DownloadCacheDirectory, $"{request.Voice}-{DateTime.UtcNow:yyyyMMddThhmmss}.{ext}");
await File.WriteAllBytesAsync(cachedPath, response.Data, cancellationToken).ConfigureAwait(true);
var clip = await Rest.DownloadAudioClipAsync($"file://{cachedPath}", audioFormat, cancellationToken: cancellationToken);
var clipName = $"{request.Voice}-{DateTime.UtcNow:yyyyMMddThhmmss}.{ext}";
var clip = await Rest.DownloadAudioClipAsync(
GetUrl("/speech"),
audioFormat,
UnityWebRequest.kHttpVerbPOST,
clipName,
payload,
parameters: new RestParameters(client.DefaultRequestHeaders),
debug: EnableDebug,
cancellationToken: cancellationToken);
Rest.TryGetDownloadCacheItem(clipName, out var cachedPath);
return new Tuple<string, AudioClip>(cachedPath, clip);
}

Expand Down
4 changes: 2 additions & 2 deletions Runtime/Chat/Conversation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public sealed class Conversation
{
[Preserve]
[JsonConstructor]
public Conversation([JsonProperty("messages")] List<Message> messages)
public Conversation([JsonProperty("messages")] List<Message> messages = null)
{
this.messages = messages;
this.messages = messages ?? new List<Message>();
}

private readonly List<Message> messages;
Expand Down
2 changes: 1 addition & 1 deletion Runtime/Files/FilesEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public async Task<FileResponse> GetFileInfoAsync(string fileId, CancellationToke
public async Task<string> DownloadFileAsync(string fileId, IProgress<Progress> progress = null, CancellationToken cancellationToken = default)
{
var file = await GetFileInfoAsync(fileId, cancellationToken);
return await Rest.DownloadFileAsync(GetUrl($"/{file.Id}/content"), file.FileName, new RestParameters(client.DefaultRequestHeaders, progress), cancellationToken: cancellationToken);
return await Rest.DownloadFileAsync(GetUrl($"/{file.Id}/content"), file.FileName, new RestParameters(client.DefaultRequestHeaders, progress), EnableDebug, cancellationToken);
}
}
}
26 changes: 10 additions & 16 deletions Runtime/Images/ImageGenerationRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ namespace OpenAI.Images
[Preserve]
public sealed class ImageGenerationRequest
{
[Preserve]
[Obsolete("Use new constructor")]
public ImageGenerationRequest(string prompt, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null, ResponseFormat responseFormat = ResponseFormat.Url)
{
throw new NotSupportedException();
}

/// <summary>
/// Constructor.
/// </summary>
Expand Down Expand Up @@ -59,22 +52,23 @@ public ImageGenerationRequest(string prompt, int numberOfResults = 1, ImageSize
/// <param name="user">
/// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.
/// </param>
[JsonConstructor]
public ImageGenerationRequest(
string prompt,
Model model = null,
int numberOfResults = 1,
string quality = null,
ResponseFormat responseFormat = ResponseFormat.Url,
string size = null,
string style = null,
string user = null)
[JsonProperty("prompt")] string prompt,
[JsonProperty("model")] Model model = null,
[JsonProperty("n")] int numberOfResults = 1,
[JsonProperty("quality")] string quality = null,
[JsonProperty("response_format")] ResponseFormat responseFormat = ResponseFormat.Url,
[JsonProperty("size")] string size = null,
[JsonProperty("style")] string style = null,
[JsonProperty("user")] string user = null)
{
Prompt = prompt;
Model = string.IsNullOrWhiteSpace(model?.Id) ? Models.Model.DallE_2 : model;
Number = numberOfResults;
Quality = quality;
ResponseFormat = responseFormat;
Size = size;
Size = size ?? "1024x1024";
Style = style;
User = user;
}
Expand Down
38 changes: 37 additions & 1 deletion Runtime/Images/ImageResult.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Scripting;

namespace OpenAI.Images
{
[Preserve]
internal sealed class ImageResult
public sealed class ImageResult
{
[Preserve]
[JsonConstructor]
Expand All @@ -31,5 +32,40 @@ public ImageResult(
[Preserve]
[JsonProperty("revised_prompt")]
public string RevisedPrompt { get; private set; }

[Preserve]
[JsonIgnore]
public string CachedPath { get; internal set; }

[Preserve]
[JsonIgnore]
public Texture2D Texture { get; internal set; }

[Preserve]
public static implicit operator Texture2D(ImageResult imageResult) => imageResult.Texture;

[Preserve]
public static implicit operator string(ImageResult imageResult) => imageResult.ToString();

[Preserve]
public override string ToString()
{
if (!string.IsNullOrWhiteSpace(CachedPath))
{
return CachedPath;
}

if (!string.IsNullOrWhiteSpace(Url))
{
return Url;
}

if (!string.IsNullOrWhiteSpace(B64_Json))
{
return B64_Json;
}

return string.Empty;
}
}
}
Loading

0 comments on commit 562bf5c

Please sign in to comment.