mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-13 11:27:21 +00:00
Renamed the extension classes of interfaces to drop the I prefix (#1190)
This commit is contained in:
1 parent
d8ef328e6e
commit
6f187f1bd8
30 files changed
+59
-59
No files matched your search
@@ -16,7 +16,7 @@ namespace AIStudio.Assistants.BeyondFactsLab;
|
|||||||
/// <para>
|
/// <para>
|
||||||
/// A shortened material is the beginning of the text which passed the prompt injection filter when the person added
|
/// A shortened material is the beginning of the text which passed the prompt injection filter when the person added
|
||||||
/// it. It does not pass the filter again: cutting off the end of a text adds nothing which the filter did not see,
|
/// it. It does not pass the filter again: cutting off the end of a text adds nothing which the filter did not see,
|
||||||
/// unlike IRetrievalContextExtensions.ShortenToFitAsync, which cuts the unfiltered text of a data source.
|
/// unlike RetrievalContextExtensions.ShortenToFitAsync, which cuts the unfiltered text of a data source.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// An image takes no characters: as many images as the model takes at once go along with the first message of the
|
/// An image takes no characters: as many images as the model takes at once go along with the first message of the
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ public sealed class BflMaterialService(BeyondFactsLabStore store, RustService ru
|
|||||||
/// <returns>True when the preparation has the image now, also as a material it had already.</returns>
|
/// <returns>True when the preparation has the image now, also as a material it had already.</returns>
|
||||||
private async Task<bool> AddImageAsync(Guid projectId, string path, string name, long size, string hash)
|
private async Task<bool> AddImageAsync(Guid projectId, string path, string name, long size, string hash)
|
||||||
{
|
{
|
||||||
var prepared = await rustService.PrepareImageForModelAsync(path, IImageSourceExtensions.MAX_IMAGE_SIZE_BYTES);
|
var prepared = await rustService.PrepareImageForModelAsync(path, ImageSourceExtensions.MAX_IMAGE_SIZE_BYTES);
|
||||||
if (!prepared.IsPrepared)
|
if (!prepared.IsPrepared)
|
||||||
{
|
{
|
||||||
logger.LogWarning("The BeyondFacts Lab could not prepare the image '{Path}': {ErrorCode}.", path, prepared.ErrorCode);
|
logger.LogWarning("The BeyondFacts Lab could not prepare the image '{Path}': {ErrorCode}.", path, prepared.ErrorCode);
|
||||||
|
|||||||
@@ -5375,16 +5375,16 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T373499115"] = "Your data sources
|
|||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T713722424"] = "AI Studio could not store what the AI received separately from your chat. It remains in the chat itself, so you can still read it."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T713722424"] = "AI Studio could not store what the AI received separately from your chat. It remains in the chat itself, so you can still read it."
|
||||||
|
|
||||||
-- 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::IMAGESOURCEEXTENSIONS::T255679918"] = "The local image file does not exist. Skipping the image."
|
||||||
|
|
||||||
-- Failed to download the image from the URL. Skipping the image.
|
-- Failed to download the image from the URL. Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T2996654916"] = "Failed to download the image from the URL. Skipping the image."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T2996654916"] = "Failed to download the image from the URL. Skipping the image."
|
||||||
|
|
||||||
-- The local image file is too large (>10 MB). Skipping the image.
|
-- The local image file is too large (>10 MB). Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T3219823625"] = "The local image file is too large (>10 MB). Skipping the image."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T3219823625"] = "The local image file is too large (>10 MB). Skipping the image."
|
||||||
|
|
||||||
-- The image at the URL is too large (>10 MB). Skipping the image.
|
-- The image at the URL is too large (>10 MB). Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T349928509"] = "The image at the URL is too large (>10 MB). Skipping the image."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T349928509"] = "The image at the URL is too large (>10 MB). Skipping the image."
|
||||||
|
|
||||||
-- Export configuration
|
-- Export configuration
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Export configuration"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Export configuration"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
namespace AIStudio.Chat;
|
namespace AIStudio.Chat;
|
||||||
|
|
||||||
public static class IContentExtensions
|
public static class ContentExtensions
|
||||||
{
|
{
|
||||||
/// <param name="content">The content of a message in the chat.</param>
|
/// <param name="content">The content of a message in the chat.</param>
|
||||||
extension(IContent content)
|
extension(IContent content)
|
||||||
+2
-2
@@ -4,9 +4,9 @@ using AIStudio.Tools.PluginSystem;
|
|||||||
|
|
||||||
namespace AIStudio.Chat;
|
namespace AIStudio.Chat;
|
||||||
|
|
||||||
public static class IImageSourceExtensions
|
public static class ImageSourceExtensions
|
||||||
{
|
{
|
||||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(IImageSourceExtensions).Namespace, nameof(IImageSourceExtensions));
|
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ImageSourceExtensions).Namespace, nameof(ImageSourceExtensions));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The largest image, in bytes, we send anywhere: no image prepared for a model is larger, and
|
/// The largest image, in bytes, we send anywhere: no image prepared for a model is larger, and
|
||||||
+4
-4
@@ -5377,16 +5377,16 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T373499115"] = "Ihre Datenquellen
|
|||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T713722424"] = "AI Studio konnte die Inhalte, die die KI erhalten hat, nicht getrennt von Ihrem Chat speichern. Diese bleiben im Chat selbst, sodass Sie sie weiterhin lesen können."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T713722424"] = "AI Studio konnte die Inhalte, die die KI erhalten hat, nicht getrennt von Ihrem Chat speichern. Diese bleiben im Chat selbst, sodass Sie sie weiterhin lesen können."
|
||||||
|
|
||||||
-- 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::IMAGESOURCEEXTENSIONS::T255679918"] = "Die lokale Bilddatei existiert nicht. Das Bild wird übersprungen."
|
||||||
|
|
||||||
-- Failed to download the image from the URL. Skipping the image.
|
-- Failed to download the image from the URL. Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T2996654916"] = "Das Bild konnte nicht von der URL heruntergeladen werden. Das Bild wird übersprungen."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T2996654916"] = "Das Bild konnte nicht von der URL heruntergeladen werden. Das Bild wird übersprungen."
|
||||||
|
|
||||||
-- The local image file is too large (>10 MB). Skipping the image.
|
-- The local image file is too large (>10 MB). Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T3219823625"] = "Die lokale Bilddatei ist zu groß (>10 MB). Das Bild wird übersprungen."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T3219823625"] = "Die lokale Bilddatei ist zu groß (>10 MB). Das Bild wird übersprungen."
|
||||||
|
|
||||||
-- The image at the URL is too large (>10 MB). Skipping the image.
|
-- The image at the URL is too large (>10 MB). Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T349928509"] = "Das Bild unter der URL ist zu groß (>10 MB). Das Bild wird übersprungen."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T349928509"] = "Das Bild unter der URL ist zu groß (>10 MB). Das Bild wird übersprungen."
|
||||||
|
|
||||||
-- Export configuration
|
-- Export configuration
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Konfiguration exportieren"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Konfiguration exportieren"
|
||||||
|
|||||||
+4
-4
@@ -5377,16 +5377,16 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T373499115"] = "Your data sources
|
|||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T713722424"] = "AI Studio could not store what the AI received separately from your chat. It remains in the chat itself, so you can still read it."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTTEXT::T713722424"] = "AI Studio could not store what the AI received separately from your chat. It remains in the chat itself, so you can still read it."
|
||||||
|
|
||||||
-- 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::IMAGESOURCEEXTENSIONS::T255679918"] = "The local image file does not exist. Skipping the image."
|
||||||
|
|
||||||
-- Failed to download the image from the URL. Skipping the image.
|
-- Failed to download the image from the URL. Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T2996654916"] = "Failed to download the image from the URL. Skipping the image."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T2996654916"] = "Failed to download the image from the URL. Skipping the image."
|
||||||
|
|
||||||
-- The local image file is too large (>10 MB). Skipping the image.
|
-- The local image file is too large (>10 MB). Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T3219823625"] = "The local image file is too large (>10 MB). Skipping the image."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T3219823625"] = "The local image file is too large (>10 MB). Skipping the image."
|
||||||
|
|
||||||
-- The image at the URL is too large (>10 MB). Skipping the image.
|
-- The image at the URL is too large (>10 MB). Skipping the image.
|
||||||
UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T349928509"] = "The image at the URL is too large (>10 MB). Skipping the image."
|
UI_TEXT_CONTENT["AISTUDIO::CHAT::IMAGESOURCEEXTENSIONS::T349928509"] = "The image at the URL is too large (>10 MB). Skipping the image."
|
||||||
|
|
||||||
-- Export configuration
|
-- Export configuration
|
||||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Export configuration"
|
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ADMINEXPORTBUTTON::T975426229"] = "Export configuration"
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ public static class LLMProvidersExtensions
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The limit belongs to the API of the provider, not to the model: the same model may accept
|
/// The limit belongs to the API of the provider, not to the model: the same model may accept
|
||||||
/// larger images through another provider. What we actually send is asked through
|
/// larger images through another provider. What we actually send is asked through
|
||||||
/// IImageSourceExtensions.MaxImageSizeBytesFor, which also applies our own limit.
|
/// ImageSourceExtensions.MaxImageSizeBytesFor, which also applies our own limit.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <value>The size limit of one image file, or null when the provider states none we know of.</value>
|
/// <value>The size limit of one image file, or null when the provider states none we know of.</value>
|
||||||
public long? MaxImageSizeBytes => provider switch
|
public long? MaxImageSizeBytes => provider switch
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public static class HostExtensions
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Like the limit of a cloud provider, see LLMProvidersExtensions.MaxImageSizeBytes, this
|
/// Like the limit of a cloud provider, see LLMProvidersExtensions.MaxImageSizeBytes, this
|
||||||
/// belongs to the API of the engine, not to the model. What we actually send is asked through
|
/// belongs to the API of the engine, not to the model. What we actually send is asked through
|
||||||
/// IImageSourceExtensions.MaxImageSizeBytesFor.
|
/// ImageSourceExtensions.MaxImageSizeBytesFor.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <value>The size limit of one image file, or null when the engine states none we know of.</value>
|
/// <value>The size limit of one image file, or null when the engine states none we know of.</value>
|
||||||
public long? MaxImageSizeBytes => host switch
|
public long? MaxImageSizeBytes => host switch
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
namespace AIStudio.Tools;
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
public static class IConfidenceExtensions
|
public static class ConfidenceExtensions
|
||||||
{
|
{
|
||||||
private static readonly ILogger<IConfidence> LOGGER = Program.LOGGER_FACTORY.CreateLogger<IConfidence>();
|
private static readonly ILogger<IConfidence> LOGGER = Program.LOGGER_FACTORY.CreateLogger<IConfidence>();
|
||||||
|
|
||||||
@@ -256,7 +256,7 @@ public static class PlainFileExport
|
|||||||
/// <param name="dialogTitle">The title of the save dialog.</param>
|
/// <param name="dialogTitle">The title of the save dialog.</param>
|
||||||
/// <param name="file">The file, as ExtractFiles read it out of the message. Its format must be a
|
/// <param name="file">The file, as ExtractFiles read it out of the message. Its format must be a
|
||||||
/// plain text format, see FileExportFormatExtensions.IsPlainText.</param>
|
/// plain text format, see FileExportFormatExtensions.IsPlainText.</param>
|
||||||
/// <param name="fileContent">The finished file, see IContentExtensions.ToExportContent.</param>
|
/// <param name="fileContent">The finished file, see ContentExtensions.ToExportContent.</param>
|
||||||
/// <param name="fileName">What the file is about, used to suggest a name in the save dialog.
|
/// <param name="fileName">What the file is about, used to suggest a name in the save dialog.
|
||||||
/// Null falls back to a generic name.</param>
|
/// Null falls back to a generic name.</param>
|
||||||
/// <returns>True, when the file was written.</returns>
|
/// <returns>True, when the file was written.</returns>
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ using SharedTools;
|
|||||||
|
|
||||||
namespace AIStudio.Tools.PluginSystem;
|
namespace AIStudio.Tools.PluginSystem;
|
||||||
|
|
||||||
public static class ILangExtensions
|
public static class LangExtensions
|
||||||
{
|
{
|
||||||
private static readonly ILogger<ILang> LOGGER = Program.LOGGER_FACTORY.CreateLogger<ILang>();
|
private static readonly ILogger<ILang> LOGGER = Program.LOGGER_FACTORY.CreateLogger<ILang>();
|
||||||
|
|
||||||
+1
-1
@@ -2,7 +2,7 @@ using SharedTools;
|
|||||||
|
|
||||||
namespace AIStudio.Tools.PluginSystem;
|
namespace AIStudio.Tools.PluginSystem;
|
||||||
|
|
||||||
public static class ILanguagePluginExtensions
|
public static class LanguagePluginExtensions
|
||||||
{
|
{
|
||||||
/// <param name="plugin">The language plugin.</param>
|
/// <param name="plugin">The language plugin.</param>
|
||||||
extension(ILanguagePlugin plugin)
|
extension(ILanguagePlugin plugin)
|
||||||
@@ -84,7 +84,7 @@ public sealed class PassageBudget(int limit, Func<string, CancellationToken, Tas
|
|||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// A passage longer than the whole budget is shortened until it fits, and filtered again, see
|
/// A passage longer than the whole budget is shortened until it fits, and filtered again, see
|
||||||
/// IRetrievalContextExtensions.ShortenToFitAsync. It then has to fit into what is left like any
|
/// RetrievalContextExtensions.ShortenToFitAsync. It then has to fit into what is left like any
|
||||||
/// other passage.
|
/// other passage.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace AIStudio.Tools.RAG;
|
|||||||
/// ready to be numbered.
|
/// ready to be numbered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Made by IRetrievalContextExtensions.PrepareForModelAsync. Which number a context gets depends on
|
/// Made by RetrievalContextExtensions.PrepareForModelAsync. Which number a context gets depends on
|
||||||
/// which contexts the caller hands on in the end, so the header is written only then, see
|
/// which contexts the caller hands on in the end, so the header is written only then, see
|
||||||
/// ToMarkdown. The app writes it itself, which is why it needs no filter.
|
/// ToMarkdown. The app writes it itself, which is why it needs no filter.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ using AIStudio.Tools.Security;
|
|||||||
|
|
||||||
namespace AIStudio.Tools.RAG;
|
namespace AIStudio.Tools.RAG;
|
||||||
|
|
||||||
public static class IRetrievalContextExtensions
|
public static class RetrievalContextExtensions
|
||||||
{
|
{
|
||||||
private static readonly ILogger<IRetrievalContext> LOGGER = Program.LOGGER_FACTORY.CreateLogger<IRetrievalContext>();
|
private static readonly ILogger<IRetrievalContext> LOGGER = Program.LOGGER_FACTORY.CreateLogger<IRetrievalContext>();
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ namespace AIStudio.Tools.RAG;
|
|||||||
/// so it is not shown as if it had.<br/><br/>
|
/// so it is not shown as if it had.<br/><br/>
|
||||||
/// A passage belongs to the source it is listed under, which is why it is only made for a context
|
/// A passage belongs to the source it is listed under, which is why it is only made for a context
|
||||||
/// with a source, see SourceUrl. A context which names nothing to open, e.g., by a path which only
|
/// with a source, see SourceUrl. A context which names nothing to open, e.g., by a path which only
|
||||||
/// its ERI server knows, gets a source named as text, see IRetrievalContextExtensions.ToSources.<br/><br/>
|
/// its ERI server knows, gets a source named as text, see RetrievalContextExtensions.ToSources.<br/><br/>
|
||||||
/// Plain stored values only: a computed property would be written into every chat file as well.
|
/// Plain stored values only: a computed property would be written into every chat file as well.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public sealed record SourcePassage
|
public sealed record SourcePassage
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public sealed class ModelImageService(RustService rustService, ILogger<ModelImag
|
|||||||
return PreparedModelImage.Failed(ModelImageErrorCode.FILE_NOT_FOUND);
|
return PreparedModelImage.Failed(ModelImageErrorCode.FILE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxBytes = IImageSourceExtensions.MaxImageSizeBytesFor(provider);
|
var maxBytes = ImageSourceExtensions.MaxImageSizeBytesFor(provider);
|
||||||
var key = new CacheKey(file.FullName, file.LastWriteTimeUtc, file.Length, maxBytes);
|
var key = new CacheKey(file.FullName, file.LastWriteTimeUtc, file.Length, maxBytes);
|
||||||
if (this.cache.TryGetValue(key, out PreparedModelImage? cached) && cached is not null)
|
if (this.cache.TryGetValue(key, out PreparedModelImage? cached) && cached is not null)
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -208,7 +208,7 @@ internal sealed record PendingMail(DataSourceMailbox Mailbox, MailSummary Summar
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The attachments are numbered the way the index numbers them, cf. MailSummary.AttachmentNames.
|
/// The attachments are numbered the way the index numbers them, cf. MailSummary.AttachmentNames.
|
||||||
/// Where in an attachment is worded like the location of any other passage, cf.
|
/// Where in an attachment is worded like the location of any other passage, cf.
|
||||||
/// IRetrievalContextExtensions.DescribeLocation. A passage of the text of the mail names
|
/// RetrievalContextExtensions.DescribeLocation. A passage of the text of the mail names
|
||||||
/// no attachment, and neither does one of a mail indexed before attachments were told apart.
|
/// no attachment, and neither does one of a mail indexed before attachments were told apart.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="texts">The filtered texts of the result.</param>
|
/// <param name="texts">The filtered texts of the result.</param>
|
||||||
@@ -220,6 +220,6 @@ internal sealed record PendingMail(DataSourceMailbox Mailbox, MailSummary Summar
|
|||||||
|
|
||||||
var type = DataSourceLocalRetrievalService.GetRetrievalContentType(Path.GetExtension(this.Summary.AttachmentNames[position]));
|
var type = DataSourceLocalRetrievalService.GetRetrievalContentType(Path.GetExtension(this.Summary.AttachmentNames[position]));
|
||||||
var located = DataSourceLocalRetrievalService.LocatePassage(location, type, chunkNumber: 1);
|
var located = DataSourceLocalRetrievalService.LocatePassage(location, type, chunkNumber: 1);
|
||||||
return new(texts[attachment], IRetrievalContextExtensions.DescribeLocation(located.PageNumber, located.EndPageNumber, located.SheetName, located.StartRow, located.EndRow, located.StartLine, located.EndLine));
|
return new(texts[attachment], RetrievalContextExtensions.DescribeLocation(located.PageNumber, located.EndPageNumber, located.SheetName, located.StartRow, located.EndRow, located.StartLine, located.EndLine));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -70,7 +70,7 @@ public sealed class SemanticSearchTool(SettingsManager settingsManager, DataSour
|
|||||||
/// A chunk is as long as the embedding model takes at once, by default 8,192 tokens, so a
|
/// A chunk is as long as the embedding model takes at once, by default 8,192 tokens, so a
|
||||||
/// single passage may already fill tens of thousands of characters. A passage which does not
|
/// single passage may already fill tens of thousands of characters. A passage which does not
|
||||||
/// fit starts the next page, see SearchAsync. Only a passage longer than a whole page is
|
/// fit starts the next page, see SearchAsync. Only a passage longer than a whole page is
|
||||||
/// shortened, and filtered again, see IRetrievalContextExtensions.ShortenToFitAsync. The limit
|
/// shortened, and filtered again, see RetrievalContextExtensions.ShortenToFitAsync. The limit
|
||||||
/// is the one a web search has by default, and it leaves room for about three searches within
|
/// is the one a web search has by default, and it leaves room for about three searches within
|
||||||
/// the budget of all tool results of an answer, see ToolSelectionRules.MAX_TOOL_RESULT_CHARACTERS:
|
/// the budget of all tool results of an answer, see ToolSelectionRules.MAX_TOOL_RESULT_CHARACTERS:
|
||||||
/// a question with several aspects gets one search per aspect.
|
/// a question with several aspects gets one search per aspect.
|
||||||
@@ -422,7 +422,7 @@ public sealed class SemanticSearchTool(SettingsManager settingsManager, DataSour
|
|||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// A passage longer than a whole page would hold up every passage after it, so it is shortened
|
/// A passage longer than a whole page would hold up every passage after it, so it is shortened
|
||||||
/// to fill a page of its own, see IRetrievalContextExtensions.ShortenToFitAsync.
|
/// to fill a page of its own, see RetrievalContextExtensions.ShortenToFitAsync.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="request">The search to run.</param>
|
/// <param name="request">The search to run.</param>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public sealed class DirectI18NGetTextAnalyzer : DiagnosticAnalyzer
|
|||||||
private static bool IsLangExtensions(INamedTypeSymbol? type)
|
private static bool IsLangExtensions(INamedTypeSymbol? type)
|
||||||
{
|
{
|
||||||
var staticClass = type is { IsExtension: true } ? type.ContainingType : type;
|
var staticClass = type is { IsExtension: true } ? type.ContainingType : type;
|
||||||
return staticClass?.Name == "ILangExtensions" && staticClass.ContainingNamespace.ToDisplayString() == "AIStudio.Tools.PluginSystem";
|
return staticClass?.Name == "LangExtensions" &&staticClass.ContainingNamespace.ToDisplayString() == "AIStudio.Tools.PluginSystem";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsCollectorCompatibleWrapper(IMethodSymbol? containingMethod, IInvocationOperation invocation)
|
private static bool IsCollectorCompatibleWrapper(IMethodSymbol? containingMethod, IInvocationOperation invocation)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public sealed class DirectI18NGetTextAnalyzerTests
|
|||||||
{
|
{
|
||||||
private const string CLASSIC_FORM =
|
private const string CLASSIC_FORM =
|
||||||
"""
|
"""
|
||||||
public static class ILangExtensions
|
public static class LangExtensions
|
||||||
{
|
{
|
||||||
public static string GetText(this ILang lang, string fallbackEN) => fallbackEN;
|
public static string GetText(this ILang lang, string fallbackEN) => fallbackEN;
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ public sealed class DirectI18NGetTextAnalyzerTests
|
|||||||
|
|
||||||
private const string EXTENSION_BLOCK_FORM =
|
private const string EXTENSION_BLOCK_FORM =
|
||||||
"""
|
"""
|
||||||
public static class ILangExtensions
|
public static class LangExtensions
|
||||||
{
|
{
|
||||||
extension(ILang lang)
|
extension(ILang lang)
|
||||||
{
|
{
|
||||||
@@ -52,11 +52,11 @@ public sealed class DirectI18NGetTextAnalyzerTests
|
|||||||
|
|
||||||
[TestCase(CLASSIC_FORM, """public string Describe() => this.GetText("Hello");""", TestName = "A classic extension method called from another method")]
|
[TestCase(CLASSIC_FORM, """public string Describe() => this.GetText("Hello");""", TestName = "A classic extension method called from another method")]
|
||||||
[TestCase(CLASSIC_FORM, """public string T(string fallbackEN) => this.GetText("Hello");""", TestName = "A classic extension method called by a wrapper with a text of its own")]
|
[TestCase(CLASSIC_FORM, """public string T(string fallbackEN) => this.GetText("Hello");""", TestName = "A classic extension method called by a wrapper with a text of its own")]
|
||||||
[TestCase(CLASSIC_FORM, """public string Describe() => ILangExtensions.GetText(this, "Hello");""", TestName = "A classic extension method called as a static method")]
|
[TestCase(CLASSIC_FORM, """public string Describe() => LangExtensions.GetText(this, "Hello");""", TestName = "A classic extension method called as a static method")]
|
||||||
[TestCase(EXTENSION_BLOCK_FORM, """public string Describe() => this.GetText("Hello");""", TestName = "The member of an extension block called from another method")]
|
[TestCase(EXTENSION_BLOCK_FORM, """public string Describe() => this.GetText("Hello");""", TestName = "The member of an extension block called from another method")]
|
||||||
[TestCase(EXTENSION_BLOCK_FORM, """public string T(string fallbackEN) => this.GetText("Hello");""", TestName = "The member of an extension block called by a wrapper with a text of its own")]
|
[TestCase(EXTENSION_BLOCK_FORM, """public string T(string fallbackEN) => this.GetText("Hello");""", TestName = "The member of an extension block called by a wrapper with a text of its own")]
|
||||||
[TestCase(EXTENSION_BLOCK_FORM, """public string TA(string fallbackEN) => this.GetText("Hello");""", TestName = "The member of an extension block called by a TA wrapper with a text of its own")]
|
[TestCase(EXTENSION_BLOCK_FORM, """public string TA(string fallbackEN) => this.GetText("Hello");""", TestName = "The member of an extension block called by a TA wrapper with a text of its own")]
|
||||||
[TestCase(EXTENSION_BLOCK_FORM, """public string Describe() => ILangExtensions.GetText(this, "Hello");""", TestName = "The member of an extension block called as a static method")]
|
[TestCase(EXTENSION_BLOCK_FORM, """public string Describe() => LangExtensions.GetText(this, "Hello");""", TestName = "The member of an extension block called as a static method")]
|
||||||
public async Task ADirectLookupIsRefused(string form, string member)
|
public async Task ADirectLookupIsRefused(string form, string member)
|
||||||
{
|
{
|
||||||
var reported = await AnalyzeAsync(form, member);
|
var reported = await AnalyzeAsync(form, member);
|
||||||
@@ -99,7 +99,7 @@ public sealed class DirectI18NGetTextAnalyzerTests
|
|||||||
private static async Task<IReadOnlyList<Diagnostic>> AnalyzeAsync(string form, string member)
|
private static async Task<IReadOnlyList<Diagnostic>> AnalyzeAsync(string form, string member)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// The snippet declares its own ILang and ILangExtensions where the analyzer looks for them. They take
|
// The snippet declares its own ILang and LangExtensions where the analyzer looks for them. They take
|
||||||
// the place of those of the app, which the compilation references as well.
|
// the place of those of the app, which the compilation references as well.
|
||||||
//
|
//
|
||||||
var source =
|
var source =
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public sealed class BflImageMaterialTests
|
|||||||
Assert.That(await File.ReadAllBytesAsync(copy), Is.EqualTo(Convert.FromBase64String(FakeImageRuntime.IMAGE_BASE64)));
|
Assert.That(await File.ReadAllBytesAsync(copy), Is.EqualTo(Convert.FromBase64String(FakeImageRuntime.IMAGE_BASE64)));
|
||||||
Assert.That(copy, Does.StartWith(Path.Combine(this.dataDirectory, BeyondFactsLabStore.ROOT_DIRECTORY_NAME)), "The material must not depend on the file of the person.");
|
Assert.That(copy, Does.StartWith(Path.Combine(this.dataDirectory, BeyondFactsLabStore.ROOT_DIRECTORY_NAME)), "The material must not depend on the file of the person.");
|
||||||
Assert.That(this.runtime.RequestedPaths, Is.EqualTo(new[] { poster }));
|
Assert.That(this.runtime.RequestedPaths, Is.EqualTo(new[] { poster }));
|
||||||
Assert.That(this.runtime.RequestedBudgets, Is.EqualTo(new[] { IImageSourceExtensions.MAX_IMAGE_SIZE_BYTES }), "The copy must be as large as any provider takes.");
|
Assert.That(this.runtime.RequestedBudgets, Is.EqualTo(new[] { ImageSourceExtensions.MAX_IMAGE_SIZE_BYTES }), "The copy must be as large as any provider takes.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ namespace AIStudio.Tests.Chat;
|
|||||||
/// way the one can run into the other -- an open code fence above all. A document has no such seam.
|
/// way the one can run into the other -- an open code fence above all. A document has no such seam.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public sealed class IContentExtensionsTests
|
public sealed class ContentExtensionsTests
|
||||||
{
|
{
|
||||||
private static readonly Source TOOL_SOURCE = new("Search result", "https://example.org/search", SourceOrigin.TOOL);
|
private static readonly Source TOOL_SOURCE = new("Search result", "https://example.org/search", SourceOrigin.TOOL);
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ public sealed class ImageSizeLimitTests
|
|||||||
using (Assert.EnterMultipleScope())
|
using (Assert.EnterMultipleScope())
|
||||||
{
|
{
|
||||||
Assert.That(LLMProviders.ANTHROPIC.MaxImageSizeBytes, Is.EqualTo(3_932_160));
|
Assert.That(LLMProviders.ANTHROPIC.MaxImageSizeBytes, Is.EqualTo(3_932_160));
|
||||||
Assert.That(IImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.ANTHROPIC)), Is.EqualTo(3_932_160));
|
Assert.That(ImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.ANTHROPIC)), Is.EqualTo(3_932_160));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ public sealed class ImageSizeLimitTests
|
|||||||
using (Assert.EnterMultipleScope())
|
using (Assert.EnterMultipleScope())
|
||||||
{
|
{
|
||||||
Assert.That(LLMProviders.OPEN_AI.MaxImageSizeBytes, Is.Null, "Nobody stated a limit, and no number stands in for that.");
|
Assert.That(LLMProviders.OPEN_AI.MaxImageSizeBytes, Is.Null, "Nobody stated a limit, and no number stands in for that.");
|
||||||
Assert.That(IImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.OPEN_AI)), Is.EqualTo(IImageSourceExtensions.MAX_IMAGE_SIZE_BYTES));
|
Assert.That(ImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.OPEN_AI)), Is.EqualTo(ImageSourceExtensions.MAX_IMAGE_SIZE_BYTES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ public sealed class ImageSizeLimitTests
|
|||||||
using (Assert.EnterMultipleScope())
|
using (Assert.EnterMultipleScope())
|
||||||
{
|
{
|
||||||
Assert.That(Host.LLMMAN.MaxImageSizeBytes, Is.EqualTo(1_048_576));
|
Assert.That(Host.LLMMAN.MaxImageSizeBytes, Is.EqualTo(1_048_576));
|
||||||
Assert.That(IImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.SELF_HOSTED, Host.LLMMAN)), Is.EqualTo(1_048_576));
|
Assert.That(ImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.SELF_HOSTED, Host.LLMMAN)), Is.EqualTo(1_048_576));
|
||||||
Assert.That(IImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.SELF_HOSTED, Host.OLLAMA)), Is.EqualTo(IImageSourceExtensions.MAX_IMAGE_SIZE_BYTES), "Ollama states no limit we know of.");
|
Assert.That(ImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(LLMProviders.SELF_HOSTED, Host.OLLAMA)), Is.EqualTo(ImageSourceExtensions.MAX_IMAGE_SIZE_BYTES), "Ollama states no limit we know of.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ public sealed class ImageSizeLimitTests
|
|||||||
// to a cloud provider in the dialog:
|
// to a cloud provider in the dialog:
|
||||||
var cloudProviderWithAnOldHost = ProviderOf(LLMProviders.OPEN_AI, Host.LLMMAN);
|
var cloudProviderWithAnOldHost = ProviderOf(LLMProviders.OPEN_AI, Host.LLMMAN);
|
||||||
|
|
||||||
Assert.That(IImageSourceExtensions.MaxImageSizeBytesFor(cloudProviderWithAnOldHost), Is.EqualTo(IImageSourceExtensions.MAX_IMAGE_SIZE_BYTES));
|
Assert.That(ImageSourceExtensions.MaxImageSizeBytesFor(cloudProviderWithAnOldHost), Is.EqualTo(ImageSourceExtensions.MAX_IMAGE_SIZE_BYTES));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -62,7 +62,7 @@ public sealed class ImageSizeLimitTests
|
|||||||
{
|
{
|
||||||
foreach (var llmProvider in Enum.GetValues<LLMProviders>())
|
foreach (var llmProvider in Enum.GetValues<LLMProviders>())
|
||||||
foreach (var host in Enum.GetValues<Host>())
|
foreach (var host in Enum.GetValues<Host>())
|
||||||
Assert.That(IImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(llmProvider, host)), Is.LessThanOrEqualTo(IImageSourceExtensions.MAX_IMAGE_SIZE_BYTES), $"{llmProvider} with {host}");
|
Assert.That(ImageSourceExtensions.MaxImageSizeBytesFor(ProviderOf(llmProvider, host)), Is.LessThanOrEqualTo(ImageSourceExtensions.MAX_IMAGE_SIZE_BYTES), $"{llmProvider} with {host}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public sealed class ModelImageServiceTests
|
|||||||
|
|
||||||
using (Assert.EnterMultipleScope())
|
using (Assert.EnterMultipleScope())
|
||||||
{
|
{
|
||||||
Assert.That(this.runtime.RequestedBudgets, Is.EqualTo(new[] { 3_932_160, IImageSourceExtensions.MAX_IMAGE_SIZE_BYTES }));
|
Assert.That(this.runtime.RequestedBudgets, Is.EqualTo(new[] { 3_932_160, ImageSourceExtensions.MAX_IMAGE_SIZE_BYTES }));
|
||||||
Assert.That(this.runtime.RequestedPaths, Is.All.EqualTo(new FileInfo(this.imagePath).FullName));
|
Assert.That(this.runtime.RequestedPaths, Is.All.EqualTo(new FileInfo(this.imagePath).FullName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,8 +144,8 @@ public sealed class RetrievalContextDescriptionTests
|
|||||||
};
|
};
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
IRetrievalContextExtensions.AppendContextDescription(builder, image);
|
RetrievalContextExtensions.AppendContextDescription(builder, image);
|
||||||
IRetrievalContextExtensions.AppendImageMatch(builder);
|
RetrievalContextExtensions.AppendImageMatch(builder);
|
||||||
var description = builder.ToString();
|
var description = builder.ToString();
|
||||||
|
|
||||||
using (Assert.EnterMultipleScope())
|
using (Assert.EnterMultipleScope())
|
||||||
@@ -161,7 +161,7 @@ public sealed class RetrievalContextDescriptionTests
|
|||||||
private static string Describe(IRetrievalContext retrievalContext)
|
private static string Describe(IRetrievalContext retrievalContext)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
IRetrievalContextExtensions.AppendContextDescription(builder, retrievalContext);
|
RetrievalContextExtensions.AppendContextDescription(builder, retrievalContext);
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ public sealed class RetrievalContextPreparationTests
|
|||||||
|
|
||||||
var expected = new StringBuilder();
|
var expected = new StringBuilder();
|
||||||
expected.AppendLine("# Retrieval context");
|
expected.AppendLine("# Retrieval context");
|
||||||
IRetrievalContextExtensions.AppendContextDescription(expected, image);
|
RetrievalContextExtensions.AppendContextDescription(expected, image);
|
||||||
IRetrievalContextExtensions.AppendImageMatch(expected);
|
RetrievalContextExtensions.AppendImageMatch(expected);
|
||||||
expected.AppendLine();
|
expected.AppendLine();
|
||||||
|
|
||||||
using (Assert.EnterMultipleScope())
|
using (Assert.EnterMultipleScope())
|
||||||
|
|||||||
@@ -22,37 +22,37 @@ public sealed class RetrievalContextShorteningTests
|
|||||||
{
|
{
|
||||||
const string TEXT = "first line\nsecond line";
|
const string TEXT = "first line\nsecond line";
|
||||||
|
|
||||||
Assert.That(IRetrievalContextExtensions.CutAtLineEnd(TEXT, TEXT.Length), Is.SameAs(TEXT));
|
Assert.That(RetrievalContextExtensions.CutAtLineEnd(TEXT, TEXT.Length), Is.SameAs(TEXT));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ACutEndsAtTheLastLineEndWhichFits()
|
public void ACutEndsAtTheLastLineEndWhichFits()
|
||||||
{
|
{
|
||||||
Assert.That(IRetrievalContextExtensions.CutAtLineEnd("first\nsecond\nthird", 15), Is.EqualTo("first\nsecond"));
|
Assert.That(RetrievalContextExtensions.CutAtLineEnd("first\nsecond\nthird", 15), Is.EqualTo("first\nsecond"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ACutKeepsNoHalfOfAWindowsLineEnd()
|
public void ACutKeepsNoHalfOfAWindowsLineEnd()
|
||||||
{
|
{
|
||||||
Assert.That(IRetrievalContextExtensions.CutAtLineEnd("first\r\nsecond\r\nthird", 17), Is.EqualTo("first\r\nsecond"));
|
Assert.That(RetrievalContextExtensions.CutAtLineEnd("first\r\nsecond\r\nthird", 17), Is.EqualTo("first\r\nsecond"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ACutGivesUpAtMostHalfOfWhatFitsForALineEnd()
|
public void ACutGivesUpAtMostHalfOfWhatFitsForALineEnd()
|
||||||
{
|
{
|
||||||
Assert.That(IRetrievalContextExtensions.CutAtLineEnd("a\nbcdefghijkl", 10), Is.EqualTo("a\nbcdefghi"), "With its only line end right at the start, the text would lose nearly everything.");
|
Assert.That(RetrievalContextExtensions.CutAtLineEnd("a\nbcdefghijkl", 10), Is.EqualTo("a\nbcdefghi"), "With its only line end right at the start, the text would lose nearly everything.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ACutNeverSplitsASurrogatePair()
|
public void ACutNeverSplitsASurrogatePair()
|
||||||
{
|
{
|
||||||
Assert.That(IRetrievalContextExtensions.CutAtLineEnd("ab😀cd", 3), Is.EqualTo("ab"));
|
Assert.That(RetrievalContextExtensions.CutAtLineEnd("ab😀cd", 3), Is.EqualTo("ab"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void NothingIsLeftOfATextWithoutRoom()
|
public void NothingIsLeftOfATextWithoutRoom()
|
||||||
{
|
{
|
||||||
Assert.That(IRetrievalContextExtensions.CutAtLineEnd("text", 0), Is.Empty);
|
Assert.That(RetrievalContextExtensions.CutAtLineEnd("text", 0), Is.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ An ERI data source whose server does not answer the check of `DataSourceService`
|
|||||||
|
|
||||||
Every check of an ERI data source signs in to its server, and one message checks several times: when the tool is offered, before every search, and with every message of the classic process. `DataSourceService` therefore keeps a server's answer for one minute in an `ERISecurityCheckCache` and joins a check which is still running, so that a server which limits sign-ins does not start refusing. A server which did not answer is asked again after 15 seconds, and a changed configuration of the data source asks anew right away. Expired answers are dropped whenever a check starts. The minute holds for an answer which lets the data reach any provider as well, on purpose: when an operator opened a server by mistake and corrects it, every AI Studio follows within that minute, and until then, a chat with a cloud provider may still search the server. The cache lives only as long as the app runs, so no answer sticks for longer.
|
Every check of an ERI data source signs in to its server, and one message checks several times: when the tool is offered, before every search, and with every message of the classic process. `DataSourceService` therefore keeps a server's answer for one minute in an `ERISecurityCheckCache` and joins a check which is still running, so that a server which limits sign-ins does not start refusing. A server which did not answer is asked again after 15 seconds, and a changed configuration of the data source asks anew right away. Expired answers are dropped whenever a check starts. The minute holds for an answer which lets the data reach any provider as well, on purpose: when an operator opened a server by mistake and corrects it, every AI Studio follows within that minute, and until then, a chat with a cloud provider may still search the server. The cache lives only as long as the app runs, so no answer sticks for longer.
|
||||||
|
|
||||||
The data sources are checked again before each search, since rounds may have passed since they were offered, and then searched in parallel. A data source which fails is reported as not searched rather than left out, so that the model does not take its silence for finding nothing. Every passage goes through the same filter and into the same shape as with the classic RAG process, `IRetrievalContextExtensions.PrepareForModelAsync`: all passages of a search in one filter request, within one `PromptInjectionGuardService.BeginAction` per search, so that the user hears about what was filtered once per search, as soon as it is done. A page of the search holds passages up to 100,000 characters, measured after the filter, which can make a passage longer. A data source returns its matches in pages of its own, as many as it is set to return, see `RetrievalPaging`; each of them is cut into one or more pages of the search, numbered on across the pages of the data source, see `SemanticSearchTool.SearchAsync`. Where everything fits, both are the same. `has_more` is exact: when a page ends with a page of the data source which might have more, the search looks whether a further one holds any passage. A passage longer than a whole page is shortened, its surrounding content first, and filtered again, see `IRetrievalContextExtensions.ShortenToFitAsync`; its label tells the model, and the user is shown the shorter passage. A search of several data sources shares the first page among them. The data sources take turns: first the best passage of each, then the second best of each, and a data source stops at its first passage which no longer fits. Otherwise, the data source listed first would take the whole budget, or a shorter passage would take the place of a longer one above it. What does not fit is counted in the result, with a search of that data source alone, from page 1, as the way out; that search shows the passages read already once more. An image an ERI server returns is not passed on, in neither process: written as base64 text, it is nothing a model can look at, and it would take more room than all other passages together. The passage tells the model that an image matched and where it is, so that it can point the user to it. What an ERI server says its content is, its category, is passed on as "Source category". The passages become sources through `IRetrievalContext.ToSources()`, as with the classic process, and only the data sources whose passages reached the model raise the requirements of the chat. The passages which reached the model are also kept with the answer, through `ToolExecutionResult.Passages` and `ContentText.AddSources`: the result of the call is not saved, but the user can still read what the answer rests on after the chat was reloaded. The title of a source names the pages of all its passages, see `SourcePassageExtensions.NamePassagesInTitles`.
|
The data sources are checked again before each search, since rounds may have passed since they were offered, and then searched in parallel. A data source which fails is reported as not searched rather than left out, so that the model does not take its silence for finding nothing. Every passage goes through the same filter and into the same shape as with the classic RAG process, `RetrievalContextExtensions.PrepareForModelAsync`: all passages of a search in one filter request, within one `PromptInjectionGuardService.BeginAction` per search, so that the user hears about what was filtered once per search, as soon as it is done. A page of the search holds passages up to 100,000 characters, measured after the filter, which can make a passage longer. A data source returns its matches in pages of its own, as many as it is set to return, see `RetrievalPaging`; each of them is cut into one or more pages of the search, numbered on across the pages of the data source, see `SemanticSearchTool.SearchAsync`. Where everything fits, both are the same. `has_more` is exact: when a page ends with a page of the data source which might have more, the search looks whether a further one holds any passage. A passage longer than a whole page is shortened, its surrounding content first, and filtered again, see `RetrievalContextExtensions.ShortenToFitAsync`; its label tells the model, and the user is shown the shorter passage. A search of several data sources shares the first page among them. The data sources take turns: first the best passage of each, then the second best of each, and a data source stops at its first passage which no longer fits. Otherwise, the data source listed first would take the whole budget, or a shorter passage would take the place of a longer one above it. What does not fit is counted in the result, with a search of that data source alone, from page 1, as the way out; that search shows the passages read already once more. An image an ERI server returns is not passed on, in neither process: written as base64 text, it is nothing a model can look at, and it would take more room than all other passages together. The passage tells the model that an image matched and where it is, so that it can point the user to it. What an ERI server says its content is, its category, is passed on as "Source category". The passages become sources through `IRetrievalContext.ToSources()`, as with the classic process, and only the data sources whose passages reached the model raise the requirements of the chat. The passages which reached the model are also kept with the answer, through `ToolExecutionResult.Passages` and `ContentText.AddSources`: the result of the call is not saved, but the user can still read what the answer rests on after the chat was reloaded. The title of a source names the pages of all its passages, see `SourcePassageExtensions.NamePassagesInTitles`.
|
||||||
|
|
||||||
The classic process sends its passages along with every message, in the system prompt, and a provider refuses a message which exceeds the context window of the model. Its passages therefore get a budget, `PassageBudget`: half of the context window when it is known, `ModelProfile.Context`, counted in tokens through `ConversationTokenCounter` with the tokenizer of the provider, or the built-in one; otherwise 100,000 characters, as many as one page of `semantic_search`. When the tokenizer does not answer, characters count against the same limit, which leaves the passages less room rather than more. The budget applies to what the validation agent left, measured after the filter, each passage with the longest header it can get. The data sources take turns as in a search of several data sources, but a passage which does not fit is skipped, and the next ones still get their chance: there is no further page which could bring it later. A passage longer than the whole budget is shortened and filtered again, as in `semantic_search`. The model reads the passages grouped by data source, followed by how many were left out, and the user gets a warning with every answer which had to do without some, naming the ways out: Semantic Search, a lower token limit, or fewer data sources. Only the passages the model received are listed with the answer.
|
The classic process sends its passages along with every message, in the system prompt, and a provider refuses a message which exceeds the context window of the model. Its passages therefore get a budget, `PassageBudget`: half of the context window when it is known, `ModelProfile.Context`, counted in tokens through `ConversationTokenCounter` with the tokenizer of the provider, or the built-in one; otherwise 100,000 characters, as many as one page of `semantic_search`. When the tokenizer does not answer, characters count against the same limit, which leaves the passages less room rather than more. The budget applies to what the validation agent left, measured after the filter, each passage with the longest header it can get. The data sources take turns as in a search of several data sources, but a passage which does not fit is skipped, and the next ones still get their chance: there is no further page which could bring it later. A passage longer than the whole budget is shortened and filtered again, as in `semantic_search`. The model reads the passages grouped by data source, followed by how many were left out, and the user gets a warning with every answer which had to do without some, naming the ways out: Semantic Search, a lower token limit, or fewer data sources. Only the passages the model received are listed with the answer.
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user