From 8d15561d9750de0a15649e469afe62e8803947b0 Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Mon, 26 May 2025 00:43:26 -0300 Subject: [PATCH 1/2] docs: Add docs for new `Vector` type support --- docs/06-concepts/02-models.md | 33 +++++++- docs/06-concepts/06-database/04-indexing.md | 71 +++++++++++++++++ docs/06-concepts/06-database/06-filter.md | 43 +++++++++++ docs/08-upgrading/05-upgrade-to-pgvector.md | 86 +++++++++++++++++++++ 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 docs/08-upgrading/05-upgrade-to-pgvector.md diff --git a/docs/06-concepts/02-models.md b/docs/06-concepts/02-models.md index d91e8f56..d466675b 100644 --- a/docs/06-concepts/02-models.md +++ b/docs/06-concepts/02-models.md @@ -18,7 +18,7 @@ fields: employees: List ``` -Supported types are [bool](https://api.dart.dev/dart-core/bool-class.html), [int](https://api.dart.dev/dart-core/int-class.html), [double](https://api.dart.dev/dart-core/double-class.html), [String](https://api.dart.dev/dart-core/String-class.html), [Duration](https://api.dart.dev/dart-core/Duration-class.html), [DateTime](https://api.dart.dev/dart-core/DateTime-class.html), [ByteData](https://api.dart.dev/dart-typed_data/ByteData-class.html), [UuidValue](https://pub.dev/documentation/uuid/latest/uuid_value/UuidValue-class.html), [Uri](https://api.dart.dev/dart-core/Uri-class.html), [BigInt](https://api.dart.dev/dart-core/BigInt-class.html) and other serializable [classes](#class), [exceptions](#exception) and [enums](#enum). You can also use [List](https://api.dart.dev/dart-core/List-class.html)s, [Map](https://api.dart.dev/dart-core/Map-class.html)s and [Set](https://api.dart.dev/dart-core/Set-class.html)s of the supported types, just make sure to specify the types. All supported types can also be used inside [Record](https://api.dart.dev/dart-core/Record-class.html)s. Null safety is supported. Once your classes are generated, you can use them as parameters or return types to endpoint methods. +Supported types are [bool](https://api.dart.dev/dart-core/bool-class.html), [int](https://api.dart.dev/dart-core/int-class.html), [double](https://api.dart.dev/dart-core/double-class.html), [String](https://api.dart.dev/dart-core/String-class.html), [Duration](https://api.dart.dev/dart-core/Duration-class.html), [DateTime](https://api.dart.dev/dart-core/DateTime-class.html), [ByteData](https://api.dart.dev/dart-typed_data/ByteData-class.html), [UuidValue](https://pub.dev/documentation/uuid/latest/uuid_value/UuidValue-class.html), [Uri](https://api.dart.dev/dart-core/Uri-class.html), [BigInt](https://api.dart.dev/dart-core/BigInt-class.html), [Vector](#vector-fields) and other serializable [classes](#class), [exceptions](#exception) and [enums](#enum). You can also use [List](https://api.dart.dev/dart-core/List-class.html)s, [Map](https://api.dart.dev/dart-core/Map-class.html)s and [Set](https://api.dart.dev/dart-core/Set-class.html)s of the supported types, just make sure to specify the types. All supported types can also be used inside [Record](https://api.dart.dev/dart-core/Record-class.html)s. Null safety is supported. Once your classes are generated, you can use them as parameters or return types to endpoint methods. ### Limiting visibility of a generated class @@ -133,6 +133,35 @@ fields: employees: List ``` +## Vector fields + +The `Vector` type is used for storing high-dimensional vectors, which are specially useful for similarity search operations. + +```yaml +class: Document +table: document +fields: + ### The category of the document (e.g., article, tutorial). + category: String + + ### The contents of the document. + content: String + + ### A vector field for storing document embeddings + embedding: Vector(1536) +``` + +The number in parentheses specifies the vector dimensions. Common dimensions include: +- 1536 (OpenAI embeddings) +- 768 (many sentence transformers) +- 384 (smaller models) + +Vector fields support specialized distance operations for similarity search and filtering. See the [Vector distance operators](database/filter#vector-distance-operators) section for details. + +:::info +The usage of Vector fields requires the pgvector PostgreSQL extension to be installed, which comes by default on new Serverpod projects. To upgrade an existing project, see the [Upgrading to pgvector support](../upgrading/upgrade-to-pgvector) guide. +::: + ## Generated code Serverpod generates some convenience methods on the Dart classes. @@ -365,6 +394,8 @@ fields: | [**indexes**](database/indexing) | Create indexes on your fields / columns. | ✅ | | | | [**fields (index)**](database/indexing) | List the fields to create the indexes on. | ✅ | | | | [**type (index)**](database/indexing) | The type of index to create. | ✅ | | | +| [**parameters (index)**](database/indexing#vector-indexes) | Parameters for specialized index types like HNSW and IVFFLAT vector indexes. | ✅ | | | +| [**distanceFunction (index)**](database/indexing#vector-indexes) | Distance function for vector indexes (l2, innerProduct, cosine, l1). | ✅ | | | | [**unique**](database/indexing) | Boolean flag to make the entries unique in the database. | ✅ | | | | [**default**](#default-values) | Sets the default value for both the model and the database. This keyword cannot be used with **relation**. | ✅ | | | | [**defaultModel**](#default-values) | Sets the default value for the model side. This keyword cannot be used with **relation**. | ✅ | | | diff --git a/docs/06-concepts/06-database/04-indexing.md b/docs/06-concepts/06-database/04-indexing.md index f28ae772..800a12bb 100644 --- a/docs/06-concepts/06-database/04-indexing.md +++ b/docs/06-concepts/06-database/04-indexing.md @@ -62,3 +62,74 @@ indexes: ``` If no type is specified the default is `btree`. All [PostgreSQL index types](https://www.postgresql.org/docs/current/indexes-types.html) are supported, `btree`, `hash`, `gist`, `spgist`, `gin`, `brin`. + +### Vector indexes + +To enhance the performance of vector similarity search, it is possible to create specialized vector indexes on `Vector` fields. Serverpod supports both `HNSW` and `IVFFLAT` index types with full parameter specification. + +:::info +Each vector index can only be created on a single `Vector` field. It is not possible to create a vector index on multiple fields of any kind. +::: + +#### HNSW indexes + +Hierarchical Navigable Small World (HNSW) indexes provide fast approximate nearest neighbor search: + +```yaml +class: Document +table: document +fields: + content: String + embedding: Vector(1536) +indexes: + document_embedding_hnsw_idx: + fields: embedding + type: hnsw + distanceFunction: cosine + parameters: + m: 16 + ef_construction: 64 +``` + +Available HNSW parameters: +- `m`: Maximum number of bi-directional links for each node (default: 16) +- `efConstruction`: Size of the dynamic candidate list (default: 64) + +#### IVFFLAT indexes + +Inverted File with Flat compression (IVFFLAT) indexes are suitable for large datasets: + +```yaml +class: Document +table: document +fields: + content: String + embedding: Vector(1536) +indexes: + document_embedding_ivfflat_idx: + fields: embedding + type: ivfflat + distanceFunction: innerProduct + parameters: + lists: 100 +``` + +Available IVFFLAT parameters: +- `lists`: Number of inverted lists (default: 100) + +#### Distance functions + +Supported distance functions for vector indexes (`distanceFunction` parameter): + +| Distance Function | Description | Use Case | +|-------------------|-------------------------------|------------------------------| +| `l2` | Euclidean distance | Default for most embeddings | +| `innerProduct` | Inner product | When vectors are normalized | +| `cosine` | Cosine distance | Text embeddings | +| `l1` | Manhattan or taxicab distance | Sparse/high-dimensional data | + +:::tip +If more than one distance function is going to be frequently used on the same vector field, consider creating one index for each distance function to ensure optimal performance. +::: + +For more details on vector indexes and its configuration, refer to the [pgvector extension documentation](https://github.com/pgvector/pgvector/tree/master?tab=readme-ov-file#indexing). diff --git a/docs/06-concepts/06-database/06-filter.md b/docs/06-concepts/06-database/06-filter.md index bdfd5899..dc174fed 100644 --- a/docs/06-concepts/06-database/06-filter.md +++ b/docs/06-concepts/06-database/06-filter.md @@ -194,6 +194,49 @@ await User.db.find( In the example we fetch all users that has a name that starts with A *or* B. +### Vector distance operators + +Vector fields support specialized distance operations for similarity search. Available vector distance operations: + +- `distanceL2` - Euclidean (L2) distance. +- `distanceInnerProduct` - Inner product distance. +- `distanceCosine` - Cosine distance. +- `distanceL1` - Manhattan or taxicab (L1) distance. + +You can use vector distance operations with numeric comparisons for filtering and ordering: + +```dart +// The vector to compare against +var queryVector = Vector([0.1, 0.2, 0.3, ...]); + +// Find top documents similar to a query vector +var similarDocs = await Document.db.find( + session, + where: (t) => t.embedding.distanceCosine(queryVector) < 0.5, + orderBy: (t) => t.embedding.distanceCosine(queryVector), + limit: 10, +); + +// Filter by distance range +var mediumSimilarity = await Document.db.find( + session, + where: (t) => t.embedding.distanceL2(queryVector).between(0.3, 0.8), +); + +// Combine with other filters +var filteredSimilarity = await Document.db.find( + session, + where: (t) => t.category.equals('article') & + (t.embedding.distanceCosine(queryVector) < 0.7), + orderBy: (t) => t.embedding.distanceCosine(queryVector), + limit: 10, +); +``` + +:::tip +For optimal performance with vector similarity searches, consider creating specialized vector indexes (HNSW or IVFFLAT) on your vector fields. See the [Vector indexes](indexing#vector-indexes) section for more details. +::: + ## Relation operations If a relation between two models is defined a [one-to-one](relations/one-to-one) or [one-to-many](relations/one-to-many) object relation, then relation operations are supported in Serverpod. diff --git a/docs/08-upgrading/05-upgrade-to-pgvector.md b/docs/08-upgrading/05-upgrade-to-pgvector.md new file mode 100644 index 00000000..ec34b87f --- /dev/null +++ b/docs/08-upgrading/05-upgrade-to-pgvector.md @@ -0,0 +1,86 @@ +# Upgrading to pgvector support + +New Serverpod projects automatically include pgvector support through the `pgvector/pgvector` PostgreSQL Docker image. However, existing projects need to be upgraded to use vector functionality. + +:::info +This upgrade is only necessary if you want to use vector fields in your models. If you do not plan to use vector fields, you can skip this upgrade. +::: + +:::warning +If trying to use vector fields without upgrading, you will encounter an error when applying migrations. +::: + +## For Docker-based environments + +1. Update your `docker-compose.yml` to use a PostgreSQL image with pgvector (e.g., `pgvector/pgvector:pg16`): + +```yaml +services: + postgres: + image: pgvector/pgvector:pg16 # <-- Change from postgres image here + ports: + - '8090:5432' + environment: + POSTGRES_USER: postgres + POSTGRES_DB: + POSTGRES_PASSWORD: + volumes: + - _data:/var/lib/postgresql/data + +# Other services... + + postgres_test: + image: pgvector/pgvector:pg16 # <-- Change from postgres image here + ports: + - '9090:5432' + environment: + POSTGRES_USER: postgres + POSTGRES_DB: _test + POSTGRES_PASSWORD: + volumes: + - _test_data:/var/lib/postgresql/data +``` + +2. Recreate your containers to use the new image: + +```bash +docker-compose down +docker-compose up -d +``` + +3. Create your first vector field in a model: + +```yaml +class: Document +table: document +fields: + content: String + embedding: Vector(1536) +``` + +4. Generate and apply a migration: + +```bash +$ serverpod create-migration +$ dart run bin/main.dart --apply-migrations +``` + +For more details on creating and applying migrations, see the [Migrations](../concepts/database/migration) section. + +The pgvector extension will be automatically enabled during the first migration that includes a vector column. + +## For managed PostgreSQL services + +For cloud providers (AWS RDS, Google Cloud SQL, Azure Database, etc.), ensure that **pgvector extension is available** on your PostgreSQL instance. Most managed services already support pgvector with no additional setup required. If available, the extension will be enabled automatically when applying the migration. + +:::tip +If the cloud provider instructions is to run a `CREATE EXTENSION vector;` command, you can skip this step as Serverpod will handle it automatically during migration. +::: + +## Troubleshooting + +If you encounter issues with pgvector: + +- Verify that your PostgreSQL version supports pgvector 0.7.0+ (PostgreSQL 12+). +- Check that the pgvector extension is properly installed. +- Ensure your database user has the necessary permissions to create extensions. From 5ebf00fb4711411103329288828ff8ddfde792ec Mon Sep 17 00:00:00 2001 From: Marcelo Soares Date: Mon, 26 May 2025 00:58:18 -0300 Subject: [PATCH 2/2] fix: Fix linting and build for new docs --- docs/06-concepts/02-models.md | 1 + docs/08-upgrading/05-upgrade-to-pgvector.md | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/06-concepts/02-models.md b/docs/06-concepts/02-models.md index d466675b..c9e0e6ce 100644 --- a/docs/06-concepts/02-models.md +++ b/docs/06-concepts/02-models.md @@ -152,6 +152,7 @@ fields: ``` The number in parentheses specifies the vector dimensions. Common dimensions include: + - 1536 (OpenAI embeddings) - 768 (many sentence transformers) - 384 (smaller models) diff --git a/docs/08-upgrading/05-upgrade-to-pgvector.md b/docs/08-upgrading/05-upgrade-to-pgvector.md index ec34b87f..aeaab00f 100644 --- a/docs/08-upgrading/05-upgrade-to-pgvector.md +++ b/docs/08-upgrading/05-upgrade-to-pgvector.md @@ -41,6 +41,7 @@ services: - _test_data:/var/lib/postgresql/data ``` + 2. Recreate your containers to use the new image: ```bash @@ -48,6 +49,7 @@ docker-compose down docker-compose up -d ``` + 3. Create your first vector field in a model: ```yaml @@ -58,6 +60,7 @@ fields: embedding: Vector(1536) ``` + 4. Generate and apply a migration: ```bash @@ -65,7 +68,7 @@ $ serverpod create-migration $ dart run bin/main.dart --apply-migrations ``` -For more details on creating and applying migrations, see the [Migrations](../concepts/database/migration) section. +For more details on creating and applying migrations, see the [Migrations](../concepts/database/migrations) section. The pgvector extension will be automatically enabled during the first migration that includes a vector column.