Skip to content

Commit

Permalink
OpenAI-DotNet 7.5.0 (#209)
Browse files Browse the repository at this point in the history
- Changed OpenAIClient to implement IDisposable.
  - Disposing OpenAICLient is now required if you're not passing a custom HttpClient.
  - If passing an custom HttpClient, it will need to be expressly disposed after use.
- Updated Chat.Message.CopyFrom Content check from string.IsNullOrEmpty to null check.
  • Loading branch information
StephenHodgson authored Dec 22, 2023
1 parent f93486c commit 2365dfc
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 102 deletions.
4 changes: 2 additions & 2 deletions OpenAI-DotNet/Chat/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ internal void CopyFrom(Delta other)
Role = other.Role;
}

if (!string.IsNullOrEmpty(other?.Content))
if (other?.Content != null)
{
Content += other.Content;
}
Expand All @@ -159,7 +159,7 @@ internal void CopyFrom(Delta other)
{
toolCalls.Insert(otherToolCall.Index.Value, new Tool(otherToolCall));
}

toolCalls[otherToolCall.Index.Value].CopyFrom(otherToolCall);
}
else
Expand Down
7 changes: 6 additions & 1 deletion OpenAI-DotNet/OpenAI-DotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ More context [on Roger Pincombe's blog](https://rogerpincombe.com/openai-dotnet-
<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, dall-e-2, dall-e-3</PackageTags>
<Title>OpenAI-DotNet</Title>
<Version>7.4.4</Version>
<Version>7.5.0</Version>
<PackageReleaseNotes>
Version 7.5.0
- Changed OpenAIClient to implement IDisposable.
- Disposing OpenAICLient is now required if you're not passing a custom HttpClient.
- If passing an custom HttpClient, it will need to be expressly disposed after use.
- Updated Chat.Message.CopyFrom Content check from string.IsNullOrEmpty to null check.
Version 7.4.4
- Updated Docs
Version 7.4.3
Expand Down
102 changes: 73 additions & 29 deletions OpenAI-DotNet/OpenAIClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ namespace OpenAI
/// <summary>
/// Entry point to the OpenAI API, handling auth and allowing access to the various API endpoints
/// </summary>
public sealed class OpenAIClient
public sealed class OpenAIClient : IDisposable
{
/// <summary>
/// Creates a new entry point to the OpenAPI API, handling auth and allowing access to the various API endpoints
/// </summary>
/// <param name="openAIAuthentication">
/// The API authentication information to use for API calls,
/// or <see langword="null"/> to attempt to use the <see cref="OpenAI.OpenAIAuthentication.Default"/>,
/// or <see langword="null"/> to attempt to use the <see cref="OpenAIAuthentication.Default"/>,
/// potentially loading from environment vars or from a config file.
/// </param>
/// <param name="clientSettings">
Expand Down Expand Up @@ -65,44 +65,42 @@ public OpenAIClient(OpenAIAuthentication openAIAuthentication = null, OpenAIClie
#pragma warning restore CS0618 // Type or member is obsolete
}

private HttpClient SetupClient(HttpClient client = null)
~OpenAIClient()
{
client ??= new HttpClient(new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(15)
});
client.DefaultRequestHeaders.Add("User-Agent", "OpenAI-DotNet");
client.DefaultRequestHeaders.Add("OpenAI-Beta", "assistants=v1");
Dispose(false);
}

if (!OpenAIClientSettings.BaseRequestUrlFormat.Contains(OpenAIClientSettings.AzureOpenAIDomain) &&
(string.IsNullOrWhiteSpace(OpenAIAuthentication.ApiKey) ||
(!OpenAIAuthentication.ApiKey.Contains(AuthInfo.SecretKeyPrefix) &&
!OpenAIAuthentication.ApiKey.Contains(AuthInfo.SessionKeyPrefix))))
{
throw new InvalidCredentialException($"{OpenAIAuthentication.ApiKey} must start with '{AuthInfo.SecretKeyPrefix}'");
}
#region IDisposable

if (OpenAIClientSettings.UseOAuthAuthentication)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", OpenAIAuthentication.ApiKey);
}
else
{
client.DefaultRequestHeaders.Add("api-key", OpenAIAuthentication.ApiKey);
}
private bool isDisposed;

if (!string.IsNullOrWhiteSpace(OpenAIAuthentication.OrganizationId))
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if (!isDisposed && disposing)
{
client.DefaultRequestHeaders.Add("OpenAI-Organization", OpenAIAuthentication.OrganizationId);
}
if (!isCustomClient)
{
Client?.Dispose();
}

return client;
isDisposed = true;
}
}

#endregion IDisposable

private bool isCustomClient;

/// <summary>
/// <see cref="HttpClient"/> to use when making calls to the API.
/// </summary>
internal HttpClient Client { get; private set; }
internal HttpClient Client { get; }

/// <summary>
/// The <see cref="JsonSerializationOptions"/> to use when making calls to the API.
Expand All @@ -128,6 +126,8 @@ private HttpClient SetupClient(HttpClient client = null)
/// </summary>
public bool EnableDebug { get; set; }

#region Endpoints

/// <summary>
/// List and describe the various models available in the API.
/// You can refer to the Models documentation to understand what <see href="https://platform.openai.com/docs/models"/> are available and the differences between them.<br/>
Expand Down Expand Up @@ -208,5 +208,49 @@ private HttpClient SetupClient(HttpClient client = null)
/// </summary>
[Obsolete("Deprecated")]
public EditsEndpoint EditsEndpoint { get; }

#endregion Endpoints

private HttpClient SetupClient(HttpClient client = null)
{
if (client == null)
{
client = new HttpClient(new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(15)
});
}
else
{
isCustomClient = true;
}

client.DefaultRequestHeaders.Add("User-Agent", "OpenAI-DotNet");
client.DefaultRequestHeaders.Add("OpenAI-Beta", "assistants=v1");

if (!OpenAIClientSettings.BaseRequestUrlFormat.Contains(OpenAIClientSettings.AzureOpenAIDomain) &&
(string.IsNullOrWhiteSpace(OpenAIAuthentication.ApiKey) ||
(!OpenAIAuthentication.ApiKey.Contains(AuthInfo.SecretKeyPrefix) &&
!OpenAIAuthentication.ApiKey.Contains(AuthInfo.SessionKeyPrefix))))
{
throw new InvalidCredentialException($"{OpenAIAuthentication.ApiKey} must start with '{AuthInfo.SecretKeyPrefix}'");
}

if (OpenAIClientSettings.UseOAuthAuthentication)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", OpenAIAuthentication.ApiKey);
}
else
{
client.DefaultRequestHeaders.Add("api-key", OpenAIAuthentication.ApiKey);
}

if (!string.IsNullOrWhiteSpace(OpenAIAuthentication.OrganizationId))
{
client.DefaultRequestHeaders.Add("OpenAI-Organization", OpenAIAuthentication.OrganizationId);
}

return client;
}
}
}
Loading

0 comments on commit 2365dfc

Please sign in to comment.