feat(ai): pgvector embedding infrastructure for semantic search
Semantic-search slice 1 (infra). Adds the pgvector plumbing the backfill worker and hybrid search will use: - swap the Postgres image to pgvector/pgvector:pg16 (drop-in for pg16 data) - Pgvector + Pgvector.EntityFrameworkCore (0.2.0, EF8-compatible); UseVector() on the runtime + design-time contexts - Email.Embedding vector(768) column (nomic-embed-text dims), nullable, with an HNSW cosine index; ignored under the InMemory test provider - migration: CREATE EXTENSION vector + column + HNSW index Verified against a real pgvector container: extension, HNSW, and cosine search work, and the full EF round-trip (store a Pgvector.Vector, CosineDistance operator, nearest-first ordering) applies all migrations and passes. No vulnerable packages. Build + all 41 tests pass. Column stays null until Ollama generates embeddings (search falls back to lexical). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using NpgsqlTypes;
|
||||
using Pgvector;
|
||||
|
||||
#nullable disable
|
||||
|
||||
@@ -22,6 +23,7 @@ namespace InboxIntel.Infrastructure.Migrations
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "pg_trgm");
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "vector");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("InboxIntel.Domain.Entities.AnalyticsAggregate", b =>
|
||||
@@ -125,6 +127,9 @@ namespace InboxIntel.Infrastructure.Migrations
|
||||
b.Property<DateTimeOffset>("CreatedAtUtc")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Vector>("Embedding")
|
||||
.HasColumnType("vector(768)");
|
||||
|
||||
b.Property<string>("GmailMessageId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
@@ -194,6 +199,11 @@ namespace InboxIntel.Infrastructure.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Embedding");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Embedding"), "hnsw");
|
||||
NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("Embedding"), new[] { "vector_cosine_ops" });
|
||||
|
||||
b.HasIndex("SearchVector");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("SearchVector"), "GIN");
|
||||
|
||||
Reference in New Issue
Block a user