Skip to content

Commit

Permalink
OpenAI-DotNet 4.4.4 (RageAgainstThePixel#26)
Browse files Browse the repository at this point in the history
- `ImageEditRequest` mask is now optional so long as texture has alpha
transparency
- `ImageVariationRequest` added constructor overload for memory stream
image
- Updated `AuthInfo` parameter validation
- Renamed `OPEN_AI_ORGANIZATION_ID` -> `OPENAI_ORGANIZATION_ID`
- Updated docs
  • Loading branch information
StephenHodgson committed Feb 18, 2023
1 parent 13f6f74 commit ce9aa8d
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 73 deletions.
9 changes: 5 additions & 4 deletions OpenAI-DotNet/AuthInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ internal class AuthInfo
[JsonConstructor]
public AuthInfo(string apiKey, string organizationId = null)
{
if (!apiKey.Contains("sk-"))
if (string.IsNullOrWhiteSpace(apiKey) ||
!apiKey.Contains("sk-"))
{
throw new InvalidCredentialException($"{apiKey} parameter must start with 'sk-'");
throw new InvalidCredentialException($"{apiKey} must start with 'sk-'");
}

ApiKey = apiKey;

if (organizationId != null)
if (!string.IsNullOrWhiteSpace(organizationId))
{
if (!organizationId.Contains("org-"))
{
throw new InvalidCredentialException($"{nameof(organizationId)} parameter must start with 'org-'");
throw new InvalidCredentialException($"{nameof(organizationId)} must start with 'org-'");
}

OrganizationId = organizationId;
Expand Down
68 changes: 27 additions & 41 deletions OpenAI-DotNet/Images/ImageEditRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,46 +29,16 @@ public sealed class ImageEditRequest : IDisposable
/// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.
/// </param>
public ImageEditRequest(string imagePath, string maskPath, string prompt, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null)
: this(
File.OpenRead(imagePath),
Path.GetFileName(imagePath),
string.IsNullOrWhiteSpace(maskPath) ? null : File.OpenRead(maskPath),
string.IsNullOrWhiteSpace(maskPath) ? null : Path.GetFileName(maskPath),
prompt,
numberOfResults,
size,
user)
{
if (!File.Exists(imagePath))
{
throw new FileNotFoundException($"Could not find the {nameof(imagePath)} file located at {imagePath}");
}

Image = File.OpenRead(imagePath);
ImageName = Path.GetFileName(imagePath);

if (!File.Exists(maskPath))
{
throw new FileNotFoundException($"Could not find the {nameof(maskPath)} file located at {maskPath}");
}

Mask = File.OpenRead(maskPath);
MaskName = Path.GetFileName(maskPath);

if (prompt.Length > 1000)
{
throw new ArgumentOutOfRangeException(nameof(prompt), "The maximum character length for the prompt is 1000 characters.");
}

Prompt = prompt;

if (numberOfResults is > 10 or < 1)
{
throw new ArgumentOutOfRangeException(nameof(numberOfResults), "The number of results must be between 1 and 10");
}

Number = numberOfResults;

Size = size switch
{
ImageSize.Small => "256x256",
ImageSize.Medium => "512x512",
ImageSize.Large => "1024x1024",
_ => throw new ArgumentOutOfRangeException(nameof(size), size, null)
};

User = user;
}

/// <summary>
Expand Down Expand Up @@ -99,9 +69,25 @@ public ImageEditRequest(string imagePath, string maskPath, string prompt, int nu
public ImageEditRequest(Stream image, string imageName, Stream mask, string maskName, string prompt, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null)
{
Image = image;

if (string.IsNullOrWhiteSpace(imageName))
{
imageName = "image.png";
}

ImageName = imageName;
Mask = mask;
MaskName = maskName;

if (mask != null)
{
Mask = mask;

if (string.IsNullOrWhiteSpace(maskName))
{
maskName = "mask.png";
}

MaskName = maskName;
}

if (prompt.Length > 1000)
{
Expand Down
33 changes: 28 additions & 5 deletions OpenAI-DotNet/Images/ImageVariationRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ public sealed class ImageVariationRequest : IDisposable
/// </summary>
/// <param name="imagePath">
/// The image to edit. Must be a valid PNG file, less than 4MB, and square.
/// If mask is not provided, image must have transparency, which will be used as the mask.
/// </param>
/// <param name="numberOfResults">
/// The number of images to generate. Must be between 1 and 10.
Expand All @@ -22,14 +21,38 @@ public sealed class ImageVariationRequest : IDisposable
/// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.
/// </param>
public ImageVariationRequest(string imagePath, int numberOfResults = 1, ImageSize size = ImageSize.Large, string user = null)
: this(File.OpenRead(imagePath), Path.GetFileName(imagePath), numberOfResults, size, user)
{
if (!File.Exists(imagePath))
}

/// <summary>
/// Constructor.
/// </summary>
/// <param name="image">
/// The image to edit. Must be a valid PNG file, less than 4MB, and square.
/// </param>
/// <param name="imageName">
/// The name of the image.
/// </param>
/// <param name="numberOfResults">
/// The number of images to generate. Must be between 1 and 10.
/// </param>
/// <param name="size">
/// The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024.
/// </param>
/// <param name="user">
/// A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.
/// </param>
public ImageVariationRequest(Stream image, string imageName, int numberOfResults, ImageSize size, string user)
{
Image = image;

if (string.IsNullOrWhiteSpace(imageName))
{
throw new FileNotFoundException($"Could not find the {nameof(imagePath)} file located at {imagePath}");
imageName = "image.png";
}

Image = File.OpenRead(imagePath);
ImageName = Path.GetFileName(imagePath);
ImageName = imageName;

if (numberOfResults is > 10 or < 1)
{
Expand Down
11 changes: 8 additions & 3 deletions OpenAI-DotNet/Images/ImagesEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,14 @@ public async Task<IReadOnlyList<string>> CreateImageEditAsync(ImageEditRequest r
using var imageData = new MemoryStream();
await request.Image.CopyToAsync(imageData, cancellationToken).ConfigureAwait(false);
content.Add(new ByteArrayContent(imageData.ToArray()), "image", request.ImageName);
using var maskData = new MemoryStream();
await request.Mask.CopyToAsync(maskData, cancellationToken).ConfigureAwait(false);
content.Add(new ByteArrayContent(maskData.ToArray()), "mask", request.MaskName);

if (request.Mask != null)
{
using var maskData = new MemoryStream();
await request.Mask.CopyToAsync(maskData, cancellationToken);
content.Add(new ByteArrayContent(maskData.ToArray()), "mask", request.MaskName);
}

content.Add(new StringContent(request.Prompt), "prompt");
content.Add(new StringContent(request.Number.ToString()), "n");
content.Add(new StringContent(request.Size), "size");
Expand Down
30 changes: 19 additions & 11 deletions OpenAI-DotNet/OpenAI-DotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,36 @@ Based on OpenAI-API by OKGoDoIt (Roger Pincombe)</Description>
<RepositoryUrl>https://github.com/RageAgainstThePixel/OpenAI-DotNet</RepositoryUrl>
<PackageTags>OpenAI, AI, ML, API, gpt, gpt-3, chatGPT</PackageTags>
<Title>OpenAI API</Title>
<PackageReleaseNotes>Bump version to 4.4.0
<PackageReleaseNotes>Bump version to 4.4.4
- ImageEditRequest mask is now optional so long as texture has alpha transparency
- ImageVariationRequest added constructor overload for memory stream image
- Updated AuthInfo parameter validation
- Renamed OPEN_AI_ORGANIZATION_ID -&gt; OPENAI_ORGANIZATION_ID
Bump version to 4.4.3
- added `OPEN_AI_ORGANIZATION_ID` environment variable
- deprecated `Organization` use `OrganizationId` instead
Bump version to 4.4.2
- Removed a useless assert
- Updated docs
Bump version to 4.4.1
- hotfix to CompletionsEndpoint to use `IEnumerable&lt;string&gt;`
- hotfix to cleanup Images endpoints
Bump version to 4.4.0
- Renamed `Choice.Logprobs -&gt; Choice.LogProbabilities`
- Renamed `OpenAI.Completions.Logprobs -&gt; OpenAI.Completions.OpenAI.Completions`
- Renamed `CompletionRequest` parameter names:
- `max_tokens` -&gt; `maxTokens`
- `top_p` -&gt; `topP`
- Updated `CompletionRequest` to accept `IEnumerable&lt;string&gt;` values for `prompts` and `stopSequences`
- Refactored all endpoints to use new response validation extension
- Added `CancellationToken` to most endpoints that had long running operations
Bump version to 4.4.1
- hotfix to CompletionsEndpoint to use `IEnumerable&lt;string&gt;`
- hotfix to cleanup Images endpoints
Bump version to 4.4.2
- Removed a useless assert
- Updated docs</PackageReleaseNotes>
- Added `CancellationToken` to most endpoints that had long running operations</PackageReleaseNotes>
<SignAssembly>false</SignAssembly>
<AssemblyOriginatorKeyFile>OpenAI-DotNet.pfx</AssemblyOriginatorKeyFile>
<DelaySign>true</DelaySign>
<PackageId>OpenAI-DotNet</PackageId>
<Version>4.4.3</Version>
<AssemblyVersion>4.4.3.0</AssemblyVersion>
<FileVersion>4.4.3.0</FileVersion>
<Version>4.4.4</Version>
<AssemblyVersion>4.4.4.0</AssemblyVersion>
<FileVersion>4.4.4.0</FileVersion>
<Company>RageAgainstThePixel</Company>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
Expand Down
6 changes: 6 additions & 0 deletions OpenAI-DotNet/OpenAIAuthentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public sealed class OpenAIAuthentication
private const string OPENAI_API_KEY = "OPENAI_API_KEY";
private const string OPENAI_SECRET_KEY = "OPENAI_SECRET_KEY";
private const string TEST_OPENAI_SECRET_KEY = "TEST_OPENAI_SECRET_KEY";
private const string OPENAI_ORGANIZATION_ID = "OPENAI_ORGANIZATION_ID";
private const string OPEN_AI_ORGANIZATION_ID = "OPEN_AI_ORGANIZATION_ID";
private const string ORGANIZATION = "ORGANIZATION";

Expand Down Expand Up @@ -116,6 +117,11 @@ public static OpenAIAuthentication LoadFromEnv(string organizationId = null)
organizationId = Environment.GetEnvironmentVariable(OPEN_AI_ORGANIZATION_ID);
}

if (string.IsNullOrWhiteSpace(organizationId))
{
organizationId = Environment.GetEnvironmentVariable(OPENAI_ORGANIZATION_ID);
}

return string.IsNullOrEmpty(apiKey) ? null : new OpenAIAuthentication(apiKey, organizationId);
}

Expand Down
12 changes: 3 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ You use the `OpenAIAuthentication` when you initialize the API as shown:
#### Pass keys directly with constructor

```csharp
var api = new OpenAIClient("sk-mykeyhere");
var api = new OpenAIClient("sk-apiKey");
```

Or create a `OpenAIAuthentication` object manually

```csharp
var api = new OpenAIClient(new OpenAIAuthentication("sk-secretkey"));
var api = new OpenAIClient(new OpenAIAuthentication("sk-apiKey", "org-yourOrganizationId"));
```

#### Load key from configuration file
Expand Down Expand Up @@ -122,18 +122,12 @@ var api = new OpenAIClient(OpenAIAuthentication.LoadFromDirectory("your/path/to/
Use your system's environment variables specify an api key and organization to use.

- Use `OPENAI_API_KEY` for your api key.
- Use `OPEN_AI_ORGANIZATION_ID` to specify an organization.
- Use `OPENAI_ORGANIZATION_ID` to specify an organization.

```csharp
var api = new OpenAIClient(OpenAIAuthentication.LoadFromEnv());
```

or

```csharp
var api = new OpenAIClient(OpenAIAuthentication.LoadFromEnv("org-yourOrganizationId"));
```

### [Models](https://beta.openai.com/docs/api-reference/models)

List and describe the various models available in the API. You can refer to the [Models documentation](https://beta.openai.com/docs/models) to understand what models are available and the differences between them.
Expand Down

0 comments on commit ce9aa8d

Please sign in to comment.