Metadata-Version: 2.4
Name: intelai
Version: 0.1.9
Summary: Persona-Aware AI Analytics & RAG Copilot — multi-domain KPI intelligence, GraphRAG-lite, ML forecasting.
Author: Yacine
License: AGPL-3.0
Project-URL: Homepage, https://github.com/Yacine-ai-tech/IntelAI
Project-URL: Source, https://github.com/Yacine-ai-tech/IntelAI
Keywords: rag,personas,analytics,kpi,fastapi,graphrag,llm
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# IntelAI

[![CI](https://github.com/Yacine-ai-tech/IntelAI/actions/workflows/ci.yml/badge.svg)](https://github.com/Yacine-ai-tech/IntelAI/actions/workflows/ci.yml)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE)
[![PyPI](https://img.shields.io/pypi/v/intelai.svg)](https://pypi.org/project/intelai/)
[![Python](https://img.shields.io/badge/Python-3.11-3776AB?logo=python&logoColor=white)](https://python.org)
[![Live App](https://img.shields.io/badge/Live_App-intelai-0070f3?style=flat)](https://intelai.ysiddo-ai-projects.app)
[![Research](https://img.shields.io/badge/Research-Empirical_Methods-8a2be2?style=flat)](https://intelai.ysiddo-ai-projects.app/research)
[![Benchmarks](https://img.shields.io/badge/Benchmarks-Backtest_4.64%25-green?style=flat)](https://intelai.ysiddo-ai-projects.app/benchmark)
[![Guide](https://img.shields.io/badge/Docs-User_Guide-blue?style=flat)](https://intelai.ysiddo-ai-projects.app/guide)

**Persona-aware AI analytics and RAG copilot.** A nine-persona, role-scoped analytics
assistant with hybrid retrieval, a lightweight knowledge graph for multi-hop queries, classical
forecasting, and board-ready exports, over 146 curated KPIs.

**Live application:** [intelai.ysiddo-ai-projects.app](https://intelai.ysiddo-ai-projects.app), with role-based access control and live persona scoping.
- **Research Background:** [`RESEARCH.md`](RESEARCH.md) / [Online Research Documentation](https://intelai.ysiddo-ai-projects.app/research)
- **Empirical Benchmarks:** [`BENCHMARK.md`](BENCHMARK.md) / [Online Benchmark Dashboard](https://intelai.ysiddo-ai-projects.app/benchmark)
- **User Guide:** [Online User Guide](https://intelai.ysiddo-ai-projects.app/guide)
- **Self-Hosting Guide:** [`SELF_HOSTING.md`](SELF_HOSTING.md)

## Features

| Area | Detail |
|---|---|
| Nine-persona RAG copilot | CEO, CFO, CTO, COO, CHRO, ESG, Risk, Analyst, Assistant — role-scoped data, WebSocket streaming, source citations |
| GraphRAG-lite | A multi-hop entity graph for cross-domain queries (`USE_GRAPH_RAG=true`) |
| Hybrid retrieval | Local BGE-M3 dense embeddings + BM25 fused with Reciprocal Rank Fusion, with an optional local BGE cross-encoder reranker (`USE_RERANKER=true`) |
| Answer-block structuring | The backend parses LLM markdown into typed blocks (heading, KPI, list, quote, code) |
| 146 curated KPIs | Finance, HR, IT, Operations, Logistics, ESG, Growth — 78-month history, 7 benchmarking scenarios |
| ML forecasting | Monte Carlo forecasting with confidence bands |
| Data export/ingest | PDF, Excel, CSV, and JSON export; CSV and document ingestion |
| Auth and RBAC | JWT authentication, role-based pages, per-persona data scoping, an audit log |
| Admin governance | User management, role viewer, scenario switcher, vector-store reindexing |
| Multi-provider LLM | OpenAI-compatible providers via LiteLLM, configured through `LLM_ENDPOINT` |
| Bilingual | Full English and French UI and copilot responses |

## Architecture

```
React + Vite (Recharts, TanStack Query, i18n)     → Vercel / Netlify
        │  HTTP / WebSocket  /api/v1/*
FastAPI  (src/api/server.py)
  auth · chat (9 personas) · KPIs · insights · forecasting · admin
        │
   PostgreSQL                    LLM (OpenAI-compatible via LiteLLM)
   KPIs · auth · sessions ·      GraphRAG-lite · hybrid retrieval ·
   vectors (pgvector/Qdrant)    BGE-M3 · BM25/RRF · BGE reranker (optional)
```

## Architecture and configuration

[`ARCHITECTURE.md`](ARCHITECTURE.md) describes the components, the life of a chat turn, retrieval and
the design decisions, with an interactive version in the application under **Architecture**. Every
configuration variable is described in [`.env.example`](.env.example).

## Copilot behaviour

- **Web search without asking.** Questions about external companies, people or current events are
  searched on the web automatically, and an explicit request ("search the web", "verify online") always
  is. The decision is rule based and the search runs in parallel with internal retrieval, so it adds no
  waiting time of its own. It needs `TAVILY_API_KEY`; without it the copilot answers from internal data.
- **Visible pipeline.** The chat shows the real stages of each answer (understanding, knowledge-base
  search, web search, writing), lists sources as soon as they are found — knowledge base and web
  separately — and reveals the answer as it is generated.
- **Language.** The answer follows the language of the question (French and English). Retrieval prefers
  documents in the question's language and keeps the other language eligible; French metric names map
  to the canonical English metrics.
- **Health and readiness.** `GET /ready` returns 200 once models are loaded; `POST /embed` serves
  embeddings to sibling services with the internal token.

## Quick Start

**Prerequisites:** Python 3.11, Node 18+, a Postgres URL, and a `GROQ_API_KEY`.

```bash
git clone https://github.com/Yacine-ai-tech/IntelAI.git
cd IntelAI
cp .env.example .env   # fill in POSTGRES_URL, GROQ_API_KEY, SECRET_KEY — see SELF_HOSTING.md

# Backend (port 8000 — tables and seed data are created automatically)
pip install -r requirements.txt
python main.py

# Frontend (port 5173, proxies /api to :8000)
cd frontend && npm install && npm run dev
```

There are no built-in login credentials. Configure a unique `BOOTSTRAP_ADMIN_USERNAME` and
`BOOTSTRAP_ADMIN_PASSWORD` before starting the service, or create an account through the
registration endpoint. Passwordless demo personas are disabled by default and never grant
administrator access; enable them explicitly with `DEMO_MODE=true` only for a demo deployment.

**Docker:**

```bash
docker compose -f docker-compose.dev.yml up --build   # app only, uses .env's database
docker compose up --build                              # app plus a bundled Postgres
```

The full local retrieval pipeline uses `BAAI/bge-m3`, BM25/RRF, and
`BAAI/bge-reranker-v2-m3`. First use downloads the model weights; Docker Compose
persists them in the `model-cache` volume. Allocate several GiB of RAM to the app
container before enabling both local models.

### Retrieval pipeline and latency

Retrieval follows the standard hybrid design: dense top-50 and BM25 top-50 are merged
with Reciprocal Rank Fusion; with `USE_RERANKER=true` the top fused candidates (12 by
default) are rescored by the `BAAI/bge-reranker-v2-m3` cross-encoder, and the best five go
to the model. The pool
sizes are configuration (`RETRIEVAL_DENSE_K`, `RETRIEVAL_SPARSE_K`, `RERANK_CANDIDATES`).

A cross-encoder cannot be precomputed: it reads the query together with each candidate,
so cost grows with the pool size and runs at query time. On a CPU host this is the
dominant latency (tens of seconds on four cores for a pool of 30), while a GPU does the
same work in a fraction of a second. The application therefore keeps the ranking
identical and works on how the wait behaves instead:

* candidates are scored in small length-sorted batches, which avoids padding work
  without changing scores;
* the BM25 index is built once per corpus version instead of once per query;
* search and chat report the real stage (searching, fused, reranking *n*/*N*) and show
  the fused ranking as a preliminary result while reranking finishes;
* if a request is cancelled or exceeds its time budget, the remaining batches are
  skipped and the fused ranking is returned flagged as partial, never an empty success.

The time budget scales with the pool (`RETRIEVAL_BASE_TIMEOUT` plus
`RETRIEVAL_TIMEOUT_PER_PAIR` per candidate); set `VECTOR_RETRIEVAL_TIMEOUT` to pin it.
Reranking can also be pointed at a remote service with `RERANK_PROVIDER` and
`RERANK_URL`; local CPU or GPU inference remains the default.

`RERANK_BACKEND=onnx-int8` is available for experiments with a dynamically quantized
copy of the model. It changes scores slightly and has not shown a consistent speed-up
on small pools, so it is off by default; export or inference errors are surfaced
rather than silently switching backends.

With `VECTOR_STORE=qdrant`, chat uses the persistent Qdrant dense index fused with
BM25 through RRF and the local BGE reranker. Qdrant, BM25, and the configured reranker
are required for this mode; retrieval errors are surfaced rather than replaced with an
in-process dense index. Production startup requires `VECTOR_STORE=qdrant`. The in-process
passage index is reserved for explicit non-production memory mode. `/health` reports
model readiness and the persistent store's point count; an empty or unreachable store
is reported as degraded. `/ready` returns HTTP 503 until PostgreSQL, Qdrant, and the
configured retrieval pipeline are ready.

PostgreSQL bootstrap and additive schema migrations run transactionally during application
startup. In production or when Qdrant/pgvector is configured, a failed database migration
aborts startup; there is no in-memory auth/database fallback. CI exercises both a clean
Postgres database and legacy schemas missing the current `owner_user_id`/`source` columns.

## Configuration

Every variable and its default is documented in `.env.example`. The ones most commonly
adjusted:

| Variable | Required | Description |
|---|---|---|
| `POSTGRES_URL` | Yes | PostgreSQL connection URL (managed or self-hosted) |
| `GROQ_API_KEY` | Yes | Default-tier LLM provider key |
| `SECRET_KEY` | Yes | JWT signing key |
| `REQUIRE_INTERNAL_TOKEN` | No | Set `false` for standalone self-hosting — see [SELF_HOSTING.md](SELF_HOSTING.md) |
| `ANTHROPIC_API_KEY` | No | Reasoning-tier LLM (CEO/CFO/CTO/Risk personas); falls back to Groq if unset |
| `LLM_DEFAULT` / `LLM_REASONING` / `LLM_JUDGE` | No | LiteLLM model IDs per tier, for any provider LiteLLM supports |
| `USE_GRAPH_RAG` | No | `true` enables GraphRAG-lite multi-hop retrieval |
| `USE_HYBRID_RETRIEVAL` | No | `true` enables local BGE-M3 dense + BM25/RRF retrieval |
| `EMBEDDING_PROVIDER` / `EMBEDDING_MODEL` | No | Use `local` and `BAAI/bge-m3` for CPU-local embeddings |
| `USE_RERANKER` / `RERANK_PROVIDER` | No | Use `true` and `local` for the `BAAI/bge-reranker-v2-m3` cross-encoder. Chat and the synchronous search answer from the fused dense + BM25 ranking immediately (about 0.3 s); the progressive search job (`/api/v1/knowledge/search/async`) shows that ranking first and then refines it with the cross-encoder. Set `RERANK_IN_CHAT=true` to rerank inside chat as well. On CPU the cross-encoder costs seconds even with `RERANK_BACKEND=onnx-int8` and `RERANK_CANDIDATES=6`; on a GPU it is cheap. Reranking is also skipped when dense and lexical search agree on a clear leader (`RERANK_SKIP_WHEN_DECISIVE`, `RERANK_DECISIVE_MARGIN`). |
| `RERANK_BACKEND` | No | `torch` (default) or `onnx-int8` for local CPU reranking |
| `RERANK_MAX_LENGTH` | No | Maximum query/document pair token length (default `256`) |
| `EMBED_BATCH_SIZE` / `RERANK_BATCH_SIZE` | No | Embedding batch size / reranker candidates per inference batch (defaults `16` / `8`; the reranker batch is also the progress and cancellation granularity) |
| `RETRIEVAL_DENSE_K` / `RETRIEVAL_SPARSE_K` / `RERANK_CANDIDATES` | No | Dense and BM25 candidates, and how many fused candidates the cross-encoder scores (defaults `50` / `50` / `30`) |
| `VECTOR_STORE` | No | `chroma` (dev, default), `pgvector`, or `qdrant` (production) |
| `AUDIO_PROCESSOR_URL` / `DOC_PROCESSOR_URL` | No | Pluggable audio/document processors — for example, a VoiceFlow or DocIntel instance |
| `INGEST_WEBHOOK_SECRET` | No | Enables the HMAC-signed `/api/v1/webhook/{source}` ingestion path |

## Key API Endpoints

```
/health  ·  /ready  ·  /api/docs
POST /api/v1/auth/login          GET /api/v1/auth/me
POST /api/v1/chat                WS  /api/v1/ws/chat        GET /api/v1/personas
POST /api/v1/chat/async          GET /api/v1/chat/{job_id}  (async job+poll form for slow turns behind a timeout-limited proxy)
GET  /api/v1/kpis[/periods|/metrics|/categories]
GET  /api/v1/insights/{health,risk,summary,anomalies}
POST /api/v1/forecast            GET /api/v1/glossary
POST /api/v1/data/export         POST /api/v1/ingest/{metrics,csv,document}
GET  /api/v1/admin/{users,roles,audit,scenario}
```

Full interactive reference at `/api/docs`.

## Tests

```bash
pytest tests/ -q                        # fast unit suite — no database or LLM keys needed
pytest tests/test_smoke.py -q           # 5 zero-dependency smoke checks
pytest tests/test_api.py -q             # unit-marked subset of auth/RBAC/endpoint checks
pytest tests/test_chat.py -q            # unit-marked subset of chat/answer-block checks
pytest tests/ -o addopts="" -q          # full suite, including database-dependent integration tests
```

`pytest.ini` restricts the default run to unit-marked tests (`addopts = -m "unit"`), matching
CI's Unit Tests job, which needs no database. The full suite (42 checks in `test_api.py` alone)
also includes integration-marked tests requiring a reachable `POSTGRES_URL`/`TEST_POSTGRES_URL`;
run with `-o addopts=""` to lift the default filter.

## Benchmarking Scenarios

IntelAI provides seven seeded, deterministic, benchmark-calibrated environments (78 months ×
7 domains × 146 metrics, formula-derived where a real formula applies — see
[DATA_SEEDING.md](DATA_SEEDING.md)) for evaluating RAG retrieval accuracy and forecasting
models under structural stress. Selectable via the Admin → Scenarios tab, or the API directly
(`POST /api/v1/admin/scenario/async`, then poll `GET /api/v1/admin/scenario/{job_id}`):

| Scenario | Research application | Description |
|---|---|---|
| `healthy` | Baseline RAG evaluation | Reverts to the real baseline, removing any active scenario overlay |
| `declining_financial` | Trend reversal | Revenue contraction and margin compression; tests forecast adaptability |
| `high_churn_crisis` | Lagging indicators | Customer retention failure; tests cross-domain correlation (Growth vs. Finance) |
| `operational_meltdown` | Volatility stress | OEE collapse and quality failures; introduces severe noise to operational metrics |
| `talent_crisis` | Sentiment impact | High attrition and open-requisition spike; evaluates People-to-Operations efficiency lag |
| `cybersecurity_breach` | Shock event | Security incident; step-function disruption in SLA/SLO metrics |
| `esg_compliance_failure` | Policy violation | Governance failures and emissions spike; tests multi-hop entity reasoning |

Every scenario also carries a short cross-domain cascade (IT → Logistics/Operations → Growth →
Finance, mirroring how a real incident's financial impact lags its root cause) — see
`DATA_SEEDING.md` §4 for the full methodology.

For the reasoning behind the retrieval, evaluation, graph, and forecasting design choices, see
[RESEARCH.md](RESEARCH.md). For measured results — a live production RAG evaluation, an
out-of-sample forecast backtest, and a knowledge-graph coverage measurement — see
[BENCHMARK.md](BENCHMARK.md).

## Deploy

IntelAI deploys as one containerized service — build the included `Dockerfile`
and run it with Docker Compose, set the environment variables above, and attach the configured
Postgres and Qdrant stores. Deploy the
frontend separately (Vercel, Netlify, or as static files) with `VITE_API_BASE_URL` pointing to
the backend, and keep `VITE_USE_WS=false` in production to use the resilient `/chat/async`
job-and-poll path by default. See [SELF_HOSTING.md](SELF_HOSTING.md) for a full walkthrough.

## Support the project

If IntelAI is useful to you, a star on the repository helps other engineers find it, and following [@Yacine-ai-tech](https://github.com/Yacine-ai-tech) is the simplest way to hear about new releases. Passing the link to a colleague who has the same problem is just as welcome.

Questions and field notes go to [Discussions](https://github.com/Yacine-ai-tech/IntelAI/discussions); reproducible bugs go to [Issues](https://github.com/Yacine-ai-tech/IntelAI/issues).

## License

Open-source under the AGPL-3.0 License, free for researchers, students, and open-source use.
AGPLv3 requires that any proprietary network service built on modified code also open-source
its backend. A commercial license for closed-source use or enterprise features such as SSO,
Active Directory integration and custom VPC deployment is available on request.

## Anonymous Telemetry

The service sends one small HTTP POST at process start: `{"service": "IntelAI", "event": "startup",
"version": "<release>", "instance_id": "<random identifier>"}`. The identifier is a random value
persisted in the logs directory (delete `.telemetry_instance_id` to reset it); it is not derived
from any hardware identifier. No documents, prompts, credentials, filenames or configuration are
included, and a guard prevents more than one ping every 30 seconds per instance.
The receiving endpoint sees the request's network metadata, as any HTTP server does.

Behaviour of the destination setting (the ping is on by default and fires at start-up):

- `TELEMETRY_URL` not defined, or defined but empty: the ping goes to the project's collector.
- `TELEMETRY_URL=<your collector>`: the ping goes there instead.
- `TELEMETRY_OPT_OUT=true` or `DO_NOT_TRACK=1`: nothing is sent, whatever the URL says.

<!-- Scarf Analytics Pixel -->
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=ada53b5b-d56f-447f-b5ab-a65a061b7d5a" />

![views](https://gateway.ysiddo-ai-projects.app/pixel/readme/IntelAI.png)
