跳转到内容

快速入门

LanceDB 可以通过多种方式运行:

  • 嵌入到现有后端中(如您的Django、Flask、Node.js或FastAPI应用)
  • 直接从客户端应用程序(如Jupyter笔记本)进行分析工作负载
  • 部署为远程无服务器数据库

安装

pip install lancedb
npm install @lancedb/lancedb

使用Webpack打包@lancedb/lancedb应用

由于LanceDB包含预构建的Node二进制文件,您必须配置next.config.js以将其从webpack中排除。无论是使用Next.js还是在Vercel上部署LanceDB应用,都需要进行此配置。

/** @type {import('next').NextConfig} */
module.exports = ({
webpack(config) {
    config.externals.push({ '@lancedb/lancedb': '@lancedb/lancedb' })
    return config;
}
})

Yarn用户

与其他包管理器不同,Yarn不会自动解析对等依赖项。如果您使用Yarn,需要手动安装'apache-arrow':

yarn add apache-arrow
npm install vectordb

使用Webpack打包vectordb应用

由于LanceDB包含预构建的Node二进制文件,您必须配置next.config.js以将其从webpack中排除。无论是在Next.js中使用还是在Vercel上部署LanceDB应用都需要此配置。

/** @type {import('next').NextConfig} */
module.exports = ({
webpack(config) {
    config.externals.push({ vectordb: 'vectordb' })
    return config;
}
})

Yarn用户

与其他包管理器不同,Yarn不会自动解析对等依赖项。如果您使用Yarn,则需要手动安装'apache-arrow':

yarn add apache-arrow
cargo add lancedb

要使用lancedb create,您首先需要安装protobuf。

brew install protobuf
sudo apt install -y protobuf-compiler libssl-dev

请确保您使用的Arrow版本与lancedb crate中的版本一致

预览版本

稳定版大约每两周发布一次。如需使用最新功能和错误修复,您可以安装预览版。这些版本经过与稳定版相同的测试级别,但不保证在发布后超过6个月内仍可用。一旦您的应用程序稳定运行,我们建议切换到稳定版。

pip install --pre --extra-index-url https://pypi.fury.io/lancedb/ lancedb
npm install @lancedb/lancedb@preview
npm install vectordb@preview

我们不会将预览版本推送到crates.io,但您可以在Cargo依赖项中引用GitHub上的标签:

[dependencies]
lancedb = { git = "https://github.com/lancedb/lancedb.git", tag = "vX.Y.Z-beta.N" }

连接到数据库

import lancedb
import pandas as pd
import pyarrow as pa

uri = "data/sample-lancedb"
db = lancedb.connect(uri)
import lancedb
import pandas as pd
import pyarrow as pa

uri = "data/sample-lancedb"
db = await lancedb.connect_async(uri)
import * as lancedb from "@lancedb/lancedb";
import * as arrow from "apache-arrow";

const db = await lancedb.connect(databaseDir);
const lancedb = require("vectordb");
const uri = "data/sample-lancedb";
const db = await lancedb.connect(uri);
#[tokio::main]
async fn main() -> Result<()> {
    let uri = "data/sample-lancedb";
    let db = connect(uri).execute().await?;
}

查看examples/simple.rs获取完整可运行示例。

如果目录不存在,LanceDB 会自动创建该目录(包括父目录)。

如果需要查看URI,可以调用db.uri()

创建表格

从初始数据创建表

如果在创建表时需要插入数据,您可以同时创建表并将数据插入其中。数据的模式将用作表的模式。

如果表已存在,默认情况下LanceDB会报错。 如果你想覆盖该表,可以向create_table方法传入mode="overwrite"参数。

data = [
    {"vector": [3.1, 4.1], "item": "foo", "price": 10.0},
    {"vector": [5.9, 26.5], "item": "bar", "price": 20.0},
]

tbl = db.create_table("my_table", data=data)

你也可以直接传入一个pandas DataFrame:

df = pd.DataFrame(
    [
        {"vector": [3.1, 4.1], "item": "foo", "price": 10.0},
        {"vector": [5.9, 26.5], "item": "bar", "price": 20.0},
    ]
)
tbl = db.create_table("table_from_df", data=df)
data = [
    {"vector": [3.1, 4.1], "item": "foo", "price": 10.0},
    {"vector": [5.9, 26.5], "item": "bar", "price": 20.0},
]

