2025-02-18 11:24:43 +01:00
using System.Text ;
2025-02-22 20:51:06 +01:00
using AIStudio.Agents ;
2025-02-18 11:24:43 +01:00
using AIStudio.Chat ;
using AIStudio.Provider ;
2025-02-22 20:51:06 +01:00
using AIStudio.Settings ;
2025-05-04 14:59:30 +02:00
using AIStudio.Tools.PluginSystem ;
2025-02-18 11:24:43 +01:00
namespace AIStudio.Tools.RAG.AugmentationProcesses ;
public sealed class AugmentationOne : IAugmentationProcess
{
2025-09-25 19:47:18 +02:00
private static readonly ILogger < AugmentationOne > LOGGER = Program . LOGGER_FACTORY . CreateLogger < AugmentationOne >();
2025-05-04 14:59:30 +02:00
private static string TB ( string fallbackEN ) => I18N . I . T ( fallbackEN , typeof ( AugmentationOne ). Namespace , nameof ( AugmentationOne ));
2025-02-18 11:24:43 +01:00
#region Implementation of IAugmentationProcess
/// <inheritdoc />
public string TechnicalName => "AugmentationOne" ;
/// <inheritdoc />
2025-05-04 14:59:30 +02:00
public string UIName => TB ( "Standard augmentation process" );
2025-02-18 11:24:43 +01:00
/// <inheritdoc />
2025-05-04 14:59:30 +02:00
public string Description => TB ( "This is the standard augmentation process, which uses all retrieval contexts to augment the chat thread." );
2025-02-18 11:24:43 +01:00
/// <inheritdoc />
2025-09-25 19:47:18 +02:00
public async Task < ChatThread > ProcessAsync ( IProvider provider , IContent lastUserPrompt , ChatThread chatThread , IReadOnlyList < IRetrievalContext > retrievalContexts , CancellationToken token = default )
2025-02-18 11:24:43 +01:00
{
2025-02-22 20:51:06 +01:00
var settings = Program . SERVICE_PROVIDER . GetService < SettingsManager >()!;
2025-02-18 11:24:43 +01:00
if ( retrievalContexts . Count == 0 )
{
2025-09-25 19:47:18 +02:00
LOGGER . LogWarning ( "No retrieval contexts were issued. Skipping the augmentation process." );
2025-02-18 11:24:43 +01:00
return chatThread ;
}
2025-02-22 20:51:06 +01:00
2025-02-18 11:24:43 +01:00
var numTotalRetrievalContexts = retrievalContexts . Count ;
2025-02-22 20:51:06 +01:00
// Want the user to validate all retrieval contexts?
2025-02-23 15:05:29 +01:00
if ( settings . ConfigurationData . AgentRetrievalContextValidation . EnableRetrievalContextValidation && chatThread . DataSourceOptions . AutomaticValidation )
2025-02-22 20:51:06 +01:00
{
// Let's get the validation agent & set up its provider:
var validationAgent = Program . SERVICE_PROVIDER . GetService < AgentRetrievalContextValidation >()!;
2026-09-05 21:17:42 +02:00
if ( validationAgent . SetLLMProvider ( provider , chatThread . DataSecurity , chatThread . RequiredProviderConfidence ))
2026-08-05 15:05:17 +02:00
{
2026-08-14 12:03:52 +02:00
try
{
// Let's validate all retrieval contexts:
var validationResults = await validationAgent . ValidateRetrievalContextsAsync ( lastUserPrompt , chatThread , retrievalContexts , token );
if ( validationResults . Count == 0 )
LOGGER . LogWarning ( "Retrieval context validation returned no results. Continuing augmentation with all retrieved contexts." );
else
{
//
// Now, filter the retrieval contexts to the most relevant ones:
//
var targetWindow = validationResults . DetermineTargetWindow ( TargetWindowStrategy . TOP10_BETTER_THAN_GUESSING );
var threshold = validationResults . GetConfidenceThreshold ( targetWindow );
2026-08-05 15:05:17 +02:00
2026-08-14 12:03:52 +02:00
// Filter the retrieval contexts:
retrievalContexts = validationResults . Where ( x => x . RetrievalContext is not null && x . Confidence >= threshold ). Select ( x => x . RetrievalContext !). ToList ();
}
}
catch ( OperationCanceledException ) when ( token . IsCancellationRequested )
{
throw ;
}
catch ( Exception exception )
{
LOGGER . LogError ( exception , "Retrieval context validation failed. Continuing augmentation with all retrieved contexts." );
}
2026-08-05 15:05:17 +02:00
}
else
2026-08-14 12:03:52 +02:00
LOGGER . LogWarning ( "Skipping retrieval context validation because no sufficiently trusted validation agent provider is available. Continuing augmentation with all retrieved contexts." );
2025-02-22 20:51:06 +01:00
}
2026-08-14 12:03:52 +02:00
LOGGER . LogInformation ( $"Starting the augmentation process over {retrievalContexts.Count:###,###,###,###} of {numTotalRetrievalContexts:###,###,###,###} retrieved contexts." );
2025-02-18 11:24:43 +01:00
//
// We build a huge prompt from all retrieval contexts:
//
var sb = new StringBuilder ();
sb . AppendLine ( "The following useful information will help you in processing the user prompt:" );
sb . AppendLine ();
2025-02-22 20:51:06 +01:00
// Let's convert all retrieval contexts to Markdown:
await retrievalContexts . AsMarkdown ( sb , token );
2025-02-18 11:24:43 +01:00
2025-03-08 13:56:38 +01:00
// Add the augmented data to the chat thread:
chatThread . AugmentedData = sb . ToString ();
2025-02-18 11:24:43 +01:00
return chatThread ;
}
#endregion
}