Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Opmerking
Vector-ondersteuning is geïntroduceerd in EF Core 10.0 en wordt alleen ondersteund met SQL Server 2025 en hoger.
Met het gegevenstype SQL Server-vector kunnen insluitingen worden opgeslagen. Dit zijn weergaven van betekenis die efficiënt kunnen worden doorzocht op overeenkomsten, waardoor AI-workloads zoals semantische zoekopdrachten en het ophalen van augmented generation (RAG) mogelijk zijn.
Vectoreigenschappen instellen
Als u het vector gegevenstype wilt gebruiken, voegt u gewoon een .NET-eigenschap van het type SqlVector<float> toe aan uw entiteitstype, waarbij u de dimensies als volgt opgeeft:
public class Blog
{
// ...
[Column(TypeName = "vector(1536)")]
public SqlVector<float> Embedding { get; set; }
}
Zodra uw eigenschap is toegevoegd en de bijbehorende kolom die in de database is gemaakt, kunt u beginnen met het invoegen van insluitingen. Het genereren van embeddings wordt buiten de database uitgevoerd, meestal via een service, en de details hiervoor vallen buiten de reikwijdte van deze documentatie.
De .NET-Microsoft.Extensions.AI-bibliotheek bevat IEmbeddingGeneratorechter een abstractie ten opzichte van insluitingsgeneratoren met implementaties voor de belangrijkste providers.
Nadat u de insluitingsgenerator hebt gekozen en deze hebt ingesteld, gebruikt u deze om insluitingen te genereren en deze als volgt in te voegen:
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();
Zodra u embeddings hebt opgeslagen in uw database, bent u klaar om een vectorvergelijkingszoekopdracht daarover uit te voeren.
Exacte zoekopdracht met VECTOR_DISTANCE()
De EF.Functions.VectorDistance() functie berekent de exacte afstand tussen twee vectoren. Gebruik deze om overeenkomsten te zoeken naar een bepaalde gebruikersquery:
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();
Deze functie berekent de afstand tussen de queryvector en elke rij in de tabel en retourneert vervolgens de dichtstbijzijnde overeenkomsten. Hoewel dit perfect nauwkeurige resultaten biedt, kan het traag zijn voor grote gegevenssets, omdat SQL Server alle rijen en rekenafstanden voor elke gegevensset moet scannen.
Opmerking
De ingebouwde ondersteuning in EF 10 vervangt de vorige EFCore.SqlServer.VectorSearch-extensie , die vectorzoekopdrachten toestaat voordat het vector gegevenstype werd geïntroduceerd. Als onderdeel van een upgrade naar EF 10 verwijdert u de extensie uit uw projecten.
Zoeken bij benadering met VECTOR_SEARCH()
Waarschuwing
VECTOR_SEARCH() en vectorindexen zijn momenteel experimentele functies in SQL Server en kunnen worden gewijzigd. De API's in EF Core voor deze functies zijn ook onderhevig aan wijzigingen.
Voor grote databases kan het berekenen van exacte afstanden voor elke rij buitengewoon traag zijn. SQL Server 2025 introduceert ondersteuning voor bij benadering zoeken via een vectorindex, die veel betere prestaties biedt ten koste van het retourneren van items die ongeveer vergelijkbaar zijn - in plaats van precies vergelijkbaar - met de query.
Vectorindexen
Om VECTOR_SEARCH() te gebruiken, moet u een vectorindex maken op uw vectorkolom. Gebruik de HasVectorIndex()-methode in uw modelconfiguratie:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasVectorIndex(b => b.Embedding, "cosine");
}
Hiermee wordt de volgende SQL-migratie gegenereerd:
CREATE VECTOR INDEX [IX_Blogs_Embedding]
ON [Blogs] ([Embedding])
WITH (METRIC = COSINE)
De volgende metrische gegevens over afstand worden ondersteund voor vectorindexen:
| Metric | Beschrijving |
|---|---|
cosine |
Cosinus-gelijkenis (hoekafstand) |
euclidean |
Euclidische afstand (L2 norm) |
dot |
Dot-product (negatief binnenproduct) |
Kies de metrische gegevens die het beste overeenkomen met uw insluitmodel en use-case. Cosinus-overeenkomsten worden vaak gebruikt voor tekstinsluitingen, terwijl euclidische afstand vaak wordt gebruikt voor insluitingen van afbeeldingen.
Zoeken met VECTOR_SEARCH()
Zodra u een vectorindex hebt, gebruikt u de VectorSearch() uitbreidingsmethode op uw 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}");
}
Dit wordt omgezet in de volgende SQL:
SELECT [v].[Id], [v].[Embedding], [v].[Name]
FROM VECTOR_SEARCH([Blogs], 'Embedding', @__embedding, 'metric = cosine', @__topN)
De topN parameter geeft het maximum aantal resultaten op dat moet worden geretourneerd.
VectorSearch() retourneert VectorSearchResult<TEntity>, waarmee u toegang hebt tot zowel de entiteit als de berekende afstand:
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();
Hiermee kunt u filteren op de gelijkenisscore, deze aan gebruikers presenteren, enzovoort.
Hybride zoekopdracht
Hybride zoekopdracht combineert vector-overeenkomsten zoeken met traditionele zoekopdrachten in volledige tekst om relevantere resultaten te leveren. Vectorzoekopdrachten excelleren bij het vinden van semantisch vergelijkbare inhoud, terwijl zoeken in volledige tekst beter is bij exacte trefwoordkoppelingen. Door beide benaderingen te combineren en wederzijdse Rank Fusion (RRF) te gebruiken om de resultaten samen te voegen, kunt u intelligentere zoekervaringen bouwen.
In het volgende voorbeeld ziet u hoe u hybride zoekopdrachten implementeert met EF Core door FreeTextTable() en VectorSearch() in één query te combineren.
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();
Deze query:
- Voert een zoekopdracht in volledige tekst uit op
Article - Voert een vectorzoekopdracht uit op
Articleen combineert de resultaten met de volledige-tekstzoekresultaten via een LEFT JOIN. - Berekent de RRF-score door zowel de volledige tekst als de semantische rangschikking te combineren
- Sorteert op RRF-score, selecteert het gewenste aantal resultaten en projecteert vanuit de oorspronkelijke
Articleentiteiten.
Opmerking
In plaats van een LEFT JOIN te gebruiken, is een FULL OUTER JOIN geschikter voor dit scenario; Hierdoor kunnen zoekresultaten van beide zoekzijden worden opgenomen in het uiteindelijke resultaat, zelfs als dat resultaat helemaal niet aan de andere kant wordt weergegeven. Met de bovenstaande LEFT JOIN-benadering, als een resultaat een zeer hoge vector-gelijkenisscore heeft, wordt deze nooit opgenomen in het uiteindelijke resultaat als dat resultaat niet ook een hoge volledige tekstscore heeft. EF biedt momenteel echter geen ondersteuning voor FULL OUTER JOIN; upvote #37633 als dit iets is wat u wilt zien ondersteund.
De query produceert de volgende SQL:
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