factcircuit
FactCircuit는 불변 출처와 단계별 검증, 제한된 검색, 재현 가능한 평가를 제공하는 감사 가능한 주장·증거 검증 루프입니다
비즈니스 질문을 자연어로 입력하면 LLM이 실시간 데이터·차트·인사이트와 함께 답변하고, SQL·도구까지 제공한다
MetricAi — ask business questions in plain English and an LLM agent answers with live data, charts & insights. ReAct agent with fine-grained tools, natural-language to SQL, schema-per-tenant multi-ten
데이터Python · TypeScriptGitHub @ayanv3419-oss온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기MetricAi — ask business questions in plain English and an LLM agent answers with live data, charts & insights. ReAct agent with fine-grained tools, natural-language to SQL, schema-per-tenant multi-tenancy on Postgres, multi-model routing (Qwen/Gemini).
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Ask your business data questions in plain English — get real numbers, narrative insight, and live charts back.
Metric AI is an LLM-orchestrated analytics platform for businesses. Upload your
sales and inventory spreadsheets (CSV / XLSX), then ask things like *"why did Brand X
drop last month?"* or "show me monthly revenue for 2025". An autonomous agent figures
out what you're asking, writes and validates the SQL itself, runs it against your data,
and streams back a grounded answer with a chart — no dashboards to build, no SQL to write.README 전문 보기 ↗Ask your business data questions in plain English — get real numbers, narrative insight, and live charts back.
Metric AI is an LLM-orchestrated analytics platform for businesses. Upload your sales and inventory spreadsheets (CSV / XLSX), then ask things like "why did Brand X drop last month?" or "show me monthly revenue for 2025". An autonomous agent figures out what you're asking, writes and validates the SQL itself, runs it against your data, and streams back a grounded answer with a chart — no dashboards to build, no SQL to write.
Live demo: https://agentic-ai-livid-eta.vercel.app Backend: FastAPI on Render · Database: Supabase Postgres · LLM: Qwen 3 via OpenRouter
Add a screenshot or short GIF here — drop the image in
docs/img/and reference it. A 10-second clip of typing a question and watching the answer + chart stream in is the single highest-impact thing you can put in this README.
docs/img/demo.gif ← the money shot: question in → chart out
docs/img/dashboard.png ← the auto-generated KPI dashboard
This is a full, end-to-end product — not a tutorial clone. It shows:
SqlDryRun) must approve it (SELECT-only, known tables/columns, no dangerous keywords)
before it ever runs.| 💬 Natural-language Q&A | Ask in plain English; the agent plans, queries, and answers. |
| 📊 Auto-charts | Trend / ranking / breakdown questions render a chart automatically (Recharts). |
| ⚡ KPI fast-path | Common metrics (total sales, orders, margin) skip the LLM and run a pre-validated SQL template — instant + free. |
| 🔎 Root-cause analysis | "Why did X change?" builds a causal contribution tree across dimensions and narrates it. |
| 🧩 Works on any schema | The concept resolver maps your column names (sales_value, net_amount, turnover…) onto canonical metrics. |
| 📈 Forecasting | Linear-regression projection of future sales from history. |
| 🔐 Auth + multi-tenant | JWT + bcrypt login; schema-per-tenant isolation on Postgres. |
| 🌊 Live streaming | Every tool call and the final answer stream to the UI over Server-Sent Events. |
| 💸 Cost guards | Hard per-turn caps on LLM iterations and spend — the agent can't run away. |
Metric AI's core is an agentic loop: the LLM is given a set of tools and decides, one step at a time, which to call. After each tool result it reflects and chooses the next move, until it has enough to answer.
┌─────────────────────────────────────────────┐
user question │ COORDINATOR LOOP │
──────────────► │ (LLM picks a tool → runs it → reflects) │
│ │
│ while not done and under cost cap: │
│ 1. ask LLM: what next? │
│ 2. dispatch the tool it chose │
│ 3. feed the result back in │
└───────────────────┬─────────────────────────┘
│ chooses from 11 tools
┌──────────────────────────────┼──────────────────────────────┐
▼ ▼ ▼
PERCEPTION SQL PIPELINE ANSWER / RCA
───────────── ───────────── ─────────────
RouteClass (intent) Schema (tables/cols) CausalTree (why-tree)
TimeKPI (date ranges) sqlWriter (LLM → SELECT) rcaReasoner (narrate)
Granularity (day/week/month) SqlDryRun (validate!) insightFmt (final answer)
EntityLoc (brands/products) SqlExecutor (run + chart)
Why it's built this way
SqlDryRunses to is a hard gate. The executor refurun any SQL the validator
hasn't approved on the same turn. LLM-written SQL never touches the database unchecked.TurnState is passed between tools and never mutated —
every change produces a new state via .apply(). No hidden cross-tool side effects.Two short-circuits sit in front of the loop:
POST /query_stream
→ response cache? ── hit ─→ stream cached answer ─→ done
→ KPI fast-path? ── hit ─→ run template SQL ─→ stream ─→ done
→ agentic loop:
RouteClass → TimeKPI → Schema → sqlWriter → SqlDryRun
→ SqlExecutor → insightFmt → turn.end
Backend — Python 3.11 · FastAPI · Pydantic v2 · asyncpg (Postgres) / aiosqlite (SQLite) ·
DuckDB (analytics) · OpenAI-compatible LLM client (Ollama locally, OpenRouter in prod) ·
bcrypt + PyJWT (auth) · NumPy · Sentry · FastMCP (MCP server)
Frontend — React 18 · TypeScript 5.6 · Vite 5 · Tailwind CSS 3 · Recharts (charts) · Zustand (state) · Server-Sent Events (streaming)
Infra — Vercel (frontend) · Render (backend) · Supabase (Postgres) · GitHub Actions (CI)
backend/
app/
coordinator/ # the agentic loop
loop.py # drives the ReAct cycle
dispatcher.py # routes tool calls through hooks
hooks.py # cost caps + the SqlDryRun→SqlExecutor gate
state.py # immutable TurnState
llm.py # OpenAI-compatible LLM client
tools/ # 8 deterministic tools (RouteClass, Schema, SqlExecutor…)
sub_agents/ # 3 LLM-backed tools (sqlWriter, rcaReasoner, insightFmt)
capabilities/ # coarse capability wrappers
schema_mapping/ # concept resolver + metric SQL builder (schema portability)
kpi/ # KPI registry, matcher, formula engine (the fast-path)
enrichment/ # forecasting, inventory snapshots, cost master
hierarchy/ # product + location trees
vector/ # embeddings + semantic retrieval
monitoring/ # Sentry, tracing, instrumentation
database/ # SQLite ↔ Postgres engine abstraction
core_system.py # FastAPI app — every HTTP route, CORS, startup
tests/ # pytest suites (schema mapping, enrichment, time engine…)
main.py # backend entry point
frontend/
src/
App.tsx # layout shell, auth gate, view switcher
ui_system.tsx # all pages: Dashboard, AI Assistant, Upload, Shop Info
client_core.ts # API client (REST + SSE) + Zustand store + types
docs/adr/ # Architectural Decision Records
render.yaml # backend deploy config (Render)
main.py # single-command launcher (runs backend + frontend together)
ollama pull qwen3:8b
cd backend
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # defaults point at local Ollama — works out of the box
cd frontend
npm install
cp .env.example .env # VITE_BACKEND_URL defaults to localhost:8000 for dev
One command from the repo root starts both servers:
python main.py
# backend → http://localhost:8000
# frontend → http://localhost:5173
Or run them separately:
# terminal 1
uvicorn backend.main:app --port 8000 --reload
# terminal 2
cd frontend && npm run dev
Open http://localhost:5173, upload a spreadsheet (a sample lives in data/), and ask away.
All config is via environment variables (backend/.env). The defaults run a fully local,
single-user setup. Key switches:
| Variable | Purpose | Default |
|---|---|---|
LLM_BASE_URL / LLM_MODEL / LLM_API_KEY | Any OpenAI-compatible endpoint | local Ollama + qwen3:8b |
DATABASE_URL | postgres://… switches from SQLite to Postgres | unset (SQLite) |
AUTH_ENABLED | Master switch for JWT auth | false |
MAX_LOOP_ITERATIONS / COST_LIMIT_USD | Per-turn agent budgets | 8 / $1.00 |
ALLOWED_ORIGINS | CORS allow-list (lock down in prod) | * |
See backend/.env.example for the full annotated list.
cd backend
python -m pytest tests/ -v
Every push and PR runs GitHub Actions:
tsc --noEmit type-check + a full vite build.The app is deployed as three managed services:
VITE_BACKEND_URLrender.yaml), Postgres via DATABASE_URLAuth, CORS lock-down, and Postgres all activate purely from environment variables — the same codebase runs as a local single-user MVP or a deployed multi-tenant service.
Status: MVP / actively developed. Honest about what's done and what isn't — see the
self-audit in PRODUCTION_READINESS_REPORT.md and
TECHNICAL_DEBT_REPORT.md.
Working today: NL Q&A, auto-charts, KPI fast-path, schema mapping, RCA, forecasting, auth, multi-tenant isolation, streaming, Postgres + SQLite, CI.
Known limitations / next up:
MIT — free to use, learn from, and build on.
Built by Ayan Mansuri — @ayanv3419-oss. A from-scratch exploration of agentic AI systems, LLM-to-SQL, and full-stack product engineering. Questions and feedback welcome via GitHub Issues.