using System.Text.Json.Serialization; using AIStudio.Provider; using AIStudio.Provider.HuggingFace; using AIStudio.Tools.PluginSystem; using Lua; using Host = AIStudio.Provider.SelfHosted.Host; namespace AIStudio.Settings; /// /// Data model for configured providers. /// /// The provider's number. /// The provider's ID. /// The provider's instance name. Useful for multiple instances of the same provider, e.g., to distinguish between different OpenAI API keys. /// The provider used. /// Whether the provider is self-hosted. /// The hostname of the provider. Useful for self-hosted providers. /// The LLM model to use for chat. public sealed record Provider( uint Num, string Id, string InstanceName, LLMProviders UsedLLMProvider, Model Model, bool IsSelfHosted = false, bool IsEnterpriseConfiguration = false, Guid EnterpriseConfigurationPluginId = default, string Hostname = "http://localhost:1234", Host Host = Host.NONE, HFInferenceProvider HFInferenceProvider = HFInferenceProvider.NONE) : ConfigurationBaseObject, ISecretId { private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(); public static readonly Provider NONE = new(); public Provider() : this( 0, Guid.Empty.ToString(), string.Empty, LLMProviders.NONE, default, false, false, Guid.Empty) { } #region Overrides of ValueType /// /// Returns a string that represents the current provider in a human-readable format. /// We use this to display the provider in the chat UI. /// /// A string that represents the current provider in a human-readable format. public override string ToString() { if(this.IsSelfHosted) return $"{this.InstanceName} ({this.UsedLLMProvider.ToName()}, {this.Host}, {this.Hostname}, {this.Model})"; return $"{this.InstanceName} ({this.UsedLLMProvider.ToName()}, {this.Model})"; } #endregion #region Implementation of ISecretId /// [JsonIgnore] public string SecretId => this.Id; /// [JsonIgnore] public string SecretName => this.InstanceName; #endregion #region Implementation of IConfigurationObject public override string Name { get => this.InstanceName; init => this.InstanceName = value; } #endregion public static bool TryParseProviderTable(int idx, LuaTable table, Guid configPluginId, out ConfigurationBaseObject provider) { provider = NONE; if (!table.TryGetValue("Id", out var idValue) || !idValue.TryRead(out var idText) || !Guid.TryParse(idText, out var id)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid ID. The ID must be a valid GUID."); return false; } if (!table.TryGetValue("InstanceName", out var instanceNameValue) || !instanceNameValue.TryRead(out var instanceName)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid instance name."); return false; } if (!table.TryGetValue("UsedLLMProvider", out var usedLLMProviderValue) || !usedLLMProviderValue.TryRead(out var usedLLMProviderText) || !Enum.TryParse(usedLLMProviderText, true, out var usedLLMProvider)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid LLM provider enum value."); return false; } if (!table.TryGetValue("Host", out var hostValue) || !hostValue.TryRead(out var hostText) || !Enum.TryParse(hostText, true, out var host)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid host enum value."); return false; } if (!table.TryGetValue("Hostname", out var hostnameValue) || !hostnameValue.TryRead(out var hostname)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid hostname."); return false; } if (!table.TryGetValue("Model", out var modelValue) || !modelValue.TryRead(out var modelTable)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid model table."); return false; } if (!TryReadModelTable(idx, modelTable, out var model)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid model configuration."); return false; } provider = new Provider { Num = 0, Id = id.ToString(), InstanceName = instanceName, UsedLLMProvider = usedLLMProvider, Model = model, IsSelfHosted = usedLLMProvider is LLMProviders.SELF_HOSTED, IsEnterpriseConfiguration = true, EnterpriseConfigurationPluginId = configPluginId, Hostname = hostname, Host = host }; return true; } private static bool TryReadModelTable(int idx, LuaTable table, out Model model) { model = default; if (!table.TryGetValue("Id", out var idValue) || !idValue.TryRead(out var id)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid model ID."); return false; } if (!table.TryGetValue("DisplayName", out var displayNameValue) || !displayNameValue.TryRead(out var displayName)) { LOGGER.LogWarning($"The configured provider {idx} does not contain a valid model display name."); return false; } model = new(id, displayName); return true; } }