Skip to main content

fenecdb for Python

A client for fenec-server's HTTP endpoint (fenec-server --http <address>), and vector stores for LangChain and LlamaIndex on top of it.

pip install "fenecdb[langchain]"      # or "fenecdb[llama-index]"
from fenecdb import Client

db = Client("http://127.0.0.1:8080", token="...")
db.query("get articles select title near embed $1 limit 5", [[0.1, 0.2, 0.3]])

Or the query builder writes the statement -- every value a parameter, every name checked -- the same text the JavaScript, Go and .NET builders make of the same chain:

from fenecdb import or_

docs = db.collection("articles")
rows = (docs.select("title")
            .where("year", ">=", 2024)
            .where(or_({"lang": "tr"}, {"tags": {"has": "rust"}}))
            .near("embed", [0.1, 0.2, 0.3], ef=64)
            .limit(5)
            .rows())
docs.insert({"title": "Dunes", "year": 2021})
docs.where("year", "<", 2000).delete()        # no filter: refused unless all=True
docs.where("lang", "tr").count()

To see the text and parameters a chain builds, for logging or a test, to_fenecql() returns them and runs nothing: docs.select("title").limit(5).to_fenecql() is ("get articles select title limit 5", []). A query needs no call to it before it runs.

In an event loop -- FastAPI, aiohttp, an agent -- AsyncClient makes the same calls awaited, over one kept-alive connection, the standard library alone:

from fenecdb import AsyncClient

async with AsyncClient("http://127.0.0.1:8080", token="...") as db:
    rows = await db.query("get articles select title near embed $1 limit 5", [[0.1, 0.2, 0.3]])
    await db.batch([("put articles {title: $1}", ["a"]), ("put articles {title: $1}", ["b"])])
    rows = await db.collection("articles").where("year", ">=", 2024).rows()

Every write on the server's disk (fenec-server --cdc), for a consumer whose cursor the server keeps -- each batch committed once the loop comes back for the next, so each write comes at least once -- and the same handed on to another program or a webhook:

for batch in db.follow("search-index"):
    for change in batch:               # {"seq", "at", "collection", "op", "id", "doc"}
        index(change)
python -m fenecdb.relay http://127.0.0.1:8080 --consumer kafka | kcat -P -b broker:9092 -t fenec
from fenecdb.langchain import FenecVectorStore

store = FenecVectorStore(embeddings, "docs", url="http://127.0.0.1:8080", token="...",
                         metadata_fields={"source": "text"})
store.add_documents(documents)
store.similarity_search("how do I compact", k=4, filter={"source": "handbook"})
from fenecdb.llama_index import FenecVectorStore
from llama_index.core import StorageContext, VectorStoreIndex

store = FenecVectorStore("docs", url="http://127.0.0.1:8080", token="...")
index = VectorStoreIndex.from_documents(
    documents, storage_context=StorageContext.from_defaults(vector_store=store)
)

A document or node is a row -- its id, text, metadata as JSON and vector under @hnsw -- in a collection created on the first write. Fields named in metadata_fields get columns of their own under @hash, and filters over them are answered by the index before the search runs.

With full_text=True the text is indexed for BM25 too, and both stores search by the words alone or by the words and the vector fused -- LangChain's mode="text" and mode="hybrid", LlamaIndex's TEXT_SEARCH and HYBRID. quant="int8" or "bit" keeps the graph over codes.

store = FenecVectorStore(embeddings, "docs", url=..., token=..., full_text=True)
store.similarity_search("how do I compact", k=4, mode="hybrid")

./run-tests.sh runs LangChain's standard vector store suite and the tests LlamaIndex's own integrations run against a fenec-server it builds and starts, and the query builder against every case of integrations/builder-golden.json. Full reference: https://fenecdb.com/docs/integrations

Metadata

Release files for fenecdb 0.1.9

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

Source distribution (sdist)

Source distribution for fenecdb 0.1.9
File Size Uploaded
fenecdb-0.1.9.tar.gz 34.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fenecdb 0.1.9
File Interpreter ABI Platform
fenecdb-0.1.9-py3-none-any.whl Python 3 none any Details

Total release size: 61.8 kB

Release files / fenecdb-0.1.9.tar.gz

Download URL fenecdb-0.1.9.tar.gz
Size 34.0 kB
Tags Source
SHA-256 checksum
How to use checksums
7d0cfc92e392aa01c7c214f4118cd4881a2b674aa335c4f1c90087c9002ebfe8
BLAKE2b-256 checksum
How to use checksums
6143f8da2c89b1459c9a8b2b083e28f7eedc925a1864fc27137926529ab83347
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / fenecdb-0.1.9-py3-none-any.whl

Download URL fenecdb-0.1.9-py3-none-any.whl
Size 27.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e6b5fe785e55d24206d3db19b810915441a2b3f26ddf101e4d6dc1479e9b5e0a
BLAKE2b-256 checksum
How to use checksums
912620ae61361e36fc13dceb320da2abf5fb5496dcc3fe09f6f8d398fdff643a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.1.9 This release

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

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