Removed the denormalized data source name from the RAG storage (#977)
Some checks are pending
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Sync Flatpak repo (push) Blocked by required conditions
Build and Release / Collect Flatpak artifacts (push) Blocked by required conditions
Build and Release / Verify (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Thorsten Sommer 2026-09-16 11:15:32 +02:00 committed by GitHub
parent 186f10cee2
commit b8d971c586
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 44 additions and 49 deletions

View File

@ -4,8 +4,6 @@ internal sealed class EmbeddingStateDataSourceEntity
{ {
public string DataSourceId { get; set; } = string.Empty; public string DataSourceId { get; set; } = string.Empty;
public string DataSourceName { get; set; } = string.Empty;
public string DataSourceType { get; set; } = string.Empty; public string DataSourceType { get; set; } = string.Empty;
public string EmbeddingProviderId { get; set; } = string.Empty; public string EmbeddingProviderId { get; set; } = string.Empty;

View File

@ -8,7 +8,6 @@ public abstract class IndexStoreClient(string name, string path) : DatabaseClien
public abstract Task UpsertDataSourceAsync( public abstract Task UpsertDataSourceAsync(
string dataSourceId, string dataSourceId,
string dataSourceName,
string dataSourceType, string dataSourceType,
string embeddingProviderId, string embeddingProviderId,
string embeddingSignature, string embeddingSignature,

View File

@ -29,7 +29,6 @@ internal sealed class IndexStoreDbContext(DbContextOptions<IndexStoreDbContext>
entity.HasKey(dataSource => dataSource.DataSourceId); entity.HasKey(dataSource => dataSource.DataSourceId);
entity.Property(dataSource => dataSource.DataSourceId).HasColumnName("data_source_id"); entity.Property(dataSource => dataSource.DataSourceId).HasColumnName("data_source_id");
entity.Property(dataSource => dataSource.DataSourceName).HasColumnName("data_source_name").IsRequired();
entity.Property(dataSource => dataSource.DataSourceType).HasColumnName("data_source_type").IsRequired(); entity.Property(dataSource => dataSource.DataSourceType).HasColumnName("data_source_type").IsRequired();
entity.Property(dataSource => dataSource.EmbeddingProviderId).HasColumnName("embedding_provider_id").IsRequired(); entity.Property(dataSource => dataSource.EmbeddingProviderId).HasColumnName("embedding_provider_id").IsRequired();
entity.Property(dataSource => dataSource.EmbeddingSignature).HasColumnName("embedding_signature").IsRequired(); entity.Property(dataSource => dataSource.EmbeddingSignature).HasColumnName("embedding_signature").IsRequired();

View File

@ -9,6 +9,7 @@ internal static class IndexStoreSchemaMigrator
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Migrations.InitialRagIndex))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Migrations.InitialRagIndex))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Migrations.PermanentIndexingFailures))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Migrations.PermanentIndexingFailures))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Migrations.DropFileConfidenceLevel))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Migrations.DropFileConfidenceLevel))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Migrations.DropDataSourceName))]
public static async Task MigrateAsync(IndexStoreDbContext context, CancellationToken token) public static async Task MigrateAsync(IndexStoreDbContext context, CancellationToken token)
{ {
await context.Database.MigrateAsync(token); await context.Database.MigrateAsync(token);

View File

@ -4,7 +4,6 @@ public sealed record IndexStoreSearchResult(
string ChunkId, string ChunkId,
string ParentFileId, string ParentFileId,
string DataSourceId, string DataSourceId,
string DataSourceName,
string DataSourceType, string DataSourceType,
string AbsolutePath, string AbsolutePath,
string FileName, string FileName,

View File

@ -8,8 +8,6 @@ internal sealed class IndexStoreSearchResultEntity
public string DataSourceId { get; set; } = string.Empty; public string DataSourceId { get; set; } = string.Empty;
public string DataSourceName { get; set; } = string.Empty;
public string DataSourceType { get; set; } = string.Empty; public string DataSourceType { get; set; } = string.Empty;
public string AbsolutePath { get; set; } = string.Empty; public string AbsolutePath { get; set; } = string.Empty;

View File

@ -0,0 +1,36 @@
#nullable disable
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
namespace AIStudio.Tools.Databases.IndexStore.Migrations;
/// <summary>
/// Drops the copy of the data source name which the index kept next to each indexed data source.
/// </summary>
/// <remarks>
/// The name a user gives a data source lives in the configuration and is read from there whenever
/// it is needed. The copy here was only ever written, never read, and a copy of a name people are
/// free to change can do nothing but go stale.
/// </remarks>
[DbContext(typeof(IndexStoreDbContext))]
[Migration("20260916000000_DropDataSourceName")]
public partial class DropDataSourceName : Migration
{
/// <remarks>
/// The column goes through raw SQL instead of DropColumn on purpose. The SQLite provider answers
/// DropColumn by rebuilding the table, and dropping the old data_sources table would let the
/// cascade of the foreign key in embedded_files take every indexed file and chunk with it. A
/// native ALTER TABLE ... DROP COLUMN leaves the table itself alone. No index names this column,
/// so nothing has to be dropped first.
/// </remarks>
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("ALTER TABLE data_sources DROP COLUMN data_source_name;");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("ALTER TABLE data_sources ADD COLUMN data_source_name TEXT NOT NULL DEFAULT '';");
}
}

View File

@ -23,11 +23,6 @@ partial class IndexStoreDbContextModelSnapshot : ModelSnapshot
.HasColumnType("TEXT") .HasColumnType("TEXT")
.HasColumnName("data_source_id"); .HasColumnName("data_source_id");
entity.Property<string>("DataSourceName")
.IsRequired()
.HasColumnType("TEXT")
.HasColumnName("data_source_name");
entity.Property<string>("DataSourceType") entity.Property<string>("DataSourceType")
.IsRequired() .IsRequired()
.HasColumnType("TEXT") .HasColumnType("TEXT")
@ -274,10 +269,6 @@ partial class IndexStoreDbContextModelSnapshot : ModelSnapshot
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
entity.Property<string>("DataSourceName")
.IsRequired()
.HasColumnType("TEXT");
entity.Property<string>("DataSourceType") entity.Property<string>("DataSourceType")
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");

View File

@ -28,7 +28,6 @@ public sealed class NoIndexStoreClient(string name, string? unavailableReason, D
public override Task UpsertDataSourceAsync( public override Task UpsertDataSourceAsync(
string dataSourceId, string dataSourceId,
string dataSourceName,
string dataSourceType, string dataSourceType,
string embeddingProviderId, string embeddingProviderId,
string embeddingSignature, string embeddingSignature,

View File

@ -118,7 +118,6 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
public override async Task UpsertDataSourceAsync( public override async Task UpsertDataSourceAsync(
string dataSourceId, string dataSourceId,
string dataSourceName,
string dataSourceType, string dataSourceType,
string embeddingProviderId, string embeddingProviderId,
string embeddingSignature, string embeddingSignature,
@ -137,7 +136,7 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
context.DataSources.Add(dataSource); context.DataSources.Add(dataSource);
} }
ApplyDataSource(dataSource, dataSourceName, dataSourceType, embeddingProviderId, embeddingSignature, sourceHash, vectorSize); ApplyDataSource(dataSource, dataSourceType, embeddingProviderId, embeddingSignature, sourceHash, vectorSize);
await context.SaveChangesAsync(token); await context.SaveChangesAsync(token);
} }
@ -287,7 +286,6 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
c.chunk_id AS ChunkId, c.chunk_id AS ChunkId,
c.parent_file_id AS ParentFileId, c.parent_file_id AS ParentFileId,
ds.data_source_id AS DataSourceId, ds.data_source_id AS DataSourceId,
ds.data_source_name AS DataSourceName,
ds.data_source_type AS DataSourceType, ds.data_source_type AS DataSourceType,
f.absolute_path AS AbsolutePath, f.absolute_path AS AbsolutePath,
f.file_name AS FileName, f.file_name AS FileName,
@ -363,14 +361,12 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
private static void ApplyDataSource( private static void ApplyDataSource(
EmbeddingStateDataSourceEntity dataSource, EmbeddingStateDataSourceEntity dataSource,
string dataSourceName,
string dataSourceType, string dataSourceType,
string embeddingProviderId, string embeddingProviderId,
string embeddingSignature, string embeddingSignature,
string sourceHash, string sourceHash,
int vectorSize) int vectorSize)
{ {
dataSource.DataSourceName = dataSourceName;
dataSource.DataSourceType = dataSourceType; dataSource.DataSourceType = dataSourceType;
dataSource.EmbeddingProviderId = embeddingProviderId; dataSource.EmbeddingProviderId = embeddingProviderId;
dataSource.EmbeddingSignature = embeddingSignature; dataSource.EmbeddingSignature = embeddingSignature;
@ -426,7 +422,6 @@ public sealed class SqliteIndexStoreClientImplementation(string name, string dat
result.ChunkId, result.ChunkId,
result.ParentFileId, result.ParentFileId,
result.DataSourceId, result.DataSourceId,
result.DataSourceName,
result.DataSourceType, result.DataSourceType,
result.AbsolutePath, result.AbsolutePath,
result.FileName, result.FileName,

View File

@ -4,7 +4,6 @@ public sealed record VectorSearchResult(
string PointId, string PointId,
double Score, double Score,
string DataSourceId, string DataSourceId,
string DataSourceName,
string DataSourceType, string DataSourceType,
string ChunkId, string ChunkId,
string ParentFileId, string ParentFileId,

View File

@ -4,7 +4,6 @@ public sealed record VectorStoragePoint(
string PointId, string PointId,
IReadOnlyList<float> Vector, IReadOnlyList<float> Vector,
string DataSourceId, string DataSourceId,
string DataSourceName,
string DataSourceType, string DataSourceType,
string ChunkId, string ChunkId,
string ParentFileId, string ParentFileId,

View File

@ -2,7 +2,6 @@ using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using AIStudio.Provider;
using AIStudio.Settings; using AIStudio.Settings;
using AIStudio.Settings.DataModel; using AIStudio.Settings.DataModel;
using AIStudio.Tools.Databases.IndexStore; using AIStudio.Tools.Databases.IndexStore;

View File

@ -1015,7 +1015,6 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
item.ChunkId, item.ChunkId,
vectors[index], vectors[index],
dataSource.Id, dataSource.Id,
dataSource.Name,
dataSource.Type.ToString(), dataSource.Type.ToString(),
item.ChunkId, item.ChunkId,
parentFile.ParentFileId, parentFile.ParentFileId,
@ -1274,7 +1273,6 @@ public sealed partial class DataSourceEmbeddingService(SettingsManager settingsM
await indexStore.UpsertDataSourceAsync( await indexStore.UpsertDataSourceAsync(
dataSource.Id, dataSource.Id,
dataSource.Name,
dataSource.Type.ToString(), dataSource.Type.ToString(),
manifest.EmbeddingProviderId, manifest.EmbeddingProviderId,
manifest.EmbeddingSignature, manifest.EmbeddingSignature,

View File

@ -42,7 +42,6 @@ public sealed class DataSourceLocalRetrievalService(
string ChunkId, string ChunkId,
string ParentFileId, string ParentFileId,
string DataSourceId, string DataSourceId,
string DataSourceName,
string DataSourceType, string DataSourceType,
string AbsolutePath, string AbsolutePath,
string FileName, string FileName,
@ -93,7 +92,7 @@ public sealed class DataSourceLocalRetrievalService(
return hits return hits
.Where(hit => !string.IsNullOrWhiteSpace(hit.Text)) .Where(hit => !string.IsNullOrWhiteSpace(hit.Text))
.Select(ToRetrievalContext) .Select(hit => ToRetrievalContext(hit, dataSource))
.ToList(); .ToList();
} }
@ -342,7 +341,6 @@ public sealed class DataSourceLocalRetrievalService(
result.ChunkId, result.ChunkId,
result.ParentFileId, result.ParentFileId,
result.DataSourceId, result.DataSourceId,
result.DataSourceName,
result.DataSourceType, result.DataSourceType,
FirstNonEmpty(result.AbsolutePath, result.FilePath), FirstNonEmpty(result.AbsolutePath, result.FilePath),
result.FileName, result.FileName,
@ -360,7 +358,6 @@ public sealed class DataSourceLocalRetrievalService(
result.ChunkId, result.ChunkId,
result.ParentFileId, result.ParentFileId,
result.DataSourceId, result.DataSourceId,
result.DataSourceName,
result.DataSourceType, result.DataSourceType,
result.AbsolutePath, result.AbsolutePath,
result.FileName, result.FileName,
@ -372,9 +369,9 @@ public sealed class DataSourceLocalRetrievalService(
result.Score, result.Score,
rank); rank);
private static RetrievalTextContext ToRetrievalContext(LocalRetrievalHit hit) private static RetrievalTextContext ToRetrievalContext(LocalRetrievalHit hit, IInternalDataSource dataSource)
{ {
var sourceName = FirstNonEmpty(hit.FileName, hit.DataSourceName); var sourceName = FirstNonEmpty(hit.FileName, dataSource.Name);
var path = FirstNonEmpty(hit.AbsolutePath, hit.RelativePath); var path = FirstNonEmpty(hit.AbsolutePath, hit.RelativePath);
var referenceLink = string.IsNullOrWhiteSpace(path) ? string.Empty : BuildReferenceLink(path, hit); var referenceLink = string.IsNullOrWhiteSpace(path) ? string.Empty : BuildReferenceLink(path, hit);
@ -387,15 +384,15 @@ public sealed class DataSourceLocalRetrievalService(
Links = [], Links = [],
MatchedText = hit.Text, MatchedText = hit.Text,
SurroundingContent = [], SurroundingContent = [],
ReferenceTitle = BuildReferenceTitle(hit), ReferenceTitle = BuildReferenceTitle(hit, dataSource),
ReferenceLink = referenceLink, ReferenceLink = referenceLink,
PageNumber = hit.PageNumber is > 0 ? hit.PageNumber : null, PageNumber = hit.PageNumber is > 0 ? hit.PageNumber : null,
}; };
} }
private static string BuildReferenceTitle(LocalRetrievalHit hit) private static string BuildReferenceTitle(LocalRetrievalHit hit, IInternalDataSource dataSource)
{ {
var sourceName = FirstNonEmpty(hit.FileName, hit.DataSourceName); var sourceName = FirstNonEmpty(hit.FileName, dataSource.Name);
return BuildLocatedReferenceTitle(sourceName, hit.ChunkIndex, hit.PageNumber); return BuildLocatedReferenceTitle(sourceName, hit.ChunkIndex, hit.PageNumber);
} }

View File

@ -70,7 +70,6 @@ pub struct QdrantEdgeStoragePoint {
pub point_id: String, pub point_id: String,
pub vector: Vec<f32>, pub vector: Vec<f32>,
pub data_source_id: String, pub data_source_id: String,
pub data_source_name: String,
pub data_source_type: String, pub data_source_type: String,
pub chunk_id: String, pub chunk_id: String,
pub parent_file_id: String, pub parent_file_id: String,
@ -141,7 +140,6 @@ pub struct QdrantEdgeSearchResult {
pub point_id: String, pub point_id: String,
pub score: f32, pub score: f32,
pub data_source_id: String, pub data_source_id: String,
pub data_source_name: String,
pub data_source_type: String, pub data_source_type: String,
pub chunk_id: String, pub chunk_id: String,
pub parent_file_id: String, pub parent_file_id: String,
@ -299,15 +297,7 @@ impl QdrantEdgeDatabase {
return Err("All vectors in one insert request must have the same size.".into()); return Err("All vectors in one insert request must have the same size.".into());
} }
let data_source_name = first_point.data_source_name.clone();
validate_data_source_name(&data_source_name)?;
if points.iter().any(|point| point.data_source_name != data_source_name) {
return Err("All points in one insert request must belong to the same data source name.".into());
}
let store_path = self.store_path(store_name)?;
let (shard, _) = self.get_or_create_store(store_name, vector_size)?; let (shard, _) = self.get_or_create_store(store_name, vector_size)?;
write_store_display_name(&store_path, &data_source_name)?;
let points = points let points = points
.into_iter() .into_iter()
.map(to_qdrant_edge_point) .map(to_qdrant_edge_point)
@ -738,7 +728,6 @@ fn to_qdrant_edge_point(point: QdrantEdgeStoragePoint) -> QdrantEdgeResult<qdran
Vectors::new_named([(VECTOR_NAME, point.vector)]), Vectors::new_named([(VECTOR_NAME, point.vector)]),
json!({ json!({
"data_source_id": point.data_source_id, "data_source_id": point.data_source_id,
"data_source_name": point.data_source_name,
"data_source_type": point.data_source_type, "data_source_type": point.data_source_type,
"chunk_id": point.chunk_id, "chunk_id": point.chunk_id,
"parent_file_id": point.parent_file_id, "parent_file_id": point.parent_file_id,
@ -765,7 +754,6 @@ fn to_qdrant_edge_search_result(point: ScoredPoint) -> QdrantEdgeSearchResult {
point_id: point_id_to_string(point.id), point_id: point_id_to_string(point.id),
score: point.score, score: point.score,
data_source_id: payload_string(&payload, "data_source_id"), data_source_id: payload_string(&payload, "data_source_id"),
data_source_name: payload_string(&payload, "data_source_name"),
data_source_type: payload_string(&payload, "data_source_type"), data_source_type: payload_string(&payload, "data_source_type"),
chunk_id: payload_string(&payload, "chunk_id"), chunk_id: payload_string(&payload, "chunk_id"),
parent_file_id: payload_string(&payload, "parent_file_id"), parent_file_id: payload_string(&payload, "parent_file_id"),