mirror of
https://github.com/lancedb/lancedb.git
synced 2025-12-23 05:19:58 +00:00
Compare commits
7 Commits
v0.1.4-pyt
...
v0.1.3-nod
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
091fb9b665 | ||
|
|
03013a4434 | ||
|
|
3e14b357e7 | ||
|
|
99cbda8b07 | ||
|
|
e50b642d80 | ||
|
|
6d8cf52e01 | ||
|
|
53f3882d6e |
48
.github/workflows/make_release_commit.yml
vendored
Normal file
48
.github/workflows/make_release_commit.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
name: Create release commit
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
dry_run:
|
||||||
|
description: 'Just create the local commit/tags but do not push it'
|
||||||
|
required: true
|
||||||
|
default: "false"
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- "true"
|
||||||
|
- "false"
|
||||||
|
part:
|
||||||
|
description: 'What kind of release is this?'
|
||||||
|
required: true
|
||||||
|
default: 'patch'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- patch
|
||||||
|
- minor
|
||||||
|
- major
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bump-version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out main
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
persist-credentials: false
|
||||||
|
fetch-depth: 0
|
||||||
|
lfs: true
|
||||||
|
- name: Install cargo utils
|
||||||
|
run: cargo install cargo-edit
|
||||||
|
- name: Bump versions
|
||||||
|
run: |
|
||||||
|
NEW_VERSION=$(bash ci/bump_versions.sh ${{ inputs.part }})
|
||||||
|
echo "New version: v$NEW_VERSION"
|
||||||
|
git tag v$NEW_VERSION
|
||||||
|
- name: Push new version and tag
|
||||||
|
if: ${{ inputs.dry_run }} == "false"
|
||||||
|
uses: ad-m/github-push-action@master
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
branch: main
|
||||||
|
tags: true
|
||||||
12
.github/workflows/node.yml
vendored
12
.github/workflows/node.yml
vendored
@@ -67,8 +67,12 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
npm ci
|
npm ci
|
||||||
npm run build
|
|
||||||
npm run tsc
|
npm run tsc
|
||||||
|
npm run build
|
||||||
|
npm run pack-build
|
||||||
|
npm install --no-save ./dist/lancedb-vectordb-*.tgz
|
||||||
|
# Remove index.node to test with dependency installed
|
||||||
|
rm index.node
|
||||||
- name: Test
|
- name: Test
|
||||||
run: npm run test
|
run: npm run test
|
||||||
macos:
|
macos:
|
||||||
@@ -94,8 +98,12 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
npm ci
|
npm ci
|
||||||
npm run build
|
|
||||||
npm run tsc
|
npm run tsc
|
||||||
|
npm run build
|
||||||
|
npm run pack-build
|
||||||
|
npm install --no-save ./dist/lancedb-vectordb-*.tgz
|
||||||
|
# Remove index.node to test with dependency installed
|
||||||
|
rm index.node
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
npm run test
|
npm run test
|
||||||
|
|||||||
167
.github/workflows/release.yml
vendored
Normal file
167
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
name: Prepare Release
|
||||||
|
|
||||||
|
# NOTE: Python is a separate release for now.
|
||||||
|
|
||||||
|
# Currently disabled until it can be completed.
|
||||||
|
# on:
|
||||||
|
# push:
|
||||||
|
# tags:
|
||||||
|
# - v*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
draft-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
prerelease: true # hardcoded on for now
|
||||||
|
generate_release_notes: true
|
||||||
|
|
||||||
|
rust:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: draft-release
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
working-directory: rust/vectordb
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
lfs: true
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y protobuf-compiler libssl-dev
|
||||||
|
- name: Package Rust
|
||||||
|
run: cargo package --all-features
|
||||||
|
- uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
files: target/package/vectordb-*.crate
|
||||||
|
fail_on_unmatched_files: true
|
||||||
|
|
||||||
|
node:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: draft-release
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
working-directory: node
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: node/package-lock.json
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y protobuf-compiler libssl-dev
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
npm run tsc
|
||||||
|
npm pack
|
||||||
|
- uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
files: node/vectordb-*.tgz
|
||||||
|
fail_on_unmatched_files: true
|
||||||
|
|
||||||
|
node-macos:
|
||||||
|
runs-on: macos-12
|
||||||
|
needs: draft-release
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target: [x86_64-apple-darwin, aarch64-apple-darwin]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v33
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: brew install protobuf
|
||||||
|
- name: Install npm dependencies
|
||||||
|
run: |
|
||||||
|
cd node
|
||||||
|
npm ci
|
||||||
|
- name: Install rustup target
|
||||||
|
if: ${{ matrix.target == 'aarch64-apple-darwin' }}
|
||||||
|
run: rustup target add aarch64-apple-darwin
|
||||||
|
- name: Build MacOS native node modules
|
||||||
|
run: bash ci/build_macos_artifacts.sh ${{ matrix.target }}
|
||||||
|
- uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
files: node/dist/lancedb-vectordb-darwin*.tgz
|
||||||
|
fail_on_unmatched_files: true
|
||||||
|
|
||||||
|
node-linux:
|
||||||
|
name: node-linux (${{ matrix.arch}}-unknown-linux-${{ matrix.libc }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: draft-release
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
libc:
|
||||||
|
- gnu
|
||||||
|
# TODO: re-enable musl once we have refactored to pre-built containers
|
||||||
|
# Right now we have to build node from source which is too expensive.
|
||||||
|
# - musl
|
||||||
|
arch:
|
||||||
|
- x86_64
|
||||||
|
# Building on aarch64 is too slow for now
|
||||||
|
# - aarch64
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Change owner to root (for npm)
|
||||||
|
# The docker container is run as root, so we need the files to be owned by root
|
||||||
|
# Otherwise npm is a nightmare: https://github.com/npm/cli/issues/3773
|
||||||
|
run: sudo chown -R root:root .
|
||||||
|
- name: Set up QEMU
|
||||||
|
if: ${{ matrix.arch == 'aarch64' }}
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
with:
|
||||||
|
platforms: arm64
|
||||||
|
- name: Build Linux GNU native node modules
|
||||||
|
if: ${{ matrix.libc == 'gnu' }}
|
||||||
|
run: |
|
||||||
|
docker run \
|
||||||
|
-v $(pwd):/io -w /io \
|
||||||
|
quay.io/pypa/manylinux2014_${{ matrix.arch }} \
|
||||||
|
bash ci/build_linux_artifacts.sh ${{ matrix.arch }}-unknown-linux-gnu
|
||||||
|
- name: Build musl Linux native node modules
|
||||||
|
if: ${{ matrix.libc == 'musl' }}
|
||||||
|
run: |
|
||||||
|
docker run --platform linux/arm64/v8 \
|
||||||
|
-v $(pwd):/io -w /io \
|
||||||
|
quay.io/pypa/musllinux_1_1_${{ matrix.arch }} \
|
||||||
|
bash ci/build_linux_artifacts.sh ${{ matrix.arch }}-unknown-linux-musl
|
||||||
|
- uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
files: node/dist/lancedb-vectordb-linux*.tgz
|
||||||
|
fail_on_unmatched_files: true
|
||||||
|
|
||||||
|
release:
|
||||||
|
needs: [rust, node, node-macos, node-linux]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
- name: Publish to NPM
|
||||||
|
run: |
|
||||||
|
for filename in node/dist/*.tgz; do
|
||||||
|
npm publish --dry-run $filename
|
||||||
|
done
|
||||||
|
- name: Publish to crates.io
|
||||||
|
env:
|
||||||
|
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
run: |
|
||||||
|
cargo publish --dry-run --no-verify rust/target/vectordb-*.crate
|
||||||
|
# - uses: softprops/action-gh-release@v1
|
||||||
|
# with:
|
||||||
|
# draft: false
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,6 +4,8 @@
|
|||||||
**/__pycache__
|
**/__pycache__
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
.vscode
|
||||||
|
|
||||||
rust/target
|
rust/target
|
||||||
rust/Cargo.lock
|
rust/Cargo.lock
|
||||||
|
|
||||||
|
|||||||
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -3358,7 +3358,7 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vectordb"
|
name = "vectordb"
|
||||||
version = "0.0.1"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-data",
|
"arrow-data",
|
||||||
@@ -3366,13 +3366,14 @@ dependencies = [
|
|||||||
"lance",
|
"lance",
|
||||||
"object_store",
|
"object_store",
|
||||||
"rand",
|
"rand",
|
||||||
|
"snafu",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vectordb-node"
|
name = "vectordb-node"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrow-array",
|
"arrow-array",
|
||||||
"arrow-ipc",
|
"arrow-ipc",
|
||||||
|
|||||||
91
ci/build_linux_artifacts.sh
Normal file
91
ci/build_linux_artifacts.sh
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Builds the Linux artifacts (node binaries).
|
||||||
|
# Usage: ./build_linux_artifacts.sh [target]
|
||||||
|
# Targets supported:
|
||||||
|
# - x86_64-unknown-linux-gnu:centos
|
||||||
|
# - aarch64-unknown-linux-gnu:centos
|
||||||
|
# - aarch64-unknown-linux-musl
|
||||||
|
# - x86_64-unknown-linux-musl
|
||||||
|
|
||||||
|
# TODO: refactor this into a Docker container we can pull
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
setup_dependencies() {
|
||||||
|
echo "Installing system dependencies..."
|
||||||
|
if [[ $1 == *musl ]]; then
|
||||||
|
# musllinux
|
||||||
|
apk add openssl-dev
|
||||||
|
else
|
||||||
|
# manylinux2014
|
||||||
|
yum install -y openssl-devel unzip
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $1 == x86_64* ]]; then
|
||||||
|
ARCH=x86_64
|
||||||
|
else
|
||||||
|
# gnu target
|
||||||
|
ARCH=aarch_64
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install new enough protobuf (yum-provided is old)
|
||||||
|
PB_REL=https://github.com/protocolbuffers/protobuf/releases
|
||||||
|
PB_VERSION=23.1
|
||||||
|
curl -LO $PB_REL/download/v$PB_VERSION/protoc-$PB_VERSION-linux-$ARCH.zip
|
||||||
|
unzip protoc-$PB_VERSION-linux-$ARCH.zip -d /usr/local
|
||||||
|
}
|
||||||
|
|
||||||
|
install_node() {
|
||||||
|
echo "Installing node..."
|
||||||
|
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
|
||||||
|
source "$HOME"/.bashrc
|
||||||
|
|
||||||
|
if [[ $1 == *musl ]]; then
|
||||||
|
# This node version is 15, we need 16 or higher:
|
||||||
|
# apk add nodejs-current npm
|
||||||
|
# So instead we install from source (nvm doesn't provide binaries for musl):
|
||||||
|
nvm install -s --no-progress 17
|
||||||
|
else
|
||||||
|
nvm install --no-progress 17 # latest that supports glibc 2.17
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_rust() {
|
||||||
|
echo "Installing rust..."
|
||||||
|
curl https://sh.rustup.rs -sSf | bash -s -- -y
|
||||||
|
export PATH="$PATH:/root/.cargo/bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_node_binary() {
|
||||||
|
echo "Building node library for $1..."
|
||||||
|
pushd node
|
||||||
|
|
||||||
|
npm ci
|
||||||
|
|
||||||
|
if [[ $1 == *musl ]]; then
|
||||||
|
# This is needed for cargo to allow build cdylibs with musl
|
||||||
|
export RUSTFLAGS="-C target-feature=-crt-static"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cargo can run out of memory while pulling dependencies, espcially when running
|
||||||
|
# in QEMU. This is a workaround for that.
|
||||||
|
export CARGO_NET_GIT_FETCH_WITH_CLI=true
|
||||||
|
|
||||||
|
# We don't pass in target, since the native target here already matches
|
||||||
|
# and openblas-src doesn't do well with cross-compilation.
|
||||||
|
npm run build-release
|
||||||
|
npm run pack-build
|
||||||
|
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
TARGET=${1:-x86_64-unknown-linux-gnu}
|
||||||
|
# Others:
|
||||||
|
# aarch64-unknown-linux-gnu
|
||||||
|
# x86_64-unknown-linux-musl
|
||||||
|
# aarch64-unknown-linux-musl
|
||||||
|
|
||||||
|
setup_dependencies $TARGET
|
||||||
|
install_node $TARGET
|
||||||
|
install_rust
|
||||||
|
build_node_binary $TARGET
|
||||||
33
ci/build_macos_artifacts.sh
Normal file
33
ci/build_macos_artifacts.sh
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Builds the macOS artifacts (node binaries).
|
||||||
|
# Usage: ./ci/build_macos_artifacts.sh [target]
|
||||||
|
# Targets supported: x86_64-apple-darwin aarch64-apple-darwin
|
||||||
|
|
||||||
|
prebuild_rust() {
|
||||||
|
# Building here for the sake of easier debugging.
|
||||||
|
pushd rust/ffi/node
|
||||||
|
echo "Building rust library for $1"
|
||||||
|
export RUST_BACKTRACE=1
|
||||||
|
cargo build --release --target $1
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
build_node_binaries() {
|
||||||
|
pushd node
|
||||||
|
echo "Building node library for $1"
|
||||||
|
npm run build-release -- --target $1
|
||||||
|
npm run pack-build -- --target $1
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
targets=$1
|
||||||
|
else
|
||||||
|
targets="x86_64-apple-darwin aarch64-apple-darwin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Building artifacts for targets: $targets"
|
||||||
|
for target in $targets
|
||||||
|
do
|
||||||
|
prebuild_rust $target
|
||||||
|
build_node_binaries $target
|
||||||
|
done
|
||||||
58
ci/bump_versions.sh
Normal file
58
ci/bump_versions.sh
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# if cargo bump isn't installed return an error
|
||||||
|
if ! cargo set-version &> /dev/null
|
||||||
|
then
|
||||||
|
echo "cargo-edit could not be found. Install with `cargo install cargo-edit`"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUMP_PART=${1:-patch}
|
||||||
|
|
||||||
|
# if BUMP_PART isn't patch, minor, or major return an error
|
||||||
|
if [ "$BUMP_PART" != "patch" ] && [ "$BUMP_PART" != "minor" ] && [ "$BUMP_PART" != "major" ]
|
||||||
|
then
|
||||||
|
echo "BUMP_PART must be one of patch, minor, or major"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
function get_crate_version() {
|
||||||
|
cargo pkgid -p $1 | cut -d@ -f2 | cut -d# -f2
|
||||||
|
}
|
||||||
|
|
||||||
|
# First, validate versions are starting as same
|
||||||
|
VECTORDB_VERSION=$(get_crate_version vectordb)
|
||||||
|
FFI_NODE_VERSION=$(get_crate_version vectordb-node)
|
||||||
|
|
||||||
|
# FYI, we pipe all output to /dev/null because the only thing we want to ouput
|
||||||
|
# if success is the new tag. This way it can be then used with `git tag`.
|
||||||
|
pushd node > /dev/null
|
||||||
|
NODE_VERSION=$(npm pkg get version | xargs echo)
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
if [ "$VECTORDB_VERSION" != "$FFI_NODE_VERSION" ] || [ "$VECTORDB_VERSION" != "$NODE_VERSION" ]
|
||||||
|
then
|
||||||
|
echo "Version mismatch between rust/vectordb, rust/ffi/node, and node"
|
||||||
|
echo "rust/vectordb: $VECTORDB_VERSION"
|
||||||
|
echo "rust/ffi/node: $FFI_NODE_VERSION"
|
||||||
|
echo "node: $NODE_VERSION"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
cargo set-version --bump $BUMP_PART > /dev/null 2>&1
|
||||||
|
NEW_VERSION=$(get_crate_version vectordb)
|
||||||
|
|
||||||
|
pushd node > /dev/null
|
||||||
|
npm version $BUMP_PART > /dev/null
|
||||||
|
|
||||||
|
# Also need to update version of the native modules
|
||||||
|
NATIVE_MODULES=$(npm pkg get optionalDependencies | jq 'keys[]' | grep @vectordb/ | tr -d '"')
|
||||||
|
for module in $NATIVE_MODULES
|
||||||
|
do
|
||||||
|
npm install $module@$NEW_VERSION --save-optional > /dev/null
|
||||||
|
done
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
|
||||||
|
echo $NEW_VERSION
|
||||||
136
ci/release_process.md
Normal file
136
ci/release_process.md
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# How to release
|
||||||
|
|
||||||
|
This is for the Rust crate and Node module. For now, the Python module is
|
||||||
|
released separately.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The release is started by bumping the versions and pushing a new tag. To do this
|
||||||
|
automatically, use the `make_release_commit` GitHub action.
|
||||||
|
|
||||||
|
When the tag is pushed, GitHub actions will start building the libraries and
|
||||||
|
will upload them to a draft release.
|
||||||
|
|
||||||
|
While those jobs are running, edit the release notes as needed. For example,
|
||||||
|
bring relevant new features and bugfixes to the top of the notes and the testing
|
||||||
|
and CI changes to the bottom.
|
||||||
|
|
||||||
|
Once the jobs have finished, the release will be marked as not draft and the
|
||||||
|
artifacts will be released to crates.io, NPM, and PyPI.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Manual process
|
||||||
|
|
||||||
|
The manual release process can be completed on a MacOS machine.
|
||||||
|
|
||||||
|
### Bump the versions
|
||||||
|
|
||||||
|
You can use the script `ci/bump_versions.sh` to bump the versions. It defaults
|
||||||
|
to a `patch` bump, but you can also pass `minor` and `major`. Once you have the
|
||||||
|
tag created, push it to GitHub.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
VERSION=$(bash ci/bump_versions.sh)
|
||||||
|
git tag v$VERSION
|
||||||
|
git push origin v$VERSION
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build the MacOS release libraries
|
||||||
|
|
||||||
|
One-time setup:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
rustup target add x86_64-apple-darwin aarch64-apple-darwin
|
||||||
|
```
|
||||||
|
|
||||||
|
To build both x64 and arm64, run `ci/build_macos_artifacts.sh` without any args:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
bash ci/build_macos_artifacts.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build the Linux release libraries
|
||||||
|
|
||||||
|
To build a Linux library, we need to use docker with a different build script:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ARCH=aarch64
|
||||||
|
docker run \
|
||||||
|
-v $(pwd):/io -w /io \
|
||||||
|
quay.io/pypa/manylinux2014_$ARCH \
|
||||||
|
bash ci/build_linux_artifacts.sh $ARCH-unknown-linux-gnu
|
||||||
|
```
|
||||||
|
|
||||||
|
For x64, change `ARCH` to `x86_64`. NOTE: compiling for a different architecture
|
||||||
|
than your machine in Docker is very slow. It's best to do this on a machine with
|
||||||
|
matching architecture.
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Similar script for musl binaries (not yet working):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ARCH=aarch64
|
||||||
|
docker run \
|
||||||
|
--user $(id -u) \
|
||||||
|
-v $(pwd):/io -w /io \
|
||||||
|
quay.io/pypa/musllinux_1_1_$ARCH \
|
||||||
|
bash ci/build_linux_artifacts.sh $ARCH-unknown-linux-musl
|
||||||
|
```
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
For debugging, use these snippets:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ARCH=aarch64
|
||||||
|
docker run -it \
|
||||||
|
-v $(pwd):/io -w /io \
|
||||||
|
quay.io/pypa/manylinux2014_$ARCH \
|
||||||
|
bash
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ARCH=aarch64
|
||||||
|
docker run -it \
|
||||||
|
-v $(pwd):/io -w /io \
|
||||||
|
quay.io/pypa/musllinux_1_1_$ARCH \
|
||||||
|
bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: musllinux_1_1 is Alpine Linux 3.12
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
### Build the npm module
|
||||||
|
|
||||||
|
To build the typescript and create a release tarball, run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm ci
|
||||||
|
npm tsc
|
||||||
|
npm pack
|
||||||
|
```
|
||||||
|
|
||||||
|
### Release to npm
|
||||||
|
|
||||||
|
Assuming you still have `VERSION` set from earlier:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pushd node
|
||||||
|
npm publish lancedb-vectordb-$VERSION.tgz
|
||||||
|
for tarball in ./dist/lancedb-vectordb-*-$VERSION.tgz;
|
||||||
|
do
|
||||||
|
npm publish $tarball
|
||||||
|
done
|
||||||
|
popd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Release to crates.io
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cargo publish -p vectordb
|
||||||
|
cargo publish -p vectordb-node
|
||||||
|
```
|
||||||
@@ -38,7 +38,7 @@ result = table.search([100, 100]).limit(2).to_df()
|
|||||||
## Complete Demos
|
## Complete Demos
|
||||||
|
|
||||||
We will be adding completed demo apps built using LanceDB.
|
We will be adding completed demo apps built using LanceDB.
|
||||||
- [YouTube Transcript Search](../notebooks/youtube_transcript_search.ipynb)
|
- [YouTube Transcript Search](../../notebooks/youtube_transcript_search.ipynb)
|
||||||
|
|
||||||
|
|
||||||
## Documentation Quick Links
|
## Documentation Quick Links
|
||||||
|
|||||||
4
node/.npmignore
Normal file
4
node/.npmignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
gen_test_data.py
|
||||||
|
index.node
|
||||||
|
dist/lancedb*.tgz
|
||||||
|
vectordb*.tgz
|
||||||
@@ -8,6 +8,10 @@ A JavaScript / Node.js library for [LanceDB](https://github.com/lancedb/lancedb)
|
|||||||
npm install vectordb
|
npm install vectordb
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This will download the appropriate native library for your platform. We currently
|
||||||
|
support x86_64 Linux, aarch64 Linux, Intel MacOS, and ARM (M1/M2) MacOS. We do not
|
||||||
|
yet support Windows or musl-based Linux (such as Alpine Linux).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Basic Example
|
### Basic Example
|
||||||
@@ -24,17 +28,33 @@ The [examples](./examples) folder contains complete examples.
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
The LanceDB javascript is built with npm:
|
To build everything fresh:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run tsc
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you should be able to run the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebuilding Rust library
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebuilding Typescript
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run tsc
|
npm run tsc
|
||||||
```
|
```
|
||||||
|
|
||||||
Run the tests with
|
### Fix lints
|
||||||
|
|
||||||
```bash
|
|
||||||
npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
To run the linter and have it automatically fix all errors
|
To run the linter and have it automatically fix all errors
|
||||||
|
|
||||||
|
|||||||
41
node/examples/js-openai/index.js
Normal file
41
node/examples/js-openai/index.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
async function example () {
|
||||||
|
const lancedb = require('vectordb')
|
||||||
|
// You need to provide an OpenAI API key, here we read it from the OPENAI_API_KEY environment variable
|
||||||
|
const apiKey = process.env.OPENAI_API_KEY
|
||||||
|
// The embedding function will create embeddings for the 'text' column(text in this case)
|
||||||
|
const embedding = new lancedb.OpenAIEmbeddingFunction('text', apiKey)
|
||||||
|
|
||||||
|
const db = await lancedb.connect('data/sample-lancedb')
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ id: 1, text: 'Black T-Shirt', price: 10 },
|
||||||
|
{ id: 2, text: 'Leather Jacket', price: 50 }
|
||||||
|
]
|
||||||
|
|
||||||
|
const table = await db.createTable('vectors', data, embedding)
|
||||||
|
console.log(await db.tableNames())
|
||||||
|
|
||||||
|
const results = await table
|
||||||
|
.search('keeps me warm')
|
||||||
|
.limit(1)
|
||||||
|
.execute()
|
||||||
|
console.log(results[0].text)
|
||||||
|
}
|
||||||
|
|
||||||
|
example().then(_ => { console.log('All done!') })
|
||||||
15
node/examples/js-openai/package.json
Normal file
15
node/examples/js-openai/package.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "vectordb-example-js-openai",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "Lance Devs",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"vectordb": "file:../..",
|
||||||
|
"openai": "^3.2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,6 @@
|
|||||||
"author": "Lance Devs",
|
"author": "Lance Devs",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vectordb": "^0.1.0"
|
"vectordb": "file:../.."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,6 @@
|
|||||||
"typescript": "*"
|
"typescript": "*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vectordb": "^0.1.0"
|
"vectordb": "file:../.."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,29 +12,26 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
const { currentTarget } = require('@neon-rs/load');
|
||||||
|
|
||||||
let nativeLib;
|
let nativeLib;
|
||||||
|
|
||||||
function getPlatformLibrary() {
|
|
||||||
if (process.platform === "darwin" && process.arch == "arm64") {
|
|
||||||
return require('./aarch64-apple-darwin.node');
|
|
||||||
} else if (process.platform === "darwin" && process.arch == "x64") {
|
|
||||||
return require('./x86_64-apple-darwin.node');
|
|
||||||
} else if (process.platform === "linux" && process.arch == "x64") {
|
|
||||||
return require('./x86_64-unknown-linux-gnu.node');
|
|
||||||
} else {
|
|
||||||
throw new Error(`vectordb: unsupported platform ${process.platform}_${process.arch}. Please file a bug report at https://github.com/lancedb/lancedb/issues`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nativeLib = require('./index.node')
|
nativeLib = require(`@lancedb/vectordb-${currentTarget()}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === "MODULE_NOT_FOUND") {
|
try {
|
||||||
nativeLib = getPlatformLibrary();
|
// Might be developing locally, so try that. But don't expose that error
|
||||||
} else {
|
// to the user.
|
||||||
throw new Error('vectordb: failed to load native library. Please file a bug report at https://github.com/lancedb/lancedb/issues');
|
nativeLib = require("./index.node");
|
||||||
}
|
} catch {
|
||||||
|
throw new Error(`vectordb: failed to load native library.
|
||||||
|
You may need to run \`npm install @lancedb/vectordb-${currentTarget()}\`.
|
||||||
|
|
||||||
|
If that does not work, please file a bug report at https://github.com/lancedb/lancedb/issues
|
||||||
|
|
||||||
|
Source error: ${e}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = nativeLib
|
// Dynamic require for runtime.
|
||||||
|
module.exports = nativeLib;
|
||||||
|
|||||||
548
node/package-lock.json
generated
548
node/package-lock.json
generated
@@ -1,18 +1,28 @@
|
|||||||
{
|
{
|
||||||
"name": "vectordb",
|
"name": "vectordb",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "vectordb",
|
"name": "vectordb",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
|
"cpu": [
|
||||||
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
"os": [
|
||||||
|
"darwin",
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apache-arrow/ts": "^12.0.0",
|
"@apache-arrow/ts": "^12.0.0",
|
||||||
|
"@neon-rs/load": "^0.0.74",
|
||||||
"apache-arrow": "^12.0.0"
|
"apache-arrow": "^12.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@neon-rs/cli": "^0.0.74",
|
||||||
"@types/chai": "^4.3.4",
|
"@types/chai": "^4.3.4",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
"@types/node": "^18.16.2",
|
"@types/node": "^18.16.2",
|
||||||
@@ -26,10 +36,18 @@
|
|||||||
"eslint-plugin-n": "^15.7.0",
|
"eslint-plugin-n": "^15.7.0",
|
||||||
"eslint-plugin-promise": "^6.1.1",
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
|
"openai": "^3.2.1",
|
||||||
|
"sinon": "^15.1.0",
|
||||||
"temp": "^0.9.4",
|
"temp": "^0.9.4",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"ts-node-dev": "^2.0.0",
|
"ts-node-dev": "^2.0.0",
|
||||||
"typescript": "*"
|
"typescript": "*"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@lancedb/vectordb-darwin-arm64": "0.1.2",
|
||||||
|
"@lancedb/vectordb-darwin-x64": "0.1.2",
|
||||||
|
"@lancedb/vectordb-linux-arm64-gnu": "0.1.2",
|
||||||
|
"@lancedb/vectordb-linux-x64-gnu": "0.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@apache-arrow/ts": {
|
"node_modules/@apache-arrow/ts": {
|
||||||
@@ -197,6 +215,46 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@lancedb/vectordb-darwin-arm64": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://npm.pkg.github.com/download/@lancedb/vectordb-darwin-arm64/0.1.2/84d71331e03e8aaeb9fb12cdacc759dc82cfd3b0",
|
||||||
|
"integrity": "sha512-DU6tHmmn/coSj5r5FGwTMXMQfsSSxQN1ozOl9mFUXr0aVtlx5nlA8ZY5BAF/V371yL5QzNPKtaNpogP6iw51NA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@lancedb/vectordb-linux-arm64-gnu": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://npm.pkg.github.com/download/@lancedb/vectordb-linux-arm64-gnu/0.1.2/d5a9d66c3969494cf3546195fb5511f9f49aa295",
|
||||||
|
"integrity": "sha512-LZZ4KgoGqD5AzKX/utBrsxrwXq6whpUNa02tWxl/ND/601ruNi9ZUaXCTb1rSVUWJkgMR2wASk15kssyaPRSjw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@neon-rs/cli": {
|
||||||
|
"version": "0.0.74",
|
||||||
|
"resolved": "https://registry.npmjs.org/@neon-rs/cli/-/cli-0.0.74.tgz",
|
||||||
|
"integrity": "sha512-9lPmNmjej5iKKOTMPryOMubwkgMRyTWRuaq1yokASvI5mPhr2kzPN7UVjdCOjQvpunNPngR9yAHoirpjiWhUHw==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"neon": "index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@neon-rs/load": {
|
||||||
|
"version": "0.0.74",
|
||||||
|
"resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.74.tgz",
|
||||||
|
"integrity": "sha512-/cPZD907UNz55yrc/ud4wDgQKtU1TvkD9jeqZWG6J4IMmZkp6zgjkQcKA8UvpkZlcpPHvc8J17sGzLFbP/LUYg=="
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -232,6 +290,50 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@sinonjs/commons": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"type-detect": "4.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sinonjs/fake-timers": {
|
||||||
|
"version": "10.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz",
|
||||||
|
"integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@sinonjs/commons": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sinonjs/samsam": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@sinonjs/commons": "^2.0.0",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
|
"type-detect": "^4.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"type-detect": "4.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sinonjs/text-encoding": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@tsconfig/node10": {
|
"node_modules/@tsconfig/node10": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||||
@@ -307,6 +409,21 @@
|
|||||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/sinon": {
|
||||||
|
"version": "10.0.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz",
|
||||||
|
"integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/sinonjs__fake-timers": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/sinonjs__fake-timers": {
|
||||||
|
"version": "8.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz",
|
||||||
|
"integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/strip-bom": {
|
"node_modules/@types/strip-bom": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||||
@@ -744,6 +861,12 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/available-typed-arrays": {
|
"node_modules/available-typed-arrays": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
||||||
@@ -756,6 +879,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "0.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||||
|
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.14.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@@ -968,6 +1100,18 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/command-line-args": {
|
"node_modules/command-line-args": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz",
|
||||||
@@ -1179,6 +1323,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/diff": {
|
"node_modules/diff": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||||
@@ -1942,6 +2095,26 @@
|
|||||||
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
|
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/for-each": {
|
"node_modules/for-each": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||||
@@ -1951,6 +2124,20 @@
|
|||||||
"is-callable": "^1.1.3"
|
"is-callable": "^1.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fs.realpath": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
@@ -2584,6 +2771,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/isarray": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@@ -2644,6 +2837,12 @@
|
|||||||
"json5": "lib/cli.js"
|
"json5": "lib/cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/just-extend": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/levn": {
|
"node_modules/levn": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||||
@@ -2677,6 +2876,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
|
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.get": {
|
||||||
|
"version": "4.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||||
|
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
@@ -2748,6 +2953,27 @@
|
|||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
@@ -2925,6 +3151,28 @@
|
|||||||
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
|
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/nise": {
|
||||||
|
"version": "5.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz",
|
||||||
|
"integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@sinonjs/commons": "^2.0.0",
|
||||||
|
"@sinonjs/fake-timers": "^10.0.2",
|
||||||
|
"@sinonjs/text-encoding": "^0.7.1",
|
||||||
|
"just-extend": "^4.0.2",
|
||||||
|
"path-to-regexp": "^1.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nise/node_modules/@sinonjs/commons": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"type-detect": "4.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
@@ -2996,6 +3244,16 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/openai": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/openai/-/openai-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-762C9BNlJPbjjlWZi4WYK9iM2tAVAv0uUp1UmI34vb0CN5T2mjB/qM6RYBmNKMh/dN9fC+bxqPwWJZUTWW052A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.26.0",
|
||||||
|
"form-data": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.1",
|
"version": "0.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
|
||||||
@@ -3099,6 +3357,15 @@
|
|||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/path-to-regexp": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"isarray": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/path-type": {
|
"node_modules/path-type": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||||
@@ -3406,6 +3673,45 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sinon": {
|
||||||
|
"version": "15.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.0.tgz",
|
||||||
|
"integrity": "sha512-cS5FgpDdE9/zx7no8bxROHymSlPLZzq0ChbbLk1DrxBfc+eTeBK3y8nIL+nu/0QeYydhhbLIr7ecHJpywjQaoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@sinonjs/commons": "^3.0.0",
|
||||||
|
"@sinonjs/fake-timers": "^10.2.0",
|
||||||
|
"@sinonjs/samsam": "^8.0.0",
|
||||||
|
"diff": "^5.1.0",
|
||||||
|
"nise": "^5.1.4",
|
||||||
|
"supports-color": "^7.2.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/sinon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sinon/node_modules/diff": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sinon/node_modules/supports-color": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/slash": {
|
"node_modules/slash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
@@ -4191,6 +4497,29 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@lancedb/vectordb-darwin-arm64": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://npm.pkg.github.com/download/@lancedb/vectordb-darwin-arm64/0.1.2/84d71331e03e8aaeb9fb12cdacc759dc82cfd3b0",
|
||||||
|
"integrity": "sha512-DU6tHmmn/coSj5r5FGwTMXMQfsSSxQN1ozOl9mFUXr0aVtlx5nlA8ZY5BAF/V371yL5QzNPKtaNpogP6iw51NA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@lancedb/vectordb-linux-arm64-gnu": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://npm.pkg.github.com/download/@lancedb/vectordb-linux-arm64-gnu/0.1.2/d5a9d66c3969494cf3546195fb5511f9f49aa295",
|
||||||
|
"integrity": "sha512-LZZ4KgoGqD5AzKX/utBrsxrwXq6whpUNa02tWxl/ND/601ruNi9ZUaXCTb1rSVUWJkgMR2wASk15kssyaPRSjw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@neon-rs/cli": {
|
||||||
|
"version": "0.0.74",
|
||||||
|
"resolved": "https://registry.npmjs.org/@neon-rs/cli/-/cli-0.0.74.tgz",
|
||||||
|
"integrity": "sha512-9lPmNmjej5iKKOTMPryOMubwkgMRyTWRuaq1yokASvI5mPhr2kzPN7UVjdCOjQvpunNPngR9yAHoirpjiWhUHw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@neon-rs/load": {
|
||||||
|
"version": "0.0.74",
|
||||||
|
"resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.74.tgz",
|
||||||
|
"integrity": "sha512-/cPZD907UNz55yrc/ud4wDgQKtU1TvkD9jeqZWG6J4IMmZkp6zgjkQcKA8UvpkZlcpPHvc8J17sGzLFbP/LUYg=="
|
||||||
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -4217,6 +4546,52 @@
|
|||||||
"fastq": "^1.6.0"
|
"fastq": "^1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@sinonjs/commons": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"type-detect": "4.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sinonjs/fake-timers": {
|
||||||
|
"version": "10.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz",
|
||||||
|
"integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@sinonjs/commons": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sinonjs/samsam": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@sinonjs/commons": "^2.0.0",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
|
"type-detect": "^4.0.8"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sinonjs/commons": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"type-detect": "4.0.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@sinonjs/text-encoding": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@tsconfig/node10": {
|
"@tsconfig/node10": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||||
@@ -4292,6 +4667,21 @@
|
|||||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/sinon": {
|
||||||
|
"version": "10.0.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz",
|
||||||
|
"integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/sinonjs__fake-timers": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/sinonjs__fake-timers": {
|
||||||
|
"version": "8.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz",
|
||||||
|
"integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/strip-bom": {
|
"@types/strip-bom": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||||
@@ -4579,12 +4969,27 @@
|
|||||||
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"available-typed-arrays": {
|
"available-typed-arrays": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
||||||
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
|
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"axios": {
|
||||||
|
"version": "0.26.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||||
|
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"follow-redirects": "^1.14.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
@@ -4749,6 +5154,15 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"command-line-args": {
|
"command-line-args": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz",
|
||||||
@@ -4908,6 +5322,12 @@
|
|||||||
"object-keys": "^1.1.1"
|
"object-keys": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"diff": {
|
"diff": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||||
@@ -5475,6 +5895,12 @@
|
|||||||
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
|
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"follow-redirects": {
|
||||||
|
"version": "1.15.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||||
|
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"for-each": {
|
"for-each": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||||
@@ -5484,6 +5910,17 @@
|
|||||||
"is-callable": "^1.1.3"
|
"is-callable": "^1.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"form-data": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fs.realpath": {
|
"fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
@@ -5912,6 +6349,12 @@
|
|||||||
"call-bind": "^1.0.2"
|
"call-bind": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"isarray": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@@ -5959,6 +6402,12 @@
|
|||||||
"minimist": "^1.2.0"
|
"minimist": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"just-extend": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"levn": {
|
"levn": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||||
@@ -5983,6 +6432,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
|
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
|
||||||
},
|
},
|
||||||
|
"lodash.get": {
|
||||||
|
"version": "4.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||||
|
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"lodash.merge": {
|
"lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
@@ -6039,6 +6494,21 @@
|
|||||||
"picomatch": "^2.3.1"
|
"picomatch": "^2.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
@@ -6172,6 +6642,30 @@
|
|||||||
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
|
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"nise": {
|
||||||
|
"version": "5.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz",
|
||||||
|
"integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@sinonjs/commons": "^2.0.0",
|
||||||
|
"@sinonjs/fake-timers": "^10.0.2",
|
||||||
|
"@sinonjs/text-encoding": "^0.7.1",
|
||||||
|
"just-extend": "^4.0.2",
|
||||||
|
"path-to-regexp": "^1.7.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sinonjs/commons": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"type-detect": "4.0.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
@@ -6222,6 +6716,16 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"openai": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/openai/-/openai-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-762C9BNlJPbjjlWZi4WYK9iM2tAVAv0uUp1UmI34vb0CN5T2mjB/qM6RYBmNKMh/dN9fC+bxqPwWJZUTWW052A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"axios": "^0.26.0",
|
||||||
|
"form-data": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"optionator": {
|
"optionator": {
|
||||||
"version": "0.9.1",
|
"version": "0.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
|
||||||
@@ -6295,6 +6799,15 @@
|
|||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"path-to-regexp": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"isarray": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"path-type": {
|
"path-type": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||||
@@ -6484,6 +6997,37 @@
|
|||||||
"object-inspect": "^1.9.0"
|
"object-inspect": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sinon": {
|
||||||
|
"version": "15.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.0.tgz",
|
||||||
|
"integrity": "sha512-cS5FgpDdE9/zx7no8bxROHymSlPLZzq0ChbbLk1DrxBfc+eTeBK3y8nIL+nu/0QeYydhhbLIr7ecHJpywjQaoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@sinonjs/commons": "^3.0.0",
|
||||||
|
"@sinonjs/fake-timers": "^10.2.0",
|
||||||
|
"@sinonjs/samsam": "^8.0.0",
|
||||||
|
"diff": "^5.1.0",
|
||||||
|
"nise": "^5.1.4",
|
||||||
|
"supports-color": "^7.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"diff": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"slash": {
|
"slash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "vectordb",
|
"name": "vectordb",
|
||||||
"version": "0.1.1",
|
"version": "0.1.2",
|
||||||
"description": " Serverless, low-latency vector database for AI applications",
|
"description": " Serverless, low-latency vector database for AI applications",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"tsc": "tsc -b",
|
"tsc": "tsc -b",
|
||||||
"build": "cargo-cp-artifact --artifact cdylib vectordb-node index.node -- cargo build --message-format=json-render-diagnostics",
|
"build": "cargo-cp-artifact --artifact cdylib vectordb-node index.node -- cargo build --message-format=json",
|
||||||
"build-release": "npm run build -- --release",
|
"build-release": "npm run build -- --release",
|
||||||
|
"cross-release": "cargo-cp-artifact --artifact cdylib vectordb-node index.node -- cross build --message-format=json --release -p vectordb-node",
|
||||||
"test": "mocha -recursive dist/test",
|
"test": "mocha -recursive dist/test",
|
||||||
"lint": "eslint src --ext .js,.ts"
|
"lint": "eslint src --ext .js,.ts",
|
||||||
|
"pack-build": "neon pack-build",
|
||||||
|
"check-npm": "printenv && which node && which npm && npm --version"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -24,9 +27,11 @@
|
|||||||
"author": "Lance Devs",
|
"author": "Lance Devs",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@neon-rs/cli": "^0.0.74",
|
||||||
"@types/chai": "^4.3.4",
|
"@types/chai": "^4.3.4",
|
||||||
"@types/mocha": "^10.0.1",
|
"@types/mocha": "^10.0.1",
|
||||||
"@types/node": "^18.16.2",
|
"@types/node": "^18.16.2",
|
||||||
|
"@types/sinon": "^10.0.15",
|
||||||
"@types/temp": "^0.9.1",
|
"@types/temp": "^0.9.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
"@typescript-eslint/eslint-plugin": "^5.59.1",
|
||||||
"cargo-cp-artifact": "^0.1",
|
"cargo-cp-artifact": "^0.1",
|
||||||
@@ -37,6 +42,8 @@
|
|||||||
"eslint-plugin-n": "^15.7.0",
|
"eslint-plugin-n": "^15.7.0",
|
||||||
"eslint-plugin-promise": "^6.1.1",
|
"eslint-plugin-promise": "^6.1.1",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
|
"sinon": "^15.1.0",
|
||||||
|
"openai": "^3.2.1",
|
||||||
"temp": "^0.9.4",
|
"temp": "^0.9.4",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"ts-node-dev": "^2.0.0",
|
"ts-node-dev": "^2.0.0",
|
||||||
@@ -44,6 +51,29 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apache-arrow/ts": "^12.0.0",
|
"@apache-arrow/ts": "^12.0.0",
|
||||||
|
"@neon-rs/load": "^0.0.74",
|
||||||
"apache-arrow": "^12.0.0"
|
"apache-arrow": "^12.0.0"
|
||||||
|
},
|
||||||
|
"os": [
|
||||||
|
"darwin",
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"cpu": [
|
||||||
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"neon": {
|
||||||
|
"targets": {
|
||||||
|
"x86_64-apple-darwin": "@lancedb/vectordb-darwin-x64",
|
||||||
|
"aarch64-apple-darwin": "@lancedb/vectordb-darwin-arm64",
|
||||||
|
"x86_64-unknown-linux-gnu": "@lancedb/vectordb-linux-x64-gnu",
|
||||||
|
"aarch64-unknown-linux-gnu": "@lancedb/vectordb-linux-arm64-gnu"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@lancedb/vectordb-darwin-arm64": "0.1.2",
|
||||||
|
"@lancedb/vectordb-darwin-x64": "0.1.2",
|
||||||
|
"@lancedb/vectordb-linux-x64-gnu": "0.1.2",
|
||||||
|
"@lancedb/vectordb-linux-arm64-gnu": "0.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
} from 'apache-arrow'
|
} from 'apache-arrow'
|
||||||
import { type EmbeddingFunction } from './index'
|
import { type EmbeddingFunction } from './index'
|
||||||
|
|
||||||
export function convertToTable<T> (data: Array<Record<string, unknown>>, embeddings?: EmbeddingFunction<T>): Table {
|
export async function convertToTable<T> (data: Array<Record<string, unknown>>, embeddings?: EmbeddingFunction<T>): Promise<Table> {
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
throw new Error('At least one record needs to be provided')
|
throw new Error('At least one record needs to be provided')
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ export function convertToTable<T> (data: Array<Record<string, unknown>>, embeddi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (columnsKey === embeddings?.sourceColumn) {
|
if (columnsKey === embeddings?.sourceColumn) {
|
||||||
const vectors = embeddings.embed(values as T[])
|
const vectors = await embeddings.embed(values as T[])
|
||||||
const listBuilder = newVectorListBuilder()
|
const listBuilder = newVectorListBuilder()
|
||||||
vectors.map(v => listBuilder.append(v))
|
vectors.map(v => listBuilder.append(v))
|
||||||
records.vector = listBuilder.finish().toVector()
|
records.vector = listBuilder.finish().toVector()
|
||||||
@@ -79,7 +79,7 @@ function newVectorListBuilder (): ListBuilder<Float32, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function fromRecordsToBuffer<T> (data: Array<Record<string, unknown>>, embeddings?: EmbeddingFunction<T>): Promise<Buffer> {
|
export async function fromRecordsToBuffer<T> (data: Array<Record<string, unknown>>, embeddings?: EmbeddingFunction<T>): Promise<Buffer> {
|
||||||
const table = convertToTable(data, embeddings)
|
const table = await convertToTable(data, embeddings)
|
||||||
const writer = RecordBatchFileWriter.writeAll(table)
|
const writer = RecordBatchFileWriter.writeAll(table)
|
||||||
return Buffer.from(await writer.toUint8Array())
|
return Buffer.from(await writer.toUint8Array())
|
||||||
}
|
}
|
||||||
|
|||||||
28
node/src/embedding/embedding_function.ts
Normal file
28
node/src/embedding/embedding_function.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An embedding function that automatically creates vector representation for a given column.
|
||||||
|
*/
|
||||||
|
export interface EmbeddingFunction<T> {
|
||||||
|
/**
|
||||||
|
* The name of the column that will be used as input for the Embedding Function.
|
||||||
|
*/
|
||||||
|
sourceColumn: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a vector representation for the given values.
|
||||||
|
*/
|
||||||
|
embed: (data: T[]) => Promise<number[][]>
|
||||||
|
}
|
||||||
51
node/src/embedding/openai.ts
Normal file
51
node/src/embedding/openai.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
import { type EmbeddingFunction } from '../index'
|
||||||
|
|
||||||
|
export class OpenAIEmbeddingFunction implements EmbeddingFunction<string> {
|
||||||
|
private readonly _openai: any
|
||||||
|
private readonly _modelName: string
|
||||||
|
|
||||||
|
constructor (sourceColumn: string, openAIKey: string, modelName: string = 'text-embedding-ada-002') {
|
||||||
|
let openai
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
openai = require('openai')
|
||||||
|
} catch {
|
||||||
|
throw new Error('please install openai using npm install openai')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sourceColumn = sourceColumn
|
||||||
|
const configuration = new openai.Configuration({
|
||||||
|
apiKey: openAIKey
|
||||||
|
})
|
||||||
|
this._openai = new openai.OpenAIApi(configuration)
|
||||||
|
this._modelName = modelName
|
||||||
|
}
|
||||||
|
|
||||||
|
async embed (data: string[]): Promise<number[][]> {
|
||||||
|
const response = await this._openai.createEmbedding({
|
||||||
|
model: this._modelName,
|
||||||
|
input: data
|
||||||
|
})
|
||||||
|
const embeddings: number[][] = []
|
||||||
|
for (let i = 0; i < response.data.data.length; i++) {
|
||||||
|
embeddings.push(response.data.data[i].embedding as number[])
|
||||||
|
}
|
||||||
|
return embeddings
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceColumn: string
|
||||||
|
}
|
||||||
@@ -19,10 +19,14 @@ import {
|
|||||||
Vector
|
Vector
|
||||||
} from 'apache-arrow'
|
} from 'apache-arrow'
|
||||||
import { fromRecordsToBuffer } from './arrow'
|
import { fromRecordsToBuffer } from './arrow'
|
||||||
|
import type { EmbeddingFunction } from './embedding/embedding_function'
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const { databaseNew, databaseTableNames, databaseOpenTable, tableCreate, tableSearch, tableAdd, tableCreateVectorIndex } = require('../native.js')
|
const { databaseNew, databaseTableNames, databaseOpenTable, tableCreate, tableSearch, tableAdd, tableCreateVectorIndex } = require('../native.js')
|
||||||
|
|
||||||
|
export type { EmbeddingFunction }
|
||||||
|
export { OpenAIEmbeddingFunction } from './embedding/openai'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a LanceDB instance at the given URI
|
* Connect to a LanceDB instance at the given URI
|
||||||
* @param uri The uri of the database.
|
* @param uri The uri of the database.
|
||||||
@@ -135,14 +139,8 @@ export class Table<T = number[]> {
|
|||||||
* Creates a search query to find the nearest neighbors of the given search term
|
* Creates a search query to find the nearest neighbors of the given search term
|
||||||
* @param query The query search term
|
* @param query The query search term
|
||||||
*/
|
*/
|
||||||
search (query: T): Query {
|
search (query: T): Query<T> {
|
||||||
let queryVector: number[]
|
return new Query(this._tbl, query, this._embeddings)
|
||||||
if (this._embeddings !== undefined) {
|
|
||||||
queryVector = this._embeddings.embed([query])[0]
|
|
||||||
} else {
|
|
||||||
queryVector = query as number[]
|
|
||||||
}
|
|
||||||
return new Query(this._tbl, queryVector)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,32 +226,35 @@ export type VectorIndexParams = IvfPQIndexConfig
|
|||||||
/**
|
/**
|
||||||
* A builder for nearest neighbor queries for LanceDB.
|
* A builder for nearest neighbor queries for LanceDB.
|
||||||
*/
|
*/
|
||||||
export class Query {
|
export class Query<T = number[]> {
|
||||||
private readonly _tbl: any
|
private readonly _tbl: any
|
||||||
private readonly _queryVector: number[]
|
private readonly _query: T
|
||||||
|
private _queryVector?: number[]
|
||||||
private _limit: number
|
private _limit: number
|
||||||
private _refineFactor?: number
|
private _refineFactor?: number
|
||||||
private _nprobes: number
|
private _nprobes: number
|
||||||
private readonly _columns?: string[]
|
private readonly _columns?: string[]
|
||||||
private _filter?: string
|
private _filter?: string
|
||||||
private _metricType?: MetricType
|
private _metricType?: MetricType
|
||||||
|
private readonly _embeddings?: EmbeddingFunction<T>
|
||||||
|
|
||||||
constructor (tbl: any, queryVector: number[]) {
|
constructor (tbl: any, query: T, embeddings?: EmbeddingFunction<T>) {
|
||||||
this._tbl = tbl
|
this._tbl = tbl
|
||||||
this._queryVector = queryVector
|
this._query = query
|
||||||
this._limit = 10
|
this._limit = 10
|
||||||
this._nprobes = 20
|
this._nprobes = 20
|
||||||
this._refineFactor = undefined
|
this._refineFactor = undefined
|
||||||
this._columns = undefined
|
this._columns = undefined
|
||||||
this._filter = undefined
|
this._filter = undefined
|
||||||
this._metricType = undefined
|
this._metricType = undefined
|
||||||
|
this._embeddings = embeddings
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Sets the number of results that will be returned
|
* Sets the number of results that will be returned
|
||||||
* @param value number of results
|
* @param value number of results
|
||||||
*/
|
*/
|
||||||
limit (value: number): Query {
|
limit (value: number): Query<T> {
|
||||||
this._limit = value
|
this._limit = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -262,7 +263,7 @@ export class Query {
|
|||||||
* Refine the results by reading extra elements and re-ranking them in memory.
|
* Refine the results by reading extra elements and re-ranking them in memory.
|
||||||
* @param value refine factor to use in this query.
|
* @param value refine factor to use in this query.
|
||||||
*/
|
*/
|
||||||
refineFactor (value: number): Query {
|
refineFactor (value: number): Query<T> {
|
||||||
this._refineFactor = value
|
this._refineFactor = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -271,7 +272,7 @@ export class Query {
|
|||||||
* The number of probes used. A higher number makes search more accurate but also slower.
|
* The number of probes used. A higher number makes search more accurate but also slower.
|
||||||
* @param value The number of probes used.
|
* @param value The number of probes used.
|
||||||
*/
|
*/
|
||||||
nprobes (value: number): Query {
|
nprobes (value: number): Query<T> {
|
||||||
this._nprobes = value
|
this._nprobes = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -280,7 +281,7 @@ export class Query {
|
|||||||
* A filter statement to be applied to this query.
|
* A filter statement to be applied to this query.
|
||||||
* @param value A filter in the same format used by a sql WHERE clause.
|
* @param value A filter in the same format used by a sql WHERE clause.
|
||||||
*/
|
*/
|
||||||
filter (value: string): Query {
|
filter (value: string): Query<T> {
|
||||||
this._filter = value
|
this._filter = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -289,7 +290,7 @@ export class Query {
|
|||||||
* The MetricType used for this Query.
|
* The MetricType used for this Query.
|
||||||
* @param value The metric to the. @see MetricType for the different options
|
* @param value The metric to the. @see MetricType for the different options
|
||||||
*/
|
*/
|
||||||
metricType (value: MetricType): Query {
|
metricType (value: MetricType): Query<T> {
|
||||||
this._metricType = value
|
this._metricType = value
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -298,6 +299,12 @@ export class Query {
|
|||||||
* Execute the query and return the results as an Array of Objects
|
* Execute the query and return the results as an Array of Objects
|
||||||
*/
|
*/
|
||||||
async execute<T = Record<string, unknown>> (): Promise<T[]> {
|
async execute<T = Record<string, unknown>> (): Promise<T[]> {
|
||||||
|
if (this._embeddings !== undefined) {
|
||||||
|
this._queryVector = (await this._embeddings.embed([this._query]))[0]
|
||||||
|
} else {
|
||||||
|
this._queryVector = this._query as number[]
|
||||||
|
}
|
||||||
|
|
||||||
const buffer = await tableSearch.call(this._tbl, this)
|
const buffer = await tableSearch.call(this._tbl, this)
|
||||||
const data = tableFromIPC(buffer)
|
const data = tableFromIPC(buffer)
|
||||||
return data.toArray().map((entry: Record<string, unknown>) => {
|
return data.toArray().map((entry: Record<string, unknown>) => {
|
||||||
@@ -319,21 +326,6 @@ export enum WriteMode {
|
|||||||
Append = 'append'
|
Append = 'append'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An embedding function that automatically creates vector representation for a given column.
|
|
||||||
*/
|
|
||||||
export interface EmbeddingFunction<T> {
|
|
||||||
/**
|
|
||||||
* The name of the column that will be used as input for the Embedding Function.
|
|
||||||
*/
|
|
||||||
sourceColumn: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a vector representation for the given values.
|
|
||||||
*/
|
|
||||||
embed: (data: T[]) => number[][]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Distance metrics type.
|
* Distance metrics type.
|
||||||
*/
|
*/
|
||||||
|
|||||||
50
node/src/test/embedding/openai.ts
Normal file
50
node/src/test/embedding/openai.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
import { describe } from 'mocha'
|
||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { OpenAIEmbeddingFunction } from '../../embedding/openai'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const { OpenAIApi } = require('openai')
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const { stub } = require('sinon')
|
||||||
|
|
||||||
|
describe('OpenAPIEmbeddings', function () {
|
||||||
|
const stubValue = {
|
||||||
|
data: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
embedding: Array(1536).fill(1.0)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
embedding: Array(1536).fill(2.0)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('#embed', function () {
|
||||||
|
it('should create vector embeddings', async function () {
|
||||||
|
const openAIStub = stub(OpenAIApi.prototype, 'createEmbedding').returns(stubValue)
|
||||||
|
const f = new OpenAIEmbeddingFunction('text', 'sk-key')
|
||||||
|
const vectors = await f.embed(['abc', 'def'])
|
||||||
|
assert.isTrue(openAIStub.calledOnce)
|
||||||
|
assert.equal(vectors.length, 2)
|
||||||
|
assert.deepEqual(vectors[0], stubValue.data.data[0].embedding)
|
||||||
|
assert.deepEqual(vectors[1], stubValue.data.data[1].embedding)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -154,7 +154,7 @@ describe('LanceDB client', function () {
|
|||||||
['bar', [3.1, 3.2]]
|
['bar', [3.1, 3.2]]
|
||||||
])
|
])
|
||||||
|
|
||||||
embed (data: string[]): number[][] {
|
async embed (data: string[]): Promise<number[][]> {
|
||||||
return data.map(datum => this._embedding_map.get(datum) ?? [0.0, 0.0])
|
return data.map(datum => this._embedding_map.get(datum) ?? [0.0, 0.0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
108
notebooks/diffusiondb/datagen.py
Executable file
108
notebooks/diffusiondb/datagen.py
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2023 LanceDB 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.
|
||||||
|
|
||||||
|
"""Dataset hf://poloclub/diffusiondb
|
||||||
|
"""
|
||||||
|
|
||||||
|
import io
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
import lance
|
||||||
|
import lancedb
|
||||||
|
import pyarrow as pa
|
||||||
|
from datasets import load_dataset
|
||||||
|
from PIL import Image
|
||||||
|
from transformers import CLIPModel, CLIPProcessor, CLIPTokenizerFast
|
||||||
|
|
||||||
|
MODEL_ID = "openai/clip-vit-base-patch32"
|
||||||
|
|
||||||
|
device = "cuda"
|
||||||
|
|
||||||
|
tokenizer = CLIPTokenizerFast.from_pretrained(MODEL_ID)
|
||||||
|
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device)
|
||||||
|
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
|
||||||
|
|
||||||
|
schema = pa.schema(
|
||||||
|
[
|
||||||
|
pa.field("prompt", pa.string()),
|
||||||
|
pa.field("seed", pa.uint32()),
|
||||||
|
pa.field("step", pa.uint16()),
|
||||||
|
pa.field("cfg", pa.float32()),
|
||||||
|
pa.field("sampler", pa.string()),
|
||||||
|
pa.field("width", pa.uint16()),
|
||||||
|
pa.field("height", pa.uint16()),
|
||||||
|
pa.field("timestamp", pa.timestamp("s")),
|
||||||
|
pa.field("image_nsfw", pa.float32()),
|
||||||
|
pa.field("prompt_nsfw", pa.float32()),
|
||||||
|
pa.field("vector", pa.list_(pa.float32(), 512)),
|
||||||
|
pa.field("image", pa.binary()),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def pil_to_bytes(img) -> list[bytes]:
|
||||||
|
buf = io.BytesIO()
|
||||||
|
img.save(buf, format="PNG")
|
||||||
|
return buf.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
def generate_clip_embeddings(batch) -> pa.RecordBatch:
|
||||||
|
image = processor(text=None, images=batch["image"], return_tensors="pt")[
|
||||||
|
"pixel_values"
|
||||||
|
].to(device)
|
||||||
|
img_emb = model.get_image_features(image)
|
||||||
|
batch["vector"] = img_emb.cpu().tolist()
|
||||||
|
|
||||||
|
with Pool() as p:
|
||||||
|
batch["image_bytes"] = p.map(pil_to_bytes, batch["image"])
|
||||||
|
return batch
|
||||||
|
|
||||||
|
|
||||||
|
def datagen(args):
|
||||||
|
"""Generate DiffusionDB dataset, and use CLIP model to generate image embeddings."""
|
||||||
|
dataset = load_dataset("poloclub/diffusiondb", args.subset)
|
||||||
|
data = []
|
||||||
|
for b in dataset.map(
|
||||||
|
generate_clip_embeddings, batched=True, batch_size=256, remove_columns=["image"]
|
||||||
|
)["train"]:
|
||||||
|
b["image"] = b["image_bytes"]
|
||||||
|
del b["image_bytes"]
|
||||||
|
data.append(b)
|
||||||
|
tbl = pa.Table.from_pylist(data, schema=schema)
|
||||||
|
return tbl
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"-o", "--output", metavar="DIR", help="Output lance directory", required=True
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--subset",
|
||||||
|
choices=["2m_all", "2m_first_10k", "2m_first_100k"],
|
||||||
|
default="2m_first_10k",
|
||||||
|
help="subset of the hg dataset",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
batches = datagen(args)
|
||||||
|
lance.write_dataset(batches, args.output)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
9
notebooks/diffusiondb/requirements.txt
Normal file
9
notebooks/diffusiondb/requirements.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
datasets
|
||||||
|
Pillow
|
||||||
|
lancedb
|
||||||
|
isort
|
||||||
|
black
|
||||||
|
transformers
|
||||||
|
--index-url https://download.pytorch.org/whl/cu118
|
||||||
|
torch
|
||||||
|
torchvision
|
||||||
240
notebooks/multimodal_search.ipynb
Normal file
240
notebooks/multimodal_search.ipynb
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"\n",
|
||||||
|
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip available: \u001b[0m\u001b[31;49m22.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.1.2\u001b[0m\n",
|
||||||
|
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
|
||||||
|
"\n",
|
||||||
|
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip available: \u001b[0m\u001b[31;49m22.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.1.2\u001b[0m\n",
|
||||||
|
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"!pip install --quiet -U lancedb\n",
|
||||||
|
"!pip install --quiet gradio transformers torch torchvision"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 60,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import io\n",
|
||||||
|
"import PIL\n",
|
||||||
|
"import duckdb\n",
|
||||||
|
"import lancedb"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## First run setup: Download data and pre-process"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 30,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"<lance.dataset.LanceDataset at 0x3045db590>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 30,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# remove null prompts\n",
|
||||||
|
"import lance\n",
|
||||||
|
"import pyarrow.compute as pc\n",
|
||||||
|
"\n",
|
||||||
|
"# download s3://eto-public/datasets/diffusiondb/small_10k.lance to this uri\n",
|
||||||
|
"data = lance.dataset(\"~/datasets/rawdata.lance\").to_table()\n",
|
||||||
|
"\n",
|
||||||
|
"# First data processing and full-text-search index\n",
|
||||||
|
"db = lancedb.connect(\"~/datasets/demo\")\n",
|
||||||
|
"tbl = db.create_table(\"diffusiondb\", data.filter(~pc.field(\"prompt\").is_null()))\n",
|
||||||
|
"tbl = tbl.create_fts_index([\"prompt\"])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Create / Open LanceDB Table"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 62,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"db = lancedb.connect(\"~/datasets/demo\")\n",
|
||||||
|
"tbl = db.open_table(\"diffusiondb\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Create CLIP embedding function for the text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 63,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from transformers import CLIPModel, CLIPProcessor, CLIPTokenizerFast\n",
|
||||||
|
"\n",
|
||||||
|
"MODEL_ID = \"openai/clip-vit-base-patch32\"\n",
|
||||||
|
"\n",
|
||||||
|
"tokenizer = CLIPTokenizerFast.from_pretrained(MODEL_ID)\n",
|
||||||
|
"model = CLIPModel.from_pretrained(MODEL_ID)\n",
|
||||||
|
"processor = CLIPProcessor.from_pretrained(MODEL_ID)\n",
|
||||||
|
"\n",
|
||||||
|
"def embed_func(query):\n",
|
||||||
|
" inputs = tokenizer([query], padding=True, return_tensors=\"pt\")\n",
|
||||||
|
" text_features = model.get_text_features(**inputs)\n",
|
||||||
|
" return text_features.detach().numpy()[0]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Search functions for Gradio"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 64,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def find_image_vectors(query):\n",
|
||||||
|
" emb = embed_func(query)\n",
|
||||||
|
" return _extract(tbl.search(emb).limit(9).to_df())\n",
|
||||||
|
"\n",
|
||||||
|
"def find_image_keywords(query):\n",
|
||||||
|
" return _extract(tbl.search(query).limit(9).to_df())\n",
|
||||||
|
"\n",
|
||||||
|
"def find_image_sql(query):\n",
|
||||||
|
" diffusiondb = tbl.to_lance()\n",
|
||||||
|
" return _extract(duckdb.query(query).to_df())\n",
|
||||||
|
"\n",
|
||||||
|
"def _extract(df):\n",
|
||||||
|
" image_col = \"image\"\n",
|
||||||
|
" return [(PIL.Image.open(io.BytesIO(row[image_col])), row[\"prompt\"]) for _, row in df.iterrows()]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Setup Gradio interface"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 65,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Running on local URL: http://127.0.0.1:7867\n",
|
||||||
|
"\n",
|
||||||
|
"To create a public link, set `share=True` in `launch()`.\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/html": [
|
||||||
|
"<div><iframe src=\"http://127.0.0.1:7867/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
"<IPython.core.display.HTML object>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": []
|
||||||
|
},
|
||||||
|
"execution_count": 65,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import gradio as gr\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"with gr.Blocks() as demo:\n",
|
||||||
|
"\n",
|
||||||
|
" with gr.Row():\n",
|
||||||
|
" with gr.Tab(\"Embeddings\"):\n",
|
||||||
|
" vector_query = gr.Textbox(value=\"portraits of a person\", show_label=False)\n",
|
||||||
|
" b1 = gr.Button(\"Submit\")\n",
|
||||||
|
" with gr.Tab(\"Keywords\"):\n",
|
||||||
|
" keyword_query = gr.Textbox(value=\"ninja turtle\", show_label=False)\n",
|
||||||
|
" b2 = gr.Button(\"Submit\")\n",
|
||||||
|
" with gr.Tab(\"SQL\"):\n",
|
||||||
|
" sql_query = gr.Textbox(value=\"SELECT * from diffusiondb WHERE image_nsfw >= 2 LIMIT 9\", show_label=False)\n",
|
||||||
|
" b3 = gr.Button(\"Submit\")\n",
|
||||||
|
" with gr.Row():\n",
|
||||||
|
" gallery = gr.Gallery(\n",
|
||||||
|
" label=\"Found images\", show_label=False, elem_id=\"gallery\"\n",
|
||||||
|
" ).style(columns=[3], rows=[3], object_fit=\"contain\", height=\"auto\") \n",
|
||||||
|
" \n",
|
||||||
|
" b1.click(find_image_vectors, inputs=vector_query, outputs=gallery)\n",
|
||||||
|
" b2.click(find_image_keywords, inputs=keyword_query, outputs=gallery)\n",
|
||||||
|
" b3.click(find_image_sql, inputs=sql_query, outputs=gallery)\n",
|
||||||
|
" \n",
|
||||||
|
"demo.launch()"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.11.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 1
|
||||||
|
}
|
||||||
@@ -253,8 +253,7 @@ def _sanitize_vector_column(data: pa.Table, vector_column_name: str) -> pa.Table
|
|||||||
vector_column_name: str
|
vector_column_name: str
|
||||||
The name of the vector column.
|
The name of the vector column.
|
||||||
"""
|
"""
|
||||||
i = data.column_names.index(vector_column_name)
|
if vector_column_name not in data.column_names:
|
||||||
if i < 0:
|
|
||||||
raise ValueError(f"Missing vector column: {vector_column_name}")
|
raise ValueError(f"Missing vector column: {vector_column_name}")
|
||||||
vec_arr = data[vector_column_name].combine_chunks()
|
vec_arr = data[vector_column_name].combine_chunks()
|
||||||
if pa.types.is_fixed_size_list(vec_arr.type):
|
if pa.types.is_fixed_size_list(vec_arr.type):
|
||||||
@@ -266,4 +265,4 @@ def _sanitize_vector_column(data: pa.Table, vector_column_name: str) -> pa.Table
|
|||||||
values = values.cast(pa.float32())
|
values = values.cast(pa.float32())
|
||||||
list_size = len(values) / len(data)
|
list_size = len(values) / len(data)
|
||||||
vec_arr = pa.FixedSizeListArray.from_arrays(values, list_size)
|
vec_arr = pa.FixedSizeListArray.from_arrays(values, list_size)
|
||||||
return data.set_column(i, vector_column_name, vec_arr)
|
return data.set_column(data.column_names.index(vector_column_name), vector_column_name, vec_arr)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vectordb-node"
|
name = "vectordb-node"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
description = "Serverless, low-latency vector database for AI applications"
|
description = "Serverless, low-latency vector database for AI applications"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "vectordb"
|
name = "vectordb"
|
||||||
version = "0.0.1"
|
version = "0.1.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Serverless, low-latency vector database for AI applications"
|
description = "Serverless, low-latency vector database for AI applications"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
@@ -13,7 +13,7 @@ arrow-array = "37.0"
|
|||||||
arrow-data = "37.0"
|
arrow-data = "37.0"
|
||||||
arrow-schema = "37.0"
|
arrow-schema = "37.0"
|
||||||
object_store = "0.5.6"
|
object_store = "0.5.6"
|
||||||
|
snafu = "0.7.4"
|
||||||
lance = "0.4.17"
|
lance = "0.4.17"
|
||||||
tokio = { version = "1.23", features = ["rt-multi-thread"] }
|
tokio = { version = "1.23", features = ["rt-multi-thread"] }
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ use std::path::Path;
|
|||||||
|
|
||||||
use arrow_array::RecordBatchReader;
|
use arrow_array::RecordBatchReader;
|
||||||
use lance::io::object_store::ObjectStore;
|
use lance::io::object_store::ObjectStore;
|
||||||
|
use snafu::prelude::*;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::{CreateDirSnafu, Result};
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
|
|
||||||
pub struct Database {
|
pub struct Database {
|
||||||
@@ -43,10 +44,7 @@ impl Database {
|
|||||||
pub async fn connect(uri: &str) -> Result<Database> {
|
pub async fn connect(uri: &str) -> Result<Database> {
|
||||||
let object_store = ObjectStore::new(uri).await?;
|
let object_store = ObjectStore::new(uri).await?;
|
||||||
if object_store.is_local() {
|
if object_store.is_local() {
|
||||||
let path = Path::new(uri);
|
Self::try_create_dir(uri).context(CreateDirSnafu { path: uri })?;
|
||||||
if !path.try_exists()? {
|
|
||||||
create_dir_all(&path)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(Database {
|
Ok(Database {
|
||||||
uri: uri.to_string(),
|
uri: uri.to_string(),
|
||||||
@@ -54,6 +52,15 @@ impl Database {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to create a local directory to store the lancedb dataset
|
||||||
|
fn try_create_dir(path: &str) -> core::result::Result<(), std::io::Error> {
|
||||||
|
let path = Path::new(path);
|
||||||
|
if !path.try_exists()? {
|
||||||
|
create_dir_all(&path)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the names of all tables in the database.
|
/// Get the names of all tables in the database.
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
|
|||||||
@@ -12,44 +12,50 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#[derive(Debug)]
|
use snafu::Snafu;
|
||||||
pub enum Error {
|
|
||||||
IO(String),
|
|
||||||
Lance(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Error {
|
#[derive(Debug, Snafu)]
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
#[snafu(visibility(pub(crate)))]
|
||||||
let (catalog, message) = match self {
|
pub enum Error {
|
||||||
Self::IO(s) => ("I/O", s.as_str()),
|
#[snafu(display("LanceDBError: Invalid table name: {name}"))]
|
||||||
Self::Lance(s) => ("Lance", s.as_str()),
|
InvalidTableName { name: String },
|
||||||
};
|
#[snafu(display("LanceDBError: Table '{name}' was not found"))]
|
||||||
write!(f, "LanceDBError({catalog}): {message}")
|
TableNotFound { name: String },
|
||||||
}
|
#[snafu(display("LanceDBError: Table '{name}' already exists"))]
|
||||||
|
TableAlreadyExists { name: String },
|
||||||
|
#[snafu(display("LanceDBError: Unable to created lance dataset at {path}: {source}"))]
|
||||||
|
CreateDir {
|
||||||
|
path: String,
|
||||||
|
source: std::io::Error,
|
||||||
|
},
|
||||||
|
#[snafu(display("LanceDBError: {message}"))]
|
||||||
|
Store { message: String },
|
||||||
|
#[snafu(display("LanceDBError: {message}"))]
|
||||||
|
Lance { message: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
impl From<std::io::Error> for Error {
|
|
||||||
fn from(e: std::io::Error) -> Self {
|
|
||||||
Self::IO(e.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<lance::Error> for Error {
|
impl From<lance::Error> for Error {
|
||||||
fn from(e: lance::Error) -> Self {
|
fn from(e: lance::Error) -> Self {
|
||||||
Self::Lance(e.to_string())
|
Self::Lance {
|
||||||
|
message: e.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<object_store::Error> for Error {
|
impl From<object_store::Error> for Error {
|
||||||
fn from(e: object_store::Error) -> Self {
|
fn from(e: object_store::Error) -> Self {
|
||||||
Self::IO(e.to_string())
|
Self::Store {
|
||||||
|
message: e.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<object_store::path::Error> for Error {
|
impl From<object_store::path::Error> for Error {
|
||||||
fn from(e: object_store::path::Error) -> Self {
|
fn from(e: object_store::path::Error) -> Self {
|
||||||
Self::IO(e.to_string())
|
Self::Store {
|
||||||
|
message: e.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ use std::sync::Arc;
|
|||||||
use arrow_array::{Float32Array, RecordBatchReader};
|
use arrow_array::{Float32Array, RecordBatchReader};
|
||||||
use lance::dataset::{Dataset, WriteMode, WriteParams};
|
use lance::dataset::{Dataset, WriteMode, WriteParams};
|
||||||
use lance::index::IndexType;
|
use lance::index::IndexType;
|
||||||
|
use snafu::prelude::*;
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, InvalidTableNameSnafu, Result};
|
||||||
use crate::index::vector::VectorIndexBuilder;
|
use crate::index::vector::VectorIndexBuilder;
|
||||||
use crate::query::Query;
|
use crate::query::Query;
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ pub const VECTOR_COLUMN_NAME: &str = "vector";
|
|||||||
pub const LANCE_FILE_EXTENSION: &str = "lance";
|
pub const LANCE_FILE_EXTENSION: &str = "lance";
|
||||||
|
|
||||||
/// A table in a LanceDB database.
|
/// A table in a LanceDB database.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
name: String,
|
name: String,
|
||||||
uri: String,
|
uri: String,
|
||||||
@@ -57,9 +59,16 @@ impl Table {
|
|||||||
let uri = table_uri
|
let uri = table_uri
|
||||||
.as_path()
|
.as_path()
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or(Error::IO(format!("Invalid table name: {}", name)))?;
|
.context(InvalidTableNameSnafu { name })?;
|
||||||
|
|
||||||
let dataset = Dataset::open(&uri).await?;
|
let dataset = Dataset::open(&uri).await.map_err(|e| match e {
|
||||||
|
lance::Error::DatasetNotFound { .. } => Error::TableNotFound {
|
||||||
|
name: name.to_string(),
|
||||||
|
},
|
||||||
|
e => Error::Lance {
|
||||||
|
message: e.to_string(),
|
||||||
|
},
|
||||||
|
})?;
|
||||||
Ok(Table {
|
Ok(Table {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
uri: uri.to_string(),
|
uri: uri.to_string(),
|
||||||
@@ -88,14 +97,22 @@ impl Table {
|
|||||||
let uri = table_uri
|
let uri = table_uri
|
||||||
.as_path()
|
.as_path()
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or(Error::IO(format!("Invalid table name: {}", name)))?
|
.context(InvalidTableNameSnafu { name })?
|
||||||
.to_string();
|
.to_string();
|
||||||
let dataset =
|
let dataset = Dataset::write(&mut batches, &uri, Some(WriteParams::default()))
|
||||||
Arc::new(Dataset::write(&mut batches, &uri, Some(WriteParams::default())).await?);
|
.await
|
||||||
|
.map_err(|e| match e {
|
||||||
|
lance::Error::DatasetAlreadyExists { .. } => Error::TableAlreadyExists {
|
||||||
|
name: name.to_string(),
|
||||||
|
},
|
||||||
|
e => Error::Lance {
|
||||||
|
message: e.to_string(),
|
||||||
|
},
|
||||||
|
})?;
|
||||||
Ok(Table {
|
Ok(Table {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
uri,
|
uri,
|
||||||
dataset,
|
dataset: Arc::new(dataset),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,15 +195,6 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::index::vector::IvfPQIndexBuilder;
|
use crate::index::vector::IvfPQIndexBuilder;
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_new_table_not_exists() {
|
|
||||||
let tmp_dir = tempdir().unwrap();
|
|
||||||
let uri = tmp_dir.path().to_str().unwrap();
|
|
||||||
|
|
||||||
let table = Table::open(&uri, "test").await;
|
|
||||||
assert!(table.is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_open() {
|
async fn test_open() {
|
||||||
let tmp_dir = tempdir().unwrap();
|
let tmp_dir = tempdir().unwrap();
|
||||||
@@ -203,6 +211,14 @@ mod tests {
|
|||||||
assert_eq!(table.name, "test")
|
assert_eq!(table.name, "test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_open_not_found() {
|
||||||
|
let tmp_dir = tempdir().unwrap();
|
||||||
|
let uri = tmp_dir.path().to_str().unwrap();
|
||||||
|
let table = Table::open(uri, "test").await;
|
||||||
|
assert!(matches!(table.unwrap_err(), Error::TableNotFound { .. }));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_object_store_path() {
|
fn test_object_store_path() {
|
||||||
use std::path::Path as StdPath;
|
use std::path::Path as StdPath;
|
||||||
@@ -211,6 +227,23 @@ mod tests {
|
|||||||
assert_eq!(c.to_str().unwrap(), "s3://bucket/path/to/file/subfile");
|
assert_eq!(c.to_str().unwrap(), "s3://bucket/path/to/file/subfile");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_already_exists() {
|
||||||
|
let tmp_dir = tempdir().unwrap();
|
||||||
|
let uri = tmp_dir.path().to_str().unwrap();
|
||||||
|
|
||||||
|
let batches: Box<dyn RecordBatchReader> = Box::new(make_test_batches());
|
||||||
|
let schema = batches.schema().clone();
|
||||||
|
Table::create(&uri, "test", batches).await.unwrap();
|
||||||
|
|
||||||
|
let batches: Box<dyn RecordBatchReader> = Box::new(make_test_batches());
|
||||||
|
let result = Table::create(&uri, "test", batches).await;
|
||||||
|
assert!(matches!(
|
||||||
|
result.unwrap_err(),
|
||||||
|
Error::TableAlreadyExists { .. }
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_add() {
|
async fn test_add() {
|
||||||
let tmp_dir = tempdir().unwrap();
|
let tmp_dir = tempdir().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user