mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-04-28 11:59:48 +00:00
Allow selection of self-hosted models
This commit is contained in:
parent
8af8426f5d
commit
52caf96cf4
@ -1,5 +1,6 @@
|
||||
@page "/settings"
|
||||
@using AIStudio.Provider
|
||||
@using Host = AIStudio.Provider.SelfHosted.Host
|
||||
|
||||
<MudText Typo="Typo.h3" Class="mb-12">Settings</MudText>
|
||||
|
||||
@ -26,10 +27,18 @@
|
||||
<MudTd>@context.InstanceName</MudTd>
|
||||
<MudTd>@context.UsedProvider</MudTd>
|
||||
<MudTd>
|
||||
@if(context.UsedProvider is not Providers.SELF_HOSTED)
|
||||
@if (context.UsedProvider is not Providers.SELF_HOSTED)
|
||||
{
|
||||
@context.Model
|
||||
}
|
||||
else if (context.UsedProvider is Providers.SELF_HOSTED && context.Host is not Host.LLAMACPP)
|
||||
{
|
||||
@context.Model
|
||||
}
|
||||
else
|
||||
{
|
||||
@("as selected by provider")
|
||||
}
|
||||
</MudTd>
|
||||
<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)">
|
||||
|
@ -33,7 +33,7 @@ public sealed class ProviderSelfHosted(Settings.Provider provider) : BaseProvide
|
||||
// Prepare the OpenAI HTTP chat request:
|
||||
var providerChatRequest = JsonSerializer.Serialize(new ChatRequest
|
||||
{
|
||||
Model = (await this.GetTextModels(jsRuntime, settings, token: token)).First().Id,
|
||||
Model = chatModel.Id,
|
||||
|
||||
// Build the messages:
|
||||
// - First of all the system prompt
|
||||
@ -137,17 +137,33 @@ public sealed class ProviderSelfHosted(Settings.Provider provider) : BaseProvide
|
||||
|
||||
public async Task<IEnumerable<Provider.Model>> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "models");
|
||||
var response = await this.httpClient.SendAsync(request, token);
|
||||
if(!response.IsSuccessStatusCode)
|
||||
try
|
||||
{
|
||||
switch (provider.Host)
|
||||
{
|
||||
case Host.LLAMACPP:
|
||||
// Right now, llama.cpp only supports one model.
|
||||
// There is no API to list the model(s).
|
||||
return [ new Provider.Model("as configured by llama.cpp") ];
|
||||
|
||||
case Host.LM_STUDIO:
|
||||
case Host.OLLAMA:
|
||||
var lmStudioRequest = new HttpRequestMessage(HttpMethod.Get, "models");
|
||||
var lmStudioResponse = await this.httpClient.SendAsync(lmStudioRequest, token);
|
||||
if(!lmStudioResponse.IsSuccessStatusCode)
|
||||
return [];
|
||||
|
||||
var lmStudioModelResponse = await lmStudioResponse.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
||||
return lmStudioModelResponse.Data.Select(n => new Provider.Model(n.Id));
|
||||
}
|
||||
|
||||
return [];
|
||||
|
||||
var modelResponse = await response.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
||||
if (modelResponse.Data.Length > 1)
|
||||
Console.WriteLine("Warning: multiple models found; using the first one.");
|
||||
|
||||
var firstModel = modelResponse.Data.First();
|
||||
return [ new Provider.Model(firstModel.Id) ];
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine($"Failed to load text models from self-hosted provider: {e.Message}");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
|
@ -51,8 +51,8 @@
|
||||
</MudSelect>
|
||||
|
||||
<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>
|
||||
<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">
|
||||
<MudButton Disabled="@(!this.CanLoadModels())" Variant="Variant.Filled" Size="Size.Small" StartIcon="@Icons.Material.Filled.Refresh" OnClick="this.ReloadModels">Load</MudButton>
|
||||
<MudSelect Disabled="@this.IsNoneProvider" @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)
|
||||
{
|
||||
<MudSelectItem Value="@model">@model</MudSelectItem>
|
||||
|
@ -122,10 +122,11 @@ public partial class ProviderDialog : ComponentBase
|
||||
this.dataEditingPreviousInstanceName = this.DataInstanceName.ToLowerInvariant();
|
||||
|
||||
//
|
||||
// We cannot load the API key nor models for self-hosted providers:
|
||||
// We cannot load the API key for self-hosted providers:
|
||||
//
|
||||
if (this.DataProvider is Providers.SELF_HOSTED)
|
||||
{
|
||||
await this.ReloadModels();
|
||||
await base.OnInitializedAsync();
|
||||
return;
|
||||
}
|
||||
@ -182,17 +183,19 @@ public partial class ProviderDialog : ComponentBase
|
||||
// Use the data model to store the provider.
|
||||
// We just return this data to the parent component:
|
||||
var addedProviderSettings = this.CreateProviderSettings();
|
||||
|
||||
// We need to instantiate the provider to store the API key:
|
||||
var provider = addedProviderSettings.CreateProvider();
|
||||
|
||||
// Store the API key in the OS secure storage:
|
||||
var storeResponse = await this.SettingsManager.SetAPIKey(this.JsRuntime, provider, this.dataAPIKey);
|
||||
if (!storeResponse.Success)
|
||||
if (addedProviderSettings.UsedProvider != Providers.SELF_HOSTED)
|
||||
{
|
||||
this.dataAPIKeyStorageIssue = $"Failed to store the API key in the operating system. The message was: {storeResponse.Issue}. Please try again.";
|
||||
await this.form.Validate();
|
||||
return;
|
||||
// We need to instantiate the provider to store the API key:
|
||||
var provider = addedProviderSettings.CreateProvider();
|
||||
|
||||
// Store the API key in the OS secure storage:
|
||||
var storeResponse = await this.SettingsManager.SetAPIKey(this.JsRuntime, provider, this.dataAPIKey);
|
||||
if (!storeResponse.Success)
|
||||
{
|
||||
this.dataAPIKeyStorageIssue = $"Failed to store the API key in the operating system. The message was: {storeResponse.Issue}. Please try again.";
|
||||
await this.form.Validate();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.MudDialog.Close(DialogResult.Ok(addedProviderSettings));
|
||||
@ -219,7 +222,7 @@ public partial class ProviderDialog : ComponentBase
|
||||
|
||||
private string? ValidatingModel(Model model)
|
||||
{
|
||||
if(this.DataProvider is Providers.SELF_HOSTED)
|
||||
if(this.DataProvider is Providers.SELF_HOSTED && this.DataHost == Host.LLAMACPP)
|
||||
return null;
|
||||
|
||||
if (model == default)
|
||||
@ -319,12 +322,44 @@ public partial class ProviderDialog : ComponentBase
|
||||
this.availableModels.AddRange(orderedModels);
|
||||
}
|
||||
|
||||
private bool CanLoadModels => !string.IsNullOrWhiteSpace(this.dataAPIKey) && this.DataProvider != Providers.NONE && this.DataProvider != Providers.SELF_HOSTED;
|
||||
private bool CanLoadModels()
|
||||
{
|
||||
if (this.DataProvider is Providers.SELF_HOSTED)
|
||||
{
|
||||
switch (this.DataHost)
|
||||
{
|
||||
case Host.NONE:
|
||||
return false;
|
||||
|
||||
case Host.LLAMACPP:
|
||||
return false;
|
||||
|
||||
case Host.LM_STUDIO:
|
||||
return true;
|
||||
|
||||
case Host.OLLAMA:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.DataProvider is Providers.NONE)
|
||||
return false;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(this.dataAPIKey))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsCloudProvider => this.DataProvider is not Providers.SELF_HOSTED;
|
||||
|
||||
private bool IsSelfHostedOrNone => this.DataProvider is Providers.SELF_HOSTED or Providers.NONE;
|
||||
|
||||
private bool IsNoneProvider => this.DataProvider is Providers.NONE;
|
||||
|
||||
private string GetProviderCreationURL() => this.DataProvider switch
|
||||
{
|
||||
Providers.OPEN_AI => "https://platform.openai.com/signup",
|
||||
|
Loading…
Reference in New Issue
Block a user