mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
Closes FE-3966 ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## Problem - The admonition uses both 'tip' and 'note', but the visual distinction has long-ago collapsed. - 'Note' is used far more frequently than 'tip' - The two are very similar and it is confusing to know which one to use when they are visually identical ## Solution Collapse 'tip' and 'note' into one by removing all places where there is 'tip' and updating all references to 'tip' into 'note'. **Note:** This PR also resolves new broken links flagged by the E2E docs checker. It may move to another PR since E2Es keep erroring. ### Specific changes See below for an AI-generated list of changes: - **Type system** — removed `'tip'` from `AdmonitionType`, its `TYPE_TO_VARIANT`/`TYPE_LABEL` entries, and the test case in [`packages/ui-patterns/src/Admonition/](packages/ui-patterns/src/Admonition/) - **Remark plugin** — [remarkAdmonition.ts](apps/docs/lib/mdx/plugins/remarkAdmonition.ts) now maps mkdocs `tip` → `note` - **Lint allowlist** — `tip` dropped from `supa-mdx-lint.config.toml` - **Content migration** — all 109 files with `type="tip"` (across `apps/docs`, `apps/www`, `apps/studio`) converted to `type="note"`; zero remaining hits confirmed by repo-wide grep - **Style guide** — `CONTRIBUTING.md` and `contributing/content.mdx` updated to describe 4 admonition types instead of 5 ### Usage before implementation See the usage table that points toward 'note' as being dominant across all apps: Here's the usage table: | Location | `note` | `tip` | |---|---|---| | apps/docs | ~480 | ~143 | | apps/studio | 34 | 6 | | apps/www (blog) | 19 | 3 | | packages/ui-patterns (tests) | 3 | 1 (parametrized) | | design-system / ui-library / packages/ui / packages/common | 0–1 (test fixture only) | 0 | ## Preview links | App | Page | Search text (Ctrl+F) | Verify | |---|---|---|---| | docs | [/docs/guides/ai-tools/byo-mcp](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/ai-tools/byo-mcp) | official MCP TypeScript SDK | callout's aria-label="Note" | | docs | [/docs/guides/ai-tools/mcp](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/ai-tools/mcp) | MCP server is available at | callout's aria-label="Note" | | docs | [/docs/guides/ai/python-clients](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/ai/python-clients) | Click Connect at the top of any project page | callout's aria-label="Note" | | docs | [/docs/guides/auth/audit-logs](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/auth/audit-logs) | Disabling Postgres storage reduces your database storage costs | callout's aria-label="Note" | | docs | [/docs/guides/database/tables](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/database/tables) | access a custom schema through the Supabase Data API | callout's aria-label="Note" | | docs | [/docs/guides/troubleshooting/edge-function-404-error-response](https://docs-git-admonition-collapse-note-tip-supabase.vercel.app/docs/guides/troubleshooting/edge-function-404-error-response) | Always configure an appropriate time frame | callout's aria-label="Note" (was single-quoted type='tip') | | www | [blog: cli-v2-config-as-code](https://zone-www-dot-com-git-admonition-collapse-note-tip-supabase.vercel.app/blog/cli-v2-config-as-code) | Detecting config drift | callout's aria-label="Note" | | www | [blog: cli-v2-config-as-code](https://zone-www-dot-com-git-admonition-collapse-note-tip-supabase.vercel.app/blog/cli-v2-config-as-code) | Setting Edge Function secrets | callout's aria-label="Note" | | www | [blog: nosql-mongodb-compatibility-with-ferretdb-and-flydotio](https://zone-www-dot-com-git-admonition-collapse-note-tip-supabase.vercel.app/blog/nosql-mongodb-compatibility-with-ferretdb-and-flydotio) | If your network supports IPv6 connections | callout's aria-label="Note" | Note: the `www` rows use the `zone-www-dot-com` preview host, not the `docs` one you gave — since blog pages are served from the www app, not docs. ## Manual testing 1. Open preview links for affected pages. 2. Inspect. Open console. 3. Paste the following in and see there is no 'Tip' on the page: ``` document.querySelectorAll('[role="alert"]').forEach(el => console.log(el.getAttribute('aria-label'), el.textContent.slice(0,60))) ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Standardized informational callouts across docs and tutorials from **“Tip”** to **“Note”**, updating multiple examples and guidance blocks. * Updated a few related doc references/links and conditional “Next steps” content. * **UI Updates** * Switched various in-app banners and notices to the **“Note”** style variant. * **Bug Fixes / Improvements** * Removed support for the retired **“Tip”** callout type and aligned docs linting, component behavior, and aria labeling to the remaining admonition types. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
176 lines
7.3 KiB
Plaintext
176 lines
7.3 KiB
Plaintext
---
|
|
id: 'ai-vector-columns'
|
|
title: 'Vector columns'
|
|
description: 'Learn how to use vectors within your own Postgres tables'
|
|
sidebar_label: 'Vector columns'
|
|
---
|
|
|
|
Supabase offers a number of different ways to store and query vectors within Postgres. The SQL included in this guide is applicable for clients in all programming languages. If you are a Python user, see your [Python client options](/docs/guides/ai/python-clients) after reading the `Learn` section.
|
|
|
|
Vectors in Supabase are enabled via [pgvector](https://github.com/pgvector/pgvector/), a Postgres extension for storing and querying vectors in Postgres. It can be used to store [embeddings](/docs/guides/ai/concepts#what-are-embeddings).
|
|
|
|
## Usage
|
|
|
|
### Enable the extension
|
|
|
|
<Tabs
|
|
scrollable
|
|
size="small"
|
|
type="underlined"
|
|
defaultActiveId="dashboard"
|
|
queryGroup="database-method"
|
|
>
|
|
<TabPanel id="dashboard" label="Dashboard">
|
|
|
|
1. Go to the [Database](/dashboard/project/_/database/tables) page in the Dashboard.
|
|
2. Click on **Extensions** in the sidebar.
|
|
3. Search for "vector" and enable the extension.
|
|
|
|
</TabPanel>
|
|
<TabPanel id="sql" label="SQL">
|
|
|
|
```sql
|
|
-- Example: enable the "vector" extension.
|
|
create extension vector
|
|
with
|
|
schema extensions;
|
|
|
|
-- Example: disable the "vector" extension
|
|
drop
|
|
extension if exists vector;
|
|
```
|
|
|
|
Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension".
|
|
To disable an extension, call `drop extension`.
|
|
|
|
</TabPanel>
|
|
</Tabs>
|
|
|
|
### Create a table to store vectors
|
|
|
|
After enabling the `vector` extension, you will get access to a new data type called `vector`. The size of the vector (indicated in parentheses) represents the number of dimensions stored in that vector.
|
|
|
|
```sql
|
|
create table documents (
|
|
id serial primary key,
|
|
title text not null,
|
|
body text not null,
|
|
embedding extensions.vector(384)
|
|
);
|
|
```
|
|
|
|
In the SQL snippet above, we create a `documents` table with an `embedding` column. This is a standard Postgres column, so you can name it anything you like. The `embedding` column uses the `vector` data type with 384 dimensions. Change this number to match the dimensions your embedding model produces. For example, if you're [generating embeddings](/docs/guides/ai/quickstarts/generate-text-embeddings) using the open source [`gte-small`](https://huggingface.co/Supabase/gte-small) model, set this to 384.
|
|
|
|
<Admonition type="note">
|
|
|
|
In general, embeddings with fewer dimensions perform best. See our [analysis on fewer dimensions in pgvector](/blog/fewer-dimensions-are-better-pgvector).
|
|
|
|
</Admonition>
|
|
|
|
### Storing a vector / embedding
|
|
|
|
In this example we'll generate a vector using Transformers.js, then store it in the database using the Supabase JavaScript client.
|
|
|
|
```js
|
|
import { pipeline } from '@huggingface/transformers'
|
|
|
|
const generateEmbedding = await pipeline('feature-extraction', 'Supabase/gte-small')
|
|
|
|
const title = 'First post!'
|
|
const body = 'Hello world!'
|
|
|
|
// Generate a vector using Transformers.js
|
|
const output = await generateEmbedding(body, {
|
|
pooling: 'mean',
|
|
normalize: true,
|
|
})
|
|
|
|
// Extract the embedding output
|
|
const embedding = Array.from(output.data)
|
|
|
|
// Store the vector in Postgres
|
|
const { data, error } = await supabase.from('documents').insert({
|
|
title,
|
|
body,
|
|
embedding,
|
|
})
|
|
```
|
|
|
|
This example uses the JavaScript Supabase client, but you can modify it to work with any [supported language library](/docs#client-libraries).
|
|
|
|
### Querying a vector / embedding
|
|
|
|
Similarity search is the most common use case for vectors. `pgvector` supports 3 new operators for computing distance:
|
|
|
|
| Operator | Description |
|
|
| -------- | ---------------------- |
|
|
| `<->` | Euclidean distance |
|
|
| `<#>` | negative inner product |
|
|
| `<=>` | cosine distance |
|
|
|
|
Choosing the right operator depends on your needs. Dot product tends to be the fastest if your vectors are normalized. For more information on how embeddings work and how they relate to each other, see [What are Embeddings?](/docs/guides/ai/concepts#what-are-embeddings).
|
|
|
|
Supabase client libraries like `supabase-js` connect to your Postgres instance via [PostgREST](/docs/guides/getting-started/architecture#postgrest-api). PostgREST does not currently support `pgvector` similarity operators, so we'll need to wrap our query in a Postgres function and call it via the `rpc()` method:
|
|
|
|
```sql
|
|
create or replace function match_documents (
|
|
query_embedding extensions.vector(384),
|
|
match_threshold float,
|
|
match_count int
|
|
)
|
|
returns table (
|
|
id bigint,
|
|
title text,
|
|
body text,
|
|
similarity float
|
|
)
|
|
language sql stable
|
|
as $$
|
|
select
|
|
documents.id,
|
|
documents.title,
|
|
documents.body,
|
|
1 - (documents.embedding <=> query_embedding) as similarity
|
|
from documents
|
|
where 1 - (documents.embedding <=> query_embedding) > match_threshold
|
|
order by (documents.embedding <=> query_embedding) asc
|
|
limit match_count;
|
|
$$;
|
|
```
|
|
|
|
This function takes a `query_embedding` argument and compares it to all other embeddings in the `documents` table. Each comparison returns a similarity score. If the similarity is greater than the `match_threshold` argument, it is returned. The number of rows returned is limited by the `match_count` argument.
|
|
|
|
Feel free to modify this method to fit the needs of your application. The `match_threshold` ensures that only documents that have a minimum similarity to the `query_embedding` are returned. Without this, you may end up returning documents that subjectively don't match. This value will vary for each application - you will need to perform your own testing to determine the threshold that makes sense for your app.
|
|
|
|
If you index your vector column, ensure that the `order by` sorts by the distance function directly (rather than sorting by the calculated `similarity` column, which may lead to the index being ignored and poor performance).
|
|
|
|
To execute the function from your client library, call `rpc()` with the name of your Postgres function:
|
|
|
|
```ts
|
|
const { data: documents } = await supabaseClient.rpc('match_documents', {
|
|
query_embedding: embedding, // Pass the embedding you want to compare
|
|
match_threshold: 0.78, // Choose an appropriate threshold for your data
|
|
match_count: 10, // Choose the number of matches
|
|
})
|
|
```
|
|
|
|
In this example `embedding` would be another embedding you wish to compare against your table of pre-generated embedding documents. For example if you were building a search engine, every time the user submits their query you would first generate an embedding on the search query itself, then pass it into the above `rpc()` function to match.
|
|
|
|
<Admonition type="note">
|
|
|
|
To filter your vector search by another column from the JS client, extend the function above with an extra parameter and `where` clause. See [Filtering vector search by metadata](/docs/guides/ai/semantic-search#filtering-vector-search-by-metadata) for a worked example.
|
|
|
|
</Admonition>
|
|
|
|
<Admonition type="note">
|
|
|
|
Be sure to use embeddings produced from the same embedding model when calculating distance. Comparing embeddings from two different models will produce no meaningful result.
|
|
|
|
</Admonition>
|
|
|
|
Vectors and embeddings can be used for much more than search. Learn more about embeddings at [What are Embeddings?](/docs/guides/ai/concepts#what-are-embeddings).
|
|
|
|
### Indexes
|
|
|
|
Once your vector table starts to grow, you will likely want to add an index to speed up queries. See [Vector indexes](/docs/guides/ai/vector-indexes) to learn how vector indexes work and how to create them.
|