mirror of
				https://github.com/MindWorkAI/AI-Studio.git
				synced 2025-11-04 07:20:20 +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