Embedded storage and search engine for portable .vera archives
Project description
vera-doc
vera-doc is VERA's embedded storage and search engine. It stores ready-made
text chunks in a portable SQLite .vera file and provides transactional CRUD,
embeddings, metadata filters, keyword search, vector search, hybrid search,
corpus search, and rebuildable library indexes.
It intentionally contains no PDF parsing, OCR, source extraction, chunking,
MCP, CLI, or desktop dependencies. Applications extract and chunk content
before calling vera-doc. The separate vera-ingest package provides the
standard PDF pipeline.
Documentation: vera-doc guides and API reference
Install
python -m pip install vera-doc
Python 3.10 or newer is required. The default hashing embedder needs no model download or API key.
Quick start
from vera import ChunkRecord, VeraDocument
records = [
ChunkRecord(
id="pipe-requirement",
text="The minimum pipe diameter is 12 inches.",
metadata={
"source_filename": "manual.pdf",
"page_start": 42,
"heading_path": "Chapter 4 > Pipe Design",
},
)
]
with VeraDocument.create("manual.vera") as document:
document.add(records)
with VeraDocument.open("manual.vera") as document:
results = document.search(
text="minimum pipe size",
mode="hybrid",
top_k=5,
)
for result in results:
print(result.score, result.record.text)
VeraDocument.open() is read-only by default. Use mode="write" when adding,
updating, or deleting records.
What is stored in a .vera file?
A VERA 0.2 file is one SQLite database containing:
manual.vera
├── vera_metadata Format, embedding configuration, archive metadata
├── chunks Final searchable text and JSON metadata
├── embeddings One float32 vector per chunk
├── chunks_fts SQLite FTS5 keyword index
├── attachments Optional opaque binary payloads
└── chunk_attachments Typed links from chunks to attachments
The core schema is conceptually:
CREATE TABLE chunks (
chunk_id TEXT PRIMARY KEY,
text TEXT NOT NULL,
metadata_json TEXT NOT NULL,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE embeddings (
chunk_id TEXT PRIMARY KEY REFERENCES chunks(chunk_id),
model_name TEXT NOT NULL,
model_dimension INTEGER NOT NULL,
vector BLOB NOT NULL,
vector_format TEXT NOT NULL,
created_at TEXT NOT NULL
);
CREATE TABLE attachments (
attachment_id TEXT PRIMARY KEY,
mime_type TEXT NOT NULL,
filename TEXT,
data BLOB NOT NULL,
hash TEXT NOT NULL,
metadata_json TEXT NOT NULL,
created_at TEXT NOT NULL
);
Pages, headings, citations, bounding boxes, and source identity are optional
chunk metadata. Original files and extracted images may be stored as opaque
attachments. vera-doc stores these values but does not interpret or extract
them.
Public objects
ChunkRecord
The only indexed record type:
ChunkRecord(
id: str,
text: str,
metadata: Mapping[str, JSONValue] = {},
vector: Sequence[float] | None = None,
attachments: tuple[AttachmentRef, ...] = (),
)
idis a non-empty caller-controlled identifier.textis final chunk text.vera-docnever splits or cleans it.metadatamay contain any JSON-compatible object.vectormay contain a precomputed embedding. When omitted, the configured embedding function embedstext.attachmentslinks the chunk to stored attachments.
Records are immutable. IDs, text, metadata, vectors, and attachment references are validated when the object is created or written.
AttachmentRecord
An optional opaque binary payload:
AttachmentRecord(
id: str,
data: bytes,
media_type: str,
filename: str | None = None,
checksum: str | None = None,
metadata: Mapping[str, JSONValue] = {},
)
The SHA-256 checksum is computed automatically. If a checksum is supplied, it must match the bytes. Attachments are not embedded or searchable.
AttachmentRef
Links a chunk to an attachment:
AttachmentRef(
attachment_id="source-pdf",
role="source",
)
The role is caller-defined. Common roles include source, figure, and
viewer_data.
QueryResult
Returned by VeraDocument.search():
QueryResult(
record: ChunkRecord,
score: float,
semantic_score: float | None,
keyword_score: float | None,
)
Call result.as_dict() for a JSON-compatible result without the raw vector.
EmbeddingFunction
A structural protocol for custom embedders:
class EmbeddingFunction:
model_name: str
dimension: int
def embed(self, texts: list[str]) -> numpy.ndarray:
...
The same model and dimension must be used for stored records and text queries.
VeraDocument methods
Create and open
VeraDocument.create(
path,
*,
embedding_function=None,
model="hashing",
metadata=None,
overwrite=False,
)
VeraDocument.open(
path,
*,
mode="read",
embedding_function=None,
)
create() publishes a valid database atomically. It raises FileExistsError
unless overwrite=True. Both methods return context managers.
Add records
document.add(records)
Inserts an iterable of ChunkRecord objects. Existing IDs raise
DuplicateRecordError. The chunk row, embedding, FTS row, and attachment links
are written in one transaction.
Insert or replace records
document.upsert(records)
Inserts new IDs and replaces existing records. Replacement updates text, metadata, embedding, keyword index, and attachment links together.
Retrieve records
document.get(
ids=None,
*,
where=None,
limit=None,
)
Returns ChunkRecord objects, including their vectors and attachment links.
where performs exact equality matching on top-level metadata keys:
records = document.get(where={"discipline": "civil"})
Delete records
deleted_count = document.delete(
ids=None,
*,
where=None,
)
Deleting a chunk also deletes its embedding, keyword-index row, and attachment links. It does not delete the attachments themselves.
Search
document.search(
*,
text=None,
vector=None,
mode="hybrid",
where=None,
top_k=10,
)
Supported modes:
keyworduses SQLite FTS5 and BM25 ranking.semanticuses cosine similarity against stored vectors.hybridindependently normalizes semantic and keyword scores, then combines them with equal weight.
Semantic search accepts query text or a compatible precomputed vector.
Keyword and hybrid search require text.
Attachments
document.put_attachments(attachments, upsert=False)
attachment = document.get_attachment("source-pdf")
document.delete_attachment("source-pdf")
Referenced attachments cannot be deleted until their chunk links are removed.
Missing attachments raise RecordNotFoundError.
Archive metadata
metadata = document.metadata
document.set_metadata({"project": "stormwater"})
Archive metadata is a JSON-compatible object separate from per-chunk metadata.
Transactions
with document.transaction():
document.put_attachments(attachments)
document.add(records)
The entire block commits together. An exception rolls it back. Nested transactions are intentionally rejected.
Inspection and validation
info = document.inspect()
report = document.validate()
Inspection reports the format, model, dimension, normalization policy, counts,
and archive metadata. Validation checks SQLite integrity, required tables and
metadata, embedding and FTS parity, vector lengths, declared L2 normalization,
JSON payloads, foreign keys, and attachment hashes. Older archives without a
normalization policy report unknown and remain valid.
Close
document.close()
Context managers call close() automatically.
Exceptions
DuplicateRecordError—add()received an existing ID.RecordNotFoundError— a chunk references an unknown attachment or a requested attachment does not exist.ReadOnlyError— a mutation was attempted after a read-only open.- Standard
FileNotFoundError,FileExistsError,TypeError, andValueErrorare used for ordinary path and validation failures.
Optional attachments example
from vera import (
AttachmentRecord,
AttachmentRef,
ChunkRecord,
VeraDocument,
)
source = AttachmentRecord(
id="source-pdf",
data=pdf_bytes,
media_type="application/pdf",
filename="manual.pdf",
metadata={"role": "source"},
)
chunk = ChunkRecord(
id="chunk-1",
text="The final, already-extracted chunk.",
metadata={"page_start": 42},
attachments=(AttachmentRef("source-pdf", role="source"),),
)
with VeraDocument.create("manual.vera") as document:
with document.transaction():
document.put_attachments([source])
document.add([chunk])
Custom embeddings
import numpy as np
from vera import ChunkRecord, VeraDocument
class MyEmbedder:
model_name = "example/my-embedder"
dimension = 2
def embed(self, texts: list[str]) -> np.ndarray:
return np.asarray([[1.0, 0.0] for _ in texts], dtype=np.float32)
embedder = MyEmbedder()
with VeraDocument.create(
"custom.vera",
embedding_function=embedder,
) as document:
document.add([ChunkRecord(id="one", text="Example text")])
with VeraDocument.open(
"custom.vera",
embedding_function=embedder,
) as document:
results = document.search(text="example", mode="semantic")
Callers may instead provide ChunkRecord.vector and search with a query
vector.
Libraries of .vera files
VeraCorpus searches a directory of .vera files as one corpus:
from vera import VeraCorpus
with VeraCorpus.open("./library", recursive=True) as corpus:
results = corpus.search("detention requirements", top_k=5)
For larger libraries, create a persistent derived index:
from vera import (
build_library_index,
library_index_status,
update_library_index,
)
build_library_index("./library", recursive=True)
print(library_index_status("./library"))
update_library_index("./library")
The .vera-index/ directory is rebuildable. Individual .vera files remain
the source of truth.
Package source structure
src/vera/
├── __init__.py Public exports
├── models.py Chunk, attachment, and query value objects
├── document.py Storage, CRUD, search, and viewer helpers
├── corpus.py Multi-file corpus search
├── collection.py Persistent library index
└── core/
├── schema.py SQLite schema and format version
├── validation.py Integrity and contract validation
└── embeddings.py Embedders and vector serialization
Source ingestion lives under packages/vera-ingest, and MCP integration
lives under packages/vera-mcp.
Format and API references
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vera_doc-0.2.3.tar.gz.
File metadata
- Download URL: vera_doc-0.2.3.tar.gz
- Upload date:
- Size: 31.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a1d121d63219878802e16fe36b736773694eeb627176a17e3f6ed5efd3402eb4
|
|
| MD5 |
a9cb6352ad67d1ab947fc3c0fabcc171
|
|
| BLAKE2b-256 |
ed0839a85d123e4112f8611476347cab35fc2314218525702c5a4141c7df89ce
|
Provenance
The following attestation bundles were made for vera_doc-0.2.3.tar.gz:
Publisher:
publish-pypi.yml on dkylewillis/vera
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vera_doc-0.2.3.tar.gz -
Subject digest:
a1d121d63219878802e16fe36b736773694eeb627176a17e3f6ed5efd3402eb4 - Sigstore transparency entry: 2338092771
- Sigstore integration time:
-
Permalink:
dkylewillis/vera@484b6ad1a7dff7880738c7f4858c74fb9d1c5215 -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/dkylewillis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@484b6ad1a7dff7880738c7f4858c74fb9d1c5215 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file vera_doc-0.2.3-py3-none-any.whl.
File metadata
- Download URL: vera_doc-0.2.3-py3-none-any.whl
- Upload date:
- Size: 36.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a220cae1875f061398a656f7340cb4331ece0f8a2672c3d43f453b7ca9994e8
|
|
| MD5 |
24a9eb69999d85b0027fd26bfd36dd91
|
|
| BLAKE2b-256 |
13fc0f5d36b3558023663ba6df970415464fb6bf6f7d776d49bee3726aa0c4f6
|
Provenance
The following attestation bundles were made for vera_doc-0.2.3-py3-none-any.whl:
Publisher:
publish-pypi.yml on dkylewillis/vera
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vera_doc-0.2.3-py3-none-any.whl -
Subject digest:
3a220cae1875f061398a656f7340cb4331ece0f8a2672c3d43f453b7ca9994e8 - Sigstore transparency entry: 2338092788
- Sigstore integration time:
-
Permalink:
dkylewillis/vera@484b6ad1a7dff7880738c7f4858c74fb9d1c5215 -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/dkylewillis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@484b6ad1a7dff7880738c7f4858c74fb9d1c5215 -
Trigger Event:
workflow_dispatch
-
Statement type: