Metadata-Version: 2.5
Name: fintom8
Version: 0.1.4
Summary: LiteLLM connector for Gemini, Vertex AI, OpenAI, and Azure — chat, stream, and document extract.
Project-URL: Homepage, https://github.com/NikolaienkoIgor/f8_templates
Project-URL: Documentation, https://github.com/NikolaienkoIgor/f8_templates/tree/main/fintom8
Author: Igor Nikolaienko
Author-email: Harsh Bansal <harshhb6@gmail.com>
License: MIT
Keywords: azure,gemini,litellm,llm,openai,vertex
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Requires-Dist: litellm[google]<2.0.0,>=1.94.0
Requires-Dist: openpyxl>=3.1.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: tenacity>=8.2.0
Provides-Extra: dev
Requires-Dist: build>=1.2.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: twine>=5.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# fintom8

LiteLLM connector for **Gemini / Vertex AI / OpenAI / Azure**. Chat, stream, and document extract. Students install with pip and call a few methods — keys stay in `.env`.

### Install from Git (recommended for private use)

GitHub Packages Python upload is currently unreliable (SSL issues). Install directly from this repo instead:

```bash
# HTTPS (use a PAT with repo read access if the repo is private)
pip install "git+https://github.com/NikolaienkoIgor/f8_templates.git#subdirectory=fintom8"

# Pin a tag / commit
pip install "git+https://github.com/NikolaienkoIgor/f8_templates.git@fintom8-v0.1.4#subdirectory=fintom8"

# SSH (no token in the URL if your SSH key is set up)
pip install "git+ssh://git@github.com/NikolaienkoIgor/f8_templates.git#subdirectory=fintom8"
```

Private HTTPS with an explicit token:

```bash
pip install "git+https://<GITHUB_USERNAME>:<GITHUB_PAT>@github.com/NikolaienkoIgor/f8_templates.git#subdirectory=fintom8"
```

### Other install options

```bash
# Public PyPI (when published)
pip install fintom8

# Local editable install from this checkout
pip install -e ./fintom8
# or: pip install -e "./fintom8[dev]"
```

```python
from fintom8 import LLM

llm = LLM()  # reads .env / environment
print(llm.chat("Summarize this invoice").text)
```

## Configuration

Resolution order: **constructor kwargs / `LLMConfig` > environment > defaults**.

Copy [`.env.example`](./.env.example) to `.env` in your project (never commit it).

| Param | Env | Default | When needed |
|-------|-----|---------|-------------|
| `model` | `LLM_MODEL` | `gemini/gemini-3.5-flash` | always |
| `temperature` | `LLM_TEMPERATURE` | unset (Gemini 3+), `1.0` (older Gemini/Vertex), else `0.0` | optional; omitted for Gemini 3+ (deprecated by Google) |
| `num_retries` | — | `3` | optional |
| `api_key` | `GEMINI_API_KEY` / `OPENAI_API_KEY` / `AZURE_API_KEY` (from model prefix) | unset | Gemini / OpenAI / Azure (`azure/` → required) |
| `api_base` | `AZURE_API_BASE` / `OPENAI_API_BASE` | unset | Azure (`azure/` → required) |
| `api_version` | `AZURE_API_VERSION` | unset | Azure (`azure/` → required) |
| `vertex_project` | `VERTEXAI_PROJECT` | unset | Vertex |
| `vertex_location` | `VERTEXAI_LOCATION` | `eu` | Vertex |

For `azure/<deployment>`, missing `api_key`, `api_base`, or `api_version` raises `Fintom8Error` (set via constructor or `AZURE_*` env vars).

```python
from fintom8 import LLM, LLMConfig

llm = LLM()  # env defaults
llm = LLM(model="gpt-4o", api_key="sk-...", temperature=0)
llm = LLM(LLMConfig(
    model="azure/my-deploy",
    api_key="...",
    api_base="https://....openai.azure.com",
    api_version="2024-10-21",
))
```

### Switch provider

