Metadata-Version: 2.4
Name: kpi-assembler
Version: 0.5.1
Summary: Schema-driven KPI proposal and deterministic SQL certification
Author: KPIAssembler contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/Akshatsrivastava700/kpi-assembler-python
Project-URL: Source, https://github.com/Akshatsrivastava700/kpi-assembler-python
Project-URL: Issues, https://github.com/Akshatsrivastava700/kpi-assembler-python/issues
Keywords: kpi,metrics,sql,fastapi,sqlite,postgresql,llm
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
Provides-Extra: web
Requires-Dist: fastapi>=0.100; extra == "web"
Requires-Dist: uvicorn>=0.23; extra == "web"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: httpx>=0.24; extra == "dev"
Requires-Dist: fastapi>=0.100; extra == "dev"
Requires-Dist: uvicorn>=0.23; extra == "dev"
Dynamic: license-file

# KPIAssembler (Python)

KPIAssembler reads any SQLite or PostgreSQL schema, uses an LLM or generic
heuristics to propose KPIs, lets a person choose candidates, and certifies the
SQL in deterministic Python code.

**The LLM proposes. Deterministic code certifies.**

PyPI: [kpi-assembler](https://pypi.org/project/kpi-assembler/)
Source: [github.com/Akshatsrivastava700/kpi-assembler-python](https://github.com/Akshatsrivastava700/kpi-assembler-python)

A separate Ruby implementation exists as the
[kpi_assembler](https://rubygems.org/gems/kpi_assembler) gem. The two projects
are independent.

## Install

```bash
pip install kpi-assembler
```

With the FastAPI UI and REST API:

```bash
pip install "kpi-assembler[web]"
```

With PostgreSQL support:

```bash
pip install "kpi-assembler[postgres,web]"
```

Then:

```bash
kpi-assembler-web
```

Open http://127.0.0.1:9292 and click **Discover metrics**.

The package provides:

- library and six-stage CLI pipeline
- interactive Discover → Propose → Certify → Publish UI
- versioned REST API
- embeddable `<kpi-assembler>` web component
- JSON and static HTML reports

It has no vertical-specific KPI catalog. The bundled demo database uses generic
accounts, customers, orders, and payments only so the project runs without a
host application.

## Develop from this repository

```bash
git clone https://github.com/Akshatsrivastava700/kpi-assembler-python.git
cd kpi-assembler-python
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
kpi-assembler-web
```

The default server uses the in-memory demo database and schema heuristics. Stop
it with `Ctrl+C`.

## Connect a database

SQLite:

```bash
KPI_DATABASE_PATH=/absolute/path/application.sqlite3 kpi-assembler-web
```

PostgreSQL:

```bash
pip install "kpi-assembler[postgres,web]"
KPI_DATABASE_URL=postgresql://user:pass@localhost/application kpi-assembler-web
```

Always use a read-only database user or replica. Certification runs `EXPLAIN`
and executes candidate queries against a sample period.

Useful scope settings:

```bash
KPI_INCLUDE_TABLES=orders,payments,events \
KPI_MAX_TABLES=20 \
KPI_DB_SCHEMA=public \
KPI_TENANT_COLUMN=account_id \
KPI_TENANT_ID=123 \
kpi-assembler-web
```

When a configured tenant column exists on the candidate fact table, SQL that
omits the configured tenant predicate is held as a draft.

## Use Gemini or Ollama

The web server enables its configured provider by default and falls back to
generic schema heuristics when the provider is unavailable.

```bash
GEMINI_API_KEY=your_key \
KPI_LLM_PROVIDER=gemini \
kpi-assembler-web
```

```bash
ollama serve
ollama pull llama3
KPI_LLM_PROVIDER=ollama KPI_OLLAMA_MODEL=llama3 kpi-assembler-web
```

Force offline heuristics with:

```bash
KPI_USE_LLM=false kpi-assembler-web
```

## REST API

```text
GET  /api/v1/health
GET or POST /api/v1/discover
POST /api/v1/certify
GET  /api/v1/pack
GET  /api/v1/integration
```

Certification accepts explicitly selected candidate IDs:

```json
{"accepted_ids": ["orders_total_sum", "payments_amount_sum"]}
```

Set `KPI_ALLOWED_ORIGIN` for browser clients. Optionally set `KPI_API_TOKEN`;
API clients then send either `Authorization: Bearer <token>` or
`X-KPI-API-Key: <token>`.

## Embed the complete UI

```html
<script src="http://127.0.0.1:9292/kpi-assembler.js"></script>
<kpi-assembler
  service-url="http://127.0.0.1:9292"
  height="820px">
</kpi-assembler>
```

The component dispatches `kpi-assembler-ready` after its iframe loads.

## Mount in an existing FastAPI app

Install the web extra and mount the app factory:

```python
from fastapi import FastAPI
from kpi_assembler.web_app import create_app

app = FastAPI()
app.mount(
    "/kpi-assembler",
    create_app(
        connection_provider=lambda request: request.app.state.reporting_db,
        options={"use_llm": False, "tenant_column": "account_id"},
        tenant_resolver=lambda request: request.state.account_id,
        authorize=lambda request: request.state.user.is_admin,
    ),
)
```

The provider should return the same long-lived `sqlite3`/`psycopg` connection
or `Connection` wrapper for requests that share state.

## CLI and reports

```bash
kpi-assembler
kpi-assembler --db /path/to/application.sqlite3
kpi-assembler --url postgresql://user@localhost/application --tables orders,payments
kpi-assembler --gemini
kpi-assembler --ollama --ollama-model llama3
```

The CLI writes `output/kpi_pack.json` and `output/kpi_pack.html`. The HTML
report includes the briefing, all-data and per-dimension metric views, and the
certification report.

## Library

```python
from kpi_assembler import Connection, Pipeline, SampleDatabase

db = Connection.wrap(SampleDatabase.build())
pack = Pipeline(
    db_connection=db,
    options={"use_llm": False, "accept_all": True},
).run()
```

## State and production use

Discovery candidates and the latest web pack live in process memory and are
cleared by rediscovery or process restart. Persist packs in your host
application before production use.
