Tworzenie wyszukiwania wektorowego w .NET za pomocą PgVector, przewodnik dla programistów
Jeśli tworzysz aplikacje .NET, które obsługują duże ilości danych, dokumentów, katalogów produktów, rekordów klientów lub zeskanowanych plików, wyszukiwanie zawsze stanowi wyzwanie. Wyszukiwanie słów kluczowych nie uwzględnia kontekstu. Wyszukiwanie pełnotekstowe ma swoje ograniczenia. Jednak wyszukiwanie wektorowe całkowicie zmienia sytuację.
Niedawno natknęliśmy się na doskonały przewodnik autorstwa Milana Jovanovicia, jednego z najbardziej szanowanych głosów w społeczności .NET i Microsoft MVP, który szczegółowo opisuje, jak zaimplementować wyszukiwanie wektorowe w .NET przy użyciu PgVector, rozszerzenia PostgreSQL, które wprowadza możliwości wyszukiwania semantycznego bezpośrednio do bazy danych, którą już posiadasz.
Co to jest wyszukiwanie wektorowe i jak działa?
Tradycyjne wyszukiwanie dopasowuje dokładne słowa lub frazy. Jeżeli użytkownik szuka "przeterminowanej faktury", wyszukiwanie według słów kluczowych znajdzie jedynie dokumenty zawierające te dokładne słowa. Nie zwróci dokumentu, który mówi "płatność oczekuje" lub "należność do uregulowania", mimo że oznaczają to samo.
Wyszukiwanie wektorowe działa inaczej. Zamiast dopasowywać słowa, dopasowuje znaczenie.
Oto jak działa pipeline w praktyce:
Po pierwsze, tekst jest konwertowany na reprezentację numeryczną zwaną osadzeniem, czyli wielowymiarową tablicę liczb zmiennoprzecinkowych, która uchwyca znaczenie semantyczne treści. Na przykład, zdania "przeterminowana faktura" i "płatność oczekuje" wygenerowałyby osadzenia, które są matematycznie bliskie sobie w przestrzeni wektorowej, mimo że nie mają wspólnych słów.
Te osadzenia są generowane przez model uczenia maszynowego, zazwyczaj za pośrednictwem API, takiego jak modele osadzania tekstu OpenAI, i przechowywane razem z danymi w bazie danych.

Gdy użytkownik uruchamia zapytanie wyszukiwania, to zapytanie jest również konwertowane na osadzenie przy użyciu tego samego modelu. Baza danych następnie oblicza odległość między osadzeniem zapytania a każdym przechowywanym osadzeniem, zwracając wyniki, które są najbliższe w przestrzeni wektorowej, co oznacza najbardziej semantycznie podobne, a nie tylko dopasowane słowami kluczowymi.
PgVector umożliwia to bezpośrednio w PostgreSQL, wspierając efektywne wyszukiwanie podobieństw obok danych relacyjnych, bez potrzeby dedykowanej bazy danych wektorowej.
Inicjalizacja bazy danych
Przed przechowywaniem wektorów, należy włączyć rozszerzenie PgVector i skonfigurować tabelę.
var builder = DistributedApplication.CreateBuilder(args);
var ollama = builder.AddOllama("ollama")
.WithLifetime(ContainerLifetime.Persistent)
.WithDataVolume()
.WithGPUSupport();
var embeddingModel = ollama.AddModel("qwen3-embedding:0.6b");
var postgres = builder.AddPostgres("postgres", port: 6432)
.WithLifetime(ContainerLifetime.Persistent)
.WithDataVolume()
.WithImage("pgvector/pgvector", "pg17")
.AddDatabase("articles");
builder.AddProject<Projects.PgVector_Articles>("pgvector-articles")
.WithReference(embeddingModel)
.WithReference(postgres)
.WaitFor(embeddingModel)
.WaitFor(postgres);
builder.Build().Run();
var builder = DistributedApplication.CreateBuilder(args);
var ollama = builder.AddOllama("ollama")
.WithLifetime(ContainerLifetime.Persistent)
.WithDataVolume()
.WithGPUSupport();
var embeddingModel = ollama.AddModel("qwen3-embedding:0.6b");
var postgres = builder.AddPostgres("postgres", port: 6432)
.WithLifetime(ContainerLifetime.Persistent)
.WithDataVolume()
.WithImage("pgvector/pgvector", "pg17")
.AddDatabase("articles");
builder.AddProject<Projects.PgVector_Articles>("pgvector-articles")
.WithReference(embeddingModel)
.WithReference(postgres)
.WaitFor(embeddingModel)
.WaitFor(postgres);
builder.Build().Run();
Jeśli nie używasz Aspire, możesz uruchomić ten sam obraz pgvector/pgvector:pg17 za pośrednictwem docker-compose i wskazać na niego za pomocą zwykłego łańcucha połączenia.
Ta sekcja opiera się na oryginalnym artykułe Milana Jovanovicia. Pełne przykłady kodu i szczegóły implementacji są dostępne tutaj.
Dłączego to jest ważne dla klientów Iron Software
Wielu naszych klientów używa IronPDF, IronOCR i IronBarcode do przetwarzania dużych ilości dokumentów; faktur, raportów, zeskanowanych dokumentów, etykiet wysyłkowych.
Praktyczny przepływ pracy łączący biblioteki Iron Software z PgVectorem może wyglądać tak:
Extract– Użyj IronOCR do wyodrębnienia tekstu z zeskanowanych PDF-ów lub obrazówEmbed– Prześlij wyodrębniony tekst do modelu osadzającego, aby wygenerować reprezentacje wektoroweStore– Zapisz osadzenia wraz z metadanymi dokumentu w PostgreSQL przy użyciu PgvectorSearch– Wykonaj zapytanie według znaczenia, zwracając najbardziej semantycznie odpowiednie dokumenty, a nie tylko dokładnie dopasowane słowa kluczowe
Wynikiem jest inteligentniejszy system wyszukiwania dokumentów zbudowany całkowicie w ramach istniejącego stosu .NET i PostgreSQL, bez dodatkowej infrastruktury.
Co obejmuje przewodnik Milana
Artykuł Milana opisuje pełną implementację w C#: ustawienie rozszerzenia PgVector w PostgreSQL, konfigurowanie Entity Framework Core z Npgsql, generowanie osadzeń, tworzenie indeksów wektorowych dla wydajności i wykonywanie zapytań o podobieństwo. Jest praktyczny, zoptymalizowany do produkcji i od razu użyteczny dla każdego programisty .NET.
Zespół programistów Iron Software regularnie dzieli się zasobami .NET, poradnikami i wnioskami inżynieryjnymi z naszą społecznością.
Budujesz przepływy pracy z dokumentami w .NET? Iron Suite ma wszystko, czego potrzebujesz.