From 7042eb07701f07a139df405ed19fa93e4fd39a78 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Wed, 6 Sep 2023 10:51:13 -0600 Subject: [PATCH] docs: hnsw indexes --- .../NavigationMenu.constants.ts | 2 +- .../pages/guides/ai/managing-collections.mdx | 2 +- apps/docs/pages/guides/ai/vector-columns.mdx | 2 +- apps/docs/pages/guides/ai/vector-indexes.mdx | 43 ++++++++ .../guides/ai/vector-indexes/hnsw-indexes.mdx | 101 ++++++++++++++++++ .../ivf-indexes.mdx} | 95 ++++++++-------- .../ai/vector-indexes/hnsw-indexes/nsw.png | Bin 0 -> 33195 bytes .../hnsw-indexes/skip-list--dark.png | Bin 0 -> 17088 bytes .../hnsw-indexes/skip-list--light.png | Bin 0 -> 16989 bytes apps/docs/public/sitemap.xml | 2 +- ...3-fewer-dimensions-are-better-pgvector.mdx | 2 +- ...-06-increase-performance-pgvector-hnsw.mdx | 2 +- apps/www/lib/redirects.js | 5 + 13 files changed, 207 insertions(+), 49 deletions(-) create mode 100644 apps/docs/pages/guides/ai/vector-indexes.mdx create mode 100644 apps/docs/pages/guides/ai/vector-indexes/hnsw-indexes.mdx rename apps/docs/pages/guides/ai/{managing-indexes.mdx => vector-indexes/ivf-indexes.mdx} (63%) create mode 100644 apps/docs/public/img/ai/vector-indexes/hnsw-indexes/nsw.png create mode 100644 apps/docs/public/img/ai/vector-indexes/hnsw-indexes/skip-list--dark.png create mode 100644 apps/docs/public/img/ai/vector-indexes/hnsw-indexes/skip-list--light.png diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 81f0c44369e..a66433385c4 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -977,8 +977,8 @@ export const ai: NavMenuConstant = { url: undefined, items: [ { name: 'Managing collections', url: '/guides/ai/managing-collections' }, - { name: 'Managing indexes', url: '/guides/ai/managing-indexes' }, { name: 'Vector columns', url: '/guides/ai/vector-columns' }, + { name: 'Vector indexes', url: '/guides/ai/vector-indexes' }, { name: 'Engineering for scale', url: '/guides/ai/engineering-for-scale' }, { name: 'Choosing Compute Add-on', url: '/guides/ai/choosing-compute-addon' }, { name: 'Going to Production', url: '/guides/ai/going-to-prod' }, diff --git a/apps/docs/pages/guides/ai/managing-collections.mdx b/apps/docs/pages/guides/ai/managing-collections.mdx index 5ed4d45ce42..fc56a8ae249 100644 --- a/apps/docs/pages/guides/ai/managing-collections.mdx +++ b/apps/docs/pages/guides/ai/managing-collections.mdx @@ -106,7 +106,7 @@ The time required to create an index grows with the number of records and size o -For an in-depth guide on vector indexes, see [Managing indexes](/docs/guides/ai/managing-indexes). +For an in-depth guide on vector indexes, see [Vector indexes](/docs/guides/ai/vector-indexes). ### Query diff --git a/apps/docs/pages/guides/ai/vector-columns.mdx b/apps/docs/pages/guides/ai/vector-columns.mdx index b263cb9b619..4cfa8259708 100644 --- a/apps/docs/pages/guides/ai/vector-columns.mdx +++ b/apps/docs/pages/guides/ai/vector-columns.mdx @@ -162,7 +162,7 @@ Vectors and embeddings can be used for much more than search. Learn more about e ### Indexes -Once your vector table starts to grow, you will likely want to add an index to speed up queries. See [Managing indexes](/docs/guides/ai/managing-indexes) to learn how vector indexes work and how to create them. +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. export const Page = ({ children }) => diff --git a/apps/docs/pages/guides/ai/vector-indexes.mdx b/apps/docs/pages/guides/ai/vector-indexes.mdx new file mode 100644 index 00000000000..4343fc46056 --- /dev/null +++ b/apps/docs/pages/guides/ai/vector-indexes.mdx @@ -0,0 +1,43 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'ai-vector-indexes', + title: 'Vector indexes', + description: 'Understanding vector indexes', + sidebar_label: 'Vector indexes', +} + +Once your vector table starts to grow, you will likely want to add an index to speed up queries. Without indexes, you'll be performing a sequential scan which can be a resource-intensive operation when you have many records. + +## Choosing an index + +Today `pgvector` supports two types of indexes: + +- [HNSW](/docs/guides/ai/vector-indexes/hnsw-indexes) +- [IVFFlat](/docs/guides/ai/vector-indexes/ivf-indexes) + +In general we recommend using [HNSW](/docs/guides/ai/vector-indexes/hnsw-indexes) because of its [performance gain](/blog/increase-performance-pgvector-hnsw#hnsw-performance-1536-dimensions) and [robustness against changing data](/docs/guides/ai/vector-indexes/hnsw-indexes#when-should-you-create-hnsw-indexes). + +## Distance operators + +The type of index required depends on the distance operator you are using. `pgvector` includes 3 distance operators: + +| Operator | Description | [**Operator class**](https://www.postgresql.org/docs/current/sql-createopclass.html) | +| -------- | ---------------------- | ------------------------------------------------------------------------------------ | +| `<->` | Euclidean distance | `vector_l2_ops` | +| `<#>` | negative inner product | `vector_ip_ops` | +| `<=>` | cosine distance | `vector_cosine_ops` | + +Use the following SQL commands to create an index for the operator(s) used in your queries. + +Currently vectors with up to 2,000 dimensions can be indexed. + +If you are using the `vecs` Python library, follow the instructions in [Managing collections](/docs/guides/ai/managing-collections#create-an-index) to create indexes. + +## Resources + +Read more about indexing on `pgvector`'s [GitHub page](https://github.com/pgvector/pgvector#indexing). + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/ai/vector-indexes/hnsw-indexes.mdx b/apps/docs/pages/guides/ai/vector-indexes/hnsw-indexes.mdx new file mode 100644 index 00000000000..12ac6cda2b6 --- /dev/null +++ b/apps/docs/pages/guides/ai/vector-indexes/hnsw-indexes.mdx @@ -0,0 +1,101 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'ai-hnsw-indexes', + title: 'HNSW indexes', + description: 'Understanding HNSW indexes in pgvector', + sidebar_label: 'HNSW indexes', +} + +HNSW is a type of vector index for approximate nearest neighbor search, used in high-dimensional spaces like those found in embeddings. + +## Usage + +The way you create an HNSW index depends on the distance operator you are using. `pgvector` includes 3 distance operators: + +| Operator | Description | [**Operator class**](https://www.postgresql.org/docs/current/sql-createopclass.html) | +| -------- | ---------------------- | ------------------------------------------------------------------------------------ | +| `<->` | Euclidean distance | `vector_l2_ops` | +| `<#>` | negative inner product | `vector_ip_ops` | +| `<=>` | cosine distance | `vector_cosine_ops` | + +Use the following SQL commands to create an HNSW index for the operator(s) used in your queries. + +### Euclidean L2 distance (`vector_l2_ops`) + +```sql +create index on items using hnsw (column_name vector_l2_ops); +``` + +### Inner product (`vector_ip_ops`) + +```sql +create index on items using hnsw (column_name vector_ip_ops); +``` + +### Cosine distance (`vector_cosine_ops`) + +```sql +create index on items using hnsw (column_name vector_cosine_ops); +``` + +Currently vectors with up to 2,000 dimensions can be indexed. + +If you are using the `vecs` Python library, follow the instructions in [Managing collections](/docs/guides/ai/managing-collections#create-an-index) to create indexes. + +## How does HNSW work? + +HNSW uses proximity graphs (graphs connecting nodes based on distance between them) to approximate nearest-neighbor search. To understand HNSW, we can break it down into 2 parts: + +- **Hierarchical (H):** The algorithm operates over multiple layers +- **Navigable Small World (NSW):** Each vector is a node within a graph and is connected to several other nodes + +### Hierarchical + +The hierarchical aspect of HNSW builds off of the idea of skip lists. + +Skip lists are multi-layer linked lists. The bottom layer is a regular linked list connecting an ordered sequence of elements. Each new layer above removes some elements from the underlying layer (based on a fixed probability), producing a sparser subsequence that “skips” over elements. + +
+ visual of an example skip list (light) + visual of an example skip list (dark) +
+ +When searching for an element, the algorithm begins at the top layer and traverses its linked list horizontally. If the target element is found, the algorithm stops and returns it. Otherwise if the next element in the list is greater than the target (or NIL), the algorithm drops down to the next layer below. Since each layer below is less sparse than the layer above (with the bottom layer connecting all elements), the target will eventually be found. Skip lists offer O(log n) average complexity for both search and insertion/deletion. + +### Navigable Small World + +A navigable small world (NSW) is a special type of proximity graph that also includes long-range connections between nodes. These long-range connections support the “small world” property of the graph, meaning almost every node can be reached from any other node within a few hops. Without these additional long-range connections, many hops would be required to reach a far-away node. + +visual of an example navigable small world graph + +The “navigable” part of NSW specifically refers to the ability to logarithmically scale the greedy search algorithm on the graph, an algorithm that attempts to make only the locally optimal choice at each hop. Without this property, the graph may still be considered a small world with short paths between far-away nodes, but the greedy algorithm tends to miss them. Greedy search is ideal for NSW because it is quick to navigate and has low computational costs. + +### **Hierarchical +** Navigable Small World + +HNSW combines these two concepts. From the hierarchical perspective, the bottom layer consists of a NSW made up of short links between nodes. Each layer above “skips” elements and creates longer links between nodes further away from each other. + +Just like skip lists, search starts at the top layer and works its way down until it finds the target element. However instead of comparing a scalar value at each layer to determine whether or not to descend to the layer below, a multi-dimensional distance measure (such as Euclidean distance) is used. + +## When should you create HNSW indexes? + +Unlike IVFFlat indexes, you are safe to build an HNSW index immediately after the table is created. HNSW indexes are based on graphs which inherently are not affected by the same limitations as IVFFlat. As new data is added to the table, the index will be filled automatically and the index structure will remain optimal. + +## Resources + +Read more about indexing on `pgvector`'s [GitHub page](https://github.com/pgvector/pgvector#indexing). + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/ai/managing-indexes.mdx b/apps/docs/pages/guides/ai/vector-indexes/ivf-indexes.mdx similarity index 63% rename from apps/docs/pages/guides/ai/managing-indexes.mdx rename to apps/docs/pages/guides/ai/vector-indexes/ivf-indexes.mdx index 6269919badf..ebab0ae0f8f 100644 --- a/apps/docs/pages/guides/ai/managing-indexes.mdx +++ b/apps/docs/pages/guides/ai/vector-indexes/ivf-indexes.mdx @@ -1,17 +1,60 @@ import Layout from '~/layouts/DefaultGuideLayout' export const meta = { - id: 'ai-managing-indexes', - title: 'Managing indexes', - description: 'Understanding vector indexes', - sidebar_label: 'Managing indexes', + id: 'ai-ivf-indexes', + title: 'IVFFlat indexes', + description: 'Understanding IVFFlat indexes in pgvector', + sidebar_label: 'IVFFlat indexes', } -Once your vector table starts to grow, you will likely want to add an index to speed up queries. Without indexes, you'll be performing a sequential scan which can be a resource-intensive operation when you have many records. +IVFFlat is a type of vector index for approximate nearest neighbor search, used in high-dimensional spaces like those found in embeddings. -## IVFFlat indexes +## Choosing an index -Today `pgvector` indexes use an algorithm called IVFFlat. IVF stands for 'inverted file indexes'. It works by clustering your vectors in order to reduce the similarity search scope. Rather than comparing a vector to every other vector, the vector is only compared against vectors within the same cell cluster (or nearby clusters, depending on your configuration). +Today `pgvector` supports two types of indexes: + +- [HNSW](/docs/guides/ai/vector-indexes/hnsw-indexes) +- [IVFFlat](/docs/guides/ai/vector-indexes/ivf-indexes) + +In general we recommend using [HNSW](/docs/guides/ai/vector-indexes/hnsw-indexes) because of its [performance gain](/blog/increase-performance-pgvector-hnsw#hnsw-performance-1536-dimensions) and [robustness against changing data](/docs/guides/ai/vector-indexes/hnsw-indexes#when-should-you-create-hnsw-indexes). If you have a special use case that requires IVFFlat instead, keep reading. + +## Usage + +The way you create an IVFFlat index depends on the distance operator you are using. `pgvector` includes 3 distance operators: + +| Operator | Description | [**Operator class**](https://www.postgresql.org/docs/current/sql-createopclass.html) | +| -------- | ---------------------- | ------------------------------------------------------------------------------------ | +| `<->` | Euclidean distance | `vector_l2_ops` | +| `<#>` | negative inner product | `vector_ip_ops` | +| `<=>` | cosine distance | `vector_cosine_ops` | + +Use the following SQL commands to create an IVFFlat index for the operator(s) used in your queries. + +### Euclidean L2 distance (`vector_l2_ops`) + +```sql +create index on items using ivfflat (column_name vector_l2_ops) with (lists = 100); +``` + +### Inner product (`vector_ip_ops`) + +```sql +create index on items using ivfflat (column_name vector_ip_ops) with (lists = 100); +``` + +### Cosine distance (`vector_cosine_ops`) + +```sql +create index on items using ivfflat (column_name vector_cosine_ops) with (lists = 100); +``` + +Currently vectors with up to 2,000 dimensions can be indexed. + +If you are using the `vecs` Python library, follow the instructions in [Managing collections](/docs/guides/ai/managing-collections#create-an-index) to create indexes. + +## How does IVFFlat work? + +IVF stands for 'inverted file indexes'. It works by clustering your vectors in order to reduce the similarity search scope. Rather than comparing a vector to every other vector, the vector is only compared against vectors within the same cell cluster (or nearby clusters, depending on your configuration). ### Inverted lists (cell clusters) @@ -48,43 +91,9 @@ If the number of probes is the same as the number of lists, exact nearest neighb One important note with IVF indexes is that nearest neighbor search is approximate, since exact search on high dimensional data can't be indexed efficiently. This means that similarity results will change (slightly) after you add an index (trading recall for speed). -## Distance operators +## When should you create IVFFlat indexes? -The type of index required depends on the distance operator you are using. `pgvector` includes 3 distance operators: - -| Operator | Description | [**Operator class**](https://www.postgresql.org/docs/current/sql-createopclass.html) | -| -------- | ---------------------- | ------------------------------------------------------------------------------------ | -| `<->` | Euclidean distance | `vector_l2_ops` | -| `<#>` | negative inner product | `vector_ip_ops` | -| `<=>` | cosine distance | `vector_cosine_ops` | - -Use the following SQL commands to create an index for the operator(s) used in your queries. - -### Euclidean L2 distance (`vector_l2_ops`) - -```sql -create index on items using ivfflat (column_name vector_l2_ops) with (lists = 100); -``` - -### Inner product (`vector_ip_ops`) - -```sql -create index on items using ivfflat (column_name vector_ip_ops) with (lists = 100); -``` - -### Cosine distance (`vector_cosine_ops`) - -```sql -create index on items using ivfflat (column_name vector_cosine_ops) with (lists = 100); -``` - -Currently vectors with up to 2,000 dimensions can be indexed. - -If you are using the `vecs` Python library, follow the instructions in [Managing collections](/docs/guides/ai/managing-collections#create-an-index) to create indexes. - -## When should you add indexes? - -`pgvector` recommends adding indexes only after the table has sufficient data, so that the internal IVFFlat cell clusters are based on your data's distribution. Anytime the distribution changes significantly, consider recreating indexes. +`pgvector` recommends buliding IVFFlat indexes only after the table has sufficient data, so that the internal IVFFlat cell clusters are based on your data's distribution. Anytime the distribution changes significantly, consider rebuilding indexes. ## Resources diff --git a/apps/docs/public/img/ai/vector-indexes/hnsw-indexes/nsw.png b/apps/docs/public/img/ai/vector-indexes/hnsw-indexes/nsw.png new file mode 100644 index 0000000000000000000000000000000000000000..63387dd738e404135b128c1aa19d01e88ae0d4c5 GIT binary patch literal 33195 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ðg(mKKCUixx|iEGc_Ll2T+T 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

SV$~;Wm!!>ezj!wtf%(LcbNT^Y3zRd&hwAO zj}3W#>!Ap;$ZUCh(2*ff7+^o=c;eKl%AwB*C?UImS`Fu@>ZdbBc))6GE(}sTpAXSH z_0^*)K1~&E`!h%?1(&@YYthjewN+0HOfkQ6{QQi$Bk#mc z@mAK0nGSpzt0?TkwNm|xMM^cH*p-!4!QUsg!NY^{GR7CkRB(7uI+JlB?Cs^|V1(t2W$Q1OdNzbalrR%kywEW~tb zS>9LyREO>0my&lJ_Xl#v+$d+N$`u~1?Pzpk`*ez3$5Q_c8Ei;m;S_zK|d0A}CcgdFUORl-4uO9?aFr z?Yc5($AfY=Y&vsmi*>KK-IOz1OUy;c{0sZ-0PlDV(N^{S1$<|tukaZ5vb-7%FHHOH z?F1@`s{(szAeH>qC?^!W%!PtVOZ zp`!!N$O*428noX*os>PO4(Qq~I0hESu-`~%uLw_zc2p%lljwWXkMNCZ5!qsBJ)|p) zN^0JQ&NDaM%SHi$9hY{YfXbP;aFmBX(5P?L3`;pjGG2|U>qmxFn8TWWgb3XVPN$i& zA2h3IAOp7!SrA@g9Tm3g6gA|IX~oS%H3?xuQKdHEg6>z5?m18cw4O@8Kwa85!eJsH zNDp4|@@#1s_8i`)JwM}lEt{l;@jRCUG90LR*Cfi1G|00R`g* zwz^fz#EMp!R4VPL8S)D!2uf139Y*dJxp~eu(PvA=f(C9`$F8SgPR#^pbq!hwqdr5< zI6FtB5*{4+Dnm*Z&)}Yvjw(DrwvZ{8hqiB&iCo&uzChZ~ z?X`sc=#DjSKUh^>VW$Qo0S5#UBzaxaFB=AKhk;iHF=6P@y2Ciu(nr2&a(f6J zcv0Z{*GzV6M-_l8tAG`lVE1&%r+T}hM-QJ{OL;pMnaHA{Qj}mF&L2rHq_BPM36v-Q zsN|)iuD+PWm~}1W9Jj|t<6qLttbcIED)+-L3xO!Yz}p57*?EdiO}^ zs_;89IWrquT-*;jK^~WT&d3W|_mW-&-IK;=?0}uS3!>7TYyD5H2)>Yu%sW%9CRsTN zSLRpRs$b1ZL$(y6&5k+^{ezb!5pYGuNV|~NFXrOpSQ>t|IhYKj^j+sTG^@6<$lg_% zmBZc*A)bpzt4AChvyPBGpNb9^Zl7gCy#`Zr7Si68CJ);vz8N-}p@j6p6ZX0mWF}u5FW_e9!hc`#l96~`@9S8axnFXi4E2nK%adJp!VN11!6#8X z|82cZe+j2m_DILXzORzo4yOeH+kWqkLk661GgBcUA^sqpUuw>MTOz)ujZr9{g|G)v zQME7&JIN7DcWmM7C@S<6Mv1`aLyuWB@F|{hjoxPN<25|g20R}BS|;47m|E0S__Yt5 z)$X)0;OIw#(dpIm<*@^fDCpT-gN=Q0QiqYMl9w)5j#IdP$zr%w8rvMHx~>VWY0$WE zD^M%jxY7#R*_>gH=LovE4c4$;DNa{0xiA7tcQKYmO&}(=aMTC3Uz^B6v{wa-#uzKz zI&Y!7XV@b040PY^vZ6h{1wow5r1Yl)*#*jqN=l;xNn PkYV!Y2XvLYyGVv<0ke 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 literal 0 HcmV?d00001 diff --git a/apps/docs/public/img/ai/vector-indexes/hnsw-indexes/skip-list--dark.png b/apps/docs/public/img/ai/vector-indexes/hnsw-indexes/skip-list--dark.png new file mode 100644 index 0000000000000000000000000000000000000000..856fa59c0ced4e2790320c8b6fd9b1e308c482d9 GIT binary patch literal 17088 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 GAN(&J>9T - https://supabase.com/docs/guides/ai/managing-indexes + https://supabase.com/docs/guides/ai/vector-indexes weekly 0.5 diff --git a/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx b/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx index 3aedde1e0dc..f54e8bf05a1 100644 --- a/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx +++ b/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx @@ -29,7 +29,7 @@ Without indexes, pgvector performs a full table scan when you run a similarity q To solve this, pgvector offers indexes. Indexes reorganize the data into data structures that exploit internal structure and enable approximate similarity search without referring to every record. Currently, pgvector supports an IVF index, with HNSW expected in the next release. -IVF [indexes](https://supabase.com/docs/guides/ai/managing-indexes) work by clustering vectors into `lists`, and then querying only vectors within the same list (or multiple nearby lists, depending on the value of `probes`). +IVF [indexes](https://supabase.com/docs/guides/ai/vector-indexes/ivf-indexes#how-does-ivfflat-work) work by clustering vectors into `lists`, and then querying only vectors within the same list (or multiple nearby lists, depending on the value of `probes`). ### Scaling indexes diff --git a/apps/www/_blog/2023-09-06-increase-performance-pgvector-hnsw.mdx b/apps/www/_blog/2023-09-06-increase-performance-pgvector-hnsw.mdx index 7fe68f90546..0ce3b312e93 100644 --- a/apps/www/_blog/2023-09-06-increase-performance-pgvector-hnsw.mdx +++ b/apps/www/_blog/2023-09-06-increase-performance-pgvector-hnsw.mdx @@ -37,7 +37,7 @@ USING hnsw (embedding vector_ip_ops); ## How does HNSW work? -Compared to inverted file (IVF) indexes which use [clusters](https://supabase.com/docs/guides/ai/managing-indexes#ivfflat-indexes) to approximate nearest-neighbor search, HNSW uses proximity graphs (graphs connecting nodes based on distance between them). To understand HNSW, we can break it down into 2 parts: +Compared to inverted file (IVF) indexes which use [clusters](https://supabase.com/docs/guides/ai/vector-indexes/ivf-indexes#how-does-ivfflat-work) to approximate nearest-neighbor search, HNSW uses proximity graphs (graphs connecting nodes based on distance between them). To understand HNSW, we can break it down into 2 parts: - **Hierarchical (H):** The algorithm operates over multiple layers - **Navigable Small World (NSW):** Each vector is a node within a graph and is connected to several other nodes diff --git a/apps/www/lib/redirects.js b/apps/www/lib/redirects.js index 6e759559be9..ea2d46573fb 100644 --- a/apps/www/lib/redirects.js +++ b/apps/www/lib/redirects.js @@ -2293,4 +2293,9 @@ module.exports = [ source: '/blog/pgvector-v0-5-0-hnsw', destination: '/blog/increase-performance-pgvector-hnsw', }, + { + permanent: true, + source: '/docs/guides/ai/managing-indexes', + destination: '/docs/guides/ai/vector-indexes', + }, ]