Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,4 @@ jobs:
# Avoid workflow to fail if the version has already been published
skip-existing: true
# Upload to Test Pypi for testing
repository-url: https://test.pypi.org/legacy/
# repository-url: https://test.pypi.org/legacy/
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ SELECT load_extension('./vector');

Or embed it directly into your application.

### Python Package

Python developers can quickly get started using the ready-to-use `sqlite-vector` package available on PyPI:

```bash
pip install sqlite-vector
```

For usage details and examples, see the [Python package documentation](./packages/python/README.md).

## Example Usage

```sql
Expand Down
3 changes: 3 additions & 0 deletions packages/python/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include README.md
include LICENSE
recursive-include src/sqlite-vector/binaries *
46 changes: 46 additions & 0 deletions packages/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## SQLite Vector Python package

This package provides the sqlite-vector extension prebuilt binaries for multiple platforms and architectures.

### SQLite Vector

SQLite Vector is a cross-platform, ultra-efficient SQLite extension that brings vector search capabilities to your embedded database. It works seamlessly on iOS, Android, Windows, Linux, and macOS, using just 30MB of memory by default. With support for Float32, Float16, BFloat16, Int8, and UInt8, and highly optimized distance functions, it's the ideal solution for Edge AI applications.

More details on the official repository [sqliteai/sqlite-vector](https://github.com/sqliteai/sqlite-vector).

### Documentation

For detailed information on all available functions, their parameters, and examples, refer to the [comprehensive API Reference](https://github.com/sqliteai/sqlite-vector/blob/main/API.md).

### Supported Platforms and Architectures

| Platform | Arch | Subpackage name | Binary name |
| ------------- | ------------ | ------------------------ | ------------ |
| Linux (CPU) | x86_64/arm64 | sqlite-vector.binaries | vector.so |
| Windows (CPU) | x86_64 | sqlite-vector.binaries | vector.dll |
| macOS (CPU) | x86_64/arm64 | sqlite-vector.binaries | vector.dylib |

## Usage

> **Note:** Some SQLite installations on certain operating systems may have extension loading disabled by default.
If you encounter issues loading the extension, refer to the [sqlite-extensions-guide](https://github.com/sqliteai/sqlite-extensions-guide/) for platform-specific instructions on enabling and using SQLite extensions.

```python
import importlib.resources
import sqlite3

# Connect to your SQLite database
conn = sqlite3.connect("example.db")

# Load the sqlite-vector extension
# pip will install the correct binary package for your platform and architecture
ext_path = importlib.resources.files("sqlite-vector.binaries") / "vector"

conn.enable_load_extension(True)
conn.load_extension(str(ext_path))
conn.enable_load_extension(False)


