Metadata-Version: 2.4
Name: llama-index-graph-stores-ladybug
Version: 0.3.4
Summary: llama-index Ladybug graph store integration
Author-email: Your Name <you@example.com>
License-Expression: MIT
License-File: LICENSE
Requires-Python: <4.0,>=3.10
Requires-Dist: ladybug>=0.18.2
Requires-Dist: llama-index-core<0.15,>=0.14.20
Provides-Extra: dev
Requires-Dist: black[jupyter]<=23.9.1,>=23.7.0; extra == 'dev'
Requires-Dist: codespell[toml]>=v2.2.6; extra == 'dev'
Requires-Dist: diff-cover>=9.2.0; extra == 'dev'
Requires-Dist: ipython==8.10.0; extra == 'dev'
Requires-Dist: jupyter<2,>=1.0.0; extra == 'dev'
Requires-Dist: mypy==0.991; extra == 'dev'
Requires-Dist: nbstripout>=0.9.0; extra == 'dev'
Requires-Dist: pre-commit==3.2.0; extra == 'dev'
Requires-Dist: pylint==2.15.10; extra == 'dev'
Requires-Dist: pytest-cov>=6.1.1; extra == 'dev'
Requires-Dist: pytest-mock>=3.11.1; extra == 'dev'
Requires-Dist: pytest>=8.4.0; extra == 'dev'
Requires-Dist: ruff==0.11.11; extra == 'dev'
Requires-Dist: types-deprecated>=0.1.0; extra == 'dev'
Requires-Dist: types-protobuf<5,>=4.24.0.4; extra == 'dev'
Requires-Dist: types-pyyaml<7,>=6.0.12.12; extra == 'dev'
Requires-Dist: types-redis==4.5.5.0; extra == 'dev'
Requires-Dist: types-requests==2.28.11.8; extra == 'dev'
Requires-Dist: types-setuptools==67.1.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# llama-index-ladybug

