Skip to content

Commit

Permalink
Add option to override the OpenAI api url
Browse files Browse the repository at this point in the history
  • Loading branch information
wieslawsoltes committed Apr 28, 2023
1 parent 153a760 commit b6ecccc
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<VersionPrefix>1.0.0</VersionPrefix>
<VersionSuffix>preview.17</VersionSuffix>
<VersionSuffix>preview.18</VersionSuffix>
<Authors>Wiesław Šoltés</Authors>
<Company>Wiesław Šoltés</Company>
<Copyright>Copyright © Wiesław Šoltés 2023</Copyright>
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ You can try client using browser version [here](https://wieslawsoltes.github.io/

# Overriding OpenAI api url

```C#
var chat = Defaults.Locator.GetService<IChatService>();
chat.SetApiUrl("you api url");
```bash
To override the OpenAI api url set `OPENAI_API_URL_CHAT_COMPLETIONS` environment variable or set API url directly in app settings.
```

# OpenAI ChatGPT web version import
Expand Down Expand Up @@ -95,6 +94,7 @@ Options:
--frequencyPenalty <frequencypenalty> Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.
--maxTokens <maxtokens> The maximum number of tokens to generate in the chat completion.
--apiKey <apikey> Override OpenAI api key. By default OPENAI_API_KEY environment variable is used.
--apiUrl <apiUrl> Override OpenAI api url. By default OPENAI_API_URL_CHAT_COMPLETIONS environment variable is used.
--model <model> ID of the model to use. See the model endpoint compatibility table for details on which models work with the Chat API.
--directions <directions> The system message (directions) helps set the behavior of the assistant. Typically, a conversation is formatted with a system message first, followed by alternating user and assistant messages.
-t, --threads <threads> The number of parallel job threads
Expand Down Expand Up @@ -155,7 +155,8 @@ dotnet run -- -d ./ -e md -p *.cs --directions "You are a technical documentatio
"maxTokens": 2000,
"apiKey": "",
"model": "gpt-3.5-turbo",
"directions": "You are a helpful assistant."
"directions": "You are a helpful assistant.",
"apiUrl": ""
}
```

Expand Down
1 change: 1 addition & 0 deletions src/ChatGPT.CLI/Chat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ private static List<ChatJob> GetJobs(CliSettings cliSettings, List<FileInfo> pat
ApiKey = cliSettings.ApiKey,
Model = cliSettings.Model,
Directions = cliSettings.Directions,
ApiUrl = cliSettings.ApiUrl,
};

for (var i = 0; i < paths.Count; i++)
Expand Down
1 change: 1 addition & 0 deletions src/ChatGPT.CLI/CliSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class CliSettings
public string? ApiKey { get; set; } = null;
public string? Model { get; set; } = "gpt-3.5-turbo";
public string? Directions { get; set; } = "You are a helpful assistant.";
public string? ApiUrl { get; set; } = null;
// Job settings
public int Threads { get; set; } = 1;
public bool Quiet { get; set; } = false;
Expand Down
10 changes: 9 additions & 1 deletion src/ChatGPT.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,14 @@ RootCommand CreateRootCommand()
{
Argument = new Argument<string?>(getDefaultValue: () => null)
};


var optionApiUrl = new Option(
new[] { "--apiUrl" },
"Override OpenAI api url. By default OPENAI_API_URL_CHAT_COMPLETIONS environment variable is used.")
{
Argument = new Argument<string?>(getDefaultValue: () => null)
};

var optionModel = new Option(
new[] { "--model" },
"ID of the model to use. See the model endpoint compatibility table for details on which models work with the Chat API.")
Expand Down Expand Up @@ -150,6 +157,7 @@ RootCommand CreateRootCommand()
rootCommand.AddOption(optionFrequencyPenalty);
rootCommand.AddOption(optionMaxTokens);
rootCommand.AddOption(optionApiKey);
rootCommand.AddOption(optionApiUrl);
rootCommand.AddOption(optionModel);
rootCommand.AddOption(optionDirections);

Expand Down
10 changes: 10 additions & 0 deletions src/ChatGPT.Core/ViewModels/Chat/ChatSettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public partial class ChatSettingsViewModel : ObservableObject
private string? _model;
private string? _directions;
private string? _format;
private string? _apiUrl;

[JsonConstructor]
public ChatSettingsViewModel()
Expand All @@ -26,6 +27,7 @@ public ChatSettingsViewModel()
_apiKey = null;
_model = "gpt-3.5-turbo";
_directions = "You are a helpful assistant.";
_apiUrl = null;
}