tbl = await db.create_table("my_table_async", data=data)

你也可以直接传入一个pandas DataFrame:

df = pd.DataFrame(
    [
        {"vector": [3.1, 4.1], "item": "foo", "price": 10.0},
        {"vector": [5.9, 26.5], "item": "bar", "price": 20.0},
    ]
)

tbl = await db.create_table("table_from_df_async", df)
const _tbl = await db.createTable(
  "myTable",
  [
    { vector: [3.1, 4.1], item: "foo", price: 10.0 },
    { vector: [5.9, 26.5], item: "bar", price: 20.0 },
  ],
  { mode: "overwrite" },
);
const tbl = await db.createTable(
  "myTable",
  [
    { vector: [3.1, 4.1], item: "foo", price: 10.0 },
    { vector: [5.9, 26.5], item: "bar", price: 20.0 },
  ],
  { writeMode: lancedb.WriteMode.Overwrite },
);

如果表已存在,默认情况下LanceDB会报错。 如果你想覆盖该表,可以向createTable函数传入mode:"overwrite"参数。

let initial_data = create_some_records()?;
let tbl = db
    .create_table("my_table", initial_data)
    .execute()
    .await
    .unwrap();

如果表已存在,默认情况下LanceDB会报错。有关如何覆盖(或打开)现有表的详细信息,请参阅 模式选项

提供

Rust SDK 目前要求数据以 Arrow RecordBatchReader 格式提供。支持其他格式(如 serde 或 polars)已在规划中。

在底层实现上,LanceDB会读取Apache Arrow数据并通过Lance格式将其持久化存储到磁盘。

通过Embedding API自动生成嵌入向量

在使用嵌入模型时,建议使用LanceDB嵌入API来自动在后台生成数据和查询的向量表示。请参阅快速入门示例或嵌入API指南

创建一个空表

有时您可能在创建表时没有要插入的数据。 在这种情况下,您可以创建一个空表并指定模式(schema),以便稍后向表中添加数据(只要数据符合该模式)。这类似于SQL中的CREATE TABLE语句。

schema = pa.schema([pa.field("vector", pa.list_(pa.float32(), list_size=2))])
tbl = db.create_table("empty_table", schema=schema)
schema = pa.schema([pa.field("vector", pa.list_(pa.float32(), list_size=2))])
tbl = await db.create_table("empty_table_async", schema=schema)

您可以在Pydantic中定义模式

LanceDB 内置了对 Pydantic 的支持,允许您使用 Pydantic 模型定义数据结构模式。这使得与 LanceDB 表和数据交互变得更加简单。了解更多支持的类型,请参阅表格指南

const schema = new arrow.Schema([
  new arrow.Field("id", new arrow.Int32()),
  new arrow.Field("name", new arrow.Utf8()),
]);

const emptyTbl = await db.createEmptyTable("empty_table", schema);
const schema = new arrow.Schema([
  new arrow.Field("id", new arrow.Int32()),
  new arrow.Field("name", new arrow.Utf8()),
]);

const empty_tbl = await db.createTable({ name: "empty_table", schema });
let schema = Arc::new(Schema::new(vec![
    Field::new("id", DataType::Int32, false),
    Field::new("item", DataType::Utf8, true),
]));
db.create_empty_table("empty_table", schema).execute().await

打开现有表格

创建完成后,您可以按如下方式打开表:

tbl = db.open_table("my_table")
tbl = await db.open_table("my_table_async")
const _tbl = await db.openTable("myTable");
const tbl = await db.openTable("myTable");
let table = db.open_table("my_table").execute().await.unwrap();

如果您忘记了表名,可以随时获取所有表名的列表:

print(db.table_names())
print(await db.table_names())
const tableNames = await db.tableNames();
console.log(await db.tableNames());
println!("{:?}", db.table_names().execute().await?);

向表中添加数据

创建表后,您始终可以按以下方式向其添加更多数据:

