mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-18 01:37:59 +00:00
refactored confidence levels and ensured checks work
This commit is contained in:
1 parent
786b106096
commit
88999d985c
44 files changed
+324
-335
No files matched your search
@@ -43,8 +43,8 @@ public sealed record EmbeddingStateFile(
|
||||
DateTimeOffset LastWriteUtc,
|
||||
DateTimeOffset EmbeddedAtUtc,
|
||||
int ChunkCount,
|
||||
string ComplianceLevel,
|
||||
int ComplianceLevelRank);
|
||||
string ConfidenceLevel,
|
||||
int ConfidenceLevelRank);
|
||||
|
||||
public sealed record EmbeddingStateChunk(
|
||||
string ChunkId,
|
||||
@@ -74,5 +74,5 @@ public sealed record EmbeddingStateSearchResult(
|
||||
DateTimeOffset LastWriteUtc,
|
||||
DateTimeOffset EmbeddedAtUtc,
|
||||
int ChunkCount,
|
||||
string ComplianceLevel,
|
||||
int ComplianceLevelRank);
|
||||
string ConfidenceLevel,
|
||||
int ConfidenceLevelRank);
|
||||
@@ -62,13 +62,13 @@ internal sealed class EmbeddingStateDbContext(DbContextOptions<EmbeddingStateDbC
|
||||
entity.Property(file => file.LastWriteUtc).HasColumnName("last_write_utc").HasConversion(utcDateTimeOffsetConverter).IsRequired();
|
||||
entity.Property(file => file.EmbeddedAtUtc).HasColumnName("embedded_at_utc").HasConversion(utcDateTimeOffsetConverter).IsRequired();
|
||||
entity.Property(file => file.ChunkCount).HasColumnName("chunk_count");
|
||||
entity.Property(file => file.ComplianceLevel).HasColumnName("compliance_level").IsRequired();
|
||||
entity.Property(file => file.ComplianceLevelRank).HasColumnName("compliance_level_rank");
|
||||
entity.Property(file => file.ConfidenceLevel).HasColumnName("confidence_level").IsRequired();
|
||||
entity.Property(file => file.ConfidenceLevelRank).HasColumnName("confidence_level_rank");
|
||||
|
||||
entity.HasIndex(file => file.DataSourceId).HasDatabaseName("idx_embedded_files_data_source");
|
||||
entity.HasIndex(file => file.AbsolutePath).HasDatabaseName("idx_embedded_files_absolute_path");
|
||||
entity.HasIndex(file => file.FileType).HasDatabaseName("idx_embedded_files_file_type");
|
||||
entity.HasIndex(file => file.ComplianceLevelRank).HasDatabaseName("idx_embedded_files_compliance");
|
||||
entity.HasIndex(file => file.ConfidenceLevelRank).HasDatabaseName("idx_embedded_files_confidence");
|
||||
entity.HasIndex(file => new { file.DataSourceId, file.AbsolutePath }).HasDatabaseName("idx_embedded_files_data_source_absolute_path").IsUnique();
|
||||
|
||||
entity
|
||||
@@ -165,9 +165,9 @@ internal sealed class EmbeddingStateFileEntity
|
||||
|
||||
public int ChunkCount { get; set; }
|
||||
|
||||
public string ComplianceLevel { get; set; } = string.Empty;
|
||||
public string ConfidenceLevel { get; set; } = string.Empty;
|
||||
|
||||
public int ComplianceLevelRank { get; set; }
|
||||
public int ConfidenceLevelRank { get; set; }
|
||||
|
||||
public EmbeddingStateDataSourceEntity? DataSource { get; set; }
|
||||
|
||||
@@ -233,9 +233,9 @@ internal sealed class EmbeddingStateSearchResultEntity
|
||||
|
||||
public int ChunkCount { get; set; }
|
||||
|
||||
public string ComplianceLevel { get; set; } = string.Empty;
|
||||
public string ConfidenceLevel { get; set; } = string.Empty;
|
||||
|
||||
public int ComplianceLevelRank { get; set; }
|
||||
public int ConfidenceLevelRank { get; set; }
|
||||
}
|
||||
|
||||
internal sealed class EmbeddingStateDateTimeOffsetConverter() : ValueConverter<DateTimeOffset, string>(
|
||||
|
||||
+4
-4
@@ -45,8 +45,8 @@ public partial class InitialRagIndex : Migration
|
||||
last_write_utc = table.Column<string>(type: "TEXT", nullable: false),
|
||||
embedded_at_utc = table.Column<string>(type: "TEXT", nullable: false),
|
||||
chunk_count = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
compliance_level = table.Column<string>(type: "TEXT", nullable: false),
|
||||
compliance_level_rank = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
confidence_level = table.Column<string>(type: "TEXT", nullable: false),
|
||||
confidence_level_rank = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -89,9 +89,9 @@ public partial class InitialRagIndex : Migration
|
||||
column: "absolute_path");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "idx_embedded_files_compliance",
|
||||
name: "idx_embedded_files_confidence",
|
||||
table: "embedded_files",
|
||||
column: "compliance_level_rank");
|
||||
column: "confidence_level_rank");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "idx_embedded_files_data_source",
|
||||
|
||||
+8
-8
@@ -77,14 +77,14 @@ partial class EmbeddingStateDbContextModelSnapshot : ModelSnapshot
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("chunk_count");
|
||||
|
||||
entity.Property<string>("ComplianceLevel")
|
||||
entity.Property<string>("ConfidenceLevel")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("compliance_level");
|
||||
.HasColumnName("confidence_level");
|
||||
|
||||
entity.Property<int>("ComplianceLevelRank")
|
||||
entity.Property<int>("ConfidenceLevelRank")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("compliance_level_rank");
|
||||
.HasColumnName("confidence_level_rank");
|
||||
|
||||
entity.Property<DateTimeOffset>("CreationUtc")
|
||||
.HasConversion(utcDateTimeOffsetConverter)
|
||||
@@ -135,8 +135,8 @@ partial class EmbeddingStateDbContextModelSnapshot : ModelSnapshot
|
||||
entity.HasIndex("AbsolutePath")
|
||||
.HasDatabaseName("idx_embedded_files_absolute_path");
|
||||
|
||||
entity.HasIndex("ComplianceLevelRank")
|
||||
.HasDatabaseName("idx_embedded_files_compliance");
|
||||
entity.HasIndex("ConfidenceLevelRank")
|
||||
.HasDatabaseName("idx_embedded_files_confidence");
|
||||
|
||||
entity.HasIndex("DataSourceId")
|
||||
.HasDatabaseName("idx_embedded_files_data_source");
|
||||
@@ -226,11 +226,11 @@ partial class EmbeddingStateDbContextModelSnapshot : ModelSnapshot
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
entity.Property<string>("ComplianceLevel")
|
||||
entity.Property<string>("ConfidenceLevel")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
entity.Property<int>("ComplianceLevelRank")
|
||||
entity.Property<int>("ConfidenceLevelRank")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
entity.Property<DateTimeOffset>("CreationUtc")
|
||||
|
||||
+6
-6
@@ -268,8 +268,8 @@ public sealed class SqliteEmbeddingStateClientImplementation(
|
||||
f.last_write_utc AS LastWriteUtc,
|
||||
c.embedded_at_utc AS EmbeddedAtUtc,
|
||||
f.chunk_count AS ChunkCount,
|
||||
f.compliance_level AS ComplianceLevel,
|
||||
f.compliance_level_rank AS ComplianceLevelRank
|
||||
f.confidence_level AS ConfidenceLevel,
|
||||
f.confidence_level_rank AS ConfidenceLevelRank
|
||||
FROM embedding_chunks_fts
|
||||
JOIN embedding_chunks c ON c.id = embedding_chunks_fts.rowid
|
||||
JOIN embedded_files f ON f.parent_file_id = c.parent_file_id
|
||||
@@ -359,8 +359,8 @@ public sealed class SqliteEmbeddingStateClientImplementation(
|
||||
fileEntity.LastWriteUtc = file.LastWriteUtc;
|
||||
fileEntity.EmbeddedAtUtc = file.EmbeddedAtUtc;
|
||||
fileEntity.ChunkCount = file.ChunkCount;
|
||||
fileEntity.ComplianceLevel = file.ComplianceLevel;
|
||||
fileEntity.ComplianceLevelRank = file.ComplianceLevelRank;
|
||||
fileEntity.ConfidenceLevel = file.ConfidenceLevel;
|
||||
fileEntity.ConfidenceLevelRank = file.ConfidenceLevelRank;
|
||||
}
|
||||
|
||||
private static void ApplyChunk(EmbeddingStateChunkEntity chunkEntity, EmbeddingStateChunk chunk)
|
||||
@@ -393,8 +393,8 @@ public sealed class SqliteEmbeddingStateClientImplementation(
|
||||
result.LastWriteUtc,
|
||||
result.EmbeddedAtUtc,
|
||||
result.ChunkCount,
|
||||
result.ComplianceLevel,
|
||||
result.ComplianceLevelRank);
|
||||
result.ConfidenceLevel,
|
||||
result.ConfidenceLevelRank);
|
||||
|
||||
private static string BuildFtsQuery(string query)
|
||||
{
|
||||
|
||||
@@ -20,5 +20,5 @@ public sealed record VectorSearchResult(
|
||||
string CreationUtc,
|
||||
string LastWriteUtc,
|
||||
string EmbeddedAtUtc,
|
||||
string ComplianceLevel,
|
||||
int ComplianceLevelRank);
|
||||
string ConfidenceLevel,
|
||||
int ConfidenceLevelRank);
|
||||
@@ -20,5 +20,5 @@ public sealed record VectorStoragePoint(
|
||||
DateTimeOffset CreationUtc,
|
||||
DateTimeOffset LastWriteUtc,
|
||||
DateTimeOffset EmbeddedAtUtc,
|
||||
string ComplianceLevel,
|
||||
int ComplianceLevelRank);
|
||||
string ConfidenceLevel,
|
||||
int ConfidenceLevelRank);
|
||||
@@ -43,7 +43,7 @@ public sealed class AugmentationOne : IAugmentationProcess
|
||||
{
|
||||
// Let's get the validation agent & set up its provider:
|
||||
var validationAgent = Program.SERVICE_PROVIDER.GetService<AgentRetrievalContextValidation>()!;
|
||||
if (validationAgent.SetLLMProvider(provider, chatThread.DataSecurity, chatThread.DataComplianceLevel))
|
||||
if (validationAgent.SetLLMProvider(provider, chatThread.DataSecurity, chatThread.DataConfidenceLevel))
|
||||
{
|
||||
// Let's validate all retrieval contexts:
|
||||
var validationResults = await validationAgent.ValidateRetrievalContextsAsync(lastUserPrompt, chatThread, retrievalContexts, token);
|
||||
@@ -58,7 +58,7 @@ public sealed class AugmentationOne : IAugmentationProcess
|
||||
retrievalContexts = validationResults.Where(x => x.RetrievalContext is not null && x.Confidence >= threshold).Select(x => x.RetrievalContext!).ToList();
|
||||
}
|
||||
else
|
||||
LOGGER.LogWarning("Skipping retrieval context validation because no compliant validation agent provider is available.");
|
||||
LOGGER.LogWarning("Skipping retrieval context validation because no sufficiently trusted validation agent provider is available.");
|
||||
}
|
||||
|
||||
LOGGER.LogInformation($"Starting the augmentation process over {numTotalRetrievalContexts:###,###,###,###} retrieval contexts.");
|
||||
|
||||
@@ -74,7 +74,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, preselectedDataSources);
|
||||
var dataSources = await dataSourceService.GetDataSources(provider, chatThread.DataSourceOptions, preselectedDataSources);
|
||||
var selectedDataSources = dataSources.SelectedDataSources;
|
||||
|
||||
//
|
||||
@@ -104,13 +104,15 @@ public sealed class AISrcSelWithRetCtxVal : IRagProcess
|
||||
else
|
||||
{
|
||||
var previousDataSecurity = chatThread.DataSecurity;
|
||||
var previousDataComplianceLevel = chatThread.DataComplianceLevel;
|
||||
var previousDataConfidenceLevel = chatThread.DataConfidenceLevel;
|
||||
|
||||
//
|
||||
// Update the data security of the chat thread. We consider the current data security
|
||||
// of the chat thread and the data security of the selected data sources:
|
||||
//
|
||||
var dataSecurityRestrictedToSelfHosted = selectedDataSources.Any(x => x is not IInternalDataSource && x.SecurityPolicy is DataSourceSecurity.SELF_HOSTED);
|
||||
var dataSecurityRestrictedToSelfHosted = selectedDataSources
|
||||
.OfType<IExternalDataSource>()
|
||||
.Any(dataSource => dataSource.SecurityPolicy is DataSourceSecurity.SELF_HOSTED);
|
||||
chatThread.DataSecurity = dataSecurityRestrictedToSelfHosted switch
|
||||
{
|
||||
//
|
||||
@@ -152,12 +154,12 @@ public sealed class AISrcSelWithRetCtxVal : IRagProcess
|
||||
if (previousDataSecurity != chatThread.DataSecurity)
|
||||
LOGGER.LogInformation($"The data security of the chat thread was updated from '{previousDataSecurity}' to '{chatThread.DataSecurity}'.");
|
||||
|
||||
foreach (var dataSource in selectedDataSources)
|
||||
if (dataSource.ComplianceLevel > chatThread.DataComplianceLevel)
|
||||
chatThread.DataComplianceLevel = dataSource.ComplianceLevel;
|
||||
foreach (var dataSource in selectedDataSources.OfType<IInternalDataSource>())
|
||||
if (dataSource.ConfidenceLevel > chatThread.DataConfidenceLevel)
|
||||
chatThread.DataConfidenceLevel = dataSource.ConfidenceLevel;
|
||||
|
||||
if (previousDataComplianceLevel != chatThread.DataComplianceLevel)
|
||||
LOGGER.LogInformation($"The data compliance level of the chat thread was updated from '{previousDataComplianceLevel.GetName()}' to '{chatThread.DataComplianceLevel.GetName()}'.");
|
||||
if (previousDataConfidenceLevel != chatThread.DataConfidenceLevel)
|
||||
LOGGER.LogInformation($"The data confidence level of the chat thread was updated from '{previousDataConfidenceLevel.GetName()}' to '{chatThread.DataConfidenceLevel.GetName()}'.");
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -946,7 +946,7 @@ public sealed partial class DataSourceEmbeddingService
|
||||
embeddingProvider.Hostname,
|
||||
embeddingProvider.TokenizerPath,
|
||||
embeddingProvider.EffectiveTokenLimit,
|
||||
GetDataSourceComplianceLevel(dataSource).ToString(),
|
||||
GetDataSourceConfidenceLevel(dataSource).ToString(),
|
||||
dataSource is IInternalDataSource internalDataSource ? internalDataSource.MaxChunkTokenLength : 0,
|
||||
dataSource is IInternalDataSource overlapDataSource ? overlapDataSource.ChunkOverlapTokenLength : 0,
|
||||
chunkingOptions.MaxChunkTokenLength,
|
||||
@@ -1050,7 +1050,7 @@ public sealed partial class DataSourceEmbeddingService
|
||||
{
|
||||
file.Refresh();
|
||||
var absolutePath = Path.GetFullPath(file.FullName);
|
||||
var complianceLevel = GetDataSourceComplianceLevel(dataSource);
|
||||
var confidenceLevel = GetDataSourceConfidenceLevel(dataSource);
|
||||
return new(
|
||||
this.CreateParentFileId(dataSource.Id, absolutePath),
|
||||
absolutePath,
|
||||
@@ -1063,8 +1063,8 @@ public sealed partial class DataSourceEmbeddingService
|
||||
file.Exists ? new DateTimeOffset(file.LastWriteTimeUtc) : DateTimeOffset.UnixEpoch,
|
||||
embeddedAtUtc,
|
||||
chunkCount,
|
||||
complianceLevel.ToString(),
|
||||
(int)complianceLevel);
|
||||
confidenceLevel.ToString(),
|
||||
(int)confidenceLevel);
|
||||
}
|
||||
|
||||
private IReadOnlyList<EmbeddingStateChunk> CreateEmbeddingStateChunks(EmbeddingStateFile parentFile, IReadOnlyList<EmbeddingChunkDraft> batch, DateTimeOffset embeddedAtUtc)
|
||||
@@ -1080,10 +1080,10 @@ public sealed partial class DataSourceEmbeddingService
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static ConfidenceLevel GetDataSourceComplianceLevel(IDataSource dataSource) =>
|
||||
dataSource.ComplianceLevel is ConfidenceLevel.NONE
|
||||
private static ConfidenceLevel GetDataSourceConfidenceLevel(IDataSource dataSource) =>
|
||||
dataSource is not IInternalDataSource internalDataSource || internalDataSource.ConfidenceLevel is ConfidenceLevel.NONE
|
||||
? ConfidenceLevel.UNKNOWN
|
||||
: dataSource.ComplianceLevel;
|
||||
: internalDataSource.ConfidenceLevel;
|
||||
|
||||
private static string GetFileType(FileInfo file)
|
||||
{
|
||||
|
||||
@@ -393,6 +393,15 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
||||
|
||||
private async Task ProcessDataSourceAsync(IDataSource dataSource, DataSourceEmbeddingRefreshMode refreshMode, CancellationToken token)
|
||||
{
|
||||
if (dataSource is not IInternalDataSource internalDataSource)
|
||||
{
|
||||
logger.LogWarning(
|
||||
"Skipping background embeddings for non-internal data source '{DataSourceName}' ({DataSourceId}).",
|
||||
dataSource.Name,
|
||||
dataSource.Id);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.LogInformation(
|
||||
"Starting background embedding hash check for data source '{DataSourceName}' ({DataSourceId}). RefreshMode={RefreshMode}.",
|
||||
dataSource.Name,
|
||||
@@ -451,17 +460,16 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
||||
return;
|
||||
}
|
||||
|
||||
if (!embeddingProvider.AllowsDataSourceAccess(settingsManager, dataSource.SecurityPolicy, dataSource.ComplianceLevel))
|
||||
if (!embeddingProvider.GetConfidenceLevel(settingsManager).AllowsDataSourceConfidenceLevel(internalDataSource.ConfidenceLevel))
|
||||
{
|
||||
var errorMessage = $"The selected embedding provider is not allowed to embed this data source. The data source requires provider confidence '{dataSource.ComplianceLevel.GetName()}'. The embedding provider has confidence '{embeddingProvider.GetConfidenceLevel(settingsManager).GetName()}'.";
|
||||
var errorMessage = $"The selected embedding provider is not allowed to embed this data source. The data source requires provider confidence '{internalDataSource.ConfidenceLevel.GetName()}'. The embedding provider has confidence '{embeddingProvider.GetConfidenceLevel(settingsManager).GetName()}'.";
|
||||
logger.LogWarning(
|
||||
"Skipping background embeddings for data source '{DataSourceName}' ({DataSourceId}) because embedding provider '{EmbeddingProviderName}' ({EmbeddingProviderId}) is not allowed. RequiredDataSecurity={RequiredDataSecurity}, RequiredCompliance={RequiredCompliance}, EmbeddingProviderConfidence={EmbeddingProviderConfidence}.",
|
||||
"Skipping background embeddings for data source '{DataSourceName}' ({DataSourceId}) because embedding provider '{EmbeddingProviderName}' ({EmbeddingProviderId}) does not meet the required confidence. RequiredConfidence={RequiredConfidence}, EmbeddingProviderConfidence={EmbeddingProviderConfidence}.",
|
||||
dataSource.Name,
|
||||
dataSource.Id,
|
||||
embeddingProvider.Name,
|
||||
embeddingProvider.Id,
|
||||
dataSource.SecurityPolicy,
|
||||
dataSource.ComplianceLevel.GetName(),
|
||||
internalDataSource.ConfidenceLevel.GetName(),
|
||||
embeddingProvider.GetConfidenceLevel(settingsManager).GetName());
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
@@ -877,8 +885,8 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
|
||||
parentFile.CreationUtc,
|
||||
parentFile.LastWriteUtc,
|
||||
embeddedAtUtc,
|
||||
parentFile.ComplianceLevel,
|
||||
parentFile.ComplianceLevelRank)).ToList();
|
||||
parentFile.ConfidenceLevel,
|
||||
parentFile.ConfidenceLevelRank)).ToList();
|
||||
|
||||
await vectorStore.InsertEmbedding(collectionName, points, token);
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ public sealed class DataSourceLocalRetrievalService(
|
||||
string Text,
|
||||
double Score,
|
||||
int Rank,
|
||||
string ComplianceLevel,
|
||||
int ComplianceLevelRank);
|
||||
string ConfidenceLevel,
|
||||
int ConfidenceLevelRank);
|
||||
|
||||
public Task<IReadOnlyList<IRetrievalContext>> RetrieveDataAsync(DataSourceLocalFile dataSource, IContent lastUserPrompt, ChatThread thread, CancellationToken token = default) =>
|
||||
this.RetrieveDataAsync((IInternalDataSource)dataSource, lastUserPrompt, token);
|
||||
@@ -296,8 +296,8 @@ public sealed class DataSourceLocalRetrievalService(
|
||||
result.Text,
|
||||
result.Score,
|
||||
rank,
|
||||
result.ComplianceLevel,
|
||||
result.ComplianceLevelRank);
|
||||
result.ConfidenceLevel,
|
||||
result.ConfidenceLevelRank);
|
||||
|
||||
private static LocalRetrievalHit FromBm25Result(EmbeddingStateSearchResult result, int rank) =>
|
||||
new(
|
||||
@@ -316,8 +316,8 @@ public sealed class DataSourceLocalRetrievalService(
|
||||
result.ChunkText,
|
||||
result.Score,
|
||||
rank,
|
||||
result.ComplianceLevel,
|
||||
result.ComplianceLevelRank);
|
||||
result.ConfidenceLevel,
|
||||
result.ConfidenceLevelRank);
|
||||
|
||||
private static RetrievalTextContext ToRetrievalContext(LocalRetrievalHit hit)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace AIStudio.Tools.Services;
|
||||
|
||||
public sealed class DataSourceService
|
||||
{
|
||||
private readonly record struct ParticipatingProvider(string Role, bool IsTrusted, ConfidenceLevel ConfidenceLevel);
|
||||
|
||||
private readonly RustService rustService;
|
||||
private readonly SettingsManager settingsManager;
|
||||
private readonly ILogger<DataSourceService> logger;
|
||||
@@ -27,9 +29,10 @@ public sealed class DataSourceService
|
||||
/// It also returns the data sources selected before when they are still allowed.
|
||||
/// </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="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, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
public async Task<AllowedSelectedDataSources> GetDataSources(AIStudio.Settings.Provider selectedLLMProvider, DataSourceOptions dataSourceOptions, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
{
|
||||
//
|
||||
// Case: Somehow the selected LLM provider was not set. The default provider
|
||||
@@ -42,10 +45,10 @@ public sealed class DataSourceService
|
||||
return new([], []);
|
||||
}
|
||||
|
||||
return await this.GetDataSources(
|
||||
selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager),
|
||||
selectedLLMProvider.GetConfidenceLevel(this.settingsManager),
|
||||
previousSelectedDataSources);
|
||||
var usingTrustedProvider = selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager);
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.Id, dataSourceOptions,
|
||||
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||
return await this.GetDataSources(usingTrustedProvider, participatingProviders, previousSelectedDataSources);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,9 +56,10 @@ public sealed class DataSourceService
|
||||
/// It also returns the data sources selected before when they are still allowed.
|
||||
/// </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="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, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
public async Task<AllowedSelectedDataSources> GetDataSources(IProvider selectedLLMProvider, DataSourceOptions dataSourceOptions, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
{
|
||||
//
|
||||
// Case: Somehow the selected LLM provider was not set. The default provider
|
||||
@@ -68,13 +72,42 @@ public sealed class DataSourceService
|
||||
return new([], []);
|
||||
}
|
||||
|
||||
return await this.GetDataSources(
|
||||
selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager),
|
||||
selectedLLMProvider.GetConfidenceLevel(this.settingsManager),
|
||||
previousSelectedDataSources);
|
||||
var usingTrustedProvider = selectedLLMProvider.IsTrustedForDataSourceSecurityChecks(this.settingsManager);
|
||||
var participatingProviders = this.GetParticipatingProviders(selectedLLMProvider.ConfiguredProviderId, dataSourceOptions,
|
||||
new("chat provider", usingTrustedProvider, selectedLLMProvider.GetConfidenceLevel(this.settingsManager)));
|
||||
return await this.GetDataSources(usingTrustedProvider, participatingProviders, previousSelectedDataSources);
|
||||
}
|
||||
|
||||
private async Task<AllowedSelectedDataSources> GetDataSources(bool usingTrustedProvider, ConfidenceLevel providerConfidenceLevel, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
private IReadOnlyList<ParticipatingProvider> GetParticipatingProviders(string currentProviderId, DataSourceOptions dataSourceOptions, 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");
|
||||
|
||||
return providers;
|
||||
}
|
||||
|
||||
private void AddAgentProvider(List<ParticipatingProvider> providers, Components component, string currentProviderId, string role)
|
||||
{
|
||||
var provider = this.settingsManager.GetPreselectedProvider(component, currentProviderId, true);
|
||||
if (provider == Settings.Provider.NONE)
|
||||
{
|
||||
this.logger.LogWarning($"No provider is available for the {role}. Data sources cannot be made available while this agent is enabled.");
|
||||
providers.Add(new(role, false, ConfidenceLevel.NONE));
|
||||
return;
|
||||
}
|
||||
|
||||
providers.Add(new(
|
||||
role,
|
||||
provider.IsTrustedForDataSourceSecurityChecks(this.settingsManager),
|
||||
provider.GetConfidenceLevel(this.settingsManager)));
|
||||
}
|
||||
|
||||
private async Task<AllowedSelectedDataSources> GetDataSources(bool usingTrustedProvider, IReadOnlyList<ParticipatingProvider> participatingProviders, IReadOnlyCollection<IDataSource>? previousSelectedDataSources = null)
|
||||
{
|
||||
var allDataSources = this.settingsManager.ConfigurationData.DataSources.ToList();
|
||||
var previousSelectedDataSourceIds = previousSelectedDataSources?.Select(source => source.Id).ToHashSet(StringComparer.Ordinal) ?? [];
|
||||
@@ -84,7 +117,7 @@ public sealed class DataSourceService
|
||||
|
||||
// Start all checks in parallel:
|
||||
foreach (var source in allDataSources)
|
||||
tasks.Add(this.CheckOneDataSource(source, usingTrustedProvider, providerConfidenceLevel));
|
||||
tasks.Add(this.CheckOneDataSource(source, usingTrustedProvider, participatingProviders));
|
||||
|
||||
// Wait for all checks and collect the results:
|
||||
foreach (var task in tasks)
|
||||
@@ -101,16 +134,34 @@ public sealed class DataSourceService
|
||||
return new(filteredDataSources, filteredSelectedDataSources);
|
||||
}
|
||||
|
||||
private async Task<IDataSource?> CheckOneDataSource(IDataSource source, bool usingTrustedProvider, ConfidenceLevel providerConfidenceLevel)
|
||||
private async Task<IDataSource?> CheckOneDataSource(IDataSource source, bool usingTrustedProvider, IReadOnlyList<ParticipatingProvider> participatingProviders)
|
||||
{
|
||||
if (!providerConfidenceLevel.AllowsDataSourceComplianceLevel(source.ComplianceLevel))
|
||||
if (source is IInternalDataSource internalSource)
|
||||
{
|
||||
this.logger.LogWarning($"The data source '{source.Name}' (id={source.Id}) requires provider confidence '{source.ComplianceLevel.GetName()}'. The selected provider only has confidence '{providerConfidenceLevel.GetName()}'. We skip this source.");
|
||||
return null;
|
||||
}
|
||||
foreach (var provider in participatingProviders)
|
||||
{
|
||||
if (!provider.ConfidenceLevel.AllowsDataSourceConfidenceLevel(internalSource.ConfidenceLevel))
|
||||
{
|
||||
this.logger.LogWarning($"The internal data source '{source.Name}' (id={source.Id}) requires provider confidence '{internalSource.ConfidenceLevel.GetName()}'. The {provider.Role} only has confidence '{provider.ConfidenceLevel.GetName()}'. We skip this source.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!DataSourceEmbeddingProviders.TryResolve(this.settingsManager, source, out var embeddingProvider))
|
||||
{
|
||||
this.logger.LogWarning($"The internal data source '{source.Name}' (id={source.Id}) has no usable embedding provider. We skip this source.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var embeddingProviderConfidence = embeddingProvider.GetConfidenceLevel(this.settingsManager);
|
||||
if (!embeddingProviderConfidence.AllowsDataSourceConfidenceLevel(internalSource.ConfidenceLevel))
|
||||
{
|
||||
this.logger.LogWarning($"The internal data source '{source.Name}' (id={source.Id}) requires provider confidence '{internalSource.ConfidenceLevel.GetName()}'. Its embedding provider '{embeddingProvider.Name}' only has confidence '{embeddingProviderConfidence.GetName()}'. We skip this source.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (source is IInternalDataSource)
|
||||
return source;
|
||||
}
|
||||
|
||||
//
|
||||
// Unfortunately, we have to live-check any ERI source for its security requirements.
|
||||
@@ -146,8 +197,11 @@ public sealed class DataSourceService
|
||||
eriSourceRequirements = securityRequest.Data;
|
||||
this.logger.LogInformation($"Security requirements for ERI source '{source.Name}' (id={source.Id}) retrieved successfully.");
|
||||
}
|
||||
|
||||
switch (source.SecurityPolicy)
|
||||
|
||||
if (source is not IExternalDataSource externalSource)
|
||||
return source;
|
||||
|
||||
switch (externalSource.SecurityPolicy)
|
||||
{
|
||||
case DataSourceSecurity.ALLOW_ANY:
|
||||
|
||||
|
||||
@@ -23,14 +23,12 @@ public sealed class DataSourceValidation
|
||||
public Func<AuthMethod> GetAuthMethod { get; init; } = () => AuthMethod.NONE;
|
||||
|
||||
public Func<SecurityRequirements?> GetSecurityRequirements { get; init; } = () => null;
|
||||
|
||||
|
||||
public Func<bool> GetSelectedCloudEmbedding { get; init; } = () => false;
|
||||
|
||||
public Func<EmbeddingProvider?> GetSelectedEmbeddingProvider { get; init; } = () => null;
|
||||
|
||||
public Func<DataSourceSecurity> GetSecurityPolicy { get; init; } = () => DataSourceSecurity.ALLOW_ANY;
|
||||
|
||||
public Func<ConfidenceLevel> GetComplianceLevel { get; init; } = () => ConfidenceLevel.NONE;
|
||||
public Func<ConfidenceLevel> GetConfidenceLevel { get; init; } = () => ConfidenceLevel.NONE;
|
||||
|
||||
public Func<SettingsManager?> GetSettingsManager { get; init; } = () => null;
|
||||
|
||||
@@ -61,19 +59,19 @@ public sealed class DataSourceValidation
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public string? ValidateSecurityPolicy(DataSourceSecurity securityPolicy)
|
||||
{
|
||||
if(securityPolicy is DataSourceSecurity.NOT_SPECIFIED)
|
||||
return TB("Please select your security policy.");
|
||||
|
||||
|
||||
var dataSourceSecurity = this.GetSecurityRequirements();
|
||||
if (dataSourceSecurity is null)
|
||||
return null;
|
||||
|
||||
|
||||
if(dataSourceSecurity.Value.AllowedProviderType is ProviderType.SELF_HOSTED && securityPolicy is not DataSourceSecurity.SELF_HOSTED)
|
||||
return TB("This data source can only be used with a self-hosted LLM provider. Please change the security policy.");
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -172,10 +170,10 @@ public sealed class DataSourceValidation
|
||||
return embeddingIssue ?? this.ValidateSelectedEmbeddingProviderAccess();
|
||||
}
|
||||
|
||||
public string? ValidateDataSourceComplianceLevel(ConfidenceLevel complianceLevel)
|
||||
public string? ValidateDataSourceConfidenceLevel(ConfidenceLevel confidenceLevel)
|
||||
{
|
||||
if(complianceLevel is ConfidenceLevel.NONE)
|
||||
return TB("Please select a compliance level.");
|
||||
if(confidenceLevel is ConfidenceLevel.NONE)
|
||||
return TB("Please select a required provider confidence level.");
|
||||
|
||||
return this.ValidateSelectedEmbeddingProviderAccess();
|
||||
}
|
||||
@@ -214,17 +212,13 @@ public sealed class DataSourceValidation
|
||||
if(selectedEmbedding is null || settingsManager is null)
|
||||
return null;
|
||||
|
||||
var dataSecurity = this.GetSecurityPolicy();
|
||||
var complianceLevel = this.GetComplianceLevel();
|
||||
if(selectedEmbedding.AllowsDataSourceAccess(settingsManager, dataSecurity, complianceLevel))
|
||||
var confidenceLevel = this.GetConfidenceLevel();
|
||||
if(selectedEmbedding.GetConfidenceLevel(settingsManager).AllowsDataSourceConfidenceLevel(confidenceLevel))
|
||||
return null;
|
||||
|
||||
if(!selectedEmbedding.AllowsDataSourceSecurity(dataSecurity, settingsManager))
|
||||
return TB("The selected embedding provider is not allowed to process this data source due to its data security policy. Select a self-hosted or organization-trusted embedding provider.");
|
||||
|
||||
return string.Format(
|
||||
TB("The selected embedding provider has confidence '{0}', but this data source requires provider confidence '{1}'. Select an embedding provider with equal or higher confidence or lower the compliance level."),
|
||||
TB("The selected embedding provider has confidence '{0}', but this data source requires provider confidence '{1}'. Select an embedding provider with equal or higher confidence or lower the required confidence level."),
|
||||
selectedEmbedding.GetConfidenceLevel(settingsManager).GetName(),
|
||||
complianceLevel.GetName());
|
||||
confidenceLevel.GetName());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user