Skip to content

Commit

Permalink
OpenAI-DotNet 6.4.0 (RageAgainstThePixel#63)
Browse files Browse the repository at this point in the history
- Moved OpenAI-DotNet-Proxy back into its own project and package
- Make a few classes sealed that are not meant to be extended
  • Loading branch information
StephenHodgson committed Mar 23, 2023
1 parent d32fcea commit 0a9dbc0
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 118 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/Publish-Nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ on:
- '*'
paths:
- OpenAI-DotNet/**
types:
- opened
- synchronize

workflow_dispatch:
inputs:
Expand All @@ -24,6 +27,7 @@ env:

jobs:
build:
if: ${{ !github.event_name == 'pull_request' || !github.event.pull_request.draft }}
runs-on: windows-latest

steps:
Expand All @@ -45,7 +49,12 @@ jobs:
- name: Build Pack and Publish NuGet Package
run: |
$projectPath = "${{ github.workspace }}\OpenAI-DotNet"
$proxyProjectPath = "${{ github.workspace }}\OpenAI-DotNet-Proxy"
# build all
dotnet build --configuration Release
# pack OpenAI-DotNet
dotnet pack $projectPath --configuration Release --include-symbols
$out = "$projectPath\bin\Release"
$packagePath = Get-ChildItem -Path $out -File -Include '*.nupkg' -Exclude '*symbols*' -Recurse -ErrorAction SilentlyContinue
Expand All @@ -57,10 +66,23 @@ jobs:
exit 1
}
# pack OpenAI-DotNet-Proxy
dotnet pack $proxyProjectPath --configuration Release --include-symbols
$proxyOut = "$proxyProjectPath\bin\Release"
$proxyPackagePath = Get-ChildItem -Path $proxyOut -File -Include '*.nupkg' -Exclude '*symbols*' -Recurse -ErrorAction SilentlyContinue
if ($proxyPackagePath) {
Write-Host Package path: $proxyPackagePath
} else {
Write-Host Failed to find package at $proxyOut
exit 1
}
$isRelease = "${{ github.ref == 'refs/heads/main' }}"
if ($isRelease -eq 'true') {
dotnet nuget push $packagePath.FullName --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push $proxyPackagePath.FullName --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
}
$version = $packagePath.Name -replace "^OpenAI-DotNet.(.*).nupkg$",'$1'
Expand All @@ -74,4 +96,6 @@ jobs:
path: |
${{ github.workspace }}/OpenAI-DotNet/bin/Release/OpenAI-DotNet.${{ env.PACKAGE_VERSION }}.nupkg
${{ github.workspace }}/OpenAI-DotNet/bin/Release/OpenAI-DotNet.${{ env.PACKAGE_VERSION }}.symbols.nupkg
${{ github.workspace }}/OpenAI-DotNet/bin/Release/OpenAI-DotNet-Proxy.${{ env.PACKAGE_VERSION }}.nupkg
${{ github.workspace }}/OpenAI-DotNet/bin/Release/OpenAI-DotNet-Proxy.${{ env.PACKAGE_VERSION }}.symbols.nupkg
if-no-files-found: ignore
5 changes: 5 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project>
<PropertyGroup>
<OpenAIDotNetVersion>6.4.0</OpenAIDotNetVersion>
</PropertyGroup>
</Project>
55 changes: 41 additions & 14 deletions OpenAI-DotNet-Proxy/OpenAI-DotNet-Proxy.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>OpenAI_DotNet_Proxy</RootNamespace>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<LangVersion>latest</LangVersion>
<OutputPath>..\OpenAI-DotNet\bin\$(Configuration)\</OutputPath>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenAI-DotNet\OpenAI-DotNet.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>false</ImplicitUsings>
<Nullable>disable</Nullable>
<SignAssembly>false</SignAssembly>
<Authors>Stephen Hodgson</Authors>
<Product>OpenAI-DotNet-Proxy</Product>
<Description>A simple Proxy API gateway for OpenAI-DotNet to make authenticated requests from a front end application without exposing your API keys.</Description>
<Copyright>2023</Copyright>
<PackageLicenseExpression>CC0-1.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/RageAgainstThePixel/OpenAI-DotNet</PackageProjectUrl>
<RepositoryUrl>https://github.com/RageAgainstThePixel/OpenAI-DotNet</RepositoryUrl>
<PackageTags>OpenAI, AI, ML, API, gpt, gpt-4, gpt-3.5-turbo, gpt-3, chatGPT, api-proxy, proxy, gateway</PackageTags>
<Title>OpenAI API Proxy</Title>
<PackageId>OpenAI-DotNet-Proxy</PackageId>
<Version>$(OpenAIDotNetVersion)</Version>
<Company>RageAgainstThePixel</Company>
<RootNamespace>OpenAI.Proxy</RootNamespace>
<PackageIcon>OpenAI-DotNet-Icon.png</PackageIcon>
<PackageReleaseNotes>Initial Release!</PackageReleaseNotes>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<PackageReadmeFile>Readme.md</PackageReadmeFile>
<IncludeSymbols>True</IncludeSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\OpenAI-DotNet\OpenAI-DotNet.csproj" />
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<None Include="..\OpenAI-DotNet\Assets\OpenAI-DotNet-Icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<None Update="Readme.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
</Project>
84 changes: 84 additions & 0 deletions OpenAI-DotNet-Proxy/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@

# OpenAI-DotNet-Proxy

[![NuGet version (OpenAI-DotNet-Proxy)](https://img.shields.io/nuget/v/OpenAI-DotNet-Proxy.svg?label=OpenAI-DotNet-Proxy&logo=nuget)](https://www.nuget.org/packages/OpenAI-DotNet-Proxy/)

A simple Proxy API gateway for [OpenAI-DotNet](https://github.com/RageAgainstThePixel/OpenAI-DotNet) to make authenticated requests from a front end application without exposing your API keys.

## Getting started

### Install from NuGet

Install package [`OpenAI-DotNet-Proxy` from Nuget](https://www.nuget.org/packages/OpenAI-DotNet-Proxy/). Here's how via command line:

```powershell
Install-Package OpenAI-DotNet-Proxy
```

## Documentation

Using either the [OpenAI-DotNet](https://github.com/RageAgainstThePixel/OpenAI-DotNet) or [com.openai.unity](https://github.com/RageAgainstThePixel/com.openai.unity) packages directly in your front-end app may expose your API keys and other sensitive information. To mitigate this risk, it is recommended to set up an intermediate API that makes requests to OpenAI on behalf of your front-end app. This library can be utilized for both front-end and intermediary host configurations, ensuring secure communication with the OpenAI API.

### Front End Example

In the front end example, you will need to securely authenticate your users using your preferred OAuth provider. Once the user is authenticated, exchange your custom auth token with your API key on the backend.

Follow these steps:

1. Setup a new project using either the [OpenAI-DotNet](https://github.com/RageAgainstThePixel/OpenAI-DotNet) or [com.openai.unity](https://github.com/RageAgainstThePixel/com.openai.unity) packages.
2. Authenticate users with your OAuth provider.
3. After successful authentication, create a new `OpenAIAuthentication` object and pass in the custom token with the prefix `sess-`.
4. Create a new `OpenAIClientSettings` object and specify the domain where your intermediate API is located.
5. Pass your new `auth` and `settings` objects to the `OpenAIClient` constructor when you create the client instance.

Here's an example of how to set up the front end:

```csharp
var authToken = await LoginAsync();
var auth = new OpenAIAuthentication($"sess-{authToken}");
var settings = new OpenAIClientSettings(domain: "api.your-custom-domain.com");
var api = new OpenAIClient(auth, settings);
```

This setup allows your front end application to securely communicate with your backend that will be using the OpenAI-DotNet-Proxy, which then forwards requests to the OpenAI API. This ensures that your OpenAI API keys and other sensitive information remain secure throughout the process.

### Back End Example

In this example, we demonstrate how to set up and use `OpenAIProxyStartup` in a new ASP.NET Core web app. The proxy server will handle authentication and forward requests to the OpenAI API, ensuring that your API keys and other sensitive information remain secure.

1. Create a new [ASP.NET Core minimal web API](https://learn.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0) project.
2. Add the OpenAI-DotNet nuget package to your project.
- Powershell install: `Install-Package OpenAI-DotNet-Proxy`
- Manually editing .csproj: `<PackageReference Include="OpenAI-DotNet-Proxy" />`
3. Create a new class that inherits from `AbstractAuthenticationFilter` and override the `ValidateAuthentication` method. This will implement the `IAuthenticationFilter` that you will use to check user session token against your internal server.
4. In `Program.cs`, create a new proxy web application by calling `OpenAIProxyStartup.CreateDefaultHost` method, passing your custom `AuthenticationFilter` as a type argument.
5. Create `OpenAIAuthentication` and `OpenAIClientSettings` as you would normally with your API keys, org id, or Azure settings.

```csharp
public partial class Program
{
private class AuthenticationFilter : AbstractAuthenticationFilter
{
public override void ValidateAuthentication(IHeaderDictionary request)
{
// You will need to implement your own class to properly test
// custom issued tokens you've setup for your end users.
if (!request.Authorization.ToString().Contains(userToken))
{
throw new AuthenticationException("User is not authorized");
}
}
}

public static void Main(string[] args)
{
var auth = OpenAIAuthentication.LoadFromEnv();
var settings = new OpenAIClientSettings(/* your custom settings if using Azure OpenAI */);
var openAIClient = new OpenAIClient(auth, settings);
var proxy = OpenAIProxyStartup.CreateDefaultHost<AuthenticationFilter>(args, openAIClient);
proxy.Run();
}
}
```

Once you have set up your proxy server, your end users can now make authenticated requests to your proxy api instead of directly to the OpenAI API. The proxy server will handle authentication and forward requests to the OpenAI API, ensuring that your API keys and other sensitive information remain secure.
7 changes: 6 additions & 1 deletion OpenAI-DotNet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ VisualStudioVersion = 17.5.33424.131
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI-DotNet", "OpenAI-DotNet\OpenAI-DotNet.csproj", "{76B6480E-154A-4341-B530-AFE04B254360}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI-DotNet-Proxy", "OpenAI-DotNet-Proxy\OpenAI-DotNet-Proxy.csproj", "{A4D454D4-C21C-49D3-85A7-B4950358C6E7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI-DotNet-Proxy", "OpenAI-DotNet-Proxy\OpenAI-DotNet-Proxy.csproj", "{A4D454D4-C21C-49D3-85A7-B4950358C6E7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI-DotNet-Tests", "OpenAI-DotNet-Tests\OpenAI-DotNet-Tests.csproj", "{066EC5A5-47CE-4B91-B924-F236644037C1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI-DotNet-Tests-Proxy", "OpenAI-DotNet-Tests-Proxy\OpenAI-DotNet-Tests-Proxy.csproj", "{F8B5D079-FD33-4A9E-92C4-CC88C911CFF3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{01FAF825-F72B-4FBD-9CFF-57FDAB089F36}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
2 changes: 1 addition & 1 deletion OpenAI-DotNet/Files/FilesEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace OpenAI.Files
/// Files are used to upload documents that can be used with features like Fine-tuning.<br/>
/// <see href="https://beta.openai.com/docs/api-reference/fine-tunes"/>
/// </summary>
public class FilesEndpoint : BaseEndPoint
public sealed class FilesEndpoint : BaseEndPoint
{
private class FilesList
{
Expand Down
2 changes: 1 addition & 1 deletion OpenAI-DotNet/FineTuning/FineTuningEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace OpenAI.FineTuning
/// Manage fine-tuning jobs to tailor a model to your specific training data.<br/>
/// <see href="https://beta.openai.com/docs/guides/fine-tuning"/>
/// </summary>
public class FineTuningEndpoint : BaseEndPoint
public sealed class FineTuningEndpoint : BaseEndPoint
{
private class FineTuneList
{
Expand Down
2 changes: 1 addition & 1 deletion OpenAI-DotNet/FineTuning/FineTuningTrainingData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace OpenAI.FineTuning
/// where you might input detailed instructions or multiple examples in a single prompt.
/// <see href="https://beta.openai.com/docs/guides/fine-tuning/specific-guidelines"/>
/// </summary>
public class FineTuningTrainingData
public sealed class FineTuningTrainingData
{
/// <summary>
/// Constructor.
Expand Down
89 changes: 85 additions & 4 deletions OpenAI-DotNet/OpenAI-DotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,95 @@
<TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Authors>Stephen Hodgson</Authors>
<Product>OpenAI-DotNet</Product>
<Description>A simple C# .NET client library for OpenAI to use chat-gpt, gpt-4, gpt-3.5-turbo and Dall-E though their RESTful API (currently in beta). Independently developed, this is not an official library and I am not affiliated with OpenAI. An OpenAI API account is required.

Forked from [OpenAI-API-dotnet](https://github.com/OkGoDoIt/OpenAI-API-dotnet).

More context [on Roger Pincombe's blog](https://rogerpincombe.com/openai-dotnet-api).
</Description>
<Copyright>2023</Copyright>
<PackageLicenseExpression>CC0-1.0</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>Assets\OpenAI-DotNet-Icon.png</PackageIcon>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<PackageProjectUrl>https://github.com/RageAgainstThePixel/OpenAI-DotNet</PackageProjectUrl>
<RepositoryUrl>https://github.com/RageAgainstThePixel/OpenAI-DotNet</RepositoryUrl>
<PackageTags>OpenAI, AI, ML, API, gpt-4, gpt-3.5-tubo, gpt-3, chatGPT, chat-gpt, gpt-2, gpt</PackageTags>
<Title>OpenAI API</Title>
<PackageReleaseNotes>Bump version to 6.4.0
- Moved OpenAI-DotNet-Proxy back into its own project and package
- Make a few classes sealed that are not meant to be extended
Bump version to 6.3.2
- Attempt to fix dependency requirement for dotnet/runtime docker base images
- Made internal OpenAIClient constructor with HttpClient public
- Make sure we only copy the appropriate headers in the proxy
Bump version to 6.3.1
- Fixed apikey requiring sk- prefix with Azure OpenAI
Bump version to 6.3.0
- Removed OpenAI-DotNet-Proxy and put it directly in package on its own
Bump version to 6.2.0
- Added OpenAI-DotNet-Proxy project and package.
- Added support for custom domains
- Updated unit tests
- Updated docs
Bump version to 6.1.0
- Added support for gpt-4 models
Bump version to 6.0.1
- Updated package info
- Updated docs
Bump version to 6.0.0
- Added support for Azure OpenAI
Bump version to 5.1.2
- Fixed an issue when deleting personal account fine tuned models
Bump version to 5.1.1
- Refactored Model validation
- Added additional default models
- Deprecate OpenAIClient.DefaultModel
- Implemented chat completion streaming
- Refactored immutable types
Bump version to 5.1.0
- Add support for Audio endpoint and Whisper models
- Audio Speech to text
- Audio translation
Bump version to 5.0.2
- Support multiple inputs in embedding
- Added better model validation in all endpoints
Bump version to 5.0.1
- Fixed chat parameters
Bump version to 5.0.0
- Added Chat endpoint
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</PackageReleaseNotes>
<SignAssembly>false</SignAssembly>
<AssemblyOriginatorKeyFile>OpenAI-DotNet.pfx</AssemblyOriginatorKeyFile>
<DelaySign>true</DelaySign>
<NuspecFile>OpenAI-DotNet.nuspec</NuspecFile>
<PackageId>OpenAI-DotNet</PackageId>
<Version>$(OpenAIDotNetVersion)</Version>
<Company>RageAgainstThePixel</Company>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>Assets\OpenAI-DotNet-Icon.png</PackageIcon>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<IncludeSymbols>True</IncludeSymbols>
</PropertyGroup>
<ItemGroup>
<None Include="..\README.md">
Expand Down
Loading

0 comments on commit 0a9dbc0

Please sign in to comment.