[LlamaIndex](https://www.llamaindex.ai/) graph store integration for [Ladybug](https://github.com/LadybugDB/ladybug) — an embedded graph database built for query speed and scalability. Ladybug is optimized for handling complex analytical workloads on very large databases and provides a set of retrieval features, such as full text search and vector indices.

The database was formerly known as [Kùzu](https://kuzudb.com/).

## Installation

```bash
uv pip install llama-index-graph-stores-ladybug
```

### Vector index extension (Ladybug 0.18.x+)

With `use_vector_index=True` (the default), the store loads Ladybug's **VECTOR extension** on first
use (`INSTALL vector; LOAD vector;`). `INSTALL` downloads it over the network the first time, then
caches it under `~/.lbdb/extension/` — after that it works offline. Set `use_vector_index=False` to
skip vector indexing entirely. (On Ladybug ≤ 0.16.x this was a core function, no download needed.)

#### OpenSSL 3 requirement

The VECTOR extension dynamically links **OpenSSL 3**. OpenSSL is **not** bundled with Ladybug (it's
security-sensitive and needs its own update cadence), so it must be present on your system — install
it yourself and keep it patched. If it's missing, `LOAD vector` fails and vector indexing is
unavailable.

##### Windows

The extension links `libssl-3-x64.dll` and `libcrypto-3-x64.dll`; without them `LOAD vector` fails
with **error 126** ("The specified module could not be found"). Install with Chocolatey, **elevated**:

```powershell
choco install openssl.light
```

This installs OpenSSL 3.x to `C:\Program Files\OpenSSL`, copies `libssl-3-x64.dll` /
`libcrypto-3-x64.dll` into `C:\Windows\System32`, and appends `C:\Program Files\OpenSSL\bin` to the
system `PATH`. Because the DLLs land in System32, `LOAD vector` then works in any shell with no
further `PATH` setup.

**Then verify** in a **new** shell (so `PATH` updates):

```powershell
where.exe libssl-3-x64.dll
where.exe libcrypto-3-x64.dll
```

Important notes:
- **It must be OpenSSL 3.x.** OpenSSL 4 renames the libraries to `libssl-4-x64.dll` /
  `libcrypto-4-x64.dll`, which do **not** satisfy the extension. Avoid "install latest OpenSSL"
  package sources — at the time of writing `winget install ShiningLight.OpenSSL.Light` ships 4.x and
  will **not** work.
- The names must be **exactly** `libssl-3-x64.dll` / `libcrypto-3-x64.dll`; builds shipping
  `libssl-3.dll` (no `-x64`) or `libeay32.dll` won't satisfy it either.
- `libssl` and `libcrypto` must be the **same** OpenSSL version.
- Run choco **elevated** — a non-admin `choco install` bootstraps Chocolatey into your user profile
  and can hang installing its `vcredist140-x64` dependency.
- If a prior install is already recorded, `choco install` no-ops; `choco uninstall openssl.light`
  first (or use `--force`).
- A **new shell** is required after any `PATH` change; services, Docker, and some IDE-launched
  terminals may not inherit it.

##### macOS

```bash
brew install openssl@3
```

Apple's bundled `/usr/bin/openssl` is LibreSSL, not OpenSSL, and isn't a substitute. Homebrew's
`openssl@3` is keg-only, so if the extension still can't find it, expose the Homebrew lib directory
(e.g. add `$(brew --prefix openssl@3)/lib` to `DYLD_LIBRARY_PATH`).

##### Linux

The distro provides OpenSSL 3 (`libssl.so.3` / `libcrypto.so.3`) and it's usually already installed.
If not:

| Distro | Command |
| --- | --- |
| Debian / Ubuntu | `apt install libssl3` |
| Fedora / RHEL | `dnf install openssl-libs` |
| Alpine | `apk add openssl` |

Slim container images often omit it — install it in the image if you hit a load failure.

#### Offline / CI / proxied

Pre-download the extension once where the network is available (caches it for later offline `LOAD`):

```bash
python -c "import ladybug, tempfile, os; ladybug.Connection(ladybug.Database(os.path.join(tempfile.mkdtemp(), 'db'))).execute('INSTALL vector;')"
```

For Docker, run that during the image build (and ensure OpenSSL 3 is installed in the image), or copy
the populated `~/.lbdb/extension/` into the image.

## Quick Start

### LadybugPropertyGraphStore — unstructured (default)

No schema required. All LLM-extracted entities are stored as Entity type and only relation types are Links and Mentions.

```python
from pathlib import Path
import ladybug as lb
from llama_index.graph_stores.ladybug import LadybugPropertyGraphStore
from llama_index.core import PropertyGraphIndex, SimpleDirectoryReader
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI

# Create a Ladybug database
Path("my_graph.ladybug").unlink(missing_ok=True)
db = lb.Database("my_graph.ladybug")

embed_model = OpenAIEmbedding(model_name="text-embedding-3-small")

graph_store = LadybugPropertyGraphStore(
    db,
    use_vector_index=True,
    embed_model=embed_model,
)

documents = SimpleDirectoryReader("./data").load_data()

index = PropertyGraphIndex.from_documents(
    documents,
    embed_model=embed_model,
    property_graph_store=graph_store,
    show_progress=True,
)

query_engine = index.as_query_engine()
response = query_engine.query("What are the main topics in these documents?")
print(response)
```

### LadybugPropertyGraphStore — structured schema

Pass a `relationship_schema` to guide the LLM towards your schema.

`strict_schema=False` (default) allows the graph to expand beyond the declared types — off-schema entities and relations are stored in overflow tables alongside the schema-defined ones.

`strict_schema=True` enforces the schema strictly — off-schema entities and relations are silently dropped at ingest.

```python
graph_store = LadybugPropertyGraphStore(
    db,
    relationship_schema=[
        ("PERSON", "WORKS_FOR", "ORGANIZATION"),
        ("PERSON", "KNOWS", "PERSON"),
    ],
    has_structured_schema=True,
    strict_schema=False,   # True to reject off-schema types entirely
    use_vector_index=True,
    embed_model=embed_model,
)
```

### LadybugGraphStore

```python
import ladybug as lb
from llama_index.graph_stores.ladybug import LadybugGraphStore
from llama_index.core import KnowledgeGraphIndex, StorageContext, SimpleDirectoryReader

db = lb.Database("my_graph.ladybug")
graph_store = LadybugGraphStore(db)
storage_context = StorageContext.from_defaults(graph_store=graph_store)

documents = SimpleDirectoryReader("./data").load_data()

index = KnowledgeGraphIndex.from_documents(
    documents,
    max_triplets_per_chunk=2,
    storage_context=storage_context,
)

query_engine = index.as_query_engine()
response = query_engine.query("What are the main topics in these documents?")
print(response)
```

## Features

- **Embedded** — no server required; the database is a local directory
- **Cypher queries** — full Cypher support via `structured_query()`
- **Vector index** — HNSW vector index on chunk nodes for similarity search, built into the graph store
- **Structured schemas** — optionally enforce entity/relation types for higher-quality triple extraction
- **Both graph store APIs** — supports both `PropertyGraphIndex` (`LadybugPropertyGraphStore`) and the legacy `KnowledgeGraphIndex` (`LadybugGraphStore`)

## Documentation

- [API Reference](docs/api/README.md)
- [Property Graph Notebook](docs/notebooks/property_graph_ladybug.ipynb)
- [GraphStore Notebook](docs/notebooks/LadybugGraphDemo.ipynb)

## Development

```bash
# Clone and set up
git clone https://github.com/stevereiner/llama-index-ladybug
cd llama-index-ladybug
uv sync --group dev

# Run tests
pytest

# Install pre-commit hooks (strips notebook outputs on commit)
pre-commit install
```

## Acknowledgements

Started from the Kuzu → Ladybug llama-index support port by [@adsharma](https://github.com/adsharma) ([PR #20232](https://github.com/run-llama/llama_index/pull/20232)) — a proposed LadybugDB (formerly Kùzu) integration into the upstream llama-index repo.

## Requirements

- Python 3.10+
- `ladybug >= 0.18.2`
- `llama-index-core >= 0.14.20`
- For the vector index on Ladybug 0.18.x+: the downloadable **VECTOR extension** (see
  [Vector index extension](#vector-index-extension-ladybug-018x) above) — needs network on first
  use, then cached under `~/.lbdb/extension/`. It also requires **OpenSSL 3** on the system (Windows
  needs `libssl-3-x64.dll` / `libcrypto-3-x64.dll`) — see the
  [OpenSSL 3 requirement](#openssl-3-requirement) section.
