Skip to main content

Endee LlamaIndex Integration

LlamaIndex vector store integration for Endee.

For Endee setup, features, and server docs see docs.endee.io.

Sections: Setup | Dense | Hybrid | Multi-Field | Filters | RAG Pipeline


1. Setup

Install

pip install llama-index-vector-stores-endee

Pick an embedding model:

# Option A: Local (no API key)
pip install llama-index-embeddings-huggingface sentence-transformers

# Option B: OpenAI
pip install llama-index-embeddings-openai

Create a Collection

Collections are created with fields= — the same pattern as the Python client. Each field has a name, type, and params.

import os
from llama_index.core import Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index_endee import EndeeVectorStore

Settings.embed_model = HuggingFaceEmbedding(model_name="all-MiniLM-L6-v2")
DIMENSION = 384

# Or OpenAI:
# from llama_index.embeddings.openai import OpenAIEmbedding
# Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
# DIMENSION = 1536

# Dense-only collection (single vector field)
vector_store = EndeeVectorStore.from_params(
    api_token=os.getenv("ENDEE_API_TOKEN"),   # from app.endee.io (None for local)
    collection_name="my_collection",
    fields=[
        {
            "name": "dense",
            "type": "vector",
            "params": {
                "dimension": DIMENSION,
                "space_type": "cosine",
                "precision": "int8",
            },
        },
    ],
    force_recreate=True,
)

Endee Local (Docker)

Run Endee locally — no token needed. See GitHub for setup.

docker run -p 8000:8080 -v endee-data:/data endee-oss:latest
vector_store = EndeeVectorStore.from_params(
    collection_name="local_collection",
    fields=[
        {"name": "dense", "type": "vector",
         "params": {"dimension": DIMENSION, "space_type": "cosine", "precision": "int8"}},
    ],
    base_url="http://localhost:8000/api/v2",
)

Ingest Documents

from llama_index.core import Document, StorageContext, VectorStoreIndex

documents = [
    Document(text="Python is a high-level programming language known for readability.",
             metadata={"topic": "programming", "language": "python"}),
    Document(text="Machine learning gives systems the ability to learn from data.",
             metadata={"topic": "ai", "field": "ml"}),
    Document(text="Vector databases store embeddings for fast similarity search.",
             metadata={"topic": "database", "type": "vector"}),
]

storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

Reconnect to an Existing Collection

from_params auto-detects field names from an existing collection — no data loss:

vector_store = EndeeVectorStore.from_params(
    api_token="your-token",
    collection_name="my_existing_collection",
)
index = VectorStoreIndex.from_vector_store(vector_store)

# as_retriever
results = index.as_retriever(similarity_top_k=3).retrieve("Tell me about vector databases")
for node in results:
    print(f"{node.get_score():.4f} | {node.text}")

# Direct VectorStoreQuery
from llama_index.core.vector_stores.types import VectorStoreQuery

q_emb = Settings.embed_model.get_text_embedding("vector databases")
result = vector_store.query(VectorStoreQuery(query_embedding=q_emb, similarity_top_k=3))

# Search tuning
result = vector_store.query(
    VectorStoreQuery(query_embedding=q_emb, similarity_top_k=10),
    ef_search=256,
    prefilter_cardinality_threshold=5_000,
    filter_boost_percentage=20,
)

Loading many documents

from llama_index.core import SimpleDirectoryReader

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

storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
print(f"Indexed {len(documents)} documents")

Create a collection with both vector and sparse fields. Sparse vectors are auto-encoded via EndeeModelSparse (BM25).

from llama_index_endee import EndeeVectorStore, EndeeModelSparse

sparse = EndeeModelSparse()  # Native BM25

hybrid_store = EndeeVectorStore.from_params(
    api_token="your-token",
    collection_name="hybrid_collection",
    fields=[
        {"name": "dense", "type": "vector",
         "params": {"dimension": DIMENSION, "space_type": "cosine", "precision": "int8"}},
        {"name": "sparse", "type": "sparse", "sparse_model": "endee_bm25"},
    ],
    sparse_embedding=sparse,
    force_recreate=True,
)

add() automatically encodes sparse vectors alongside dense:

from llama_index.core.schema import TextNode

nodes = [
    TextNode(text="The error code is XJ-99-ZQ and it crashed the server.",
             embedding=embed_model.get_text_embedding("The error code is XJ-99-ZQ..."),
             metadata={"type": "error_log"}),
]
hybrid_store.add(nodes)