# Option 1: Add a list of dicts to a table
data = [
    {"vector": [1.3, 1.4], "item": "fizz", "price": 100.0},
    {"vector": [9.5, 56.2], "item": "buzz", "price": 200.0},
]
tbl.add(data)

# Option 2: Add a pandas DataFrame to a table
df = pd.DataFrame(data)
tbl.add(data)
# Option 1: Add a list of dicts to a table
data = [
    {"vector": [1.3, 1.4], "item": "fizz", "price": 100.0},
    {"vector": [9.5, 56.2], "item": "buzz", "price": 200.0},
]
await tbl.add(data)

# Option 2: Add a pandas DataFrame to a table
df = pd.DataFrame(data)
await tbl.add(data)
const data = [
  { vector: [1.3, 1.4], item: "fizz", price: 100.0 },
  { vector: [9.5, 56.2], item: "buzz", price: 200.0 },
];
await tbl.add(data);
const newData = Array.from({ length: 500 }, (_, i) => ({
  vector: [i, i + 1],
  item: "fizz",
  price: i * 0.1,
}));
await tbl.add(newData);
let new_data = create_some_records()?;
tbl.add(new_data).execute().await.unwrap();

搜索最近邻

一旦您嵌入了查询,就可以按以下方式找到其最近邻:

tbl.search([100, 100]).limit(2).to_pandas()
await tbl.vector_search([100, 100]).limit(2).to_pandas()

这将返回一个包含结果的pandas DataFrame。

const res = await tbl.search([100, 100]).limit(2).toArray();
const query = await tbl.search([100, 100]).limit(2).execute();
use futures::TryStreamExt;

table
    .query()
    .limit(2)
    .nearest_to(&[1.0; 128])?
    .execute()
    .await?
    .try_collect::<Vec<_>>()
    .await

查询

Rust目前还不支持自动执行嵌入函数。你需要自行计算嵌入向量。对此功能的支持已在规划中,可通过https://github.com/lancedb/lancedb/issues/994跟踪进展。

查询向量可以作为Arrow数组或Rust浮点数的Vec/切片提供。 支持其他格式(例如polars::series::Series)已在规划中。

默认情况下,LanceDB会对数据集执行暴力扫描以查找K个最近邻(KNN)。 对于包含超过5万个向量的表,建议创建ANN索引以提升搜索性能。 LanceDB允许您通过以下方式在表上创建ANN索引:

tbl.create_index(num_sub_vectors=1)
await tbl.create_index("vector")
await tbl.createIndex("vector");
await tbl.createIndex({
  type: "ivf_pq",
  num_partitions: 2,
  num_sub_vectors: 2,
});
table.create_index(&["vector"], Index::Auto).execute().await

为什么我需要手动创建索引?

LanceDB 不会自动创建 ANN 索引有两个原因。首先,它针对基于磁盘的索引进行了极速检索优化;其次,数据和查询工作负载可能千差万别,因此不存在通用的索引配置方案。LanceDB 提供了众多参数来微调索引大小、查询延迟和准确性。更多详情请参阅ANN索引章节。

从表中删除行

使用表上的delete()方法从表中删除行。要选择删除哪些行,请提供一个与元数据列匹配的筛选条件。这可以删除所有符合筛选条件的行。

tbl.delete('item = "fizz"')
await tbl.delete('item = "fizz"')
await tbl.delete('item = "fizz"');
await tbl.delete('item = "fizz"');
tbl.delete("id > 24").await.unwrap();

删除谓词是一个SQL表达式,支持与搜索中的where()子句(Rust中的only_if())相同的表达式。它们可以根据需要简单或复杂。要查看支持的表达式,请参阅SQL过滤器部分。

了解更多: lancedb.Table.delete

了解更多: vectordb.Table.delete

了解更多: lancedb::Table::delete

删除表

使用数据库上的drop_table()方法来删除表。

db.drop_table("my_table")
await db.drop_table("my_table_async")

这将永久删除表格且无法恢复,与删除行不同。 默认情况下,如果表格不存在会抛出异常。要忽略此情况, 可以传入ignore_missing=True参数。

await db.dropTable("myTable");
await db.dropTable("myTable");

这将永久删除表格且无法恢复,与删除行不同。如果表格不存在,则会引发异常。