| `LLM_MODEL` | Env |
|-------------|-----|
| `gemini/gemini-3.5-flash` | `GEMINI_API_KEY` |
| `vertex_ai/gemini-3.5-flash` | `VERTEXAI_PROJECT` + `VERTEXAI_LOCATION` + ADC (`gcloud auth application-default login`) |
| `gpt-4o` | `OPENAI_API_KEY` |
| `azure/<deployment>` | `AZURE_API_KEY` + `AZURE_API_BASE` + `AZURE_API_VERSION` |

## Contributors

- Igor Nikolaienko
- [Harsh Bansal](https://github.com/harshhb6)

## Usage

```python
from fintom8 import LLM

llm = LLM()

resp = llm.chat("Hello")
print(resp.text, resp.usage)

# Structured output — file only; detect format → LiteLLM SO → cleanse dates
invoice_rf = {
    "type": "json_schema",
    "json_schema": {
        "name": "Invoice",
        "strict": True,
        "schema": {
            "type": "object",
            "properties": {
                "total": {"type": "number"},
                "vendor": {"type": "string"},
                "invoiceDate": {"type": ["date", "null"]},
            },
            "required": ["total", "vendor", "invoiceDate"],
            "additionalProperties": False,
        },
    },
}
data = llm.structured(
    "invoice.pdf",  # also: .png/.jpg, .txt/.csv/.xml/.xlsx, or bytes
    structuredOutput=invoice_rf,
    dateFormat="DD.MM.YYYY",
)
# {"total": 42.5, "vendor": "Acme", "invoiceDate": "08.08.2026"}

# process() is an alias of structured()
data = llm.process(
    "invoice.pdf",
    structuredOutput=invoice_rf,
    dateFormat="DD.MM.YYYY",
    instructions="Extract invoice vendor and total.",
)

for chunk in llm.stream([{"role": "user", "content": "Write a haiku"}]):
    print(chunk, end="", flush=True)

resp = llm.extract("invoice.pdf", response_format=invoice_rf)
```

Async twins: `achat`, `astream`, `aextract`, `astructured`, `aprocess`.

Optional helpers: `detect_format`, `fields_to_schema`, `compile_fields`, `prepare_response_format`, `apply_cleanse`, `json_schema_response_format`, `structured_output`, `enforce_strict`, `inline_refs`.

### Bundled templates

```python
from fintom8.templates import invoice
# or: from fintom8 import templates; templates.invoice
# or: from fintom8 import use_template; use_template("invoice")

data = llm.structured(
    "invoice.pdf",
    structuredOutput=invoice["structuredOutput"],
    systemPrompt=invoice["systemPrompt"],
    dateFormat=invoice.get("dateFormat", "YYYY-MM-DD"),
)
```

`list_templates()` lists packaged names (`invoice`, `chemical_composition`, `recipient_statement`). Pass a path or dict to `use_template` for custom templates.

### Invoice validation

After structured invoice extraction, run the same math checks used by the extractor backend (line formulas, gross/net consistency, invoice balance; tolerance `0.03`):

```python
from fintom8 import invoice_validation

# dict → dict (endpoint-shaped; always includes _debug; full error text on failure)
response = invoice_validation(data)
```

Also exported: `Invoice`, `LineItem`, `validation_payload_from_llm`. Does not run the validate/correct retry loop or financial normalizers.

Failures raise `Fintom8Error`.

If you see an authentication error (for example missing `GEMINI_API_KEY`, `OPENAI_API_KEY`, or Vertex setup), that means package import and retries are working; configure credentials for the selected `LLM_MODEL`.

See [`examples/chat.py`](./examples/chat.py) and [`examples/extract.py`](./examples/extract.py).

## Publish (maintainers)

1. Install dev extras and run tests:

   ```bash
   cd fintom8
   pip install -e ".[dev]"
   pytest
   python -c "from fintom8 import LLM"
   ```

2. Build:

   ```bash
   python -m build
   ```

3. Upload to TestPyPI first, then PyPI:

   ```bash
   python -m twine upload --repository testpypi dist/*
   python -m twine upload dist/*
   ```

4. Tag for CI Trusted Publishing (OIDC). Create the PyPI project once and add a GitHub environment `pypi` with Trusted Publisher pointing at `.github/workflows/publish-fintom8.yml`. Then:

   ```bash
   git tag fintom8-v0.1.4
   git push origin fintom8-v0.1.4
   ```
