docs: add links to rust SDK docs, remove references to rust SDK being unstable / experimental (#1131)

This commit is contained in:
Weston Pace
2024-03-19 07:16:48 -07:00
parent abde77eafb
commit 0fe0976a0e
13 changed files with 321 additions and 104 deletions

View File

@@ -27,7 +27,6 @@ theme:
- content.tabs.link - content.tabs.link
- content.action.edit - content.action.edit
- toc.follow - toc.follow
# - toc.integrate
- navigation.top - navigation.top
- navigation.tabs - navigation.tabs
- navigation.tabs.sticky - navigation.tabs.sticky
@@ -64,7 +63,7 @@ plugins:
add_image: True # Automatically add meta image add_image: True # Automatically add meta image
add_keywords: True # Add page keywords in the header tag add_keywords: True # Add page keywords in the header tag
add_share_buttons: True # Add social share buttons add_share_buttons: True # Add social share buttons
add_authors: False # Display page authors add_authors: False # Display page authors
add_desc: False add_desc: False
add_dates: False add_dates: False
@@ -140,11 +139,13 @@ nav:
- Serverless Website Chatbot: examples/serverless_website_chatbot.md - Serverless Website Chatbot: examples/serverless_website_chatbot.md
- YouTube Transcript Search: examples/youtube_transcript_bot_with_nodejs.md - YouTube Transcript Search: examples/youtube_transcript_bot_with_nodejs.md
- TransformersJS Embedding Search: examples/transformerjs_embedding_search_nodejs.md - TransformersJS Embedding Search: examples/transformerjs_embedding_search_nodejs.md
- 🦀 Rust:
- Overview: examples/examples_rust.md
- 💭 FAQs: faq.md - 💭 FAQs: faq.md
- ⚙️ API reference: - ⚙️ API reference:
- 🐍 Python: python/python.md - 🐍 Python: python/python.md
- 👾 JavaScript: javascript/modules.md - 👾 JavaScript: javascript/modules.md
- 🦀 Rust: https://docs.rs/vectordb/latest/vectordb/ - 🦀 Rust: https://docs.rs/lancedb/latest/lancedb/
- ☁️ LanceDB Cloud: - ☁️ LanceDB Cloud:
- Overview: cloud/index.md - Overview: cloud/index.md
- API reference: - API reference:
@@ -188,21 +189,21 @@ nav:
- Pydantic: python/pydantic.md - Pydantic: python/pydantic.md
- Voxel51: integrations/voxel51.md - Voxel51: integrations/voxel51.md
- PromptTools: integrations/prompttools.md - PromptTools: integrations/prompttools.md
- Python examples: - Examples:
- examples/index.md - examples/index.md
- YouTube Transcript Search: notebooks/youtube_transcript_search.ipynb - YouTube Transcript Search: notebooks/youtube_transcript_search.ipynb
- Documentation QA Bot using LangChain: notebooks/code_qa_bot.ipynb - Documentation QA Bot using LangChain: notebooks/code_qa_bot.ipynb
- Multimodal search using CLIP: notebooks/multimodal_search.ipynb - Multimodal search using CLIP: notebooks/multimodal_search.ipynb
- Serverless QA Bot with S3 and Lambda: examples/serverless_lancedb_with_s3_and_lambda.md - Serverless QA Bot with S3 and Lambda: examples/serverless_lancedb_with_s3_and_lambda.md
- Serverless QA Bot with Modal: examples/serverless_qa_bot_with_modal_and_langchain.md - Serverless QA Bot with Modal: examples/serverless_qa_bot_with_modal_and_langchain.md
- Javascript examples: - YouTube Transcript Search (JS): examples/youtube_transcript_bot_with_nodejs.md
- Overview: examples/examples_js.md
- YouTube Transcript Search: examples/youtube_transcript_bot_with_nodejs.md
- Serverless Chatbot from any website: examples/serverless_website_chatbot.md - Serverless Chatbot from any website: examples/serverless_website_chatbot.md
- TransformersJS Embedding Search: examples/transformerjs_embedding_search_nodejs.md - TransformersJS Embedding Search: examples/transformerjs_embedding_search_nodejs.md
- API reference: - API reference:
- Overview: api_reference.md
- Python: python/python.md - Python: python/python.md
- Javascript: javascript/modules.md - Javascript: javascript/modules.md
- Rust: https://docs.rs/lancedb/latest/lancedb/index.html
- LanceDB Cloud: - LanceDB Cloud:
- Overview: cloud/index.md - Overview: cloud/index.md
- API reference: - API reference:

View File

@@ -19,39 +19,61 @@ Lance supports `IVF_PQ` index type by default.
=== "Python" === "Python"
Creating indexes is done via the [create_index](https://lancedb.github.io/lancedb/python/#lancedb.table.LanceTable.create_index) method. Creating indexes is done via the [create_index](https://lancedb.github.io/lancedb/python/#lancedb.table.LanceTable.create_index) method.
```python ```python
import lancedb import lancedb
import numpy as np import numpy as np
uri = "data/sample-lancedb" uri = "data/sample-lancedb"
db = lancedb.connect(uri) db = lancedb.connect(uri)
# Create 10,000 sample vectors # Create 10,000 sample vectors
data = [{"vector": row, "item": f"item {i}"} data = [{"vector": row, "item": f"item {i}"}
for i, row in enumerate(np.random.random((10_000, 1536)).astype('float32'))] for i, row in enumerate(np.random.random((10_000, 1536)).astype('float32'))]
# Add the vectors to a table # Add the vectors to a table
tbl = db.create_table("my_vectors", data=data) tbl = db.create_table("my_vectors", data=data)
# Create and train the index - you need to have enough data in the table for an effective training step # Create and train the index - you need to have enough data in the table for an effective training step
tbl.create_index(num_partitions=256, num_sub_vectors=96) tbl.create_index(num_partitions=256, num_sub_vectors=96)
``` ```
=== "Typescript" === "Typescript"
```typescript ```typescript
--8<--- "docs/src/ann_indexes.ts:import" --8<--- "docs/src/ann_indexes.ts:import"
--8<-- "docs/src/ann_indexes.ts:ingest" --8<-- "docs/src/ann_indexes.ts:ingest"
``` ```
- **metric** (default: "L2"): The distance metric to use. By default it uses euclidean distance "`L2`". === "Rust"
```rust
--8<-- "rust/lancedb/examples/ivf_pq.rs:create_index"
```
IVF_PQ index parameters are more fully defined in the [crate docs](https://docs.rs/lancedb/latest/lancedb/index/vector/struct.IvfPqIndexBuilder.html).
The following IVF_PQ paramters can be specified:
- **distance_type**: The distance metric to use. By default it uses euclidean distance "`L2`".
We also support "cosine" and "dot" distance as well. We also support "cosine" and "dot" distance as well.
- **num_partitions** (default: 256): The number of partitions of the index. - **num_partitions**: The number of partitions in the index. The default is the square root
- **num_sub_vectors** (default: 96): The number of sub-vectors (M) that will be created during Product Quantization (PQ). of the number of rows.
For D dimensional vector, it will be divided into `M` of `D/M` sub-vectors, each of which is presented by
a single PQ code. !!! note
In the synchronous python SDK and node's `vectordb` the default is 256. This default has
changed in the asynchronous python SDK and node's `lancedb`.
- **num_sub_vectors**: The number of sub-vectors (M) that will be created during Product Quantization (PQ).
For D dimensional vector, it will be divided into `M` subvectors with dimension `D/M`, each of which is replaced by
a single PQ code. The default is the dimension of the vector divided by 16.
!!! note
In the synchronous python SDK and node's `vectordb` the default is currently 96. This default has
changed in the asynchronous python SDK and node's `lancedb`.
<figure markdown> <figure markdown>
![IVF PQ](./assets/ivf_pq.png) ![IVF PQ](./assets/ivf_pq.png)
@@ -114,25 +136,33 @@ There are a couple of parameters that can be used to fine-tune the search:
=== "Python" === "Python"
```python ```python
tbl.search(np.random.random((1536))) \ tbl.search(np.random.random((1536))) \
.limit(2) \ .limit(2) \
.nprobes(20) \ .nprobes(20) \
.refine_factor(10) \ .refine_factor(10) \
.to_pandas() .to_pandas()
``` ```
```text ```text
vector item _distance vector item _distance
0 [0.44949695, 0.8444449, 0.06281311, 0.23338133... item 1141 103.575333 0 [0.44949695, 0.8444449, 0.06281311, 0.23338133... item 1141 103.575333
1 [0.48587373, 0.269207, 0.15095535, 0.65531915,... item 3953 108.393867 1 [0.48587373, 0.269207, 0.15095535, 0.65531915,... item 3953 108.393867
``` ```
=== "Typescript" === "Typescript"
```typescript ```typescript
--8<-- "docs/src/ann_indexes.ts:search1" --8<-- "docs/src/ann_indexes.ts:search1"
``` ```
=== "Rust"
```rust
--8<-- "rust/lancedb/examples/ivf_pq.rs:search1"
```
Vector search options are more fully defined in the [crate docs](https://docs.rs/lancedb/latest/lancedb/query/struct.Query.html#method.nearest_to).
The search will return the data requested in addition to the distance of each item. The search will return the data requested in addition to the distance of each item.
@@ -181,7 +211,7 @@ You can select the columns returned by the query using a select clause.
### Why do I need to manually create an index? ### Why do I need to manually create an index?
Currently, LanceDB does _not_ automatically create the ANN index. Currently, LanceDB does _not_ automatically create the ANN index.
LanceDB is well-optimized for kNN (exhaustive search) via a disk-based index. For many use-cases, LanceDB is well-optimized for kNN (exhaustive search) via a disk-based index. For many use-cases,
datasets of the order of ~100K vectors don't require index creation. If you can live with up to datasets of the order of ~100K vectors don't require index creation. If you can live with up to
100ms latency, skipping index creation is a simpler workflow while guaranteeing 100% recall. 100ms latency, skipping index creation is a simpler workflow while guaranteeing 100% recall.

View File

@@ -0,0 +1,7 @@
# API Reference
The API reference for the LanceDB client SDKs are available at the following locations:
- [Python](python/python.md)
- [JavaScript](javascript/modules.md)
- [Rust](https://docs.rs/lancedb/latest/lancedb/index.html)

View File

@@ -3,7 +3,7 @@
!!! info "LanceDB can be run in a number of ways:" !!! info "LanceDB can be run in a number of ways:"
* Embedded within an existing backend (like your Django, Flask, Node.js or FastAPI application) * Embedded within an existing backend (like your Django, Flask, Node.js or FastAPI application)
* Connected to directly from a client application like a Jupyter notebook for analytical workloads * Directly from a client application like a Jupyter notebook for analytical workloads
* Deployed as a remote serverless database * Deployed as a remote serverless database
![](assets/lancedb_embedded_explanation.png) ![](assets/lancedb_embedded_explanation.png)
@@ -24,13 +24,11 @@
=== "Rust" === "Rust"
!!! warning "Rust SDK is experimental, might introduce breaking changes in the near future"
```shell ```shell
cargo add vectordb cargo add lancedb
``` ```
!!! info "To use the vectordb create, you first need to install protobuf." !!! info "To use the lancedb create, you first need to install protobuf."
=== "macOS" === "macOS"
@@ -44,7 +42,7 @@
sudo apt install -y protobuf-compiler libssl-dev sudo apt install -y protobuf-compiler libssl-dev
``` ```
!!! info "Please also make sure you're using the same version of Arrow as in the [vectordb crate](https://github.com/lancedb/lancedb/blob/main/Cargo.toml)" !!! info "Please also make sure you're using the same version of Arrow as in the [lancedb crate](https://github.com/lancedb/lancedb/blob/main/Cargo.toml)"
## Connect to a database ## Connect to a database
@@ -81,10 +79,11 @@ If you need a reminder of the uri, you can call `db.uri()`.
## Create a table ## Create a table
### Directly insert data to a new table ### Create a table from initial data
If you have data to insert into the table at creation time, you can simultaneously create a If you have data to insert into the table at creation time, you can simultaneously create a
table and insert the data to it. table and insert the data into it. The schema of the data will be used as the schema of the
table.
=== "Python" === "Python"
@@ -120,21 +119,27 @@ table and insert the data to it.
=== "Rust" === "Rust"
```rust ```rust
use arrow_schema::{DataType, Schema, Field};
use arrow_array::{RecordBatch, RecordBatchIterator};
--8<-- "rust/lancedb/examples/simple.rs:create_table" --8<-- "rust/lancedb/examples/simple.rs:create_table"
``` ```
If the table already exists, LanceDB will raise an error by default. If the table already exists, LanceDB will raise an error by default. See
[the mode option](https://docs.rs/lancedb/latest/lancedb/connection/struct.CreateTableBuilder.html#method.mode)
for details on how to overwrite (or open) existing tables instead.
!!! info "Under the hood, LanceDB converts the input data into an Apache Arrow table and persists it to disk using the [Lance format](https://www.github.com/lancedb/lance)." !!! Providing table records in Rust
The Rust SDK currently expects data to be provided as an Arrow
[RecordBatchReader](https://docs.rs/arrow-array/latest/arrow_array/trait.RecordBatchReader.html)
Support for additional formats (such as serde or polars) is on the roadmap.
!!! info "Under the hood, LanceDB reads in the Apache Arrow data and persists it to disk using the [Lance format](https://www.github.com/lancedb/lance)."
### Create an empty table ### Create an empty table
Sometimes you may not have the data to insert into the table at creation time. Sometimes you may not have the data to insert into the table at creation time.
In this case, you can create an empty table and specify the schema, so that you can add In this case, you can create an empty table and specify the schema, so that you can add
data to the table at a later time (such that it conforms to the schema). data to the table at a later time (as long as it conforms to the schema). This is
similar to a `CREATE TABLE` statement in SQL.
=== "Python" === "Python"
@@ -175,7 +180,7 @@ Once created, you can open a table as follows:
=== "Rust" === "Rust"
```rust ```rust
--8<-- "rust/lancedb/examples/simple.rs:open_with_existing_file" --8<-- "rust/lancedb/examples/simple.rs:open_existing_tbl"
``` ```
If you forget the name of your table, you can always get a listing of all table names: If you forget the name of your table, you can always get a listing of all table names:
@@ -254,6 +259,14 @@ Once you've embedded the query, you can find its nearest neighbors as follows:
--8<-- "rust/lancedb/examples/simple.rs:search" --8<-- "rust/lancedb/examples/simple.rs:search"
``` ```
!!! Query vectors in Rust
Rust does not yet support automatic execution of embedding functions. You will need to
calculate embeddings yourself. Support for this is on the roadmap and can be tracked at
https://github.com/lancedb/lancedb/issues/994
Query vectors can be provided as Arrow arrays or a Vec/slice of Rust floats.
Support for additional formats (e.g. `polars::series::Series`) is on the roadmap.
By default, LanceDB runs a brute-force scan over dataset to find the K nearest neighbours (KNN). By default, LanceDB runs a brute-force scan over dataset to find the K nearest neighbours (KNN).
For tables with more than 50K vectors, creating an ANN index is recommended to speed up search performance. For tables with more than 50K vectors, creating an ANN index is recommended to speed up search performance.
LanceDB allows you to create an ANN index on a table as follows: LanceDB allows you to create an ANN index on a table as follows:
@@ -277,7 +290,7 @@ LanceDB allows you to create an ANN index on a table as follows:
``` ```
!!! note "Why do I need to create an index manually?" !!! note "Why do I need to create an index manually?"
LanceDB does not automatically create the ANN index, for two reasons. The first is that it's optimized LanceDB does not automatically create the ANN index for two reasons. The first is that it's optimized
for really fast retrievals via a disk-based index, and the second is that data and query workloads can for really fast retrievals via a disk-based index, and the second is that data and query workloads can
be very diverse, so there's no one-size-fits-all index configuration. LanceDB provides many parameters be very diverse, so there's no one-size-fits-all index configuration. LanceDB provides many parameters
to fine-tune index size, query latency and accuracy. See the section on to fine-tune index size, query latency and accuracy. See the section on
@@ -308,8 +321,9 @@ This can delete any number of rows that match the filter.
``` ```
The deletion predicate is a SQL expression that supports the same expressions The deletion predicate is a SQL expression that supports the same expressions
as the `where()` clause on a search. They can be as simple or complex as needed. as the `where()` clause (`only_if()` in Rust) on a search. They can be as
To see what expressions are supported, see the [SQL filters](sql.md) section. simple or complex as needed. To see what expressions are supported, see the
[SQL filters](sql.md) section.
=== "Python" === "Python"
@@ -319,6 +333,10 @@ To see what expressions are supported, see the [SQL filters](sql.md) section.
Read more: [vectordb.Table.delete](javascript/interfaces/Table.md#delete) Read more: [vectordb.Table.delete](javascript/interfaces/Table.md#delete)
=== "Rust"
Read more: [lancedb::Table::delete](https://docs.rs/lancedb/latest/lancedb/table/struct.Table.html#method.delete)
## Drop a table ## Drop a table
Use the `drop_table()` method on the database to remove a table. Use the `drop_table()` method on the database to remove a table.

View File

@@ -0,0 +1,3 @@
# Examples: Rust
Our Rust SDK is now stable. Examples are coming soon.

View File

@@ -2,10 +2,11 @@
## Recipes and example code ## Recipes and example code
LanceDB provides language APIs, allowing you to embed a database in your language of choice. We currently provide Python and Javascript APIs, with the Rust API and examples actively being worked on and will be available soon. LanceDB provides language APIs, allowing you to embed a database in your language of choice.
* 🐍 [Python](examples_python.md) examples * 🐍 [Python](examples_python.md) examples
* 👾 [JavaScript](exampled_js.md) examples * 👾 [JavaScript](examples_js.md) examples
* 🦀 Rust examples (coming soon)
## Applications powered by LanceDB ## Applications powered by LanceDB

View File

@@ -16,7 +16,7 @@ As we mention in our talk titled “[Lance, a modern columnar data format](https
### Why build in Rust? 🦀 ### Why build in Rust? 🦀
We believe that the Rust ecosystem has attained mainstream maturity and that Rust will form the underpinnings of large parts of the data and ML landscape in a few years. Performance, latency and reliability are paramount to a vector DB, and building in Rust allows us to iterate and release updates more rapidly due to Rusts safety guarantees. Both Lance (the data format) and LanceDB (the database) are written entirely in Rust. We also provide Python and JavaScript client libraries to interact with the database. Our Rust API is a little rough around the edges right now, but is fast becoming on par with the Python and JS APIs. We believe that the Rust ecosystem has attained mainstream maturity and that Rust will form the underpinnings of large parts of the data and ML landscape in a few years. Performance, latency and reliability are paramount to a vector DB, and building in Rust allows us to iterate and release updates more rapidly due to Rusts safety guarantees. Both Lance (the data format) and LanceDB (the database) are written entirely in Rust. We also provide Python, JavaScript, and Rust client libraries to interact with the database.
### What is the difference between LanceDB OSS and LanceDB Cloud? ### What is the difference between LanceDB OSS and LanceDB Cloud?
@@ -44,7 +44,7 @@ For large-scale (>1M) or higher dimension vectors, it is beneficial to create an
### Does LanceDB support full-text search? ### Does LanceDB support full-text search?
Yes, LanceDB supports full-text search (FTS) via [Tantivy](https://github.com/quickwit-oss/tantivy). Our current FTS integration is Python-only, and our goal is to push it down to the Rust level in future versions to enable much more powerful search capabilities available to our Python, JavaScript and Rust clients. Yes, LanceDB supports full-text search (FTS) via [Tantivy](https://github.com/quickwit-oss/tantivy). Our current FTS integration is Python-only, and our goal is to push it down to the Rust level in future versions to enable much more powerful search capabilities available to our Python, JavaScript and Rust clients. Follow along in the [Github issue](https://github.com/lancedb/lance/issues/1195)
### How can I speed up data inserts? ### How can I speed up data inserts?

View File

@@ -1,6 +1,6 @@
# Full-text search # Full-text search
LanceDB provides support for full-text search via [Tantivy](https://github.com/quickwit-oss/tantivy) (currently Python only), allowing you to incorporate keyword-based search (based on BM25) in your retrieval solutions. Our goal is to push the FTS integration down to the Rust level in the future, so that it's available for JavaScript users as well. LanceDB provides support for full-text search via [Tantivy](https://github.com/quickwit-oss/tantivy) (currently Python only), allowing you to incorporate keyword-based search (based on BM25) in your retrieval solutions. Our goal is to push the FTS integration down to the Rust level in the future, so that it's available for Rust and JavaScript users as well. Follow along at [this Github issue](https://github.com/lancedb/lance/issues/1195)
A hybrid search solution combining vector and full-text search is also on the way. A hybrid search solution combining vector and full-text search is also on the way.
@@ -77,7 +77,7 @@ table.search("puppy").limit(10).where("meta='foo'").to_list()
## Phrase queries vs. terms queries ## Phrase queries vs. terms queries
For full-text search you can specify either a **phrase** query like `"the old man and the sea"`, For full-text search you can specify either a **phrase** query like `"the old man and the sea"`,
or a **terms** search query like `"(Old AND Man) AND Sea"`. For more details on the terms or a **terms** search query like `"(Old AND Man) AND Sea"`. For more details on the terms
query syntax, see Tantivy's [query parser rules](https://docs.rs/tantivy/latest/tantivy/query/struct.QueryParser.html). query syntax, see Tantivy's [query parser rules](https://docs.rs/tantivy/latest/tantivy/query/struct.QueryParser.html).
@@ -112,7 +112,7 @@ double quotes replaced by single quotes.
## Configurations ## Configurations
By default, LanceDB configures a 1GB heap size limit for creating the index. You can By default, LanceDB configures a 1GB heap size limit for creating the index. You can
reduce this if running on a smaller node, or increase this for faster performance while reduce this if running on a smaller node, or increase this for faster performance while
indexing a larger corpus. indexing a larger corpus.
@@ -128,7 +128,6 @@ table.create_fts_index(["text1", "text2"], writer_heap_size=heap, replace=True)
If you add data after FTS index creation, it won't be reflected If you add data after FTS index creation, it won't be reflected
in search results until you do a full reindex. in search results until you do a full reindex.
2. We currently only support local filesystem paths for the FTS index. 2. We currently only support local filesystem paths for the FTS index.
This is a tantivy limitation. We've implemented an object store plugin This is a tantivy limitation. We've implemented an object store plugin
but there's no way in tantivy-py to specify to use it. but there's no way in tantivy-py to specify to use it.

View File

@@ -28,7 +28,7 @@ LanceDB **Cloud** is a SaaS (software-as-a-service) solution that runs serverles
* Fast production-scale vector similarity, full-text & hybrid search and a SQL query interface (via [DataFusion](https://github.com/apache/arrow-datafusion)) * Fast production-scale vector similarity, full-text & hybrid search and a SQL query interface (via [DataFusion](https://github.com/apache/arrow-datafusion))
* Native Python and Javascript/Typescript support * Python, Javascript/Typescript, and Rust support
* Store, query & manage multi-modal data (text, images, videos, point clouds, etc.), not just the embeddings and metadata * Store, query & manage multi-modal data (text, images, videos, point clouds, etc.), not just the embeddings and metadata
@@ -54,3 +54,4 @@ The following pages go deeper into the internal of LanceDB and how to use it.
* [Ecosystem Integrations](integrations/index.md): Integrate LanceDB with other tools in the data ecosystem * [Ecosystem Integrations](integrations/index.md): Integrate LanceDB with other tools in the data ecosystem
* [Python API Reference](python/python.md): Python OSS and Cloud API references * [Python API Reference](python/python.md): Python OSS and Cloud API references
* [JavaScript API Reference](javascript/modules.md): JavaScript OSS and Cloud API references * [JavaScript API Reference](javascript/modules.md): JavaScript OSS and Cloud API references
* [Rust API Reference](https://docs.rs/lancedb/latest/lancedb/index.html): Rust API reference

View File

@@ -22,7 +22,7 @@ Currently, LanceDB supports the following metrics:
## Exhaustive search (kNN) ## Exhaustive search (kNN)
If you do not create a vector index, LanceDB exhaustively scans the _entire_ vector space If you do not create a vector index, LanceDB exhaustively scans the _entire_ vector space
and compute the distance to every vector in order to find the exact nearest neighbors. This is effectively a kNN search. and computes the distance to every vector in order to find the exact nearest neighbors. This is effectively a kNN search.
<!-- Setup Code <!-- Setup Code
```python ```python
@@ -85,7 +85,7 @@ To perform scalable vector retrieval with acceptable latencies, it's common to b
While the exhaustive search is guaranteed to always return 100% recall, the approximate nature of While the exhaustive search is guaranteed to always return 100% recall, the approximate nature of
an ANN search means that using an index often involves a trade-off between recall and latency. an ANN search means that using an index often involves a trade-off between recall and latency.
See the [IVF_PQ index](./concepts/index_ivfpq.md.md) for a deeper description of how `IVF_PQ` See the [IVF_PQ index](./concepts/index_ivfpq.md) for a deeper description of how `IVF_PQ`
indexes work in LanceDB. indexes work in LanceDB.
## Output search results ## Output search results
@@ -184,4 +184,3 @@ Let's create a LanceDB table with a nested schema:
Note that in this case the extra `_distance` field is discarded since Note that in this case the extra `_distance` field is discarded since
it's not part of the LanceSchema. it's not part of the LanceSchema.

View File

@@ -0,0 +1,165 @@
// Copyright 2024 Lance Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This example demonstrates setting advanced parameters when building an IVF PQ index
//!
//! Snippets from this example are used in the documentation on ANN indices.
use std::sync::Arc;
use arrow_array::types::Float32Type;
use arrow_array::{
FixedSizeListArray, Int32Array, RecordBatch, RecordBatchIterator, RecordBatchReader,
};
use arrow_schema::{DataType, Field, Schema};
use futures::TryStreamExt;
use lancedb::connection::Connection;
use lancedb::index::vector::IvfPqIndexBuilder;
use lancedb::index::Index;
use lancedb::query::{ExecutableQuery, QueryBase};
use lancedb::{connect, DistanceType, Result, Table};
#[tokio::main]
async fn main() -> Result<()> {
if std::path::Path::new("data").exists() {
std::fs::remove_dir_all("data").unwrap();
}
let uri = "data/sample-lancedb";
let db = connect(uri).execute().await?;
let tbl = create_table(&db).await?;
create_index(&tbl).await?;
search_index(&tbl).await?;
Ok(())
}
fn create_some_records() -> Result<Box<dyn RecordBatchReader + Send>> {
const TOTAL: usize = 1000;
const DIM: usize = 128;
let schema = Arc::new(Schema::new(vec![
Field::new("id", DataType::Int32, false),
Field::new(
"vector",
DataType::FixedSizeList(
Arc::new(Field::new("item", DataType::Float32, true)),
DIM as i32,
),
true,
),
]));
// Create a RecordBatch stream.
let batches = RecordBatchIterator::new(
vec![RecordBatch::try_new(
schema.clone(),
vec![
Arc::new(Int32Array::from_iter_values(0..TOTAL as i32)),
Arc::new(
FixedSizeListArray::from_iter_primitive::<Float32Type, _, _>(
(0..TOTAL).map(|_| Some(vec![Some(1.0); DIM])),
DIM as i32,
),
),
],
)
.unwrap()]
.into_iter()
.map(Ok),
schema.clone(),
);
Ok(Box::new(batches))
}
async fn create_table(db: &Connection) -> Result<Table> {
let initial_data: Box<dyn RecordBatchReader + Send> = create_some_records()?;
let tbl = db
.create_table("my_table", Box::new(initial_data))
.execute()
.await
.unwrap();
Ok(tbl)
}
async fn create_index(table: &Table) -> Result<()> {
// --8<-- [start:create_index]
// For this example, `table` is a lancedb::Table with a column named
// "vector" that is a vector column with dimension 128.
// By default, if the column "vector" appears to be a vector column,
// then an IVF_PQ index with reasonable defaults is created.
table
.create_index(&["vector"], Index::Auto)
.execute()
.await?;
// For advanced cases, it is also possible to specifically request an
// IVF_PQ index and provide custom parameters.
table
.create_index(
&["vector"],
Index::IvfPq(
// Here we specify advanced indexing parameters. In this case
// we are creating an index that my have better recall than the
// default but is also larger and slower.
IvfPqIndexBuilder::default()
// This overrides the default distance type of L2
.distance_type(DistanceType::Cosine)
// With 1000 rows this have been ~31 by default
.num_partitions(50)
// With dimension 128 this would have been 8 by default
.num_sub_vectors(16),
),
)
.execute()
.await?;
// --8<-- [end:create_index]
Ok(())
}
async fn search_index(table: &Table) -> Result<()> {
// --8<-- [start:search1]
let query_vector = [1.0; 128];
// By default the index will find the 10 closest results using default
// search parameters that give a reasonable tradeoff between accuracy
// and search latency
let mut results = table
.vector_search(&query_vector)?
// Note: you should always set the distance_type to match the value used
// to train the index
.distance_type(DistanceType::Cosine)
.execute()
.await?;
while let Some(batch) = results.try_next().await? {
println!("{:?}", batch);
}
// We can also provide custom search parameters. Here we perform a
// slower but more accurate search
let mut results = table
.vector_search(&query_vector)?
.distance_type(DistanceType::Cosine)
// Override the default of 10 to get more rows
.limit(15)
// Override the default of 20 to search more partitions
.nprobes(30)
// Override the default of None to apply a refine step
.refine_factor(1)
.execute()
.await?;
while let Some(batch) = results.try_next().await? {
println!("{:?}", batch);
}
Ok(())
// --8<-- [end:search1]
}

View File

@@ -12,10 +12,16 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//! This example demonstrates basic usage of LanceDb.
//!
//! Snippets from this example are used in the quickstart documentation.
use std::sync::Arc; use std::sync::Arc;
use arrow_array::types::Float32Type; use arrow_array::types::Float32Type;
use arrow_array::{FixedSizeListArray, Int32Array, RecordBatch, RecordBatchIterator}; use arrow_array::{
FixedSizeListArray, Int32Array, RecordBatch, RecordBatchIterator, RecordBatchReader,
};
use arrow_schema::{DataType, Field, Schema}; use arrow_schema::{DataType, Field, Schema};
use futures::TryStreamExt; use futures::TryStreamExt;
@@ -58,14 +64,14 @@ async fn main() -> Result<()> {
async fn open_with_existing_tbl() -> Result<()> { async fn open_with_existing_tbl() -> Result<()> {
let uri = "data/sample-lancedb"; let uri = "data/sample-lancedb";
let db = connect(uri).execute().await?; let db = connect(uri).execute().await?;
// --8<-- [start:open_with_existing_file] #[allow(unused_variables)]
let _ = db.open_table("my_table").execute().await.unwrap(); // --8<-- [start:open_existing_tbl]
// --8<-- [end:open_with_existing_file] let table = db.open_table("my_table").execute().await.unwrap();
// --8<-- [end:open_existing_tbl]
Ok(()) Ok(())
} }
async fn create_table(db: &Connection) -> Result<LanceDbTable> { fn create_some_records() -> Result<Box<dyn RecordBatchReader + Send>> {
// --8<-- [start:create_table]
const TOTAL: usize = 1000; const TOTAL: usize = 1000;
const DIM: usize = 128; const DIM: usize = 128;
@@ -100,33 +106,22 @@ async fn create_table(db: &Connection) -> Result<LanceDbTable> {
.map(Ok), .map(Ok),
schema.clone(), schema.clone(),
); );
Ok(Box::new(batches))
}
async fn create_table(db: &Connection) -> Result<LanceDbTable> {
// --8<-- [start:create_table]
let initial_data: Box<dyn RecordBatchReader + Send> = create_some_records()?;
let tbl = db let tbl = db
.create_table("my_table", Box::new(batches)) .create_table("my_table", Box::new(initial_data))
.execute() .execute()
.await .await
.unwrap(); .unwrap();
// --8<-- [end:create_table] // --8<-- [end:create_table]
let new_batches = RecordBatchIterator::new(
vec![RecordBatch::try_new(
schema.clone(),
vec![
Arc::new(Int32Array::from_iter_values(0..TOTAL as i32)),
Arc::new(
FixedSizeListArray::from_iter_primitive::<Float32Type, _, _>(
(0..TOTAL).map(|_| Some(vec![Some(1.0); DIM])),
DIM as i32,
),
),
],
)
.unwrap()]
.into_iter()
.map(Ok),
schema.clone(),
);
// --8<-- [start:add] // --8<-- [start:add]
tbl.add(Box::new(new_batches)).execute().await.unwrap(); let new_data = create_some_records()?;
tbl.add(new_data).execute().await.unwrap();
// --8<-- [end:add] // --8<-- [end:add]
Ok(tbl) Ok(tbl)

View File

@@ -36,8 +36,6 @@
//! //!
//! ### Quick Start //! ### Quick Start
//! //!
//! <div class="warning">Rust API is not stable yet, please expect breaking changes.</div>
//!
//! #### Connect to a database. //! #### Connect to a database.
//! //!
//! ```rust //! ```rust