Skip to content

Commit

Permalink
Add HttpClient configuration support (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcominerva authored Jan 17, 2024
2 parents 97b3dba + f6462fc commit 7fbebca
Show file tree
Hide file tree
Showing 18 changed files with 295 additions and 111 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,29 @@ builder.Services.AddChatGpt((services, options) =>
});
```

### Configuring HTTP Client

**ChatGptNet** uses an [HttpClient](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient) to call the chat completion and embedding APIs. If you need to customize it, you can use the overload of the **AddChatGpt** method that accepts an [Action<IHttpClientBuiler>](https://learn.microsoft.com/dotnet/api/microsoft.extensions.dependencyinjection.ihttpclientbuilder) as argument. For example, if you want to add resiliency to the HTTP client (let's say a retry policy), you can use [Polly](https://github.com/App-vNext/Polly):

```csharp
// using Microsoft.Extensions.DependencyInjection;
// Requires: Microsoft.Extensions.Http.Resilience
builder.Services.AddChatGpt(context.Configuration,
httpClient =>
{
// Configures retry policy on the inner HttpClient using Polly.
httpClient.AddStandardResilienceHandler(options =>
{
options.AttemptTimeout.Timeout = TimeSpan.FromMinutes(1);
options.CircuitBreaker.SamplingDuration = TimeSpan.FromMinutes(3);
options.TotalRequestTimeout.Timeout = TimeSpan.FromMinutes(3);
});
})
```

More information about this topic is available on the [official documentation](https://learn.microsoft.com/dotnet/core/resilience/http-resilience).

## Usage

The library can be used in any .NET application built with .NET 6.0 or later. For example, we can create a Minimal API in this way:
Expand Down
2 changes: 1 addition & 1 deletion docs/ChatGptNet/ChatGptServiceCollectionExtensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static class ChatGptServiceCollectionExtensions

| name | description |
| --- | --- |
| static [AddChatGpt](ChatGptServiceCollectionExtensions/AddChatGpt.md)(…) | Registers a ChatGptClient instance with the specified options. (3 methods) |
| static [AddChatGpt](ChatGptServiceCollectionExtensions/AddChatGpt.md)(…) | Registers a ChatGptClient instance with the specified options. (5 methods) |

## See Also

Expand Down
75 changes: 68 additions & 7 deletions docs/ChatGptNet/ChatGptServiceCollectionExtensions/AddChatGpt.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# ChatGptServiceCollectionExtensions.AddChatGpt method (1 of 3)
# ChatGptServiceCollectionExtensions.AddChatGpt method (1 of 5)

Registers a ChatGptClient instance with the specified options.

```csharp
public static IChatGptBuilder AddChatGpt(this IServiceCollection services,
Action<ChatGptOptionsBuilder> builder)
Action<ChatGptOptionsBuilder> builder, Action<IHttpClientBuilder>? httpClientBuilder = null)
```

| parameter | description |
| --- | --- |
| services | The IServiceCollection to add services to. |
| builder | The [`ChatGptOptionsBuilder`](../ChatGptOptionsBuilder.md) to configure options. |
| httpClientBuilder | The IHttpClientBuilder to configure the HTTP client used to make HTTP requests. |

## Return Value

Expand All @@ -29,19 +30,21 @@ This method automatically adds a MemoryCache that is used to save conversation h

---

# ChatGptServiceCollectionExtensions.AddChatGpt method (2 of 3)
# ChatGptServiceCollectionExtensions.AddChatGpt method (2 of 5)

Registers a ChatGptClient instance using dynamic options.

```csharp
public static IChatGptBuilder AddChatGpt(this IServiceCollection services,
Action<IServiceProvider, ChatGptOptionsBuilder> builder)
Action<IServiceProvider, ChatGptOptionsBuilder> builder,
Action<IHttpClientBuilder>? httpClientBuilder = null)
```

| parameter | description |
| --- | --- |
| services | The IServiceCollection to add services to. |
| builder | The [`ChatGptOptionsBuilder`](../ChatGptOptionsBuilder.md) to configure options. |
| httpClientBuilder | The IHttpClientBuilder to configure the HTTP client used to make HTTP requests. |

## Return Value

Expand All @@ -61,20 +64,78 @@ Use this this method if it is necessary to dynamically set options (for example,

---

# ChatGptServiceCollectionExtensions.AddChatGpt method (3 of 3)
# ChatGptServiceCollectionExtensions.AddChatGpt method (3 of 5)

Registers a ChatGptClient instance reading configuration from the specified IConfiguration source, searching for the ChatGPT section.

```csharp
public static IChatGptBuilder AddChatGpt(this IServiceCollection services,
IConfiguration configuration, Action<IHttpClientBuilder>? httpClientBuilder = null)
```

| parameter | description |
| --- | --- |
| services | The IServiceCollection to add services to. |
| configuration | The IConfiguration being bound. |
| httpClientBuilder | The IHttpClientBuilder to configure the HTTP client used to make HTTP requests. |

## Remarks

This method automatically adds a MemoryCache that is used to save conversation history for chat completion. It is possibile to use [`WithCache`](../IChatGptBuilderExtensions/WithCache.md) to specify another cache implementation.

## See Also

* class [ChatGptOptions](../ChatGptOptions.md)
* interface [IChatGptBuilder](../IChatGptBuilder.md)
* class [ChatGptServiceCollectionExtensions](../ChatGptServiceCollectionExtensions.md)
* namespace [ChatGptNet](../../ChatGptNet.md)

---

# ChatGptServiceCollectionExtensions.AddChatGpt method (4 of 5)

Registers a ChatGptClient instance reading configuration from the specified IConfiguration source.

```csharp
public static IChatGptBuilder AddChatGpt(this IServiceCollection services,
IConfiguration configuration, string sectionName)
```

| parameter | description |
| --- | --- |
| services | The IServiceCollection to add services to. |
| configuration | The IConfiguration being bound. |
| sectionName | The name of the configuration section that holds ChatGPT settings. |

## Remarks

This method automatically adds a MemoryCache that is used to save conversation history for chat completion. It is possibile to use [`WithCache`](../IChatGptBuilderExtensions/WithCache.md) to specify another cache implementation.

## See Also

* class [ChatGptOptions](../ChatGptOptions.md)
* interface [IChatGptBuilder](../IChatGptBuilder.md)
* class [ChatGptServiceCollectionExtensions](../ChatGptServiceCollectionExtensions.md)
* namespace [ChatGptNet](../../ChatGptNet.md)

---

# ChatGptServiceCollectionExtensions.AddChatGpt method (5 of 5)

Registers a ChatGptClient instance reading configuration from the specified IConfiguration source.

```csharp
public static IChatGptBuilder AddChatGpt(this IServiceCollection services,
IConfiguration configuration, string sectionName = "ChatGPT")
IConfiguration configuration, string sectionName,
Action<IHttpClientBuilder>? httpClientBuilder = null)
```

| parameter | description |
| --- | --- |
| services | The IServiceCollection to add services to. |
| configuration | The IConfiguration being bound. |
| sectionName | The name of the configuration section that holds ChatGPT settings (default: ChatGPT). |
| sectionName | The name of the configuration section that holds ChatGPT settings. |
| httpClientBuilder | The IHttpClientBuilder to configure the HTTP client used to make HTTP requests. |

## Return Value

Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
| class [ChatGptTool](./ChatGptNet.Models/ChatGptTool.md) | Represents a tool that the model may call. |
| class [ChatGptToolCall](./ChatGptNet.Models/ChatGptToolCall.md) | A tool call generated by the model, such as a function call. |
| static class [ChatGptToolChoices](./ChatGptNet.Models/ChatGptToolChoices.md) | Contains constants for ChatGPT function call types. |
| class [ChatGptToolParameters](./ChatGptNet.Models/ChatGptToolParameters.md) | Contains parameters about the tools calls that are available for ChatGPT. |
| class [ChatGptToolParameters](./ChatGptNet.Models/ChatGptToolParameters.md) | Contains parameters about the tool calls that are available for ChatGPT. |
| static class [ChatGptToolTypes](./ChatGptNet.Models/ChatGptToolTypes.md) | Contains constants for ChatGPT tool types. |
| class [ChatGptUsage](./ChatGptNet.Models/ChatGptUsage.md) | Contains information about the API usage. |
| static class [OpenAIChatGptModels](./ChatGptNet.Models/OpenAIChatGptModels.md) | Contains all the chat completion models that are currently supported by OpenAI. |
Expand Down
26 changes: 14 additions & 12 deletions samples/ChatGptApi/ChatGptApi.csproj
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.1.0" />
<PackageReference Include="Polly.Extensions" Version="8.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ChatGptNet\ChatGptNet.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ChatGptNet\ChatGptNet.csproj" />
</ItemGroup>

</Project>
12 changes: 11 additions & 1 deletion samples/ChatGptApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,17 @@
//});

// Adds ChatGPT service using settings from IConfiguration.
builder.Services.AddChatGpt(builder.Configuration);
builder.Services.AddChatGpt(builder.Configuration,
httpClient =>
{
// Configures retry policy on the inner HttpClient using Polly.
httpClient.AddStandardResilienceHandler(options =>
{
options.AttemptTimeout.Timeout = TimeSpan.FromMinutes(1);
options.CircuitBreaker.SamplingDuration = TimeSpan.FromMinutes(3);
options.TotalRequestTimeout.Timeout = TimeSpan.FromMinutes(3);
});
});

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
Expand Down
36 changes: 19 additions & 17 deletions samples/ChatGptBlazor.Wasm/ChatGptBlazor.Wasm.csproj
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Markdig" Version="0.34.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Markdig" Version="0.34.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.1.0" />
<PackageReference Include="Polly.Extensions" Version="8.2.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ChatGptNet\ChatGptNet.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ChatGptNet\ChatGptNet.csproj" />
</ItemGroup>

<ItemGroup>
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
</ItemGroup>
<ItemGroup>
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
</ItemGroup>

</Project>
10 changes: 10 additions & 0 deletions samples/ChatGptBlazor.Wasm/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@
options.DefaultModel = "my-model";
options.MessageLimit = 16; // Default: 10
options.MessageExpiration = TimeSpan.FromMinutes(5); // Default: 1 hour
},
httpClient =>
{
// Configures retry policy on the inner HttpClient using Polly.
httpClient.AddStandardResilienceHandler(options =>
{
options.AttemptTimeout.Timeout = TimeSpan.FromMinutes(1);
options.CircuitBreaker.SamplingDuration = TimeSpan.FromMinutes(3);
options.TotalRequestTimeout.Timeout = TimeSpan.FromMinutes(3);
});
});

await builder.Build().RunAsync();
9 changes: 1 addition & 8 deletions samples/ChatGptConsole/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,8 @@

namespace ChatGptConsole;

internal class Application
internal class Application(IChatGptClient chatGptClient)
{
private readonly IChatGptClient chatGptClient;

public Application(IChatGptClient chatGptClient)
{
this.chatGptClient = chatGptClient;
}

public async Task ExecuteAsync()
{
string? message = null;
Expand Down
38 changes: 20 additions & 18 deletions samples/ChatGptConsole/ChatGptConsole.csproj
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.1.0" />
<PackageReference Include="Polly.Extensions" Version="8.2.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ChatGptNet\ChatGptNet.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ChatGptNet\ChatGptNet.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
12 changes: 11 additions & 1 deletion samples/ChatGptConsole/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@ static void ConfigureServices(HostBuilderContext context, IServiceCollection ser
services.AddSingleton<Application>();

// Adds ChatGPT service using settings from IConfiguration.
services.AddChatGpt(context.Configuration)
services.AddChatGpt(context.Configuration,
httpClient =>
{
// Configures retry policy on the inner HttpClient using Polly.
httpClient.AddStandardResilienceHandler(options =>
{
options.AttemptTimeout.Timeout = TimeSpan.FromMinutes(1);
options.CircuitBreaker.SamplingDuration = TimeSpan.FromMinutes(3);
options.TotalRequestTimeout.Timeout = TimeSpan.FromMinutes(3);
});
})
//.WithCache<LocalMessageCache>() // Uncomment this line to use a custom cache implementation instead of the default MemoryCache.
;

Expand Down
Loading

0 comments on commit 7fbebca

Please sign in to comment.