IntelAI
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, with role-based access control and live persona scoping.
- Research Background:
RESEARCH.md/ Online Research Documentation - Empirical Benchmarks:
BENCHMARK.md/ Online Benchmark Dashboard - User Guide: Online User Guide
- Self-Hosting Guide:
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 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.
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 /readyreturns 200 once models are loaded;POST /embedserves embeddings to sibling services with the internal token.
Quick Start
Prerequisites: Python 3.11, Node 18+, a Postgres URL, and a GROQ_API_KEY.
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:
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 |
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
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) 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. For measured results — a live production RAG evaluation, an out-of-sample forecast backtest, and a knowledge-graph coverage measurement — see 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 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 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; reproducible bugs go to 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_URLnot 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=trueorDO_NOT_TRACK=1: nothing is sent, whatever the URL says.
Metadata
Release files for intelai 0.1.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| intelai-0.1.9.tar.gz | 210.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| intelai-0.1.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 406.0 kB
Release files / intelai-0.1.9.tar.gz
| Download URL | intelai-0.1.9.tar.gz |
|---|---|
| Size | 210.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
586b40486e71dcebae792a7a0743ab18136d6ee7567ffc4ff45058860aebe7d1
|
|
BLAKE2b-256 checksum How to use checksums |
d1769fbd74d648c34e87f52173e9a71cbef969003646d8d9a7a608bf3d5e70c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / intelai-0.1.9-py3-none-any.whl
| Download URL | intelai-0.1.9-py3-none-any.whl |
|---|---|
| Size | 195.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b4e2c3ae9fdde926eb1597a2fe5f02bde69c9c6d773f4a711bbfb28e1ce81bc0
|
|
BLAKE2b-256 checksum How to use checksums |
779fbe47229e0177f470aa4bd06250b20081805323969f585b6d6b487910791e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|