diff --git a/backend/.env.example b/.env.example similarity index 100% rename from backend/.env.example rename to .env.example diff --git a/backend/.gitignore b/.gitignore similarity index 100% rename from backend/.gitignore rename to .gitignore diff --git a/backend/Dockerfile b/Dockerfile similarity index 100% rename from backend/Dockerfile rename to Dockerfile diff --git a/README.md b/README.md index 0a0e6384afa09bb59da2773ca7a8836846639233..c34b8d529d8807b1ae8af712a7d480bdd1525fd1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,63 @@ ---- -title: Matchlens API -emoji: 📉 -colorFrom: blue -colorTo: yellow -sdk: gradio -sdk_version: 6.31.0 -python_version: '3.12' -app_file: app.py -pinned: false ---- - -Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference +# MatchLens backend + +This FastAPI service powers the existing React replay UI. The initial data mode is +explicitly a **historical replay**, not a live feed. Cricsheet JSON files can be +placed in `app/data/matches`; the normalized parser loads them at startup. + +## Load multiple real matches + +The backend does not scrape an HTML scoreboard. It uses Cricsheet's structured, +historical ball-by-ball JSON source, which is more reliable for replay and +statistics. From the `backend` directory, download a bounded set of recent +men's T20 matches: + +```powershell +python scripts\download_cricsheet.py --count 12 +``` + +Restart Uvicorn after downloading. `GET /api/matches` will then expose the +downloaded matches alongside the bundled fallback. The downloader is +repeatable and only stores selected JSON files locally; do not commit the +downloaded match data unless your distribution policy permits it. + +## Run locally + +```powershell +cd backend +python -m venv .venv +.venv\Scripts\Activate.ps1 +pip install -r requirements.txt +Copy-Item .env.example .env +uvicorn app.main:app --reload +``` + +OpenAPI is available at `http://localhost:8000/docs`. Configure `GEMINI_API_KEY` +for grounded natural-language explanations. Without it, the API returns a +deterministic evidence-based fallback and explicitly warns that Gemini is not +configured. Configure Qdrant before running the ingestion tooling; rule +documents are never used to store changing match scores. + +## Frontend + +Use the real API by setting: + +```env +VITE_DEMO_MODE=false +VITE_API_BASE_URL=http://localhost:8000 +``` + +The frontend then calls `/api/matches`, `/api/matches/{id}/state`, +`/api/matches/{id}/timeline`, replay, catch-up, and assistant routes. Demo +fixtures remain available when `VITE_DEMO_MODE` is not `false`. + +## Offline experiments and deployment + +`app/fine_tuning/train.py` contains the PEFT/LoRA training entry point and +`evaluate.py` reports measured accuracy, macro-F1, and a confusion matrix. +Training is intentionally offline and the API does not train at startup. +`app/rag/ingestion.py` prepares idempotent document chunks for Qdrant. + +Build the Cloud Run image with `docker build -t matchlens-api backend` and pass +secrets as environment variables. Netlify should use the same +`VITE_API_BASE_URL` setting and an SPA fallback for `index.html`. Render can +run the same Docker image with the configured `PORT`. diff --git a/backend/app.py b/app.py similarity index 100% rename from backend/app.py rename to app.py diff --git a/backend/app/__init__.py b/app/__init__.py similarity index 100% rename from backend/app/__init__.py rename to app/__init__.py diff --git a/backend/app/ai/__init__.py b/app/ai/__init__.py similarity index 100% rename from backend/app/ai/__init__.py rename to app/ai/__init__.py diff --git a/backend/app/ai/graph.py b/app/ai/graph.py similarity index 100% rename from backend/app/ai/graph.py rename to app/ai/graph.py diff --git a/backend/app/api.py b/app/api.py similarity index 100% rename from backend/app/api.py rename to app/api.py diff --git a/backend/app/config.py b/app/config.py similarity index 100% rename from backend/app/config.py rename to app/config.py diff --git a/backend/app/data/__init__.py b/app/data/__init__.py similarity index 100% rename from backend/app/data/__init__.py rename to app/data/__init__.py diff --git a/backend/app/data/knowledge/cricket_rules_and_laws.txt b/app/data/knowledge/cricket_rules_and_laws.txt similarity index 100% rename from backend/app/data/knowledge/cricket_rules_and_laws.txt rename to app/data/knowledge/cricket_rules_and_laws.txt diff --git a/backend/app/data/knowledge/t20_analytics_and_chasing_dynamics.txt b/app/data/knowledge/t20_analytics_and_chasing_dynamics.txt similarity index 100% rename from backend/app/data/knowledge/t20_analytics_and_chasing_dynamics.txt rename to app/data/knowledge/t20_analytics_and_chasing_dynamics.txt diff --git a/backend/app/data/matches/.gitkeep b/app/data/matches/.gitkeep similarity index 100% rename from backend/app/data/matches/.gitkeep rename to app/data/matches/.gitkeep diff --git a/backend/app/data/matches/1082591.json b/app/data/matches/1082591.json similarity index 100% rename from backend/app/data/matches/1082591.json rename to app/data/matches/1082591.json diff --git a/backend/app/data/matches/1082592.json b/app/data/matches/1082592.json similarity index 100% rename from backend/app/data/matches/1082592.json rename to app/data/matches/1082592.json diff --git a/backend/app/data/matches/1082593.json b/app/data/matches/1082593.json similarity index 100% rename from backend/app/data/matches/1082593.json rename to app/data/matches/1082593.json diff --git a/backend/app/data/matches/1082594.json b/app/data/matches/1082594.json similarity index 100% rename from backend/app/data/matches/1082594.json rename to app/data/matches/1082594.json diff --git a/backend/app/data/matches/1082595.json b/app/data/matches/1082595.json similarity index 100% rename from backend/app/data/matches/1082595.json rename to app/data/matches/1082595.json diff --git a/backend/app/data/matches/1082596.json b/app/data/matches/1082596.json similarity index 100% rename from backend/app/data/matches/1082596.json rename to app/data/matches/1082596.json diff --git a/backend/app/data/matches/1082597.json b/app/data/matches/1082597.json similarity index 100% rename from backend/app/data/matches/1082597.json rename to app/data/matches/1082597.json diff --git a/backend/app/data/matches/1082598.json b/app/data/matches/1082598.json similarity index 100% rename from backend/app/data/matches/1082598.json rename to app/data/matches/1082598.json diff --git a/backend/app/data/matches/1082599.json b/app/data/matches/1082599.json similarity index 100% rename from backend/app/data/matches/1082599.json rename to app/data/matches/1082599.json diff --git a/backend/app/data/matches/1082600.json b/app/data/matches/1082600.json similarity index 100% rename from backend/app/data/matches/1082600.json rename to app/data/matches/1082600.json diff --git a/backend/app/data/matches/1082601.json b/app/data/matches/1082601.json similarity index 100% rename from backend/app/data/matches/1082601.json rename to app/data/matches/1082601.json diff --git a/backend/app/data/matches/1082602.json b/app/data/matches/1082602.json similarity index 100% rename from backend/app/data/matches/1082602.json rename to app/data/matches/1082602.json diff --git a/backend/app/data/matches/__init__.py b/app/data/matches/__init__.py similarity index 100% rename from backend/app/data/matches/__init__.py rename to app/data/matches/__init__.py diff --git a/backend/app/fine_tuning/__init__.py b/app/fine_tuning/__init__.py similarity index 100% rename from backend/app/fine_tuning/__init__.py rename to app/fine_tuning/__init__.py diff --git a/backend/app/fine_tuning/data/intent_examples.jsonl b/app/fine_tuning/data/intent_examples.jsonl similarity index 100% rename from backend/app/fine_tuning/data/intent_examples.jsonl rename to app/fine_tuning/data/intent_examples.jsonl diff --git a/backend/app/fine_tuning/evaluate.py b/app/fine_tuning/evaluate.py similarity index 100% rename from backend/app/fine_tuning/evaluate.py rename to app/fine_tuning/evaluate.py diff --git a/backend/app/fine_tuning/train.py b/app/fine_tuning/train.py similarity index 100% rename from backend/app/fine_tuning/train.py rename to app/fine_tuning/train.py diff --git a/backend/app/main.py b/app/main.py similarity index 100% rename from backend/app/main.py rename to app/main.py diff --git a/backend/app/models.py b/app/models.py similarity index 100% rename from backend/app/models.py rename to app/models.py diff --git a/backend/app/rag/__init__.py b/app/rag/__init__.py similarity index 100% rename from backend/app/rag/__init__.py rename to app/rag/__init__.py diff --git a/backend/app/rag/ingestion.py b/app/rag/ingestion.py similarity index 100% rename from backend/app/rag/ingestion.py rename to app/rag/ingestion.py diff --git a/backend/app/services/__init__.py b/app/services/__init__.py similarity index 100% rename from backend/app/services/__init__.py rename to app/services/__init__.py diff --git a/backend/app/services/cricket.py b/app/services/cricket.py similarity index 100% rename from backend/app/services/cricket.py rename to app/services/cricket.py diff --git a/backend/app/services/gemini.py b/app/services/gemini.py similarity index 100% rename from backend/app/services/gemini.py rename to app/services/gemini.py diff --git a/backend/app/services/intent.py b/app/services/intent.py similarity index 100% rename from backend/app/services/intent.py rename to app/services/intent.py diff --git a/backend/app/services/match_data.py b/app/services/match_data.py similarity index 100% rename from backend/app/services/match_data.py rename to app/services/match_data.py diff --git a/backend/app/services/rag.py b/app/services/rag.py similarity index 100% rename from backend/app/services/rag.py rename to app/services/rag.py diff --git a/backend/app/services/sample_data.py b/app/services/sample_data.py similarity index 100% rename from backend/app/services/sample_data.py rename to app/services/sample_data.py diff --git a/backend/app/services/stories.py b/app/services/stories.py similarity index 100% rename from backend/app/services/stories.py rename to app/services/stories.py diff --git a/backend/app/services/workflow.py b/app/services/workflow.py similarity index 100% rename from backend/app/services/workflow.py rename to app/services/workflow.py diff --git a/backend/README.md b/backend/README.md deleted file mode 100644 index c34b8d529d8807b1ae8af712a7d480bdd1525fd1..0000000000000000000000000000000000000000 --- a/backend/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# MatchLens backend - -This FastAPI service powers the existing React replay UI. The initial data mode is -explicitly a **historical replay**, not a live feed. Cricsheet JSON files can be -placed in `app/data/matches`; the normalized parser loads them at startup. - -## Load multiple real matches - -The backend does not scrape an HTML scoreboard. It uses Cricsheet's structured, -historical ball-by-ball JSON source, which is more reliable for replay and -statistics. From the `backend` directory, download a bounded set of recent -men's T20 matches: - -```powershell -python scripts\download_cricsheet.py --count 12 -``` - -Restart Uvicorn after downloading. `GET /api/matches` will then expose the -downloaded matches alongside the bundled fallback. The downloader is -repeatable and only stores selected JSON files locally; do not commit the -downloaded match data unless your distribution policy permits it. - -## Run locally - -```powershell -cd backend -python -m venv .venv -.venv\Scripts\Activate.ps1 -pip install -r requirements.txt -Copy-Item .env.example .env -uvicorn app.main:app --reload -``` - -OpenAPI is available at `http://localhost:8000/docs`. Configure `GEMINI_API_KEY` -for grounded natural-language explanations. Without it, the API returns a -deterministic evidence-based fallback and explicitly warns that Gemini is not -configured. Configure Qdrant before running the ingestion tooling; rule -documents are never used to store changing match scores. - -## Frontend - -Use the real API by setting: - -```env -VITE_DEMO_MODE=false -VITE_API_BASE_URL=http://localhost:8000 -``` - -The frontend then calls `/api/matches`, `/api/matches/{id}/state`, -`/api/matches/{id}/timeline`, replay, catch-up, and assistant routes. Demo -fixtures remain available when `VITE_DEMO_MODE` is not `false`. - -## Offline experiments and deployment - -`app/fine_tuning/train.py` contains the PEFT/LoRA training entry point and -`evaluate.py` reports measured accuracy, macro-F1, and a confusion matrix. -Training is intentionally offline and the API does not train at startup. -`app/rag/ingestion.py` prepares idempotent document chunks for Qdrant. - -Build the Cloud Run image with `docker build -t matchlens-api backend` and pass -secrets as environment variables. Netlify should use the same -`VITE_API_BASE_URL` setting and an SPA fallback for `index.html`. Render can -run the same Docker image with the configured `PORT`. diff --git a/backend/recent.zip b/recent.zip similarity index 100% rename from backend/recent.zip rename to recent.zip diff --git a/backend/requirements.txt b/requirements.txt similarity index 100% rename from backend/requirements.txt rename to requirements.txt diff --git a/backend/scripts/check_qdrant.py b/scripts/check_qdrant.py similarity index 100% rename from backend/scripts/check_qdrant.py rename to scripts/check_qdrant.py diff --git a/backend/scripts/download_cricsheet.py b/scripts/download_cricsheet.py similarity index 100% rename from backend/scripts/download_cricsheet.py rename to scripts/download_cricsheet.py diff --git a/backend/scripts/ingest_knowledge.py b/scripts/ingest_knowledge.py similarity index 100% rename from backend/scripts/ingest_knowledge.py rename to scripts/ingest_knowledge.py diff --git a/backend/tests/test_api.py b/tests/test_api.py similarity index 100% rename from backend/tests/test_api.py rename to tests/test_api.py diff --git a/backend/tests/test_cricket.py b/tests/test_cricket.py similarity index 100% rename from backend/tests/test_cricket.py rename to tests/test_cricket.py diff --git a/backend/tests/test_partnership.py b/tests/test_partnership.py similarity index 100% rename from backend/tests/test_partnership.py rename to tests/test_partnership.py