Added model availability check and error handling for unavailable models (#717)
Some checks are pending
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,deb,updater, appimage,deb) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,deb,updater, appimage,deb) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Peer Schütt 2026-04-09 08:57:06 +02:00 committed by GitHub
parent 6155442039
commit a573409a24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 85 additions and 1 deletions

View File

@ -1732,6 +1732,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "No, kee
-- Export Chat to Microsoft Word -- Export Chat to Microsoft Word
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Export Chat to Microsoft Word" UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Export Chat to Microsoft Word"
-- The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings.
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T3267850764"] = "The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings."
-- The local image file does not exist. Skipping the image. -- The local image file does not exist. Skipping the image.
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T255679918"] = "The local image file does not exist. Skipping the image." UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T255679918"] = "The local image file does not exist. Skipping the image."

View File

@ -3,6 +3,8 @@ using System.Text.Json.Serialization;
using AIStudio.Provider; using AIStudio.Provider;
using AIStudio.Settings; using AIStudio.Settings;
using AIStudio.Tools;
using AIStudio.Tools.PluginSystem;
using AIStudio.Tools.RAG.RAGProcesses; using AIStudio.Tools.RAG.RAGProcesses;
namespace AIStudio.Chat; namespace AIStudio.Chat;
@ -13,6 +15,7 @@ namespace AIStudio.Chat;
public sealed class ContentText : IContent public sealed class ContentText : IContent
{ {
private static readonly ILogger<ContentText> LOGGER = Program.LOGGER_FACTORY.CreateLogger<ContentText>(); private static readonly ILogger<ContentText> LOGGER = Program.LOGGER_FACTORY.CreateLogger<ContentText>();
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ContentText).Namespace, nameof(ContentText));
/// <summary> /// <summary>
/// The minimum time between two streaming events, when the user /// The minimum time between two streaming events, when the user
@ -48,11 +51,21 @@ public sealed class ContentText : IContent
public async Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastUserPrompt, ChatThread? chatThread, CancellationToken token = default) public async Task<ChatThread> CreateFromProviderAsync(IProvider provider, Model chatModel, IContent? lastUserPrompt, ChatThread? chatThread, CancellationToken token = default)
{ {
if(chatThread is null) if(chatThread is null)
{
await this.CompleteWithoutStreaming();
return new(); return new();
}
if(!chatThread.IsLLMProviderAllowed(provider)) if(!chatThread.IsLLMProviderAllowed(provider))
{ {
LOGGER.LogError("The provider is not allowed for this chat thread due to data security reasons. Skipping the AI process."); LOGGER.LogError("The provider is not allowed for this chat thread due to data security reasons. Skipping the AI process.");
await this.CompleteWithoutStreaming();
return chatThread;
}
if(!await this.CheckSelectedModelAvailability(provider, chatModel, token))
{
await this.CompleteWithoutStreaming();
return chatThread; return chatThread;
} }
@ -137,6 +150,67 @@ public sealed class ContentText : IContent
return chatThread; return chatThread;
} }
private async Task CompleteWithoutStreaming()
{
this.InitialRemoteWait = false;
this.IsStreaming = false;
await this.StreamingDone();
}
private static bool ModelsMatch(Model modelA, Model modelB)
{
var idA = modelA.Id.Trim();
var idB = modelB.Id.Trim();
return string.Equals(idA, idB, StringComparison.OrdinalIgnoreCase);
}
private async Task<bool> CheckSelectedModelAvailability(IProvider provider, Model chatModel, CancellationToken token = default)
{
if(chatModel.IsSystemModel)
return true;
if (string.IsNullOrWhiteSpace(chatModel.Id))
{
LOGGER.LogWarning("Skipping AI request because model ID is null or white space.");
return false;
}
IEnumerable<Model> loadedModels;
try
{
loadedModels = await provider.GetTextModels(token: token);
}
catch (OperationCanceledException)
{
return false;
}
catch (Exception e)
{
LOGGER.LogWarning(e, "Skipping selected model availability check for '{ProviderInstanceName}' (provider={ProviderType}) because the model list could not be loaded.", provider.InstanceName, provider.Provider);
return true;
}
var availableModels = loadedModels.Where(model => !string.IsNullOrWhiteSpace(model.Id)).ToList();
if (availableModels.Count == 0)
{
LOGGER.LogWarning("Skipping AI request because there are no models available from '{ProviderInstanceName}' (provider={ProviderType}).", provider.InstanceName, provider.Provider);
return false;
}
if(availableModels.Any(model => ModelsMatch(model, chatModel)))
return true;
var message = string.Format(
TB("The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings."),
chatModel.Id,
provider.InstanceName,
provider.Provider);
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.CloudOff, message));
LOGGER.LogWarning("Skipping AI request because model '{ModelId}' is not available from '{ProviderInstanceName}' (provider={ProviderType}).", chatModel.Id, provider.InstanceName, provider.Provider);
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public IContent DeepClone() => new ContentText public IContent DeepClone() => new ContentText
{ {

View File

@ -1734,6 +1734,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "Nein, b
-- Export Chat to Microsoft Word -- Export Chat to Microsoft Word
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Chat in Microsoft Word exportieren" UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Chat in Microsoft Word exportieren"
-- The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings.
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T3267850764"] = "Das ausgewählte Modell '{0}' ist bei '{1}' (Anbieter={2}) nicht mehr verfügbar. Bitte passen Sie Ihre Anbietereinstellungen an."
-- The local image file does not exist. Skipping the image. -- The local image file does not exist. Skipping the image.
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T255679918"] = "Die lokale Bilddatei existiert nicht. Das Bild wird übersprungen." UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T255679918"] = "Die lokale Bilddatei existiert nicht. Das Bild wird übersprungen."

View File

@ -1734,6 +1734,9 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4188329028"] = "No, kee
-- Export Chat to Microsoft Word -- Export Chat to Microsoft Word
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Export Chat to Microsoft Word" UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T861873672"] = "Export Chat to Microsoft Word"
-- The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings.
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T3267850764"] = "The selected model '{0}' is no longer available from '{1}' (provider={2}). Please adapt your provider settings."
-- The local image file does not exist. Skipping the image. -- The local image file does not exist. Skipping the image.
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T255679918"] = "The local image file does not exist. Skipping the image." UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T255679918"] = "The local image file does not exist. Skipping the image."

View File

@ -5,6 +5,7 @@
- Added the ability to format your user prompt in the chat using icons instead of typing Markdown directly. - Added the ability to format your user prompt in the chat using icons instead of typing Markdown directly.
- Added the ability to load a system prompt from a file when creating or editing chat templates. - Added the ability to load a system prompt from a file when creating or editing chat templates.
- Added a start-page setting, so AI Studio can now open directly on your preferred page when the app starts. Configuration plugins can also provide and optionally lock this default for organizations. - Added a start-page setting, so AI Studio can now open directly on your preferred page when the app starts. Configuration plugins can also provide and optionally lock this default for organizations.
- Added pre-call validation to check if the selected model exists for the provider before making the request.
- Added math rendering in chats for LaTeX display formulas, including block formats such as `$$ ... $$` and `\[ ... \]`. - Added math rendering in chats for LaTeX display formulas, including block formats such as `$$ ... $$` and `\[ ... \]`.
- Added the latest OpenAI models. - Added the latest OpenAI models.
- Released the document analysis assistant after an intense testing phase. - Released the document analysis assistant after an intense testing phase.