[JsonPropertyName("temperature")]
Expand Down Expand Up @@ -91,6 +93,13 @@ public string? Format
set => SetProperty(ref _format, value);
}

[JsonPropertyName("apiUrl")]
public string? ApiUrl
{
get => _apiUrl;
set => SetProperty(ref _apiUrl, value);
}

public ChatSettingsViewModel Copy()
{
return new ChatSettingsViewModel
Expand All @@ -104,6 +113,7 @@ public ChatSettingsViewModel Copy()
Model = _model,
Directions = _directions,
Format = _format,
ApiUrl = _apiUrl,
};
}
}
1 change: 1 addition & 0 deletions src/ChatGPT.Core/ViewModels/Chat/ChatViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ public ChatMessage[] CreateChatMessages()
MaxTokens = Settings.MaxTokens,
TopP = 1.0m,
Stop = null,
ApiUrl = Settings.ApiUrl,
};

var result = new ChatResultViewModel
Expand Down
21 changes: 21 additions & 0 deletions src/ChatGPT.UI/Views/Chat/ChatSettingsView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,27 @@
ToolTip.Tip="Override OpenAI api key. By default OPENAI_API_KEY environment variable is used." />
</StackPanel>

<!-- Url -->
<StackPanel Name="UrlStackPanel"
Orientation="Vertical">
<TextBlock Text="Api url:"
Margin="8,2,8,2"
Padding="0,4,0,4"
FontSize="{DynamicResource SettingHeaderFontSize}" />
<AutoCompleteBox Text="{Binding ApiUrl}"
Watermark="Override OpenAI api url"
Margin="8,4,8,4"
Padding="8"
FontSize="{DynamicResource SettingContentFontSize}"
ToolTip.Tip="Override OpenAI api url to use. By default OPENAI_API_URL_CHAT_COMPLETIONS environment variable is used if not set default api url is used.">
<AutoCompleteBox.Items>
<generic:List x:TypeArguments="system:String">
<x:String>https://api.openai.com/v1/chat/completions</x:String>
</generic:List>
</AutoCompleteBox.Items>
</AutoCompleteBox>
</StackPanel>

<!-- Format -->
<StackPanel Name="FormatStackPanel"
Orientation="Vertical">
Expand Down
4 changes: 4 additions & 0 deletions src/ChatGPT/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ public static class Constants
public const string EnvironmentVariableApiKey = "OPENAI_API_KEY";

public const string EnvironmentVariableApiModel = "OPENAI_API_MODEL";

public const string EnvironmentVariableApiUrlCompletions = "OPENAI_API_URL_COMPLETIONS";

public const string EnvironmentVariableApiUrlChatCompletions = "OPENAI_API_URL_CHAT_COMPLETIONS";
}
1 change: 1 addition & 0 deletions src/ChatGPT/Model/Services/ChatServiceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace AI.Model.Services;

