Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Die Vektorunterstützung wurde in EF Core 10.0 eingeführt und wird nur mit SQL Server 2025 und höher unterstützt.
Der SQL Server-Vektordatentyp ermöglicht das Speichern von Embeddings, die Bedeutungsrepräsentationen sind und effizient nach Ähnlichkeit durchsucht werden können. Dadurch können KI-Workloads wie semantische Suche und abruferweiterte Generierung (RAG) effektiv unterstützt werden.
Einrichten von Vektoreigenschaften
Um den Datentyp vector zu verwenden, fügen Sie einfach eine .NET Eigenschaft vom Typ SqlVector<float> zu Ihrem Entitätstyp hinzu, und geben Sie die Dimensionen wie folgt an:
public class Blog
{
// ...
[Column(TypeName = "vector(1536)")]
public SqlVector<float> Embedding { get; set; }
}
Nachdem Ihre Eigenschaft hinzugefügt wurde und die entsprechende Spalte in der Datenbank erstellt wurde, können Sie mit dem Einfügen von Einbettungen beginnen. Die Einbettungsgenerierung erfolgt außerhalb der Datenbank, in der Regel über einen Dienst, und die Details dazu sind nicht im Rahmen dieser Dokumentation.
the .NET Microsoft.Extensions.AI library enthält jedoch IEmbeddingGenerator, bei dem es sich um eine Abstraktion gegenüber den Einbettungsgeneratoren handelt, die Implementierungen für die wichtigsten Anbieter aufweisen.
Nachdem Sie ihren Einbettungsgenerator ausgewählt und eingerichtet haben, verwenden Sie ihn, um Einbettungen zu generieren und wie folgt einzufügen:
IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator = /* Set up your preferred embedding generator */;
var embedding = await embeddingGenerator.GenerateVectorAsync("Some text to be vectorized");
context.Blogs.Add(new Blog
{
Name = "Some blog",
Embedding = new SqlVector<float>(embedding)
});
await context.SaveChangesAsync();
Nachdem Sie Einbettungen in Ihrer Datenbank gespeichert haben, können Sie eine Vektorähnlichkeitssuche durchführen.
Hinweis
Ab EF Core 11 werden Vektoreigenschaften beim Abfragen von Entitäten nicht standardmäßig geladen, da Vektoren in der Regel groß sind und selten zurückgelesen werden müssen. Vor EF Core 11 wurden Vektoreigenschaften wie jede andere Eigenschaft immer geladen.
Genaue Suche mit VECTOR_DISTANCE()
Die EF.Functions.VectorDistance() Funktion berechnet den genauen Abstand zwischen zwei Vektoren. Verwenden Sie sie zum Ausführen der Ähnlichkeitssuche für eine bestimmte Benutzerabfrage:
var sqlVector = new SqlVector<float>(await embeddingGenerator.GenerateVectorAsync("Some user query to be vectorized"));
var topSimilarBlogs = await context.Blogs
.OrderBy(b => EF.Functions.VectorDistance("cosine", b.Embedding, sqlVector))
.Take(3)
.ToListAsync();
Diese Funktion berechnet den Abstand zwischen dem Abfragevektor und jeder Zeile in der Tabelle und gibt dann die nächstgelegenen Übereinstimmungen zurück. Dies bietet zwar perfekt genaue Ergebnisse, kann aber für große Datasets langsam sein, da SQL Server alle Zeilen scannen und Abstände für jeden berechnen müssen.
Hinweis
Die integrierte Unterstützung in EF 10 ersetzt die vorherige EFCore.SqlServer.VectorSearch-Erweiterung , die die Durchführung der Vektorsuche vor der Einführung des vector Datentyps erlaubte. Entfernen Sie im Rahmen des Upgrades auf EF 10 die Erweiterung aus Ihren Projekten.
Suchen mit VECTOR_SEARCH()
Warnung
VECTOR_SEARCH() und Vektorindizes sind derzeit experimentelle Features in SQL Server und können geändert werden. Die APIs in EF Core für diese Features können ebenfalls geändert werden.
SQL Server VECTOR_SEARCH() Tabellenwertfunktion ruft Zeilen basierend auf der Vektorähnlichkeit ab. Anders als VECTOR_DISTANCE() bei der Berechnung des Abstands zwischen zwei bestimmten Vektoren wird VECTOR_SEARCH() eine gesamte Tabelle nach den ähnlichsten Vektoren für einen bestimmten Abfragevektor durchsucht.
Verwenden Sie die VectorSearch()-Erweiterungsmethode für Ihr DbSet und verketten Sie OrderBy(), Take() und WithApproximate(), um eine ANN-Suche nach den nächstgelegenen Nachbarn durchzuführen, die einen Vektorindex verwendet:
var results = await context.Blogs
.VectorSearch(b => b.Embedding, embedding, "cosine")
.OrderBy(r => r.Distance)
.Take(5)
.WithApproximate()
.ToListAsync();
foreach (var result in results)
{
Console.WriteLine($"Blog {result.Value.Id} with distance {result.Distance}");
}
Dies entspricht der folgenden SQL-Syntax:
SELECT TOP(@__p_1) WITH APPROXIMATE [b].[Id], [b].[Name], [v].[Distance]
FROM VECTOR_SEARCH(
TABLE = [Blogs] AS [b],
COLUMN = [Embedding],
SIMILAR_TO = @__embedding_0,
METRIC = 'cosine'
) AS [v]
ORDER BY [v].[Distance]
VectorSearch() gibt VectorSearchResult<TEntity>zurück, mit dem Sie sowohl auf die Entität als auch auf den berechneten Abstand zugreifen können:
var searchResults = await context.Blogs
.VectorSearch(b => b.Embedding, embedding, "cosine")
.Where(r => r.Distance < 0.05)
.OrderBy(r => r.Distance)
.Select(r => new { Blog = r.Value, Distance = r.Distance })
.Take(3)
.WithApproximate()
.ToListAsync();
Auf diese Weise können Sie nach der Ähnlichkeitsbewertung filtern, es Benutzern präsentieren usw.
WithApproximate()
WithApproximate() weist SQL Server an, den Vektorindex für die approximative Suche nach den nächsten Nachbarn (ANN) zu verwenden, was bei großen Datensätzen eine deutlich bessere Leistung bietet. Dies führt dazu, dass WITH APPROXIMATE der SQL-Klausel TOP hinzugefügt wird.
WithApproximate() muss nach dem Aufruf von Take() aufgerufen werden, mit dem die Anzahl der zurückzugebenden Ergebnisse angegeben wird.
Ohne WithApproximate() führt die Abfrage eine exakte k-Nearest-Neighbor-Suche (kNN) durch, bei der alle Zeilen durchsucht werden, ohne den Vektorindex zu verwenden:
// Exact kNN search (no vector index used)
var blogs = await context.Blogs
.VectorSearch(b => b.Embedding, embedding, "cosine")
.OrderBy(r => r.Distance)
.Take(5)
.ToListAsync();
Vektorindizes
Um die ungefähre Suche mit WithApproximate()verwenden zu können, müssen Sie einen Vektorindex für Ihre Vektorspalte erstellen. Verwenden Sie die HasVectorIndex()-Methode in Ihrer Modellkonfiguration.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasVectorIndex(b => b.Embedding, "cosine");
}
Dadurch wird die folgende SQL-Migration generiert:
CREATE VECTOR INDEX [IX_Blogs_Embedding]
ON [Blogs] ([Embedding])
WITH (METRIC = COSINE)
Die folgenden Entfernungsmetriken werden für Vektorindizes unterstützt:
| Metric | Beschreibung |
|---|---|
cosine |
Kosinusähnlichkeit (Winkelabstand) |
euclidean |
Euklidischer Abstand (L2-Norm) |
dot |
Skalarprodukt (negatives inneres Produkt) |
Wählen Sie die Metrik aus, die Ihrem Einbettungsmodell und Anwendungsfall am besten entspricht. Kosinusähnlichkeit wird häufig für Texteinbettungen verwendet, während euklidischer Abstand häufig für Bildeinbettungen verwendet wird.
Hybridsuche
Die Hybridsuche kombiniert die Vektorgleichheitssuche mit der herkömmlichen Volltextsuche , um relevantere Ergebnisse zu erzielen. Die Vektorsuche zeichnet sich durch die Suche semantisch ähnlicher Inhalte aus, während die Volltextsuche bei exakter Stichwortüberstimmung besser ist. Indem Sie beide Ansätze kombinieren und reziprokierende Rangfusion (RRF) verwenden, um die Ergebnisse zusammenzuführen, können Sie intelligentere Sucherfahrungen erstellen.
Das folgende Beispiel zeigt, wie Sie die Hybridsuche mithilfe von EF Core implementieren, kombinieren FreeTextTable() und VectorSearch() in einer einzigen Abfrage:
var k = 20;
string textualQuery = ...;
SqlVector<float> queryEmbedding = ...;
var results = await context.Articles
// Perform full-text search
.FreeTextTable<Article, int>(textualQuery, topN: k)
// Perform vector (semantic) search, joining the results of both searches together
.LeftJoin(
context.Articles.VectorSearch(b => b.Embedding, queryEmbedding, "cosine")
.OrderBy(r => r.Distance)
.Take(k)
.WithApproximate(),
fts => fts.Key,
vs => vs.Value.Id,
(fts, vs) => new
{
Article = vs.Value,
FullTextRank = fts.Rank,
VectorDistance = (double?)vs.Distance
})
// Apply Reciprocal Rank Fusion (RRF) to combine the results
.Select(x => new
{
x.Article,
RrfScore = (1.0 / (k + x.FullTextRank)) + (1.0 / (k + x.VectorDistance) ?? 0.0)
})
.OrderByDescending(x => x.RrfScore)
.Take(10)
.Select(x => x.Article)
.ToListAsync();
Diese Abfrage:
- Führt eine Volltextsuche auf
Articledurch - Führt eine Vektorsuche auf
Articledurch und kombiniert die Ergebnisse mithilfe von LEFT JOIN mit den Volltextsuchergebnissen. - Berechnet die RRF-Bewertung, indem sowohl der Volltext als auch die semantische Rangfolge kombiniert werden.
- Sortiert nach RRF-Bewertung, ermittelt die gewünschte Anzahl der Ergebnisse und projiziert die ursprünglichen
Article-Entitäten.
Hinweis
Anstatt eine LEFT JOIN-Verknüpfung zu verwenden, wäre ein FULL OUTER JOIN für dieses Szenario besser geeignet; Dies würde es ermöglichen, dass hochrangige Ergebnisse von beiden Suchseiten in das Endergebnis einbezogen werden, auch wenn dieses Ergebnis nicht überhaupt auf der anderen Seite angezeigt wird. Wenn ein Ergebnis einen sehr hohen Vektor-Ähnlichkeitsscore aufweist, wird er beim obigen LEFT JOIN-Ansatz nie in das Endergebnis einbezogen, wenn das Ergebnis nicht auch eine hohe Volltextbewertung aufweist. EF unterstützt derzeit jedoch nicht FULL OUTER JOIN; geben Sie #37633 ein Upvote, wenn Sie möchten, dass diese Funktion unterstützt wird.
Die Abfrage erzeugt die folgende SQL-Datei:
SELECT TOP(@__p_4) [a0].[Id], [a0].[Content], [a0].[Title]
FROM FREETEXTTABLE([Articles], *, @__textualQuery_0, @__k_1) AS [f]
LEFT JOIN (
SELECT TOP(@__k_1) WITH APPROXIMATE [a].[Id], [a].[Content], [a].[Title], [v].[Distance]
FROM VECTOR_SEARCH(
TABLE = [Articles] AS [a],
COLUMN = [Embedding],
SIMILAR_TO = @__queryEmbedding_2,
METRIC = 'cosine'
) AS [v]
ORDER BY [v].[Distance]
) AS [t] ON [f].[KEY] = [t].[Id]
ORDER BY 1.0E0 / CAST(@__k_1 + [f].[RANK] AS float) + ISNULL(1.0E0 / (CAST(@__k_1 AS float) + [t].[Distance]), 0.0E0) DESC