using AIStudio.Chat; using AIStudio.Provider; using AIStudio.Settings; namespace AIStudio.Assistants.BeyondFactsLab; public partial class BeyondFactsLabAssistant { /// /// The provider for the chats of the preparation shown, or none. /// private AIStudio.Settings.Provider providerSettings = AIStudio.Settings.Provider.NONE; /// /// Chooses the provider of a preparation as it opens: the one the person chose for it, as long as its confidence /// is still high enough, otherwise the preselected one. /// /// The preparation, or null when none is shown. private void ResolveProvider(BflProject? project) { this.providerSettings = project is null ? AIStudio.Settings.Provider.NONE : this.SettingsManager.GetPreselectedProvider(Tools.Components.BEYOND_FACTS_LAB_ASSISTANT, project.ProviderId); } /// /// Takes over the provider the person chose and remembers it for the preparation. /// /// The provider. private async Task SelectProviderAsync(AIStudio.Settings.Provider provider) { this.providerSettings = provider; if (provider == AIStudio.Settings.Provider.NONE || this.ValidateProvider(provider) is not null) return; if (this.selectedProject?.Project is not { } project || project.ProviderId == provider.Id) return; try { this.ReplaceProject(await this.Store.SetProviderAsync(project.ProjectId, provider.Id)); } catch (Exception exception) when (exception is IOException or UnauthorizedAccessException or InvalidDataException) { // The choice holds while the page is open; only the next opening falls back to the preselected provider: this.Logger.LogWarning(exception, "Could not remember the provider of a preparation in the BeyondFacts Lab."); } } /// /// Checks whether a provider can run the chats of the lab. /// /// /// The confidence is checked before: the selection offers only providers whose confidence is high enough. /// /// The provider. /// Why the provider cannot run the chats, or null when it can. private string? ValidateProvider(AIStudio.Settings.Provider provider) { if (provider.UsedLLMProvider is LLMProviders.NONE) return TA("Please select a provider."); var contextWindow = provider.GetModelProfile().Context; if (!BflModelRequirements.HasEnoughContext(contextWindow)) return string.Format(Culture, TA("The model of this provider reads at most {0} tokens at once. The lab needs at least {1}, because its guide alone takes about 20,000. Please select another provider."), TokenAmount.Format(contextWindow.DefaultTokens, Culture), TokenAmount.Format(BflModelRequirements.MINIMUM_CONTEXT_TOKENS, Culture)); return null; } }