db.drop_table("my_table").await.unwrap();

使用Embedding API

在使用嵌入模型时,您可以使用嵌入API。它会在数据摄入和查询时自动进行向量化处理,并内置了与OpenAI、Hugging Face、Sentence Transformers、CLIP等流行嵌入模型的集成。

from lancedb.pydantic import LanceModel, Vector
from lancedb.embeddings import get_registry


db = lancedb.connect("/tmp/db")
func = get_registry().get("openai").create(name="text-embedding-ada-002")

class Words(LanceModel):
    text: str = func.SourceField()
    vector: Vector(func.ndims()) = func.VectorField()

table = db.create_table("words", schema=Words, mode="overwrite")
table.add([{"text": "hello world"}, {"text": "goodbye world"}])

query = "greetings"
actual = table.search(query).limit(1).to_pydantic(Words)[0]
print(actual.text)

即将在异步API中推出。 https://github.com/lancedb/lancedb/issues/1938

import * as lancedb from "@lancedb/lancedb";
import "@lancedb/lancedb/embedding/openai";
import { LanceSchema, getRegistry, register } from "@lancedb/lancedb/embedding";
import { EmbeddingFunction } from "@lancedb/lancedb/embedding";
import { type Float, Float32, Utf8 } from "apache-arrow";
const db = await lancedb.connect(databaseDir);
const func = getRegistry()
  .get("openai")
  ?.create({ model: "text-embedding-ada-002" }) as EmbeddingFunction;

const wordsSchema = LanceSchema({
  text: func.sourceField(new Utf8()),
  vector: func.vectorField(),
});
const tbl = await db.createEmptyTable("words", wordsSchema, {
  mode: "overwrite",
});
await tbl.add([{ text: "hello world" }, { text: "goodbye world" }]);

const query = "greetings";
const actual = (await tbl.search(query).limit(1).toArray())[0];
use std::{iter::once, sync::Arc};

use arrow_array::{Float64Array, Int32Array, RecordBatch, RecordBatchIterator, StringArray};
use arrow_schema::{DataType, Field, Schema};
use futures::StreamExt;
use lancedb::{
    arrow::IntoArrow,
    connect,
    embeddings::{openai::OpenAIEmbeddingFunction, EmbeddingDefinition, EmbeddingFunction},
    query::{ExecutableQuery, QueryBase},
    Result,
};

#[tokio::main]
async fn main() -> Result<()> {
    let tempdir = tempfile::tempdir().unwrap();
    let tempdir = tempdir.path().to_str().unwrap();
    let api_key = std::env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY is not set");
    let embedding = Arc::new(OpenAIEmbeddingFunction::new_with_model(
        api_key,
        "text-embedding-3-large",
    )?);

    let db = connect(tempdir).execute().await?;
    db.embedding_registry()
        .register("openai", embedding.clone())?;

    let table = db
        .create_table("vectors", make_data())
        .add_embedding(EmbeddingDefinition::new(
            "text",
            "openai",
            Some("embeddings"),
        ))?
        .execute()
        .await?;

    let query = Arc::new(StringArray::from_iter_values(once("something warm")));
    let query_vector = embedding.compute_query_embeddings(query)?;
    let mut results = table
        .vector_search(query_vector)?
        .limit(1)
        .execute()
        .await?;

    let rb = results.next().await.unwrap()?;
    let out = rb
        .column_by_name("text")
        .unwrap()
        .as_any()
        .downcast_ref::<StringArray>()
        .unwrap();
    let text = out.iter().next().unwrap().unwrap();
    println!("Closest match: {}", text);
    Ok(())
}

了解如何使用现有集成以及创建自定义嵌入函数,请参阅嵌入API指南

下一步

本节介绍了使用LanceDB的最基础知识。如果你是第一次学习向量数据库,可以阅读索引页面来熟悉相关概念。

如果您已经使用过其他向量数据库,可以阅读指南详细了解如何使用LanceDB。


  1. vectordb 包是一个已弃用的旧版包,建议改用 @lancedb/lancedbvectordb 包将持续接收错误修复和安全更新直至2024年9月。我们建议所有新项目使用 @lancedb/lancedb。更多信息请参阅迁移指南