mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-04-28 15:59:48 +00:00
Implemented settings for setting up self-hosted or local provider
This commit is contained in:
parent
496ae94c2d
commit
88e3e46334
@ -101,7 +101,7 @@ public partial class Chat : ComponentBase
|
|||||||
// Use the selected provider to get the AI response.
|
// Use the selected provider to get the AI response.
|
||||||
// By awaiting this line, we wait for the entire
|
// By awaiting this line, we wait for the entire
|
||||||
// content to be streamed.
|
// content to be streamed.
|
||||||
await aiText.CreateFromProviderAsync(this.selectedProvider.UsedProvider.CreateProvider(this.selectedProvider.InstanceName), this.JsRuntime, this.SettingsManager, this.selectedProvider.Model, this.chatThread);
|
await aiText.CreateFromProviderAsync(this.selectedProvider.UsedProvider.CreateProvider(this.selectedProvider.InstanceName, this.selectedProvider.Hostname), this.JsRuntime, this.SettingsManager, this.selectedProvider.Model, this.chatThread);
|
||||||
|
|
||||||
// Disable the stream state:
|
// Disable the stream state:
|
||||||
this.isStreaming = false;
|
this.isStreaming = false;
|
||||||
|
@ -25,7 +25,12 @@
|
|||||||
<MudTd>@context.Num</MudTd>
|
<MudTd>@context.Num</MudTd>
|
||||||
<MudTd>@context.InstanceName</MudTd>
|
<MudTd>@context.InstanceName</MudTd>
|
||||||
<MudTd>@context.UsedProvider</MudTd>
|
<MudTd>@context.UsedProvider</MudTd>
|
||||||
<MudTd>@context.Model</MudTd>
|
<MudTd>
|
||||||
|
@if(context.UsedProvider is not Providers.SELF_HOSTED)
|
||||||
|
@context.Model
|
||||||
|
else
|
||||||
|
@("as selected by provider")
|
||||||
|
</MudTd>
|
||||||
<MudTd Style="text-align: left;">
|
<MudTd Style="text-align: left;">
|
||||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@this.GetProviderDashboardURL(context.UsedProvider)" Target="_blank" Disabled="@(context.UsedProvider is Providers.NONE or Providers.SELF_HOSTED)">
|
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@this.GetProviderDashboardURL(context.UsedProvider)" Target="_blank" Disabled="@(context.UsedProvider is Providers.NONE or Providers.SELF_HOSTED)">
|
||||||
Open Dashboard
|
Open Dashboard
|
||||||
|
@ -50,6 +50,8 @@ public partial class Settings : ComponentBase
|
|||||||
{ x => x.DataInstanceName, provider.InstanceName },
|
{ x => x.DataInstanceName, provider.InstanceName },
|
||||||
{ x => x.DataProvider, provider.UsedProvider },
|
{ x => x.DataProvider, provider.UsedProvider },
|
||||||
{ x => x.DataModel, provider.Model },
|
{ x => x.DataModel, provider.Model },
|
||||||
|
{ x => x.DataHostname, provider.Hostname },
|
||||||
|
{ x => x.IsSelfHosted, provider.IsSelfHosted },
|
||||||
{ x => x.IsEditing, true },
|
{ x => x.IsEditing, true },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using AIStudio.Provider.Anthropic;
|
using AIStudio.Provider.Anthropic;
|
||||||
using AIStudio.Provider.Mistral;
|
using AIStudio.Provider.Mistral;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
|
using AIStudio.Provider.SelfHosted;
|
||||||
|
|
||||||
namespace AIStudio.Provider;
|
namespace AIStudio.Provider;
|
||||||
|
|
||||||
@ -10,9 +11,12 @@ namespace AIStudio.Provider;
|
|||||||
public enum Providers
|
public enum Providers
|
||||||
{
|
{
|
||||||
NONE,
|
NONE,
|
||||||
|
|
||||||
OPEN_AI,
|
OPEN_AI,
|
||||||
ANTHROPIC,
|
ANTHROPIC,
|
||||||
MISTRAL,
|
MISTRAL,
|
||||||
|
|
||||||
|
SELF_HOSTED,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -27,11 +31,14 @@ public static class ExtensionsProvider
|
|||||||
/// <returns>The human-readable name of the provider.</returns>
|
/// <returns>The human-readable name of the provider.</returns>
|
||||||
public static string ToName(this Providers provider) => provider switch
|
public static string ToName(this Providers provider) => provider switch
|
||||||
{
|
{
|
||||||
|
Providers.NONE => "No provider selected",
|
||||||
|
|
||||||
Providers.OPEN_AI => "OpenAI",
|
Providers.OPEN_AI => "OpenAI",
|
||||||
Providers.ANTHROPIC => "Anthropic",
|
Providers.ANTHROPIC => "Anthropic",
|
||||||
Providers.MISTRAL => "Mistral",
|
Providers.MISTRAL => "Mistral",
|
||||||
|
|
||||||
Providers.NONE => "No provider selected",
|
Providers.SELF_HOSTED => "Self-hosted",
|
||||||
|
|
||||||
_ => "Unknown",
|
_ => "Unknown",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,13 +47,16 @@ public static class ExtensionsProvider
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="provider">The provider value.</param>
|
/// <param name="provider">The provider value.</param>
|
||||||
/// <param name="instanceName">The used instance name.</param>
|
/// <param name="instanceName">The used instance name.</param>
|
||||||
|
/// <param name="hostname">The hostname of the provider.</param>
|
||||||
/// <returns>The provider instance.</returns>
|
/// <returns>The provider instance.</returns>
|
||||||
public static IProvider CreateProvider(this Providers provider, string instanceName) => provider switch
|
public static IProvider CreateProvider(this Providers provider, string instanceName, string hostname = "http://localhost:1234") => provider switch
|
||||||
{
|
{
|
||||||
Providers.OPEN_AI => new ProviderOpenAI { InstanceName = instanceName },
|
Providers.OPEN_AI => new ProviderOpenAI { InstanceName = instanceName },
|
||||||
Providers.ANTHROPIC => new ProviderAnthropic { InstanceName = instanceName },
|
Providers.ANTHROPIC => new ProviderAnthropic { InstanceName = instanceName },
|
||||||
Providers.MISTRAL => new ProviderMistral { InstanceName = instanceName },
|
Providers.MISTRAL => new ProviderMistral { InstanceName = instanceName },
|
||||||
|
|
||||||
|
Providers.SELF_HOSTED => new ProviderSelfHosted(hostname) { InstanceName = instanceName },
|
||||||
|
|
||||||
_ => new NoProvider(),
|
_ => new NoProvider(),
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
<MudSelectItem Value="@provider">@provider</MudSelectItem>
|
<MudSelectItem Value="@provider">@provider</MudSelectItem>
|
||||||
}
|
}
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
<MudButton Disabled="@(this.DataProvider is Providers.NONE or Providers.SELF_HOSTED)" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.OpenInBrowser" Href="@this.GetProviderCreationURL()" Target="_blank">Create account</MudButton>
|
<MudButton Disabled="@this.IsSelfHostedOrNone" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.OpenInBrowser" Href="@this.GetProviderCreationURL()" Target="_blank">Create account</MudButton>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
@* ReSharper disable once CSharpWarnings::CS8974 *@
|
||||||
@ -20,6 +20,7 @@
|
|||||||
T="string"
|
T="string"
|
||||||
@bind-Text="@this.dataAPIKey"
|
@bind-Text="@this.dataAPIKey"
|
||||||
Label="API Key"
|
Label="API Key"
|
||||||
|
Disabled="@this.IsSelfHostedOrNone"
|
||||||
Class="mb-3"
|
Class="mb-3"
|
||||||
Adornment="Adornment.Start"
|
Adornment="Adornment.Start"
|
||||||
AdornmentIcon="@Icons.Material.Filled.VpnKey"
|
AdornmentIcon="@Icons.Material.Filled.VpnKey"
|
||||||
@ -28,9 +29,21 @@
|
|||||||
Validation="@this.ValidatingAPIKey"
|
Validation="@this.ValidatingAPIKey"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<MudTextField
|
||||||
|
T="string"
|
||||||
|
@bind-Text="@this.DataHostname"
|
||||||
|
Label="Hostname"
|
||||||
|
Disabled="@this.IsCloudProvider"
|
||||||
|
Class="mb-3"
|
||||||
|
Adornment="Adornment.Start"
|
||||||
|
AdornmentIcon="@Icons.Material.Filled.Dns"
|
||||||
|
AdornmentColor="Color.Info"
|
||||||
|
Validation="@this.ValidatingHostname"
|
||||||
|
/>
|
||||||
|
|
||||||
<MudStack Row="@true" AlignItems="AlignItems.Center">
|
<MudStack Row="@true" AlignItems="AlignItems.Center">
|
||||||
<MudButton Disabled="@(!this.CanLoadModels)" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Refresh" OnClick="this.ReloadModels">Load</MudButton>
|
<MudButton Disabled="@(!this.CanLoadModels)" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Refresh" OnClick="this.ReloadModels">Load</MudButton>
|
||||||
<MudSelect @bind-Value="@this.DataModel" Label="Model" Class="mb-3" OpenIcon="@Icons.Material.Filled.FaceRetouchingNatural" AdornmentColor="Color.Info" Adornment="Adornment.Start" Validation="@this.ValidatingModel">
|
<MudSelect Disabled="@this.IsSelfHostedOrNone" @bind-Value="@this.DataModel" Label="Model" Class="mb-3" OpenIcon="@Icons.Material.Filled.FaceRetouchingNatural" AdornmentColor="Color.Info" Adornment="Adornment.Start" Validation="@this.ValidatingModel">
|
||||||
@foreach (var model in this.availableModels)
|
@foreach (var model in this.availableModels)
|
||||||
{
|
{
|
||||||
<MudSelectItem Value="@model">@model</MudSelectItem>
|
<MudSelectItem Value="@model">@model</MudSelectItem>
|
||||||
|
@ -32,6 +32,18 @@ public partial class ProviderDialog : ComponentBase
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string DataInstanceName { get; set; } = string.Empty;
|
public string DataInstanceName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The chosen hostname for self-hosted providers.
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public string DataHostname { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is this provider self-hosted?
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public bool IsSelfHosted { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The provider to use.
|
/// The provider to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -99,6 +111,7 @@ public partial class ProviderDialog : ComponentBase
|
|||||||
this.dataAPIKey = requestedSecret.Secret;
|
this.dataAPIKey = requestedSecret.Secret;
|
||||||
|
|
||||||
// Now, we try to load the list of available models:
|
// Now, we try to load the list of available models:
|
||||||
|
if(this.DataProvider is not Providers.SELF_HOSTED)
|
||||||
await this.ReloadModels();
|
await this.ReloadModels();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -142,6 +155,8 @@ public partial class ProviderDialog : ComponentBase
|
|||||||
InstanceName = this.DataInstanceName,
|
InstanceName = this.DataInstanceName,
|
||||||
UsedProvider = this.DataProvider,
|
UsedProvider = this.DataProvider,
|
||||||
Model = this.DataModel,
|
Model = this.DataModel,
|
||||||
|
IsSelfHosted = this.DataProvider is Providers.SELF_HOSTED,
|
||||||
|
Hostname = this.DataHostname,
|
||||||
};
|
};
|
||||||
|
|
||||||
// We need to instantiate the provider to store the API key:
|
// We need to instantiate the provider to store the API key:
|
||||||
@ -169,6 +184,9 @@ public partial class ProviderDialog : ComponentBase
|
|||||||
|
|
||||||
private string? ValidatingModel(Model model)
|
private string? ValidatingModel(Model model)
|
||||||
{
|
{
|
||||||
|
if(this.DataProvider is Providers.SELF_HOSTED)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (model == default)
|
if (model == default)
|
||||||
return "Please select a model.";
|
return "Please select a model.";
|
||||||
|
|
||||||
@ -206,6 +224,9 @@ public partial class ProviderDialog : ComponentBase
|
|||||||
|
|
||||||
private string? ValidatingAPIKey(string apiKey)
|
private string? ValidatingAPIKey(string apiKey)
|
||||||
{
|
{
|
||||||
|
if(this.DataProvider is Providers.SELF_HOSTED)
|
||||||
|
return null;
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(this.dataAPIKeyStorageIssue))
|
if(!string.IsNullOrWhiteSpace(this.dataAPIKeyStorageIssue))
|
||||||
return this.dataAPIKeyStorageIssue;
|
return this.dataAPIKeyStorageIssue;
|
||||||
|
|
||||||
@ -215,9 +236,24 @@ public partial class ProviderDialog : ComponentBase
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Cancel() => this.MudDialog.Cancel();
|
private string? ValidatingHostname(string hostname)
|
||||||
|
{
|
||||||
|
if(this.DataProvider != Providers.SELF_HOSTED)
|
||||||
|
return null;
|
||||||
|
|
||||||
private bool CanLoadModels => !string.IsNullOrWhiteSpace(this.dataAPIKey) && this.DataProvider != Providers.NONE;
|
if(string.IsNullOrWhiteSpace(hostname))
|
||||||
|
return "Please enter a hostname, e.g., http://localhost:1234";
|
||||||
|
|
||||||
|
if(!hostname.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) && !hostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return "The hostname must start with either http:// or https://";
|
||||||
|
|
||||||
|
if(!Uri.TryCreate(hostname, UriKind.Absolute, out _))
|
||||||
|
return "The hostname is not a valid HTTP(S) URL.";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel() => this.MudDialog.Cancel();
|
||||||
|
|
||||||
private async Task ReloadModels()
|
private async Task ReloadModels()
|
||||||
{
|
{
|
||||||
@ -234,6 +270,12 @@ public partial class ProviderDialog : ComponentBase
|
|||||||
this.availableModels.AddRange(orderedModels);
|
this.availableModels.AddRange(orderedModels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CanLoadModels => !string.IsNullOrWhiteSpace(this.dataAPIKey) && this.DataProvider != Providers.NONE && this.DataProvider != Providers.SELF_HOSTED;
|
||||||
|
|
||||||
|
private bool IsCloudProvider => this.DataProvider is not Providers.SELF_HOSTED or Providers.NONE;
|
||||||
|
|
||||||
|
private bool IsSelfHostedOrNone => this.DataProvider is Providers.SELF_HOSTED or Providers.NONE;
|
||||||
|
|
||||||
private string GetProviderCreationURL() => this.DataProvider switch
|
private string GetProviderCreationURL() => this.DataProvider switch
|
||||||
{
|
{
|
||||||
Providers.OPEN_AI => "https://platform.openai.com/signup",
|
Providers.OPEN_AI => "https://platform.openai.com/signup",
|
||||||
|
Loading…
Reference in New Issue
Block a user