Query with query_str to enable sparse matching:

q_emb = embed_model.get_text_embedding("XJ-99-ZQ")
result = hybrid_store.query(VectorStoreQuery(
    query_embedding=q_emb,
    query_str="XJ-99-ZQ",   # used for BM25 sparse encoding
    similarity_top_k=3,
))

RRF Tuning

result = hybrid_store.query(
    query,
    dense_rrf_weight=0.3,    # 0.3 dense + 0.7 sparse
    rrf_rank_constant=30,
)
dense_rrf_weight Effect
1.0 Dense only
0.5 Balanced (default)
0.0 Sparse only

4. Multi-Field & Multi-Vector

Multiple Dense Fields

Use fields= with multiple vector entries, then add_objects() and multi_field_search():

store = EndeeVectorStore.from_params(
    api_token="your-token",
    collection_name="multi_field",
    fields=[
        {"name": "title",   "type": "vector",
         "params": {"dimension": 384, "space_type": "cosine", "precision": "int8"}},
        {"name": "content", "type": "vector",
         "params": {"dimension": 768, "space_type": "cosine", "precision": "int8"}},
        {"name": "keywords","type": "sparse", "sparse_model": "default"},
    ],
    force_recreate=True,
)

# Upsert with per-field data
store.add_objects([{
    "id": "doc1",
    "meta": {"text": "...", "metadata": {...}},
    "filter": {"topic": "ai"},
    "fields": {
        "title":   title_vec,
        "content": content_vec,
        "keywords": {"indices": [10, 42], "values": [0.9, 0.4]},
    },
}])

# Search + fuse with weighted RRF
from llama_index_endee import rerank

raw = store.multi_field_search(
    fields={
        "title":   {"query": title_vec,   "limit": 20},
        "content": {"query": content_vec, "limit": 20},
    },
)
fused = rerank(raw, limit=10, field_weights={"title": 0.4, "content": 0.6})

Multi-Vector (ColBERT-style)

A multi_vector field stores N vectors per object (one per token/chunk):

store = EndeeVectorStore.from_params(
    api_token="your-token",
    collection_name="colbert_collection",
    fields=[
        {"name": "dense",   "type": "vector",
         "params": {"dimension": 384, "space_type": "cosine", "precision": "int8"}},
        {"name": "colbert", "type": "multi_vector",
         "params": {"dimension": 128, "space_type": "cosine",
                    "precision": "float16", "pooling": "mean"}},
    ],
    force_recreate=True,
)

# Upsert: colbert field gets a list of vectors
store.add_objects([{
    "id": "doc1",
    "meta": {"text": "..."},
    "filter": {"topic": "ai"},
    "fields": {
        "dense":   [0.1, 0.2, ...],                  # 1 vector
        "colbert": [[0.1, ...], [0.2, ...], ...],     # N vectors
    },
}])

# Search: query is also a list of vectors
raw = store.multi_field_search(
    fields={"colbert": {"query": [[q1], [q2], [q3]], "limit": 10}},
)

# Or fuse dense + ColBERT
raw = store.multi_field_search(
    fields={
        "dense":   {"query": dense_vec,  "limit": 10},
        "colbert": {"query": token_vecs, "limit": 10},
    },
)
fused = rerank(raw, limit=5, field_weights={"dense": 0.5, "colbert": 0.5})

5. Filters

Pass filters to as_retriever() or query() — they are converted and forwarded to the Endee API.

from llama_index.core.vector_stores.types import MetadataFilters, MetadataFilter, FilterOperator

# EQ — exact match
filters = MetadataFilters(
    filters=[MetadataFilter(key="topic", value="ai", operator=FilterOperator.EQ)]
)
results = index.as_retriever(similarity_top_k=3, filters=filters).retrieve("machine learning")

# IN — match any in list
filters = MetadataFilters(
    filters=[MetadataFilter(key="topic", value=["ai", "database"], operator=FilterOperator.IN)]
)
results = index.as_retriever(similarity_top_k=3, filters=filters).retrieve("vector search")

# Multiple filters (AND logic)
filters = MetadataFilters(filters=[
    MetadataFilter(key="topic", value="database", operator=FilterOperator.EQ),
    MetadataFilter(key="type", value="vector", operator=FilterOperator.EQ),
])

Supported operators: EQ and IN.

CRUD Operations

# Fetch objects by ID
objects = vector_store.fetch(["node-id-1", "node-id-2"])

