mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-09-27 02:33:38 +00:00
Count the agents only where the classic RAG process runs them
This commit is contained in:
parent
abb4a41a71
commit
a75ffc54a6
@ -246,7 +246,7 @@ public partial class DataSourceSelection : MSGComponentBase
|
||||
// that field holds what was usable the last time we looked, so a source filtered out once
|
||||
// would never come back, while the RAG process keeps reading it from the preselection.
|
||||
//
|
||||
var sources = await this.DataSourceService.GetDataSources(this.LLMProvider, this.DataSourceOptions, this.GetDataSourcesFromConfiguredIds());
|
||||
var sources = await this.DataSourceService.GetDataSources(this.LLMProvider, this.DataSourceOptions, DataSourceRetrievalMode.EVERY_MESSAGE, this.GetDataSourcesFromConfiguredIds());
|
||||
if (generation != this.loadAndApplyFiltersGeneration)
|
||||
return;
|
||||
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
/// <summary>
|
||||
/// How the data sources of a chat are searched.
|
||||
/// </summary>
|
||||
public enum DataSourceRetrievalMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The model searches the data sources itself, through the tool semantic_search, whenever a
|
||||
/// question calls for it. No agent takes part: the chat model picks the data sources and
|
||||
/// judges what it found.
|
||||
/// </summary>
|
||||
SEMANTIC_SEARCH,
|
||||
|
||||
/// <summary>
|
||||
/// AI Studio searches the data sources with every message, before the model answers. This is
|
||||
/// the classic RAG process, with its agents for selecting data sources and for validating what
|
||||
/// was found.
|
||||
/// </summary>
|
||||
EVERY_MESSAGE,
|
||||
}
|
||||
@ -94,7 +94,7 @@ public sealed class AISrcSelWithRetCtxVal : IRagProcess
|
||||
// data sources changed its security requirements.
|
||||
//
|
||||
List<IDataSource> preselectedDataSources = chatThread.DataSourceOptions.PreselectedDataSourceIds.Select(id => settings.ConfigurationData.DataSources.FirstOrDefault(ds => ds.Id == id)).Where(ds => ds is not null).ToList()!;
|
||||
var dataSources = await dataSourceService.GetDataSources(provider, chatThread.DataSourceOptions, preselectedDataSources);
|
||||
var dataSources = await dataSourceService.GetDataSources(provider, chatThread.DataSourceOptions, DataSourceRetrievalMode.EVERY_MESSAGE, preselectedDataSources);
|
||||
var selectedDataSources = dataSources.SelectedDataSources;
|
||||
|
||||
//
|
||||
|
||||
@ -39,9 +39,10 @@ public sealed class DataSourceService
|
||||
/// </summary>
|
||||
/// <param name="selectedLLMProvider">The selected LLM provider.</param>
|
||||
/// <param name="dataSourceOptions">The active data source options, which determine which agent providers participate.</param>
|
||||
/// <param name="retrievalMode">How the data sources are searched in effect, which decides whether any agent participates at all.</param>
|
||||
/// <param name="previousSelectedDataSources">The data sources selected before.</param>
|
||||
/// <returns>The allowed data sources and the data sources selected before -- when they are still allowed.</returns>
|
||||
public async Task<AllowedSelectedDataSources> GetDataSources(AIStudio.Settings.Provider selectedLLMProvider, DataSourceOptions dataSourceOptions, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
public async Task<AllowedSelectedDataSources> GetDataSources(AIStudio.Settings.Provider selectedLLMProvider, DataSourceOptions dataSourceOptions, DataSourceRetrievalMode retrievalMode, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
{
|
||||
//
|
||||
// Case: Somehow the selected LLM provider was not set. The default provider
|
||||
@ -55,7 +56,7 @@ public sealed class DataSourceService
|
||||
}
|
||||
|
||||
var usingTrustedProvider = selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager);
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.Id, dataSourceOptions,
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.Id, dataSourceOptions, retrievalMode,
|
||||
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||
return await this.GetDataSources(usingTrustedProvider, participatingProviders, previousSelectedDataSources);
|
||||
}
|
||||
@ -67,9 +68,10 @@ public sealed class DataSourceService
|
||||
/// </summary>
|
||||
/// <param name="selectedLLMProvider">The selected LLM provider.</param>
|
||||
/// <param name="dataSourceOptions">The active data source options, which determine which agent providers participate.</param>
|
||||
/// <param name="retrievalMode">How the data sources are searched in effect, which decides whether any agent participates at all.</param>
|
||||
/// <param name="requestedDataSources">The data sources to check.</param>
|
||||
/// <returns>The requested data sources that are allowed for the provider.</returns>
|
||||
public async Task<IReadOnlyList<IDataSource>> GetAllowedDataSources(AIStudio.Settings.Provider selectedLLMProvider, DataSourceOptions dataSourceOptions, IReadOnlyCollection<IDataSource> requestedDataSources)
|
||||
public async Task<IReadOnlyList<IDataSource>> GetAllowedDataSources(AIStudio.Settings.Provider selectedLLMProvider, DataSourceOptions dataSourceOptions, DataSourceRetrievalMode retrievalMode, IReadOnlyCollection<IDataSource> requestedDataSources)
|
||||
{
|
||||
if (selectedLLMProvider == Settings.Provider.NONE)
|
||||
{
|
||||
@ -78,7 +80,7 @@ public sealed class DataSourceService
|
||||
}
|
||||
|
||||
var usingTrustedProvider = selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager);
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.Id, dataSourceOptions,
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.Id, dataSourceOptions, retrievalMode,
|
||||
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||
var allowedDataSources = await this.GetAllowedDataSources(usingTrustedProvider, participatingProviders, requestedDataSources);
|
||||
|
||||
@ -98,9 +100,10 @@ public sealed class DataSourceService
|
||||
/// </summary>
|
||||
/// <param name="selectedLLMProvider">The selected LLM provider.</param>
|
||||
/// <param name="dataSourceOptions">The active data source options, which determine which agent providers participate.</param>
|
||||
/// <param name="retrievalMode">How the data sources are searched in effect, which decides whether any agent participates at all.</param>
|
||||
/// <param name="previousSelectedDataSources">The data sources selected before.</param>
|
||||
/// <returns>The allowed data sources and the data sources selected before -- when they are still allowed.</returns>
|
||||
public async Task<AllowedSelectedDataSources> GetDataSources(IProvider selectedLLMProvider, DataSourceOptions dataSourceOptions, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
public async Task<AllowedSelectedDataSources> GetDataSources(IProvider selectedLLMProvider, DataSourceOptions dataSourceOptions, DataSourceRetrievalMode retrievalMode, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
{
|
||||
//
|
||||
// Case: Somehow the selected LLM provider was not set. The default provider
|
||||
@ -114,24 +117,49 @@ public sealed class DataSourceService
|
||||
}
|
||||
|
||||
var usingTrustedProvider = selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager);
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.ConfiguredProviderId, dataSourceOptions,
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.ConfiguredProviderId, dataSourceOptions, retrievalMode,
|
||||
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||
return await this.GetDataSources(usingTrustedProvider, participatingProviders, previousSelectedDataSources);
|
||||
}
|
||||
|
||||
private IReadOnlyList<ParticipatingProvider> GetParticipatingProviders(string currentProviderId, DataSourceOptions dataSourceOptions, ParticipatingProvider currentProvider)
|
||||
private IReadOnlyList<ParticipatingProvider> GetParticipatingProviders(string currentProviderId, DataSourceOptions dataSourceOptions, DataSourceRetrievalMode retrievalMode, ParticipatingProvider currentProvider)
|
||||
{
|
||||
var providers = new List<ParticipatingProvider> { currentProvider };
|
||||
|
||||
if (dataSourceOptions.AutomaticDataSourceSelection)
|
||||
this.AddAgentProvider(providers, Components.AGENT_DATA_SOURCE_SELECTION, currentProviderId, "data source selection agent");
|
||||
|
||||
if (dataSourceOptions.AutomaticValidation && this.settingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
|
||||
this.AddAgentProvider(providers, Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION, currentProviderId, "retrieval context validation agent");
|
||||
var retrievalContextValidationEnabled = this.settingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation;
|
||||
foreach (var (component, role) in GetParticipatingAgents(dataSourceOptions, retrievalMode, retrievalContextValidationEnabled))
|
||||
this.AddAgentProvider(providers, component, currentProviderId, role);
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Which agents get to see the data of the data sources, besides the chat provider.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only the classic RAG process runs agents. With Semantic Search, the chat model picks the
|
||||
/// data sources and judges what it found itself, so the data reaches no other provider.
|
||||
/// Counting the providers of the agents there would hold back data sources which the chat
|
||||
/// provider alone may use.
|
||||
/// </remarks>
|
||||
/// <param name="dataSourceOptions">The active data source options.</param>
|
||||
/// <param name="retrievalMode">How the data sources are searched in effect.</param>
|
||||
/// <param name="retrievalContextValidationEnabled">Whether the validation of retrieval contexts is enabled in the settings.</param>
|
||||
/// <returns>The component of each participating agent, together with its role for the log.</returns>
|
||||
internal static IReadOnlyList<(Components Component, string Role)> GetParticipatingAgents(DataSourceOptions dataSourceOptions, DataSourceRetrievalMode retrievalMode, bool retrievalContextValidationEnabled)
|
||||
{
|
||||
if (retrievalMode is DataSourceRetrievalMode.SEMANTIC_SEARCH)
|
||||
return [];
|
||||
|
||||
var agents = new List<(Components Component, string Role)>(2);
|
||||
if (dataSourceOptions.AutomaticDataSourceSelection)
|
||||
agents.Add((Components.AGENT_DATA_SOURCE_SELECTION, "data source selection agent"));
|
||||
|
||||
if (dataSourceOptions.AutomaticValidation && retrievalContextValidationEnabled)
|
||||
agents.Add((Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION, "retrieval context validation agent"));
|
||||
|
||||
return agents;
|
||||
}
|
||||
|
||||
private void AddAgentProvider(List<ParticipatingProvider> providers, Components component, string currentProviderId, string role)
|
||||
{
|
||||
var provider = this.settingsManager.GetPreselectedProvider(component, currentProviderId, true);
|
||||
|
||||
@ -274,7 +274,7 @@ public sealed class DirectChatService(SettingsManager settingsManager, DataSourc
|
||||
// decide which agent providers take part, and an agent with too little confidence makes
|
||||
// a data source unavailable.
|
||||
//
|
||||
availableDataSources = await dataSourceService.GetAllowedDataSources(provider, chosenOptions, requestedDataSources);
|
||||
availableDataSources = await dataSourceService.GetAllowedDataSources(provider, chosenOptions, DataSourceRetrievalMode.EVERY_MESSAGE, requestedDataSources);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
51
app/Tests/Tools/DataSourceParticipatingAgentsTests.cs
Normal file
51
app/Tests/Tools/DataSourceParticipatingAgentsTests.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
namespace AIStudio.Tests.Tools;
|
||||
|
||||
/// <summary>
|
||||
/// Checks which agents count as seeing the data of the data sources.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Every provider which sees the data must be trusted enough for every data source it sees. That
|
||||
/// cuts both ways: leaving out an agent which does run would send data to a provider trusted too
|
||||
/// little, while counting an agent which does not run holds back data sources for no reason. The
|
||||
/// classic RAG process runs its agents; Semantic Search runs none, since the chat model picks the
|
||||
/// data sources and judges the passages itself.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public sealed class DataSourceParticipatingAgentsTests
|
||||
{
|
||||
[Test]
|
||||
public void SemanticSearchRunsNoAgent()
|
||||
{
|
||||
var agents = DataSourceService.GetParticipatingAgents(Options(automaticSelection: true, automaticValidation: true), DataSourceRetrievalMode.SEMANTIC_SEARCH, retrievalContextValidationEnabled: true);
|
||||
|
||||
Assert.That(agents, Is.Empty, "The chat provider alone sees the data, so its trust alone decides which data sources it may search.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TheClassicRAGProcessCountsTheAgentsItRuns()
|
||||
{
|
||||
var agents = DataSourceService.GetParticipatingAgents(Options(automaticSelection: true, automaticValidation: true), DataSourceRetrievalMode.EVERY_MESSAGE, retrievalContextValidationEnabled: true);
|
||||
|
||||
Assert.That(agents.Select(agent => agent.Component), Is.EqualTo(new[] { AIStudio.Tools.Components.AGENT_DATA_SOURCE_SELECTION, AIStudio.Tools.Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TheClassicRAGProcessCountsNoAgentItDoesNotRun()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(DataSourceService.GetParticipatingAgents(Options(automaticSelection: false, automaticValidation: false), DataSourceRetrievalMode.EVERY_MESSAGE, retrievalContextValidationEnabled: true), Is.Empty);
|
||||
Assert.That(DataSourceService.GetParticipatingAgents(Options(automaticSelection: false, automaticValidation: true), DataSourceRetrievalMode.EVERY_MESSAGE, retrievalContextValidationEnabled: false), Is.Empty, "The validation of this chat is on, but the settings switch it off everywhere.");
|
||||
});
|
||||
}
|
||||
|
||||
private static DataSourceOptions Options(bool automaticSelection, bool automaticValidation) => new()
|
||||
{
|
||||
DisableDataSources = false,
|
||||
AutomaticDataSourceSelection = automaticSelection,
|
||||
AutomaticValidation = automaticValidation,
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user