# Now you can use sqlite-vector features in your SQL queries
print(conn.execute("SELECT vector_version();").fetchone())
```
97 changes: 97 additions & 0 deletions packages/python/download_artifacts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import sys
import zipfile
import requests
from pathlib import Path
import shutil


# == USAGE ==
# python3 download_artifacts.py PLATFORM VERSION
# eg: python3 download_artifacts.py linux_x86_64 "0.5.9"

REPO = "sqliteai/sqlite-vector"
RELEASE_URL = f"https://github.com/{REPO}/releases/download"

# Map Python plat_name to artifact names
ARTIFACTS = {
"manylinux2014_x86_64": ["vector-linux-x86_64"],
"manylinux2014_aarch64": [
"vector-linux-arm64",
],
"win_amd64": ["vector-windows-x86_64"],
"macosx_10_9_x86_64": ["vector-macos"],
"macosx_11_0_arm64": ["vector-macos"],
}

BINARY_NAME = {
"manylinux2014_x86_64": "vector.so",
"manylinux2014_aarch64": "vector.so",
"win_amd64": "vector.dll",
"macosx_10_9_x86_64": "vector.dylib",
"macosx_11_0_arm64": "vector.dylib",
}

BINARIES_DIR = Path(__file__).parent / "src/sqlite-vector/binaries"


def download_and_extract(artifact_name, bin_name, version):
artifact = f"{artifact_name}-{version}.zip"
url = f"{RELEASE_URL}/{version}/{artifact}"
print(f"Downloading {url}")

r = requests.get(url)
if r.status_code != 200:
print(f"Failed to download {artifact}: {r.status_code}")
sys.exit(1)

zip_path = BINARIES_DIR / artifact
with open(zip_path, "wb") as f:
f.write(r.content)

out_dir = BINARIES_DIR
out_dir.mkdir(parents=True, exist_ok=True)

with zipfile.ZipFile(zip_path, "r") as zip_ref:
for member in zip_ref.namelist():
if member.endswith(bin_name):
zip_ref.extract(member, out_dir)

# Move to expected name/location
src = out_dir / member
dst = out_dir / bin_name
src.rename(dst)

print(f"Extracted {dst}")

zip_path.unlink()


def main():
version = None
platform = None
if len(sys.argv) == 3:
platform = sys.argv[1].lower()
version = sys.argv[2]

if not version or not platform:
print(
'Error: Version is not specified.\nUsage: \n python3 download_artifacts.py linux_x86_64 "0.5.9"'
)
sys.exit(1)

print(BINARIES_DIR)
if BINARIES_DIR.exists():
shutil.rmtree(BINARIES_DIR)
BINARIES_DIR.mkdir(parents=True, exist_ok=True)

platform_artifacts = ARTIFACTS.get(platform, [])
if not platform_artifacts:
print(f"Error: Unknown platform '{platform}'")
sys.exit(1)

for artifact_name in platform_artifacts:
download_and_extract(artifact_name, BINARY_NAME[platform], version)


if __name__ == "__main__":
main()
25 changes: 25 additions & 0 deletions packages/python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[build-system]
requires = ["setuptools>=61.0", "wheel", "toml"]
build-backend = "setuptools.build_meta"

[project]
name = "sqlite-vector"
dynamic = ["version"]
description = "Python prebuilt binaries for SQLite Vector extension for all supported platforms and architectures."
authors = [
{ name = "SQLite AI Team" }
]
readme = "README.md"
requires-python = ">=3"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: POSIX :: Linux",
"Operating System :: Microsoft :: Windows",
"Operating System :: MacOS :: MacOS X"
]

[project.urls]
Homepage = "https://sqlite.ai"
Documentation = "https://github.com/sqliteai/sqlite-vector/blob/main/API.md"
Repository = "https://github.com/sqliteai/sqlite-vector"
Issues = "https://github.com/sqliteai/sqlite-vector/issues"
3 changes: 3 additions & 0 deletions packages/python/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
requests
toml
wheel
54 changes: 54 additions & 0 deletions packages/python/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import setuptools
import toml
import os
import sys

usage = """
Usage: python setup.py bdist_wheel --plat-name <platform>
The PACKAGE_VERSION environment variable must be set to the desired version.

Example:
PACKAGE_VERSION=0.5.9 python setup.py bdist_wheel --plat-name linux_x86_64
"""

with open("pyproject.toml", "r") as f:
pyproject = toml.load(f)

project = pyproject["project"]

# Get version from environment or default
version = os.environ.get("PACKAGE_VERSION", "")
if not version:
print("PACKAGE_VERSION environment variable is not set.")
print(usage)
sys.exit(1)

# Get Python platform name from --plat-name argument
plat_name = None
for i, arg in enumerate(sys.argv):
if arg == "--plat-name" and i + 1 < len(sys.argv):
plat_name = sys.argv[i + 1]
break

if not plat_name:
print("Error: --plat-name argument is required")
print(usage)
sys.exit(1)

with open("README.md", "r", encoding="utf-8") as f:
long_description = f.read()

setuptools.setup(
name=project["name"],
version=version,
description=project.get("description", ""),
author=project["authors"][0]["name"],
long_description=long_description,
long_description_content_type="text/markdown",
url=project["urls"]["Homepage"],
packages=setuptools.find_packages(where="src"),
package_dir={"": "src"},
include_package_data=True,
python_requires=project.get("requires-python", ">=3"),
classifiers=project.get("classifiers", []),
)
Empty file.
Loading