# Update filter metadata (no re-embedding)
vector_store.update_filters([
    {"id": "node-id-1", "filter": {"topic": "updated", "priority": 1}},
])

# Delete by ID
vector_store.delete_vector("node-id-1")

# Delete by ref_doc_id filter
vector_store.delete(ref_doc_id="doc-uuid")

# Delete entire collection
vector_store.clear()

# Collection metadata
info = vector_store.describe()

# Direct access to Endee Collection object
collection = vector_store.client

6. RAG Pipeline

from llama_index.core import Settings, VectorStoreIndex
from llama_index.llms.openai import OpenAI

Settings.llm = OpenAI(model="gpt-4o-mini", temperature=0)

index = VectorStoreIndex.from_vector_store(vector_store)
query_engine = index.as_query_engine(similarity_top_k=3)

response = query_engine.query("How does vector search work?")
print(response)

With metadata filters:

from llama_index.core.vector_stores.types import MetadataFilters, MetadataFilter, FilterOperator

retriever = index.as_retriever(
    similarity_top_k=3,
    filters=MetadataFilters(filters=[
        MetadataFilter(key="topic", value="database", operator=FilterOperator.EQ),
    ]),
)

from llama_index.core.query_engine import RetrieverQueryEngine
query_engine = RetrieverQueryEngine.from_args(retriever=retriever)
response = query_engine.query("Explain vector similarity search")

Field Types

Type Shape per object Use case
vector [float, ...] Standard single-embedding (sentence-transformers, OpenAI)
sparse {indices: [int], values: [float]} BM25 / SPLADE keyword matching
multi_vector [[float, ...], ...] Token-level (ColBERT), chunk-level embeddings

from_params Parameters

Parameter Type Default Description
collection_name str required Name of the Endee collection
fields list[dict] None Field definitions (same as Python client)
api_token str | None None From app.endee.io (None for local)
base_url str | None None API base URL (e.g. http://localhost:8000/api/v2)
dimension int | None None Vector dimension (simple mode only, ignored with fields=)
space_type str "cosine" Distance metric: cosine, l2, ip
precision str "int8" Quantisation: float32, float16, int16, int8, binary
M int | None None HNSW bi-directional links per node
ef_con int | None None HNSW construction quality
sparse_embedding SparseEmbeddings | None None Sparse model for hybrid search
dense_field_name str "dense" Primary dense field name
sparse_field_name str "sparse" Sparse field name
force_recreate bool False Delete and recreate collection if exists

Exports

from llama_index_endee import (
    EndeeVectorStore,   # Main vector store class
    SparseEmbeddings,   # ABC for custom sparse models
    SparseVector,       # Sparse vector data class
    EndeeModelSparse,   # BM25 sparse encoder (endee_model)
    Precision,          # Precision enum
    rerank,             # RRF fusion for multi-field results
)

License

MIT License

Metadata

Release files for llama-index-vector-stores-endee 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for llama-index-vector-stores-endee 1.1.0
File Size Uploaded Provenance Actions
llama_index_vector_stores_endee-1.1.0.tar.gz 27.2 kB Without provenance Details for llama_index_vector_stores_endee-1.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for llama-index-vector-stores-endee 1.1.0
File Interpreter ABI Platform Actions
llama_index_vector_stores_endee-1.1.0-py3-none-any.whl Python 3 none any Details for llama_index_vector_stores_endee-1.1.0-py3-none-any.whl

Total release size: 43.5 kB

Release files / llama_index_vector_stores_endee-1.1.0.tar.gz

Download URL llama_index_vector_stores_endee-1.1.0.tar.gz
Size 27.2 kB
Tags Source
SHA-256 checksum
How to use checksums
adcf99a4438791a91c8cd58869804d0f68dfc2716183233842e2dd4f6a486bab
BLAKE2b-256 checksum
How to use checksums
0467e99224f3fdfc0b1720440656ac010e61b3d3942632438b41988147f44f2d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / llama_index_vector_stores_endee-1.1.0-py3-none-any.whl

Download URL llama_index_vector_stores_endee-1.1.0-py3-none-any.whl
Size 16.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
13d0653fe614c94aa306c4cc16ab7e2bfdea5d164f3fae69dfa916bb1829fcee
BLAKE2b-256 checksum
How to use checksums
774a2f61e1227ddb71a36bd39e4a428e992628da5e0bea0bfe8190bbdef37dff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Security for llama-index-vector-stores-endee 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page