Metadata-Version: 2.5
Name: llama-index-readers-velrim
Version: 0.1.0
Summary: LlamaIndex reader for the Velrim document-extraction API. Extract documents against a JSON Schema you supply and get back a Document carrying the extracted object, per-field state (present, null, missing), a per-field confidence score, and source anchors.
Project-URL: Homepage, https://velrim.com
Author-email: Velrim <hello@velrim.com>
License-Expression: MIT
License-File: LICENSE
Keywords: document extraction,json schema,llama-index,llamaindex,reader,velrim
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: llama-index-core<0.15,>=0.12
Requires-Dist: velrim<0.3,>=0.2.1
Description-Content-Type: text/markdown

# llama-index-readers-velrim

A LlamaIndex reader for the [Velrim](https://velrim.com) document-extraction API.

Document extraction against a JSON Schema you supply: each input file becomes one LlamaIndex
`Document` whose text is the extracted object as JSON, with the per-field state
(present / null / missing), a per-field confidence score, and source anchors (page + bounding
box) carried in the metadata.

- Runtime dependencies: `velrim` (the official Python SDK) and `llama-index-core`.
- Requires Python 3.9+.

## Install

```bash
pip install llama-index-readers-velrim
# or
uv add llama-index-readers-velrim
```

Set `VELRIM_API_KEY` in the environment, or pass `api_key=` to the reader.

## Direct use

```python
from pydantic import BaseModel
from llama_index.readers.velrim import VelrimReader


class Invoice(BaseModel):
    invoice_number: str
    total: float


reader = VelrimReader(schema=Invoice, doc_class="invoice")
docs = reader.load_data("invoice.pdf")

print(docs[0].text)  # the extracted object as indented JSON
print(docs[0].metadata["velrim_review"])  # JSON Pointers that need a human look
```

`schema` takes a Pydantic model class or a JSON-Schema dict. `load_data` accepts one input or a
list under `files=`; every input is a file path, raw `bytes`, or a `velrim.Document` (use
`velrim.Document.from_upload_key(...)` for a staged upload). One input in, one `Document` out.

```python
from velrim import Document

docs = reader.load_data(
    files=[
        "invoices/a.pdf",
        pdf_bytes,
        Document.from_upload_key("staging/acc/uuid"),
    ]
)
```

Errors raised by the SDK (`velrim.APIError` subclasses such as `InsufficientBalanceError` or
`RateLimitedError`, plus `APIConnectionError`) propagate unchanged; the reader never swallows
them.

### Options

| Option                 | Default | Meaning                                                                   |
| ---------------------- | ------- | ------------------------------------------------------------------------- |
| `schema`               | (none)  | A Pydantic model class or a JSON-Schema dict. Required.                   |
| `api_key`              | `None`  | Falls back to `VELRIM_API_KEY`.                                           |
| `doc_class`            | `None`  | Optional document class hint sent with every request.                     |
| `include_fields`       | `True`  | Put the full per-field map under `velrim_fields` in metadata.             |
| `confidence_threshold` | `None`  | When set, leaves with a confidence below it are added to `velrim_review`. |
| `client`               | `None`  | An existing `velrim.Client` to reuse (never serialized).                  |

## With SimpleDirectoryReader

Register the reader as the extractor for a file extension and `SimpleDirectoryReader` sends
every matching file through Velrim, adding its usual file metadata (`file_path`, `file_name`,
...) next to the Velrim keys:

```python
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
from llama_index.readers.velrim import VelrimReader

docs = SimpleDirectoryReader(
    input_dir="./invoices",
    file_extractor={".pdf": VelrimReader(schema=Invoice)},
).load_data()

index = VectorStoreIndex.from_documents(docs)
```

## Metadata

| Key                         | Type        | Value                                                                                                                                                          |
| --------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `source`                    | `str`       | The file path, the upload key, or `"bytes"`.                                                                                                                   |
| `velrim_request_id`         | `str`       | The request id, for support and log correlation.                                                                                                               |
| `velrim_pages`              | `int`       | Pages in the document.                                                                                                                                         |
| `velrim_billed_pages`       | `int`       | Pages billed.                                                                                                                                                  |
| `velrim_model`              | `str`       | The model that ran the extraction.                                                                                                                             |
| `velrim_calibrator_version` | `str`       | The confidence calibrator version.                                                                                                                             |
| `velrim_doc_class`          | `str`       | Only present when `doc_class` was set.                                                                                                                         |
| `velrim_review`             | `list[str]` | JSON Pointers of every missing leaf, every conflicting leaf, and every leaf below `confidence_threshold` when one is set.                                      |
| `velrim_fields`             | `dict`      | The full per-field map: `state`, `value`, `confidence`, `anchor`, `conflict`, `reason`, `grounding` per JSON Pointer. Only present when `include_fields=True`. |

Anything passed as `extra_info` is merged into the metadata as well.

`velrim_fields` is listed in both `excluded_llm_metadata_keys` and
`excluded_embed_metadata_keys`, so it never reaches the LLM prompt or the embedding text; it
stays on the node for your own review logic.

### Flat metadata for vector stores

Many vector stores accept only scalar metadata values. Turn the nested map off and keep the
flat keys plus `velrim_review`:

```python
reader = VelrimReader(schema=Invoice, include_fields=False)
```

If your store also rejects lists, drop `velrim_review` before indexing:

```python
for doc in docs:
    doc.metadata.pop("velrim_review", None)
```

## License

MIT.