public class ChatServiceSettings
{
public string? ApiUrl { get; set; }
public string? Model { get; set; }
public ChatMessage[]? Messages { get; set; }
public string? Suffix { get; set; }
Expand Down
1 change: 1 addition & 0 deletions src/ChatGPT/Model/Services/CompletionsServiceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace AI.Model.Services;

public class CompletionsServiceSettings
{
public string? Url { get; set; }
public string? Model { get; set; }
public string? Prompt { get; set; }
public string? Suffix { get; set; }
Expand Down
1 change: 0 additions & 1 deletion src/ChatGPT/Model/Services/IChatService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ namespace AI.Model.Services;

public interface IChatService
{
void SetApiUrl(string apiUrl);
Task<ChatResponse?> GetResponseDataAsync(ChatServiceSettings settings, CancellationToken token);
}
1 change: 0 additions & 1 deletion src/ChatGPT/Model/Services/ICompletionsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ namespace AI.Model.Services;

public interface ICompletionsService
{
void SetApiUrl(string apiUrl);
Task<CompletionsResponse?> GetResponseDataAsync(CompletionsServiceSettings settings, CancellationToken token);
}
26 changes: 19 additions & 7 deletions src/ChatGPT/Services/ChatService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace AI.Services;
public class ChatService : IChatService
{
private static readonly HttpClient s_client;
private string _apiUrl = "https://api.openai.com/v1/chat/completions";
private static readonly string s_apiUrl = "https://api.openai.com/v1/chat/completions";
private readonly IChatSerializer _serializer;

static ChatService()
Expand Down Expand Up @@ -101,11 +101,6 @@ private string GetRequestBodyJson(ChatServiceSettings settings)
return _serializer.Deserialize<ChatResponseSuccess>(responseBody);
}

public void SetApiUrl(string apiUrl)
{
_apiUrl = apiUrl;
}

public async Task<ChatResponse?> GetResponseDataAsync(ChatServiceSettings settings, CancellationToken token)
{
// Set up the API URL and API key
Expand All @@ -117,8 +112,25 @@ public void SetApiUrl(string apiUrl)

// Get the request body JSON
var requestBodyJson = GetRequestBodyJson(settings);

var apiUrl = s_apiUrl;
var envApiUrl = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableApiUrlChatCompletions);
if (!string.IsNullOrWhiteSpace(envApiUrl))
{
apiUrl = envApiUrl;
}

if (!string.IsNullOrWhiteSpace(settings.ApiUrl))
{
apiUrl = settings.ApiUrl;
}

if (apiUrl is null)
{
return null;
}

// Send the API request and get the response data
return await SendApiRequestAsync(_apiUrl, apiKey, requestBodyJson, token);
return await SendApiRequestAsync(apiUrl, apiKey, requestBodyJson, token);
}
}
26 changes: 19 additions & 7 deletions src/ChatGPT/Services/CompletionsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace AI.Services;
public class CompletionsService : ICompletionsService
{
private static readonly HttpClient s_client;
private string _apiUrl = "https://api.openai.com/v1/completions";
private static readonly string s_apiUrl = "https://api.openai.com/v1/completions";
private readonly IChatSerializer _serializer;

static CompletionsService()
Expand Down Expand Up @@ -102,11 +102,6 @@ private string GetRequestBodyJson(CompletionsServiceSettings settings)
return _serializer.Deserialize<CompletionsResponseSuccess>(responseBody);
}

public void SetApiUrl(string apiUrl)
{
_apiUrl = apiUrl;
}

public async Task<CompletionsResponse?> GetResponseDataAsync(CompletionsServiceSettings settings, CancellationToken token)
{
// Set up the API URL and API key
Expand All @@ -118,8 +113,25 @@ public void SetApiUrl(string apiUrl)

// Get the request body JSON
var requestBodyJson = GetRequestBodyJson(settings);

var apiUrl = s_apiUrl;
var envApiUrl = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableApiUrlCompletions);
if (!string.IsNullOrWhiteSpace(envApiUrl))
{
apiUrl = envApiUrl;
}

if (!string.IsNullOrWhiteSpace(settings.Url))
{
apiUrl = settings.Url;
}

if (apiUrl is null)
{
return null;
}

// Send the API request and get the response data
return await SendApiRequestAsync(_apiUrl, apiKey, requestBodyJson, token);
return await SendApiRequestAsync(apiUrl, apiKey, requestBodyJson, token);
}
}

0 comments on commit b6ecccc

Please sign in to comment.