InvalidOperationException, The given header was not found - on Azure
With the following config, I am able to do a request and get a proper response from the OpenAI served by Azure:
_api = new OpenAIAPI("..snipped" /*apiKey*/);
_api.ApiUrlFormat = "https://my-resource.openai.azure.com/openai/deployments/my-deployment/{1}?api-version={0}";
_api.ApiVersion = "2022-12-01";
However, processing the response fails with an InvalidOperationException thrown in EndpointBase.cs as the Openai-Organization header is not found.
I am getting the exact same problem with:
_api = OpenAIAPI.ForAzure("my-resource", "my-deployment", ".. snipped..");
_api.ApiVersion = "2023-03-15-preview";
The faulty line seems to be https://github.com/OkGoDoIt/OpenAI-API-dotnet/blob/8bc534bc0163e4ca0ddad21a6d58a57910dc6189/OpenAI_API/EndpointBase.cs#L195
How can I get the package to work for the Azure endpoint?
Update:
I have been able to make package parse the Azure API response with the ugly hack below:
if (!response.Headers.Contains("Openai-Organization"))
{
response.Headers.Add("Openai-Organization", "dummy");
response.Headers.Add("Openai-Version", "dummy");
var ms = float.Parse(response.Headers.GetValues("Openai-Processing-Ms").First());
response.Headers.Remove("Openai-Processing-Ms");
response.Headers.Add("Openai-Processing-Ms", ((int)ms).ToString());
}
Tweaking my existing IHttpClientFactory:
namespace Lokad.Prompting;
public class OpenAIClientFactory : IHttpClientFactory
{
public HttpClient CreateClient(string name)
{
return new HttpClient(new RetryHandler(new HttpClientHandler()))
{
// The OpenAI API does usually answers albeit with considerable delay.
Timeout = TimeSpan.FromMinutes(5)
};
}
public class RetryHandler : DelegatingHandler
{
private const int maxRetries = 5;
public RetryHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var delay = TimeSpan.FromSeconds(1); // Initial delay
for (int i = 0; i < maxRetries; i++)
{
var response = await base.SendAsync(request, cancellationToken);
if (response.StatusCode == (System.Net.HttpStatusCode)200 &&
!response.Headers.Contains("Openai-Organization"))
{
response.Headers.Add("Openai-Organization", "dummy");
response.Headers.Add("Openai-Version", "dummy");
var ms = float.Parse(response.Headers.GetValues("Openai-Processing-Ms").First());
response.Headers.Remove("Openai-Processing-Ms");
response.Headers.Add("Openai-Processing-Ms", ((int)ms).ToString());
}
// 429 Too Many Requests
if (response.StatusCode == (System.Net.HttpStatusCode)429 && i < maxRetries)
{
await Task.Delay(delay, cancellationToken);
delay *= 2; // Exponential backoff
continue;
}
// 500 Internal Server Error
if (response.StatusCode == (System.Net.HttpStatusCode)500 && i < maxRetries)
{
await Task.Delay(delay, cancellationToken);
delay *= 2; // Exponential backoff
continue;
}
// 502 Bad Gateway
if (response.StatusCode == (System.Net.HttpStatusCode)502 && i < maxRetries)
{
await Task.Delay(delay, cancellationToken);
delay *= 2; // Exponential backoff
continue;
}
// 503 Service Unavailable
if (response.StatusCode == (System.Net.HttpStatusCode)503 && i < maxRetries)
{
await Task.Delay(delay, cancellationToken);
delay *= 2; // Exponential backoff
continue;
}
return response;
}
throw new HttpRequestException($"Retry attempts failed after {maxRetries} retries.");
}
}
}
This works although it would be nicer to update the response parsing accordingly.