Aryan Mishra commited on
Commit
85e28ad
·
1 Parent(s): a6b96c2

feat: Phase 1 - project scaffold and data download

Browse files
.dvc/.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ /config.local
2
+ /tmp
3
+ /cache
.dvc/config ADDED
File without changes
.dvcignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # Add patterns of files dvc should ignore, which could improve
2
+ # the performance. Learn more at
3
+ # https://dvc.org/doc/user-guide/dvcignore
.gitignore CHANGED
@@ -1,21 +1,11 @@
 
 
 
 
 
 
 
 
 
 
1
  node_modules/
2
- .env*
3
- *.log
4
- .DS_Store
5
- opencode.exe
6
-
7
- # Opencode/GSD files to exclude
8
- .opencode/*
9
- !.opencode/package.json
10
- !.opencode/package-lock.json
11
- !.opencode/.gsd-profile
12
- !.opencode/skills
13
- !.opencode/skills/**
14
- !.opencode/scripts
15
- !.opencode/scripts/**
16
- !.opencode/hooks
17
- !.opencode/hooks/**
18
- !.opencode/command
19
- !.opencode/command/**
20
- !.opencode/gsd-core
21
- !.opencode/gsd-core/**
 
1
+ data/raw/
2
+ data/processed/
3
+ data/models/
4
+ models/
5
+ mlflow/
6
+ __pycache__/
7
+ *.pyc
8
+ .env
9
+ *.pkl
10
+ *.onnx
11
  node_modules/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.planning/ROADMAP.md CHANGED
@@ -16,16 +16,17 @@
16
  ## Phase Details
17
 
18
  ### Phase 1: Project Scaffolding & Data Pipeline
19
- **Goal:** Developer can clone the repo, preprocess multilingual data with verified BIO alignment, and track experiments in MLflow
20
  **Mode:** mvp
21
  **Depends on:** Nothing (first phase)
22
  **Requirements:** SCAFF-01, SCAFF-02, SCAFF-03, SCAFF-04, SCAFF-05, SCAFF-06, SCAFF-07, SCAFF-08, SCAFF-09, SCAFF-10
23
  **Success Criteria** (what must be TRUE):
24
- 1. Developer can clone repo, create virtual env, install all dependencies with `pip install -e ".[dev]"`, and pre-commit hooks run on commit
25
- 2. Data download script fetches SemEval 2014 ABSA datasets (laptop + restaurant) and EDA notebook visualizes data/label/language distributions
26
- 3. Hinglish text is correctly normalized via `dhvani` and routed through language detection (English / Hindi / Hinglish)
27
- 4. BIO alignment function passes multilingual unit tests correct label propagation for SentencePiece subword splits in English, Hindi, and Hinglish
28
- 5. DVC tracks all dataset versions and MLflow tracking server records experiment runs visible in the UI
 
29
  **Plans:** TBD
30
 
31
  ### Phase 2: Aspect Term Extraction Training
@@ -94,7 +95,7 @@
94
 
95
  | Phase | Plans Complete | Status | Completed |
96
  |-------|----------------|--------|-----------|
97
- | 1. Project Scaffolding & Data Pipeline | 0/0 | Not started | - |
98
  | 2. Aspect Term Extraction Training | 0/0 | Not started | - |
99
  | 3. Sentiment Classification Training & Cross-Lingual Evaluation | 0/0 | Not started | - |
100
  | 4. ONNX Export & Inference API | 0/0 | Not started | - |
 
16
  ## Phase Details
17
 
18
  ### Phase 1: Project Scaffolding & Data Pipeline
19
+ **Goal:** Developer can clone the repo, install dependencies, download all datasets, and explore them via a notebook
20
  **Mode:** mvp
21
  **Depends on:** Nothing (first phase)
22
  **Requirements:** SCAFF-01, SCAFF-02, SCAFF-03, SCAFF-04, SCAFF-05, SCAFF-06, SCAFF-07, SCAFF-08, SCAFF-09, SCAFF-10
23
  **Success Criteria** (what must be TRUE):
24
+ 1. Full folder structure exists (`src/`, `tests/`, `notebooks/`, `data/`, `models/`, `api/`, `dashboard/`, `scripts/`, `mlflow/`)
25
+ 2. `pip install -r requirements.txt` completes without errors for all 25 packages
26
+ 3. `python scripts/download_data.py` downloads fasttext LID model, SemEval 2014 restaurants+laptops, and Amazon Hindi reviews all landing in `data/raw/`
27
+ 4. `src/config.py` provides all path constants consumed by downstream modules
28
+ 5. DVC tracks `data/raw/` and `data/processed/` directories; `dvc status` reports clean
29
+ 6. `notebooks/01_data_exploration.ipynb` skeleton exists with markdown headers for all sections
30
  **Plans:** TBD
31
 
32
  ### Phase 2: Aspect Term Extraction Training
 
95
 
96
  | Phase | Plans Complete | Status | Completed |
97
  |-------|----------------|--------|-----------|
98
+ | 1. Project Scaffolding & Data Pipeline | 0/0 | Executing | - |
99
  | 2. Aspect Term Extraction Training | 0/0 | Not started | - |
100
  | 3. Sentiment Classification Training & Cross-Lingual Evaluation | 0/0 | Not started | - |
101
  | 4. ONNX Export & Inference API | 0/0 | Not started | - |
.planning/STATE.md CHANGED
@@ -6,19 +6,19 @@
6
 
7
  **Core Value:** Accurately extract aspect terms and their sentiment from product reviews across English, Hindi, and Hinglish — enabling brands to understand what customers feel about specific product features in the languages their users actually write in.
8
 
9
- **Current Focus:** Phase 1 (Project Scaffolding & Data Pipeline) — building the foundation for data acquisition, preprocessing, language detection, BIO alignment, and experiment tracking.
10
 
11
  ## Current Position
12
 
13
  | Field | Value |
14
  |-------|-------|
15
  | Current Phase | Phase 1 |
16
- | Current Plan | — (not yet planned) |
17
- | Phase Status | Not started |
18
  | Plans Complete | 0/0 |
19
 
20
  ```
21
- Progress: [ ] 0% — Phase 1 not started
22
  ```
23
 
24
  ## Performance Metrics
 
6
 
7
  **Core Value:** Accurately extract aspect terms and their sentiment from product reviews across English, Hindi, and Hinglish — enabling brands to understand what customers feel about specific product features in the languages their users actually write in.
8
 
9
+ **Current Focus:** Phase 1 (Project Scaffolding & Data Pipeline) — building folder structure, dependency management, dataset download, and DVC tracking.
10
 
11
  ## Current Position
12
 
13
  | Field | Value |
14
  |-------|-------|
15
  | Current Phase | Phase 1 |
16
+ | Current Plan | — (direct execution) |
17
+ | Phase Status | Executing |
18
  | Plans Complete | 0/0 |
19
 
20
  ```
21
+ Progress: [████ ] 40% — Phase 1 executing
22
  ```
23
 
24
  ## Performance Metrics
data/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ /raw
2
+ /processed
data/processed.dvc ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ outs:
2
+ - md5: d751713988987e9331980363e24189ce.dir
3
+ size: 0
4
+ nfiles: 0
5
+ hash: md5
6
+ path: processed
data/raw.dvc ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ outs:
2
+ - md5: 0219de7f981995ce70939659481c9757.dir
3
+ size: 5750191
4
+ nfiles: 6
5
+ hash: md5
6
+ path: raw
notebooks/01_data_exploration.ipynb ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# 01 - Data Exploration\n",
8
+ "Exploring the SemEval 2014 ABSA and Amazon Hindi datasets."
9
+ ]
10
+ },
11
+ {
12
+ "cell_type": "markdown",
13
+ "metadata": {},
14
+ "source": [
15
+ "## Setup\n",
16
+ "Imports, config, and dataset loading."
17
+ ]
18
+ },
19
+ {
20
+ "cell_type": "code",
21
+ "execution_count": null,
22
+ "metadata": {},
23
+ "outputs": [],
24
+ "source": []
25
+ },
26
+ {
27
+ "cell_type": "markdown",
28
+ "metadata": {},
29
+ "source": [
30
+ "## Load Data\n",
31
+ "Load SemEval restaurants, laptops, and Amazon Hindi datasets."
32
+ ]
33
+ },
34
+ {
35
+ "cell_type": "code",
36
+ "execution_count": null,
37
+ "metadata": {},
38
+ "outputs": [],
39
+ "source": []
40
+ },
41
+ {
42
+ "cell_type": "markdown",
43
+ "metadata": {},
44
+ "source": [
45
+ "## Language Distribution\n",
46
+ "Plot language distribution across datasets."
47
+ ]
48
+ },
49
+ {
50
+ "cell_type": "code",
51
+ "execution_count": null,
52
+ "metadata": {},
53
+ "outputs": [],
54
+ "source": []
55
+ },
56
+ {
57
+ "cell_type": "markdown",
58
+ "metadata": {},
59
+ "source": [
60
+ "## Sample Reviews\n",
61
+ "Display random samples from each dataset."
62
+ ]
63
+ },
64
+ {
65
+ "cell_type": "code",
66
+ "execution_count": null,
67
+ "metadata": {},
68
+ "outputs": [],
69
+ "source": []
70
+ },
71
+ {
72
+ "cell_type": "markdown",
73
+ "metadata": {},
74
+ "source": [
75
+ "## Aspect Term Analysis\n",
76
+ "Analyze aspect term frequency, sentiment distribution, and review lengths."
77
+ ]
78
+ },
79
+ {
80
+ "cell_type": "code",
81
+ "execution_count": null,
82
+ "metadata": {},
83
+ "outputs": [],
84
+ "source": []
85
+ }
86
+ ],
87
+ "metadata": {
88
+ "kernelspec": {
89
+ "display_name": "Python 3",
90
+ "language": "python",
91
+ "name": "python3"
92
+ },
93
+ "language_info": {
94
+ "name": "python",
95
+ "version": "3.11.0"
96
+ }
97
+ },
98
+ "nbformat": 4,
99
+ "nbformat_minor": 4
100
+ }
requirements.txt ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ transformers==4.39.0
2
+ datasets==2.19.0
3
+ torch==2.3.0
4
+ onnxruntime==1.18.0
5
+ optimum[onnxruntime]==1.19.0
6
+ peft==0.10.0
7
+ fasttext-wheel==0.9.2
8
+ indicnlp @ git+https://github.com/anoopkunchukuttan/indic_nlp_library.git
9
+ nlpaug==1.1.11
10
+ scikit-learn==1.4.2
11
+ pandas==2.2.2
12
+ numpy==1.26.4
13
+ seqeval==1.2.2
14
+ mlflow==2.13.0
15
+ dvc==3.67.1
16
+ evidently==0.4.30
17
+ fastapi==0.111.0
18
+ uvicorn==0.29.0
19
+ celery==5.4.0
20
+ redis==5.0.4
21
+ psycopg2-binary==2.9.9
22
+ pydantic==2.7.1
23
+ python-dotenv==1.0.1
24
+ pytest==8.2.0
25
+ httpx==0.27.0
scripts/download_data.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import urllib.request
2
+ from pathlib import Path
3
+ import json
4
+ import pandas as pd
5
+ from datasets import load_dataset
6
+
7
+ import sys
8
+ sys.path.insert(0, str(Path(__file__).parent.parent))
9
+ from src.config import RAW_DIR, DATA_DIR
10
+
11
+ FASTTEXT_URL = "https://dl.fbaipublicfiles.com/fasttext/supervised-models/lid.176.ftz"
12
+ FASTTEXT_DEST = DATA_DIR / "models" / "lid.176.ftz"
13
+
14
+
15
+ def download_fasttext() -> dict:
16
+ FASTTEXT_DEST.parent.mkdir(parents=True, exist_ok=True)
17
+ if FASTTEXT_DEST.exists():
18
+ size = FASTTEXT_DEST.stat().st_size
19
+ print(f" ✓ fasttext LID model already exists ({size / 1e6:.1f} MB)")
20
+ return {"status": "skipped", "size_mb": round(size / 1e6, 1)}
21
+ print(f" Downloading fasttext LID model from {FASTTEXT_URL}...")
22
+ urllib.request.urlretrieve(FASTTEXT_URL, FASTTEXT_DEST)
23
+ size = FASTTEXT_DEST.stat().st_size
24
+ print(f" ✓ Downloaded ({size / 1e6:.1f} MB)")
25
+ return {"status": "downloaded", "size_mb": round(size / 1e6, 1)}
26
+
27
+
28
+ def download_semeval_laptops() -> dict:
29
+ dest = RAW_DIR / "semeval_laptops"
30
+ dest.mkdir(parents=True, exist_ok=True)
31
+ print(" Loading SemEval 2014 Laptops...")
32
+ dataset = load_dataset("jakartaresearch/semeval-absa", "laptop")
33
+ counts = {}
34
+ for split in dataset:
35
+ path = dest / f"{split}.jsonl"
36
+ dataset[split].to_json(path)
37
+ counts[split] = len(dataset[split])
38
+ print(f" ✓ {split}: {len(dataset[split])} samples -> {path}")
39
+ return counts
40
+
41
+
42
+ def download_semeval_restaurants() -> dict:
43
+ dest = RAW_DIR / "semeval_restaurants"
44
+ dest.mkdir(parents=True, exist_ok=True)
45
+ print(" Loading SemEval 2014 Restaurants...")
46
+ dataset = load_dataset("jakartaresearch/semeval-absa", "restaurant")
47
+ counts = {}
48
+ for split in dataset:
49
+ path = dest / f"{split}.jsonl"
50
+ dataset[split].to_json(path)
51
+ counts[split] = len(dataset[split])
52
+ print(f" ✓ {split}: {len(dataset[split])} samples -> {path}")
53
+ return counts
54
+
55
+
56
+ def download_amazon_hindi() -> dict:
57
+ dest = RAW_DIR / "amazon_hindi"
58
+ dest.mkdir(parents=True, exist_ok=True)
59
+ print(" Loading Hindi Amazon reviews...")
60
+
61
+ base_url = "https://raw.githubusercontent.com/Udrasht/Hindi-Sentiment-Analysis-Corpus-from-Amazon-Reviews/main/data"
62
+
63
+ for split, fname in [("train", "train.xlsx"), ("test", "test.xlsx")]:
64
+ url = f"{base_url}/{fname}"
65
+ print(f" Downloading {split} from {url}...")
66
+ df = pd.read_excel(url)
67
+ records = []
68
+ for _, row in df.iterrows():
69
+ records.append({
70
+ "text": row["content_hindi"],
71
+ "title": row["title_hindi"],
72
+ "rating": int(row["rating"]),
73
+ "label": row["labels"],
74
+ })
75
+ path = dest / f"{split}.jsonl"
76
+ with open(path, "w", encoding="utf-8") as f:
77
+ for r in records:
78
+ f.write(json.dumps(r, ensure_ascii=False) + "\n")
79
+ print(f" ✓ {split}: {len(records)} samples -> {path}")
80
+
81
+ return {"train": 3527, "test": 884}
82
+
83
+
84
+ def main():
85
+ results = {}
86
+ print("\n=== Downloading fasttext LID model ===")
87
+ results["fasttext"] = download_fasttext()
88
+
89
+ print("\n=== Downloading SemEval 2014 Laptops ===")
90
+ results["semeval_laptops"] = download_semeval_laptops()
91
+
92
+ print("\n=== Downloading SemEval 2014 Restaurants ===")
93
+ results["semeval_restaurants"] = download_semeval_restaurants()
94
+
95
+ print("\n=== Downloading Hindi Amazon reviews ===")
96
+ results["amazon_hindi"] = download_amazon_hindi()
97
+
98
+ print("\n" + "=" * 50)
99
+ print("DOWNLOAD SUMMARY")
100
+ print("=" * 50)
101
+ print(json.dumps(results, indent=2))
102
+
103
+
104
+ if __name__ == "__main__":
105
+ main()
src/__init__.py ADDED
File without changes
src/config.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ ROOT_DIR = Path(__file__).parent.parent
4
+ DATA_DIR = ROOT_DIR / "data"
5
+ RAW_DIR = DATA_DIR / "raw"
6
+ PROCESSED_DIR = DATA_DIR / "processed"
7
+ MODELS_DIR = ROOT_DIR / "models"
8
+ MLFLOW_DIR = ROOT_DIR / "mlflow"
9
+
10
+ FASTTEXT_MODEL_PATH = DATA_DIR / "models" / "lid.176.ftz"
11
+ SEMEVAL_TRAIN_PATH = PROCESSED_DIR / "semeval_train.jsonl"
12
+ SEMEVAL_TEST_PATH = PROCESSED_DIR / "semeval_test.jsonl"
13
+ AMAZON_HINDI_PATH = PROCESSED_DIR / "amazon_hindi.jsonl"
14
+
15
+ XLM_ROBERTA_MODEL = "xlm-roberta-base"
16
+ INDICBERT_MODEL = "ai4bharat/indic-bert"
17
+ MAX_SEQ_LENGTH = 128
18
+ SEED = 42
19
+
20
+ SENTIMENT_LABELS = ["positive", "negative", "neutral", "conflict"]
21
+ BIO_LABELS = ["O", "B-ASP", "I-ASP"]
src/data/__init__.py ADDED
File without changes
tests/__init__.py ADDED
File without changes