mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-09-27 02:33:38 +00:00
Name the model's window when a text was too long
This commit is contained in:
parent
9c3fcbf815
commit
142f4807bf
@ -10024,6 +10024,9 @@ UI_TEXT_CONTENT["AISTUDIO::PROVIDER::BASEPROVIDER::T4049517041"] = "We tried to
|
|||||||
-- The provider '{0}' does not know the selected model. Please select another model.
|
-- The provider '{0}' does not know the selected model. Please select another model.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::BASEPROVIDER::T411393889"] = "The provider '{0}' does not know the selected model. Please select another model."
|
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::BASEPROVIDER::T411393889"] = "The provider '{0}' does not know the selected model. Please select another model."
|
||||||
|
|
||||||
|
-- The text was longer than the selected model accepts, which is {0} tokens. Please select a model which takes longer texts, or reduce the chunk size of the data source.
|
||||||
|
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::BASEPROVIDER::T479223640"] = "The text was longer than the selected model accepts, which is {0} tokens. Please select a model which takes longer texts, or reduce the chunk size of the data source."
|
||||||
|
|
||||||
-- The provider '{0}' reported an error: {1}
|
-- The provider '{0}' reported an error: {1}
|
||||||
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::BASEPROVIDER::T700894460"] = "The provider '{0}' reported an error: {1}"
|
UI_TEXT_CONTENT["AISTUDIO::PROVIDER::BASEPROVIDER::T700894460"] = "The provider '{0}' reported an error: {1}"
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using System.Text.Json;
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
|
using AIStudio.Models;
|
||||||
using AIStudio.Models.Live;
|
using AIStudio.Models.Live;
|
||||||
using AIStudio.Provider.Anthropic;
|
using AIStudio.Provider.Anthropic;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -247,13 +248,34 @@ public abstract class BaseProvider : IProvider, ISecretId
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string GetProviderRequestFailureUserMessage(ProviderRequestFailureReason failureReason) => failureReason switch
|
/// <summary>
|
||||||
|
/// Says what a failed request means for the user.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The window is only ever known where the caller knows which model the request was for, which
|
||||||
|
/// is why it is optional rather than a second required argument: most failures say nothing
|
||||||
|
/// about a length and need no number to explain themselves.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="failureReason">Why the request failed.</param>
|
||||||
|
/// <param name="contextWindow">What the model reads, where that is known.</param>
|
||||||
|
/// <returns>The message to show, or an empty string when we have nothing to say.</returns>
|
||||||
|
protected virtual string GetProviderRequestFailureUserMessage(ProviderRequestFailureReason failureReason, ContextWindow contextWindow = default) => failureReason switch
|
||||||
{
|
{
|
||||||
ProviderRequestFailureReason.TOO_MANY_REQUESTS => TB("The provider rejected the request because too many requests were sent. Please wait a moment and try again."),
|
ProviderRequestFailureReason.TOO_MANY_REQUESTS => TB("The provider rejected the request because too many requests were sent. Please wait a moment and try again."),
|
||||||
ProviderRequestFailureReason.INVALID_OR_MISSING_API_KEY => string.Format(TB("The API key for the provider '{0}' is missing or was rejected. Please check the key in the settings."), this.InstanceName),
|
ProviderRequestFailureReason.INVALID_OR_MISSING_API_KEY => string.Format(TB("The API key for the provider '{0}' is missing or was rejected. Please check the key in the settings."), this.InstanceName),
|
||||||
ProviderRequestFailureReason.AUTHENTICATION_OR_PERMISSION_ERROR => string.Format(TB("The provider '{0}' refused the request. Your account might not be allowed to use the selected model, or the provider might not serve your region."), this.InstanceName),
|
ProviderRequestFailureReason.AUTHENTICATION_OR_PERMISSION_ERROR => string.Format(TB("The provider '{0}' refused the request. Your account might not be allowed to use the selected model, or the provider might not serve your region."), this.InstanceName),
|
||||||
ProviderRequestFailureReason.PROVIDER_UNAVAILABLE => string.Format(TB("The provider '{0}' could not be reached. Please check whether it is running and reachable, then try again."), this.InstanceName),
|
ProviderRequestFailureReason.PROVIDER_UNAVAILABLE => string.Format(TB("The provider '{0}' could not be reached. Please check whether it is running and reachable, then try again."), this.InstanceName),
|
||||||
ProviderRequestFailureReason.MODEL_NOT_FOUND => string.Format(TB("The provider '{0}' does not know the selected model. Please select another model."), this.InstanceName),
|
ProviderRequestFailureReason.MODEL_NOT_FOUND => string.Format(TB("The provider '{0}' does not know the selected model. Please select another model."), this.InstanceName),
|
||||||
|
//
|
||||||
|
// Naming the number is the whole point of knowing it: "too long" leaves the user guessing
|
||||||
|
// by how much, while the window turns the next step into arithmetic. Where nobody knows the
|
||||||
|
// window, no number is invented -- the sentence below says the same thing without one.
|
||||||
|
//
|
||||||
|
// Written out in full rather than shortened the way the chat shortens it. The sentence ends
|
||||||
|
// by asking the user to set a chunk size, and 32.77k is not a number anybody types into a
|
||||||
|
// field.
|
||||||
|
//
|
||||||
|
ProviderRequestFailureReason.CONTEXT_LENGTH_EXCEEDED when contextWindow.IsKnown => string.Format(TB("The text was longer than the selected model accepts, which is {0} tokens. Please select a model which takes longer texts, or reduce the chunk size of the data source."), contextWindow.DefaultTokens.ToString("N0", I18N.I.Culture)),
|
||||||
ProviderRequestFailureReason.CONTEXT_LENGTH_EXCEEDED => TB("The text was longer than the selected model accepts. Please select a model which takes longer texts, or reduce the chunk size of the data source."),
|
ProviderRequestFailureReason.CONTEXT_LENGTH_EXCEEDED => TB("The text was longer than the selected model accepts. Please select a model which takes longer texts, or reduce the chunk size of the data source."),
|
||||||
ProviderRequestFailureReason.TOOLS_NOT_SUPPORTED => string.Format(TB("The selected model is not able to use tools. Please select a model which can, or open the settings of the provider '{0}', show its expert settings, and switch the function calling capability off there."), this.InstanceName),
|
ProviderRequestFailureReason.TOOLS_NOT_SUPPORTED => string.Format(TB("The selected model is not able to use tools. Please select a model which can, or open the settings of the provider '{0}', show its expert settings, and switch the function calling capability off there."), this.InstanceName),
|
||||||
ProviderRequestFailureReason.EMBEDDINGS_NOT_SUPPORTED => string.Format(TB("The provider '{0}' cannot create embeddings. Please select a provider which offers an embedding model."), this.InstanceName),
|
ProviderRequestFailureReason.EMBEDDINGS_NOT_SUPPORTED => string.Format(TB("The provider '{0}' cannot create embeddings. Please select a provider which offers an embedding model."), this.InstanceName),
|
||||||
@ -279,10 +301,18 @@ public abstract class BaseProvider : IProvider, ISecretId
|
|||||||
/// Shared with the providers which talk to an embedding endpoint of their own: what the user
|
/// Shared with the providers which talk to an embedding endpoint of their own: what the user
|
||||||
/// needs to know does not depend on which route the request took.
|
/// needs to know does not depend on which route the request took.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected ProviderRequestException CreateEmbeddingRequestException(HttpStatusCode statusCode, string reasonPhrase, string responseBody)
|
protected ProviderRequestException CreateEmbeddingRequestException(HttpStatusCode statusCode, string reasonPhrase, string responseBody, Model embeddingModel)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// What the rules know about this model, corrected by whatever this installation reported
|
||||||
|
// about it. That is the same walk a configured chat provider takes, minus the expert
|
||||||
|
// settings: an embedding provider has none, so there is nothing above the two to ask.
|
||||||
|
//
|
||||||
|
var stated = this.Provider.GetModelProfile(embeddingModel);
|
||||||
|
var contextWindow = ListedModels.Shared.Of(this.ConfiguredProviderId, embeddingModel.Id).ApplyTo(stated).Context;
|
||||||
|
|
||||||
var failureReason = this.ClassifyEmbeddingRequestFailure(statusCode, responseBody);
|
var failureReason = this.ClassifyEmbeddingRequestFailure(statusCode, responseBody);
|
||||||
var userMessage = this.GetProviderRequestFailureUserMessage(failureReason);
|
var userMessage = this.GetProviderRequestFailureUserMessage(failureReason, contextWindow);
|
||||||
|
|
||||||
// We know nothing about this failure, so we pass on what the provider said about it:
|
// We know nothing about this failure, so we pass on what the provider said about it:
|
||||||
if (string.IsNullOrWhiteSpace(userMessage))
|
if (string.IsNullOrWhiteSpace(userMessage))
|
||||||
@ -1551,7 +1581,7 @@ public abstract class BaseProvider : IProvider, ISecretId
|
|||||||
// thousands being indexed in the background or the one thing the user just asked
|
// thousands being indexed in the background or the one thing the user just asked
|
||||||
// for, and only it can decide how often the user should hear about it.
|
// for, and only it can decide how often the user should hear about it.
|
||||||
//
|
//
|
||||||
throw this.CreateEmbeddingRequestException(response.StatusCode, response.ReasonPhrase ?? string.Empty, responseBody);
|
throw this.CreateEmbeddingRequestException(response.StatusCode, response.ReasonPhrase ?? string.Empty, responseBody, embeddingModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
var embeddingResponse = JsonSerializer.Deserialize<EmbeddingResponse>(responseBody, JSON_SERIALIZER_OPTIONS);
|
var embeddingResponse = JsonSerializer.Deserialize<EmbeddingResponse>(responseBody, JSON_SERIALIZER_OPTIONS);
|
||||||
|
|||||||
@ -116,7 +116,7 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, new Uri("https
|
|||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
LOGGER.LogError("Embedding request failed with status code {ResponseStatusCode} and body: '{ResponseBody}'.", response.StatusCode, responseBody);
|
LOGGER.LogError("Embedding request failed with status code {ResponseStatusCode} and body: '{ResponseBody}'.", response.StatusCode, responseBody);
|
||||||
throw this.CreateEmbeddingRequestException(response.StatusCode, response.ReasonPhrase ?? string.Empty, responseBody);
|
throw this.CreateEmbeddingRequestException(response.StatusCode, response.ReasonPhrase ?? string.Empty, responseBody, embeddingModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
var embeddingResponse = JsonSerializer.Deserialize<GoogleEmbeddingResponse>(responseBody, JSON_SERIALIZER_OPTIONS);
|
var embeddingResponse = JsonSerializer.Deserialize<GoogleEmbeddingResponse>(responseBody, JSON_SERIALIZER_OPTIONS);
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
|
using AIStudio.Models;
|
||||||
using AIStudio.Models.Live;
|
using AIStudio.Models.Live;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
using AIStudio.Settings;
|
using AIStudio.Settings;
|
||||||
@ -128,10 +129,10 @@ public sealed class ProviderHuggingFace : BaseProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override string GetProviderRequestFailureUserMessage(ProviderRequestFailureReason failureReason)
|
protected override string GetProviderRequestFailureUserMessage(ProviderRequestFailureReason failureReason, ContextWindow contextWindow = default)
|
||||||
{
|
{
|
||||||
if (failureReason is not ProviderRequestFailureReason.MODEL_NOT_SUPPORTED_BY_PROVIDER)
|
if (failureReason is not ProviderRequestFailureReason.MODEL_NOT_SUPPORTED_BY_PROVIDER)
|
||||||
return base.GetProviderRequestFailureUserMessage(failureReason);
|
return base.GetProviderRequestFailureUserMessage(failureReason, contextWindow);
|
||||||
|
|
||||||
//
|
//
|
||||||
// When Hugging Face chose the provider itself, naming it back to the user would help
|
// When Hugging Face chose the provider itself, naming it back to the user would help
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
|
using AIStudio.Models;
|
||||||
using AIStudio.Settings;
|
using AIStudio.Settings;
|
||||||
using AIStudio.Tools.PluginSystem;
|
using AIStudio.Tools.PluginSystem;
|
||||||
using AIStudio.Tools.Rust;
|
using AIStudio.Tools.Rust;
|
||||||
@ -48,10 +49,10 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, new Ur
|
|||||||
return base.ClassifyProviderRequestFailure(errorCode, errorType, errorMessage, responseBody);
|
return base.ClassifyProviderRequestFailure(errorCode, errorType, errorMessage, responseBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string GetProviderRequestFailureUserMessage(ProviderRequestFailureReason failureReason) => failureReason switch
|
protected override string GetProviderRequestFailureUserMessage(ProviderRequestFailureReason failureReason, ContextWindow contextWindow = default) => failureReason switch
|
||||||
{
|
{
|
||||||
ProviderRequestFailureReason.INSUFFICIENT_QUOTA => TB("It looks like you do not have any API credits left with OpenAI. Please add credits to your account and try again."),
|
ProviderRequestFailureReason.INSUFFICIENT_QUOTA => TB("It looks like you do not have any API credits left with OpenAI. Please add credits to your account and try again."),
|
||||||
_ => base.GetProviderRequestFailureUserMessage(failureReason),
|
_ => base.GetProviderRequestFailureUserMessage(failureReason, contextWindow),
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@ -1,17 +1,38 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace AIStudio.Tools.PluginSystem;
|
namespace AIStudio.Tools.PluginSystem;
|
||||||
|
|
||||||
public class I18N : ILang
|
public class I18N : ILang
|
||||||
{
|
{
|
||||||
public static readonly I18N I = new();
|
public static readonly I18N I = new();
|
||||||
private static readonly ILogger<I18N> LOG = Program.LOGGER_FACTORY.CreateLogger<I18N>();
|
private static readonly ILogger<I18N> LOG = Program.LOGGER_FACTORY.CreateLogger<I18N>();
|
||||||
|
|
||||||
private ILanguagePlugin? language;
|
private ILanguagePlugin? language;
|
||||||
|
|
||||||
private I18N()
|
private I18N()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Init(ILanguagePlugin language) => I.language = language;
|
/// <summary>
|
||||||
|
/// How the language in use writes its numbers, or the invariant culture while none is loaded.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A number standing inside a translated sentence has to be written the way that language
|
||||||
|
/// writes numbers. AI Studio's language is chosen in its own settings and never moves the
|
||||||
|
/// thread's culture along with it, so a number formatted from the thread comes out with English
|
||||||
|
/// separators inside a German sentence. It lives here because it is the same decision as the
|
||||||
|
/// texts: whoever picked the language picked how its numbers look.
|
||||||
|
///
|
||||||
|
/// Components which already hold the active plugin may keep deriving it themselves. This is for
|
||||||
|
/// the code which has no plugin to ask -- a provider building an error message, say.
|
||||||
|
/// </remarks>
|
||||||
|
public CultureInfo Culture { get; private set; } = CultureInfo.InvariantCulture;
|
||||||
|
|
||||||
|
public static void Init(ILanguagePlugin language)
|
||||||
|
{
|
||||||
|
I.language = language;
|
||||||
|
I.Culture = CommonTools.DeriveActiveCultureOrInvariant(language.IETFTag);
|
||||||
|
}
|
||||||
|
|
||||||
#region Implementation of ILang
|
#region Implementation of ILang
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user