Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Megjegyzés:
A vektortámogatást az EF Core 10.0-ban vezették be, és csak a 2025-ös és újabb SQL Server támogatott.
A SQL Server vektoros adattípus lehetővé teszi a embeddings tárolását, amelyek olyan jelentésmegjelenítések, amelyek hatékonyan kereshetők a hasonlóság érdekében, és olyan MI-számítási feladatokat aktiválnak, mint a szemantikai keresés és a lekéréses-bővített generáció (RAG).
Vektortulajdonságok beállítása
A vector adattípus használatához egyszerűen adjon hozzá egy .NET SqlVector<float> típusú tulajdonságot az entitástípushoz, és adja meg a dimenziókat az alábbiak szerint:
public class Blog
{
// ...
[Column(TypeName = "vector(1536)")]
public SqlVector<float> Embedding { get; set; }
}
Miután hozzáadta a tulajdonságot, és létrehozta a megfelelő oszlopot az adatbázisban, megkezdheti a beágyazások beszúrását. A beágyazási generálás az adatbázison kívül, általában szolgáltatáson keresztül történik, és ennek részletei nem tartoznak a dokumentáció hatókörébe. A .NET Microsoft.Extensions.AI könyvtár tartalmaz IEmbeddingGenerator, amely egy absztrakció az implementációkat biztosító beágyazási generátorok felett, amely a fő szolgáltatókra vonatkozik.
Miután kiválasztotta a beágyazási generátort, és beállította, használja beágyazások létrehozására, és szúrja be őket az alábbiak szerint:
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();
Miután mentette a beágyazásokat az adatbázisba, készen áll arra, hogy vektoros hasonlósági keresést végezzen rajtuk.
Megjegyzés:
Az EF Core 11-től kezdődően a vektortulajdonságok alapértelmezés szerint nem töltődnek be az entitások lekérdezésekor, mivel a vektorok általában nagyok, és ritkán kell visszaolvasni. Az EF Core 11 előtt a vektortulajdonságok mindig a többi tulajdonsághoz hasonlóan lettek betöltve.
Pontos keresés a VECTOR_DISTANCE() segítségével
A EF.Functions.VectorDistance() függvény kiszámítja a két vektor közötti pontos távolságot. Használatával hasonlósági keresést végezhet egy adott felhasználói lekérdezésben:
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();
Ez a függvény kiszámítja a lekérdezésvektor és a tábla minden sora közötti távolságot, majd visszaadja a legközelebbi egyezéseket. Bár ez tökéletesen pontos eredményeket ad, a nagy adathalmazok esetében lassú lehet, mert az SQL Servernek végig kell néznie minden sort, és ki kell számítania a távolságokat mindegyikhez.
Megjegyzés:
Az EF 10 beépített támogatása lecseréli az előző EFCore.SqlServer.VectorSearch bővítményt, amely lehetővé tette a vektorkeresést az vector adattípus bevezetése előtt. Az EF 10-re való frissítés részeként távolítsa el a bővítményt a projektekből.
Keresés a VECTOR_SEARCH() használatával
Figyelmeztetés
VECTOR_SEARCH() és a vektorindexek jelenleg kísérleti funkciók az SQL Server-ben, és változhatnak. Az EF Core api-jait ezen funkciók esetében is módosítani kell.
SQL Server VECTOR_SEARCH() táblaértékű függvénye a vektorok hasonlósága alapján kéri le a sorokat. Ellentétben VECTOR_DISTANCE() – amely két adott vektor távolságát számítja ki – VECTOR_SEARCH() egy teljes táblában keresi meg a leginkább hasonló vektorokat egy adott lekérdezésvektorhoz.
Alkalmazza a VectorSearch() bővítménymetódust a DbSet objektumon, majd fűzze hozzá a OrderBy(), Take() és WithApproximate() metódusokat egy vektorindexet használó közelítő legközelebbi szomszéd (ANN) keresés végrehajtásához:
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}");
}
Ez a következő SQL-hez lesz lefordítva:
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() visszaadja VectorSearchResult<TEntity>, amely lehetővé teszi az entitás és a számított távolság elérését:
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();
Ez lehetővé teszi a hasonlósági pontszám szűrését, a felhasználók számára való bemutatását stb.
WithApproximate()
WithApproximate() arra utasítja SQL Server, hogy használja a vektorindexet a legközelebbi szomszéd (ANN) kereséshez, ami jelentősen jobb teljesítményt nyújt a nagy adathalmazok számára. Ennek hatására a(z) WITH APPROXIMATE hozzáadódik az SQL TOP záradékhoz.
WithApproximate() után Take()kell meghívni, amely megadja a visszaadni kívánt eredmények számát.
E nélkül WithApproximate()a lekérdezés egy pontos k-legközelebbi szomszéd (kNN) keresést hajt végre, amely az összes sort megvizsgálja a vektorindex használata nélkül:
// 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();
Vektorindexek
A hozzávetőleges keresés WithApproximate()használatához létre kell hoznia egy vektorindexet a vektoroszlopon. Használja a HasVectorIndex() módszert a modellkonfigurációban:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasVectorIndex(b => b.Embedding, "cosine");
}
Ez a következő SQL-migrálást hozza létre:
CREATE VECTOR INDEX [IX_Blogs_Embedding]
ON [Blogs] ([Embedding])
WITH (METRIC = COSINE)
A vektorindexek esetében a következő távolságmetrikák támogatottak:
| Metric | Leírás |
|---|---|
cosine |
Koszinusz-hasonlóság (szögtávolság) |
euclidean |
Euklideszi távolság (L2 norma) |
dot |
Pont termék (negatív belső termék) |
Válassza ki a beágyazási modellnek és a használati esetnek leginkább megfelelő metrikát. A koszin hasonlóságot gyakran használják szövegbeágyazásokhoz, míg az euklideszi távolságot gyakran használják képbeágyazásokhoz.
Hibrid keresés
A hibrid keresés kombinálja a vektoros hasonlóság keresését a hagyományos teljes szöveges kereséssel , hogy relevánsabb eredményeket jelenítsen meg. A vektoros keresés kiválóan alkalmas a szemantikailag hasonló tartalmak kereséséhez, míg a teljes szöveges keresés jobb a kulcsszavak pontos egyeztetésében. Ha mindkét megközelítést kombinálja, és a Kölcsönös rangsor fúzió (RRF) használatával egyesíti az eredményeket, intelligensebb keresési élményeket hozhat létre.
Az alábbi példa bemutatja, hogyan valósíthat meg hibrid keresést az EF Core használatával, kombinálva FreeTextTable() és VectorSearch() egyetlen lekérdezésben:
var k = 20;
string textualQuery = ...;
SqlVector<float> queryEmbedding = ...;
var results = await context.Articles
// Perform full-text search
.FreeTextTable<Article, int>(textualQuery, topN: k)
.Join(
context.Articles,
fts => fts.Key,
a => a.Id,
(fts, a) => new { Article = a, fts.Rank })
// Perform vector (semantic) search, joining the results of both searches together
.FullJoin(
context.Articles.VectorSearch(b => b.Embedding, queryEmbedding, "cosine")
.OrderBy(r => r.Distance)
.Take(k)
.WithApproximate(),
fts => fts.Article.Id,
vs => vs.Value.Id,
(fts, vs) => new
{
Article = fts != null ? fts.Article : vs.Value,
FullTextRank = fts == null ? null : (int?)fts.Rank,
VectorDistance = vs == null ? null : (double?)vs.Distance
})
// Apply Reciprocal Rank Fusion (RRF) to combine the results
.Select(x => new
{
x.Article,
RrfScore = (x.FullTextRank == null ? 0.0 : 1.0 / (k + x.FullTextRank.Value))
+ (x.VectorDistance == null ? 0.0 : 1.0 / (k + x.VectorDistance.Value))
})
.OrderByDescending(x => x.RrfScore)
.Take(10)
.Select(x => x.Article)
.ToListAsync();
Ez a lekérdezés:
- Teljes szöveges keresést hajt végre a következőn:
Article - Vektorkeresést hajt végre,
Articleés a teljes szöveges keresési eredményekkel kombinálja az eredményeket a FULL JOIN használatával - Kiszámítja az RRF-pontszámot a teljes szöveg és a szemantikai rangsor kombinálásával
- A rendelések RRF-pontszám szerinti rendezése történik, majd a kívánt számú találatot kiválasztja, és megjeleníti az eredeti
Articleentitásokat.
A lekérdezés a következő SQL-t hozza létre:
SELECT TOP(@__p_4) COALESCE([a].[Id], [t].[Id]) AS [Id], COALESCE([a].[Content], [t].[Content]) AS [Content], COALESCE([a].[Title], [t].[Title]) AS [Title]
FROM FREETEXTTABLE([Articles], *, @__textualQuery_0, @__k_1) AS [f]
INNER JOIN [Articles] AS [a] ON [f].[KEY] = [a].[Id]
FULL 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 [a].[Id] = [t].[Id]
ORDER BY ISNULL(1.0E0 / CAST(@__k_1 + [f].[RANK] AS float), 0.0E0) + ISNULL(1.0E0 / (CAST(@__k_1 AS float) + [t].[Distance]), 0.0E0) DESC