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
|
// 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.
|
// 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)
|
if (generation != this.loadAndApplyFiltersGeneration)
|
||||||
return;
|
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.
|
// 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()!;
|
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;
|
var selectedDataSources = dataSources.SelectedDataSources;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -39,9 +39,10 @@ public sealed class DataSourceService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="selectedLLMProvider">The selected LLM provider.</param>
|
/// <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="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>
|
/// <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>
|
/// <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
|
// 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 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)));
|
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||||
return await this.GetDataSources(usingTrustedProvider, participatingProviders, previousSelectedDataSources);
|
return await this.GetDataSources(usingTrustedProvider, participatingProviders, previousSelectedDataSources);
|
||||||
}
|
}
|
||||||
@ -67,9 +68,10 @@ public sealed class DataSourceService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="selectedLLMProvider">The selected LLM provider.</param>
|
/// <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="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>
|
/// <param name="requestedDataSources">The data sources to check.</param>
|
||||||
/// <returns>The requested data sources that are allowed for the provider.</returns>
|
/// <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)
|
if (selectedLLMProvider == Settings.Provider.NONE)
|
||||||
{
|
{
|
||||||
@ -78,7 +80,7 @@ public sealed class DataSourceService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var usingTrustedProvider = selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager);
|
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)));
|
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||||
var allowedDataSources = await this.GetAllowedDataSources(usingTrustedProvider, participatingProviders, requestedDataSources);
|
var allowedDataSources = await this.GetAllowedDataSources(usingTrustedProvider, participatingProviders, requestedDataSources);
|
||||||
|
|
||||||
@ -98,9 +100,10 @@ public sealed class DataSourceService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="selectedLLMProvider">The selected LLM provider.</param>
|
/// <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="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>
|
/// <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>
|
/// <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
|
// 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 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)));
|
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||||
return await this.GetDataSources(usingTrustedProvider, participatingProviders, previousSelectedDataSources);
|
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 };
|
var providers = new List<ParticipatingProvider> { currentProvider };
|
||||||
|
var retrievalContextValidationEnabled = this.settingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation;
|
||||||
if (dataSourceOptions.AutomaticDataSourceSelection)
|
foreach (var (component, role) in GetParticipatingAgents(dataSourceOptions, retrievalMode, retrievalContextValidationEnabled))
|
||||||
this.AddAgentProvider(providers, Components.AGENT_DATA_SOURCE_SELECTION, currentProviderId, "data source selection agent");
|
this.AddAgentProvider(providers, component, currentProviderId, role);
|
||||||
|
|
||||||
if (dataSourceOptions.AutomaticValidation && this.settingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
|
|
||||||
this.AddAgentProvider(providers, Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION, currentProviderId, "retrieval context validation agent");
|
|
||||||
|
|
||||||
return providers;
|
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)
|
private void AddAgentProvider(List<ParticipatingProvider> providers, Components component, string currentProviderId, string role)
|
||||||
{
|
{
|
||||||
var provider = this.settingsManager.GetPreselectedProvider(component, currentProviderId, true);
|
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
|
// decide which agent providers take part, and an agent with too little confidence makes
|
||||||
// a data source unavailable.
|
// a data source unavailable.
|
||||||
//
|
//
|
||||||
availableDataSources = await dataSourceService.GetAllowedDataSources(provider, chosenOptions, requestedDataSources);
|
availableDataSources = await dataSourceService.GetAllowedDataSources(provider, chosenOptions, DataSourceRetrievalMode.EVERY_MESSAGE, requestedDataSources);
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
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