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 Einbettungen, bei denen es sich um Darstellungen von Bedeutungen handelt, die effizient nach Ähnlichkeiten durchsucht werden können, sodass KI-Workloads wie semantische Suche und Retrieval-Augmented Generation (RAG) bereitgestellt werden können.
Einrichten von Vektoreigenschaften
Um den vector Datentyp 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. Die .NET-Microsoft.Extensions.AI-Bibliothek enthält IEmbeddingGeneratorjedoch eine Abstraktion über Einbettungsgeneratoren mit Implementierungen für die wichtigsten Anbieter.
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.
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 Entfernungen für jeden berechnen muss.
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.
Ungefähre Suche 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.
Bei großen Datasets kann das Berechnen exakter Entfernungen für jede Zeile unerschwinglich langsam sein. SQL Server 2025 führt unterstützung für die ungefähre Suche über einen Vektorindex ein, was eine wesentlich bessere Leistung auf Kosten der Rückgabe von Elementen bietet, die ungefähr ähnlich sind , und nicht genau ähnlich der Abfrage.
Vektorindizes
Zur Verwendung VECTOR_SEARCH()müssen Sie einen Vektorindex für die 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 |
Dot-Produkt (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.
Suchen mit VECTOR_SEARCH()
Nachdem Sie über einen Vektorindex verfügen, verwenden Sie die VectorSearch() Erweiterungsmethode für Folgendes DbSet:
var blogs = await context.Blogs
.VectorSearch(b => b.Embedding, "cosine", embedding, topN: 5)
.ToListAsync();
foreach (var (blog, score) in blogs)
{
Console.WriteLine($"Blog {blog.Id} with score {score}");
}
Dies entspricht der folgenden SQL-Syntax:
SELECT [v].[Id], [v].[Embedding], [v].[Name]
FROM VECTOR_SEARCH([Blogs], 'Embedding', @__embedding, 'metric = cosine', @__topN)
Der topN Parameter gibt die maximale Anzahl der zurückzugebenden Ergebnisse an.
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, "cosine", embedding, topN: 5)
.Where(r => r.Distance < 0.05)
.Select(r => new { Blog = r.Value, Distance = r.Distance })
.ToListAsync();
Auf diese Weise können Sie nach der Ähnlichkeitsbewertung filtern, es Benutzern präsentieren usw.
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", topN: k),
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; hochvoten Sie #37633, wenn Sie dies unterstützt sehen möchten.
Die Abfrage erzeugt die folgende SQL-Datei:
SELECT TOP(@p3) [a0].[Id], [a0].[Content], [a0].[Embedding], [a0].[Title]
FROM FREETEXTTABLE([Articles], *, @p, @p1) AS [f]
LEFT JOIN VECTOR_SEARCH(
TABLE = [Articles] AS [a0],
COLUMN = [Embedding],
SIMILAR_TO = @p2,
METRIC = 'cosine',
TOP_N = @p3
) AS [v] ON [f].[KEY] = [a0].[Id]
ORDER BY 1.0E0 / CAST(10 + [f].[RANK] AS float) + ISNULL(1.0E0 / (10.0E0 + [v].[Distance]), 0.0E0) DESC