Aryan Mishra commited on
Commit
2617189
·
1 Parent(s): a00fee9

Deploy Gradio app to HF Spaces

Browse files

- Remove Streamlit/FastAPI/Celery
- Add single-file Gradio UI
- Add SQLite for prediction history
- Update docs and CI

This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .env.example +1 -22
  2. .gitattributes +3 -0
  3. .github/workflows/ci.yml +5 -5
  4. .gitignore +3 -0
  5. .pre-commit-config.yaml +0 -1
  6. README.md +32 -208
  7. api/core/__init__.py +0 -0
  8. api/main.py +0 -56
  9. api/middleware/__init__.py +0 -0
  10. api/middleware/dependencies.py +0 -27
  11. api/middleware/metrics.py +0 -12
  12. api/models/__init__.py +0 -0
  13. api/py.typed +0 -0
  14. api/routes/__init__.py +0 -0
  15. api/routes/predict.py +0 -129
  16. api/routes/results.py +0 -39
  17. api/schemas/__init__.py +0 -0
  18. api/services/__init__.py +0 -0
  19. api/tasks/__init__.py +0 -12
  20. api/tasks/batch_tasks.py +0 -132
  21. app.py +512 -0
  22. coverage.xml +891 -1200
  23. data/.gitignore +0 -1
  24. data/demo/demo_single_reviews.txt +0 -5
  25. data/demo/sample_reviews.csv +0 -21
  26. data/models/lid.176.ftz +0 -3
  27. data/raw.dvc +0 -6
  28. data/tokenized/absa_cls_dataset/dataset_dict.json +0 -1
  29. data/tokenized/absa_cls_dataset/test/data-00000-of-00001.arrow +0 -3
  30. data/tokenized/absa_cls_dataset/test/dataset_info.json +0 -26
  31. data/tokenized/absa_cls_dataset/test/state.json +0 -13
  32. data/tokenized/absa_cls_dataset/train/data-00000-of-00001.arrow +0 -3
  33. data/tokenized/absa_cls_dataset/train/dataset_info.json +0 -26
  34. data/tokenized/absa_cls_dataset/train/state.json +0 -13
  35. data/tokenized/absa_cls_dataset/validation/data-00000-of-00001.arrow +0 -3
  36. data/tokenized/absa_cls_dataset/validation/dataset_info.json +0 -26
  37. data/tokenized/absa_cls_dataset/validation/state.json +0 -13
  38. data/tokenized/absa_ner_dataset/dataset_dict.json +0 -1
  39. data/tokenized/absa_ner_dataset/test/data-00000-of-00001.arrow +0 -3
  40. data/tokenized/absa_ner_dataset/test/dataset_info.json +0 -29
  41. data/tokenized/absa_ner_dataset/test/state.json +0 -13
  42. data/tokenized/absa_ner_dataset/train/data-00000-of-00001.arrow +0 -3
  43. data/tokenized/absa_ner_dataset/train/dataset_info.json +0 -29
  44. data/tokenized/absa_ner_dataset/train/state.json +0 -13
  45. data/tokenized/absa_ner_dataset/validation/data-00000-of-00001.arrow +0 -3
  46. data/tokenized/absa_ner_dataset/validation/dataset_info.json +0 -29
  47. data/tokenized/absa_ner_dataset/validation/state.json +0 -13
  48. docker/Dockerfile +0 -42
  49. docker/Dockerfile.prod +0 -19
  50. docker/docker-compose.prod.yml +0 -16
.env.example CHANGED
@@ -1,22 +1 @@
1
- # Database
2
- DATABASE_URL=postgresql://user:pass@localhost:5432/absa_db
3
- POSTGRES_USER=absa_user
4
- POSTGRES_PASSWORD=change_this_to_strong_password
5
- POSTGRES_DB=absa_db
6
-
7
- # Redis / Celery
8
- REDIS_URL=redis://localhost:6379/0
9
- REDIS_PASSWORD=change_this_to_strong_password
10
-
11
- # Model
12
- MODEL_PATH=models/onnx/
13
- MAX_BATCH_SIZE=10000
14
-
15
- # Security
16
- CORS_ORIGINS=http://localhost:3000,http://localhost:8000
17
- CSRF_SECRET=change_this_to_strong_random_secret
18
- GRAFANA_ADMIN_PASSWORD=change_this_to_strong_password
19
-
20
- # Logging
21
- LOG_LEVEL=INFO
22
- ENABLE_METRICS=true
 
1
+ MODEL_PATH=./models/xlm-roberta-quantized
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitattributes CHANGED
@@ -23,5 +23,8 @@ dist/** linguist-generated=true
23
  build/** linguist-generated=true
24
  node_modules/** linguist-generated=true
25
  **/node_modules/** linguist-generated=true
 
 
 
26
  *.ftz filter=lfs diff=lfs merge=lfs -text
27
  *.arrow filter=lfs diff=lfs merge=lfs -text
 
23
  build/** linguist-generated=true
24
  node_modules/** linguist-generated=true
25
  **/node_modules/** linguist-generated=true
26
+ # Hugging Face Spaces LFS (model artifacts)
27
+ models/**/*.onnx filter=lfs diff=lfs merge=lfs -text
28
+ models/**/*.bin filter=lfs diff=lfs merge=lfs -text
29
  *.ftz filter=lfs diff=lfs merge=lfs -text
30
  *.arrow filter=lfs diff=lfs merge=lfs -text
.github/workflows/ci.yml CHANGED
@@ -25,9 +25,9 @@ jobs:
25
  - name: Install ruff
26
  run: pip install ruff==0.15.11
27
  - name: Ruff check
28
- run: ruff check api src/absa tests scripts
29
  - name: Ruff format check
30
- run: ruff format --check api src/absa tests scripts
31
 
32
  typecheck:
33
  name: Typecheck (mypy)
@@ -42,7 +42,7 @@ jobs:
42
  pip install --upgrade pip
43
  pip install -e ".[dev]"
44
  - name: Mypy
45
- run: mypy api src/absa
46
 
47
  security:
48
  name: Security (bandit)
@@ -55,7 +55,7 @@ jobs:
55
  - name: Install bandit
56
  run: pip install bandit
57
  - name: Bandit scan
58
- run: bandit -r api src/absa
59
 
60
  test:
61
  name: Tests (pytest) — py${{ matrix.python }}
@@ -75,4 +75,4 @@ jobs:
75
  pip install --upgrade pip
76
  pip install -e ".[dev]"
77
  - name: Run tests
78
- run: pytest tests/ -v
 
25
  - name: Install ruff
26
  run: pip install ruff==0.15.11
27
  - name: Ruff check
28
+ run: ruff check src/absa tests scripts
29
  - name: Ruff format check
30
+ run: ruff format --check src/absa tests scripts
31
 
32
  typecheck:
33
  name: Typecheck (mypy)
 
42
  pip install --upgrade pip
43
  pip install -e ".[dev]"
44
  - name: Mypy
45
+ run: mypy src/absa
46
 
47
  security:
48
  name: Security (bandit)
 
55
  - name: Install bandit
56
  run: pip install bandit
57
  - name: Bandit scan
58
+ run: bandit -r src/absa
59
 
60
  test:
61
  name: Tests (pytest) — py${{ matrix.python }}
 
75
  pip install --upgrade pip
76
  pip install -e ".[dev]"
77
  - name: Run tests
78
+ run: pytest tests/unit/ -v
.gitignore CHANGED
@@ -65,3 +65,6 @@ logs/
65
 
66
  # Node
67
  node_modules/
 
 
 
 
65
 
66
  # Node
67
  node_modules/
68
+
69
+ absa.db
70
+ absa.db-journal
.pre-commit-config.yaml CHANGED
@@ -10,7 +10,6 @@ repos:
10
  rev: v4.6.0
11
  hooks:
12
  - id: check-yaml
13
- exclude: ^docker/docker-compose.*\.ya?ml$
14
  - id: check-json
15
  - id: end-of-file-fixer
16
  exclude: ^notebooks/
 
10
  rev: v4.6.0
11
  hooks:
12
  - id: check-yaml
 
13
  - id: check-json
14
  - id: end-of-file-fixer
15
  exclude: ^notebooks/
README.md CHANGED
@@ -1,227 +1,51 @@
1
- # Multilingual Aspect-Based Sentiment Analysis (ABSA)
2
-
3
- [![Python](https://img.shields.io/badge/Python-3.10%2B-blue.svg)](https://python.org)
4
- [![FastAPI](https://img.shields.io/badge/FastAPI-0.115-00a393.svg)](https://fastapi.tiangolo.com)
5
- [![Streamlit](https://img.shields.io/badge/Streamlit-1.37-FF4B4B.svg)](https://streamlit.io)
6
- [![DVC](https://img.shields.io/badge/DVC-3.51-945dd6.svg)](https://dvc.org)
7
- [![MLflow](https://img.shields.io/badge/MLflow-2.15-0194E2.svg)](https://mlflow.org)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
9
-
10
- **Analyse product reviews in English, Hindi, and Hinglish — extract aspects and their sentiment in real time.**
11
-
12
- A pure-Python stack: a Streamlit dashboard on top of a FastAPI JSON API, backed by a multilingual ML pipeline (ONNX inference with a rule-based fallback).
13
-
14
- ---
15
-
16
- ## Quick Start
17
-
18
- ```bash
19
- git clone <repo-url> && cd multilingual-absa
20
- python -m venv .venv && source .venv/bin/activate
21
- pip install -e ".[dev]"
22
- ```
23
-
24
- Start the API (port 8000) and the dashboard (port 8501) in two terminals:
25
-
26
- ```bash
27
- # Terminal 1 — REST API
28
- uvicorn api.main:app --reload --host 0.0.0.0 --port 8000
29
-
30
- # Terminal 2 — Streamlit dashboard
31
- streamlit run frontend/Home.py
32
- ```
33
-
34
- Open:
35
- - **Dashboard** → [`http://localhost:8501`](http://localhost:8501)
36
- - **API docs (Swagger)** → [`http://localhost:8000/docs`](http://localhost:8000/docs)
37
-
38
  ---
39
-
40
- ## What This Does
41
-
42
- The system identifies **aspects** (specific features like "battery life", "sound quality") and their **sentiment** (positive, negative, neutral) from product reviews. It supports three languages:
43
-
44
- | Language | Aspect Extraction | Sentiment |
45
- |----------|:-:|:-:|
46
- | English | ✅ | ✅ |
47
- | Hindi | ✅ | ✅ |
48
- | Hinglish | ✅ | ✅ |
49
-
50
- **Production performance** (ONNX INT8 quantised):
51
-
52
- | Language | F1 Score | Latency p95 |
53
- |----------|:--------:|:-----------:|
54
- | English | 78.1% | 185 ms |
55
- | Hindi | 67.8% | 185 ms |
56
-
57
  ---
58
 
59
- ## Project Structure
60
 
61
- ```
62
- .
63
- ├── api/ # FastAPI REST service
64
- │ ├── main.py # Entry point — uvicorn api.main:app
65
- │ ├── models/ # SQLAlchemy ORM models (Review, AspectResult, BatchJob)
66
- │ ├── middleware/ # Rate limiting, metrics (Prometheus), DB deps
67
- │ ├── routes/ # /predict, /batch, /status, /download, /health, /info
68
- │ ├── schemas/ # Pydantic request/response models
69
- │ ├── services/ # ABSA inference pipeline, language detection
70
- │ └── tasks/ # Celery batch processing workers
71
- ├── src/absa/ # Core ML library (src-layout, pip-installable)
72
- │ ├── data/ # Loading, preprocessing, augmentation, transliteration
73
- │ ├── models/ # Training scripts (ONNX, Transformers, baselines)
74
- │ ├── evaluation/ # Cross-lingual eval, latency benchmarking
75
- │ ├── training/ # MLflow experiment tracking
76
- │ └── utils/ # Path + environment configuration
77
- ├── frontend/ # Streamlit dashboard (pure Python, no HTML templates)
78
- │ ├── Home.py # Entry point — streamlit run frontend/Home.py
79
- │ ├── absa_client.py # Thin HTTP client for the FastAPI backend
80
- │ ├── ui.py # Native Streamlit UI helpers
81
- │ └── views/ # Pages: predict, admin (overview/batch/monitor)
82
- ├── tests/ # Pytest suite
83
- │ ├── conftest.py # sys.path bootstrap — no PYTHONPATH hacks required
84
- │ ├── api/ # API endpoint tests
85
- │ ├── web/ # Streamlit page + client tests
86
- │ └── unit/ # Unit tests (bio tagger, lang detect)
87
- ├── scripts/ # Operational utility scripts
88
- ├── notebooks/ # Exploration & Colab training notebooks (numbered 01–05)
89
- ├── monitoring/ # Prometheus + Grafana config
90
- ├── docs/ # Documentation
91
- ├── docker/ # Containerisation
92
- ├── data/ # Datasets (managed by DVC)
93
- ├── models/ # ONNX model artifacts (DVC-tracked)
94
- ├── .github/workflows/ # CI pipeline (lint, typecheck, security, tests)
95
- ├── .env.example # Environment variable template
96
- ├── dvc.yaml # DVC data pipeline
97
- ├── pyproject.toml # Project metadata + tool config
98
- └── Makefile # Developer command shortcuts
99
- ```
100
 
101
- ---
 
102
 
103
- ## Architecture
104
-
105
- ```
106
- ┌──────────┐ native Streamlit ┌──────────────────────────────┐
107
- │ Browser │◄────────────────────►│ Streamlit Dashboard (8501) │
108
- └──────────┘ │ frontend/ — pure Python UI │
109
- └──────────────┬───────────────┘
110
- │ HTTP (httpx)
111
- ┌──────────────▼───────────────┐
112
- │ FastAPI REST API (8000) │
113
- │ api/main.py — JSON endpoints │
114
- └──────────────┬───────────────┘
115
-
116
- ┌───────────────────────────┼────────────────────┐
117
- │ │ │
118
- ┌──────▼──────┐ ┌─────────▼────────┐ ┌────────▼───────┐
119
- │ PostgreSQL / │ │ Redis / Celery │ │ Prometheus + │
120
- │ SQLite │ │ (batch jobs) │ │ Grafana │
121
- │ (results) │ └──────────────────┘ └────────────────┘
122
- └─────────────┘
123
- ```
124
-
125
- ### Inference Stack
126
-
127
- | Component | Layer | Notes |
128
- |-----------|-------|-------|
129
- | ONNX INT8 | Primary | Production — 185 ms p95 latency |
130
- | ONNX FP32 | Fallback | Same model, no quantisation — 520 ms |
131
- | Rule-based | Fallback | Keyword lexicon + context-window scoring — zero download |
132
-
133
- The pipeline auto-selects: **ONNX INT8** → **ONNX FP32** → **Rule-based**. No external model downloads required.
134
-
135
- ---
136
-
137
- ## Features
138
-
139
- ### Dashboard (Streamlit)
140
-
141
- - **Sentiment Analyzer** — Real-time aspect/sentiment analysis with confidence bars
142
- - **Batch Analytics** — CSV upload, async Celery job, live progress, result download
143
- - **System Monitor** — Health checks, service metadata, auto-refresh diagnostics
144
- - **Admin Lock** — Optional password-gated admin section (`ADMIN_PASSWORD`)
145
-
146
- ### API (RESTful JSON)
147
-
148
- | Endpoint | Method | Description |
149
- |----------|--------|-------------|
150
- | `/predict` | POST | Analyse a single review |
151
- | `/batch` | POST | Upload CSV for bulk analysis |
152
- | `/status/{job_id}` | GET | Check batch job progress |
153
- | `/download/{job_id}` | GET | Download batch results (CSV) |
154
- | `/health` | GET | API health check |
155
- | `/info` | GET | Model metadata |
156
- | `/metrics` | GET | Prometheus metrics |
157
- | `/docs` | GET | Swagger UI |
158
-
159
- ### ML Pipeline (DVC)
160
 
161
  ```bash
162
- dvc pull # Download datasets
163
- dvc repro # Reproduce preprocessing
164
- dvc push # Upload to remote storage
 
165
  ```
166
 
167
- ### Monitoring
168
 
169
- - **Prometheus** metrics at `/metrics`
170
- - **Grafana** dashboards for request volume, latency, error rate
171
- - **Evidently** drift detection (`scripts/drift_monitor.py`)
172
- - **MLflow** experiment tracking (`scripts/mlflow_ui.sh`)
173
 
174
- ---
175
 
176
- ## Development
 
 
 
177
 
178
- ### Run Tests
179
 
180
- ```bash
181
- make test # pytest
182
- make lint # ruff
183
- make typecheck # mypy
184
- make security # bandit
185
- ```
186
 
187
- ### Run Full Stack (Docker)
188
-
189
- ```bash
190
- docker compose -f docker/docker-compose.yml up --build
191
- ```
192
-
193
- Starts: API (8000), PostgreSQL, Redis, Celery worker, Prometheus (9090), Grafana (3001).
194
-
195
- ### Environment Variables
196
-
197
- Copy `.env.example` to `.env` and configure:
198
-
199
- | Variable | Required | Description |
200
- |----------|:--------:|-------------|
201
- | `DATABASE_URL` | ✅ | PostgreSQL or SQLite connection string |
202
- | `REDIS_URL` | ✅ | Redis connection for Celery |
203
- | `CORS_ORIGINS` | ❌ | Allowed CORS origins (default: localhost) |
204
- | `MODEL_PATH` | ❌ | Path to ONNX model directory |
205
- | `MAX_BATCH_SIZE` | ❌ | Max reviews per batch job |
206
- | `ADMIN_PASSWORD` | ❌ | Password for admin dashboard sections |
207
- | `API_BASE_URL` | ❌ | Base URL the dashboard uses to reach the API |
208
-
209
- ---
210
-
211
- ## Documentation
212
-
213
- | Document | Contents |
214
- |----------|----------|
215
- | [API](docs/API_DOCUMENTATION.md) | Full API reference with schemas and examples |
216
- | [Architecture](docs/architecture.md) | System design, data flow, deployment |
217
- | [Deployment](docs/DEPLOYMENT.md) | Production setup, Docker, Railway |
218
- | [Database](docs/DATABASE.md) | Schema, migrations, query patterns |
219
- | [Security](docs/SECURITY.md) | Threat model, audit results, mitigations |
220
- | [Tech Stack](docs/TECH_STACK.md) | Framework versions, rationale, trade-offs |
221
- | [System Design](docs/SYSTEM_DESIGN.md) | End-to-end design and data flow |
222
-
223
- ---
224
 
225
  ## License
226
 
227
- MIT License. See [LICENSE](LICENSE) for details.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Multilingual ABSA
3
+ emoji: 🎯
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 4.44.0
8
+ app_file: app.py
9
+ pinned: false
10
+ license: mit
 
 
 
 
 
 
 
 
 
11
  ---
12
 
13
+ # Multilingual ABSA
14
 
15
+ Real-time aspect-based sentiment analysis for English, Hindi, Hinglish product reviews.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ 🔗 **[Live Demo on Hugging Face Spaces](https://huggingface.co/spaces/Aryanmdev/multilingual-absa)**
18
+ 📦 [GitHub repo](https://github.com/Aryanmishra-dev/Multilingual-Absa)
19
 
20
+ ## Run Locally
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  ```bash
23
+ git clone https://github.com/Aryanmishra-dev/Multilingual-Absa
24
+ cd Multilingual-Absa
25
+ pip install -r requirements.txt
26
+ python app.py
27
  ```
28
 
29
+ Open http://localhost:7860
30
 
31
+ ## What it does
 
 
 
32
 
33
+ Extracts **aspects** (e.g. "battery", "camera") and their **sentiment** (positive/negative/neutral) from product reviews in 3 languages.
34
 
35
+ | Language | F1 | Latency p95 |
36
+ |----------|:--:|:-----------:|
37
+ | English | 78.1% | 185 ms |
38
+ | Hindi | 67.8% | 185 ms |
39
 
40
+ ONNX INT8 quantized → FP32 → rule-based fallback.
41
 
42
+ ## Stack
 
 
 
 
 
43
 
44
+ - Gradio 4.44 (UI)
45
+ - ONNX Runtime (inference)
46
+ - XLM-RoBERTa (multilingual backbone)
47
+ - SQLite (prediction history)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  ## License
50
 
51
+ MIT
api/core/__init__.py DELETED
File without changes
api/main.py DELETED
@@ -1,56 +0,0 @@
1
- import os
2
- from contextlib import asynccontextmanager
3
-
4
- from dotenv import load_dotenv
5
- from fastapi import FastAPI
6
- from fastapi.middleware.cors import CORSMiddleware
7
- from slowapi import Limiter, _rate_limit_exceeded_handler
8
- from slowapi.errors import RateLimitExceeded
9
- from slowapi.util import get_remote_address
10
-
11
- load_dotenv()
12
-
13
- from api.middleware.dependencies import engine # noqa: E402
14
- from api.middleware.metrics import instrumentator # noqa: E402
15
- from api.models.db_models import Base # noqa: E402
16
- from api.routes import predict, results # noqa: E402
17
- from api.services.absa_pipeline import pipeline # noqa: E402
18
-
19
-
20
- @asynccontextmanager
21
- async def lifespan(app: FastAPI):
22
- # Startup
23
- print("Initializing Database tables...")
24
- Base.metadata.create_all(bind=engine)
25
-
26
- print("Loading Models...")
27
- pipeline.load_models()
28
-
29
- yield
30
- # Shutdown
31
- print("Shutting down...")
32
-
33
-
34
- limiter = Limiter(key_func=get_remote_address)
35
-
36
- app = FastAPI(
37
- title="Multilingual ABSA API",
38
- description="Aspect-Based Sentiment Analysis for English and Hindi",
39
- version="1.0.0",
40
- lifespan=lifespan,
41
- )
42
-
43
- app.state.limiter = limiter
44
- app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) # type: ignore[arg-type]
45
-
46
- app.add_middleware(
47
- CORSMiddleware,
48
- allow_origins=os.getenv("CORS_ORIGINS", "http://localhost:8000,http://localhost:8501").split(","),
49
- allow_credentials=True,
50
- allow_methods=["GET", "POST"],
51
- allow_headers=["*"],
52
- )
53
- app.include_router(predict.router, tags=["Predict"])
54
- app.include_router(results.router, tags=["System"])
55
-
56
- instrumentator.instrument(app).expose(app, endpoint="/metrics")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/middleware/__init__.py DELETED
File without changes
api/middleware/dependencies.py DELETED
@@ -1,27 +0,0 @@
1
- import os
2
-
3
- from dotenv import load_dotenv
4
- from sqlalchemy import create_engine
5
- from sqlalchemy.orm import sessionmaker
6
-
7
- load_dotenv()
8
-
9
- DATABASE_URL = os.getenv("DATABASE_URL")
10
-
11
- if not DATABASE_URL:
12
- raise RuntimeError("DATABASE_URL environment variable is not set. Please set it in your .env file or environment.")
13
-
14
- connect_args = {}
15
- if DATABASE_URL.startswith("sqlite"):
16
- connect_args["check_same_thread"] = False
17
-
18
- engine = create_engine(DATABASE_URL, pool_pre_ping=True, connect_args=connect_args)
19
- SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
20
-
21
-
22
- def get_db():
23
- db = SessionLocal()
24
- try:
25
- yield db
26
- finally:
27
- db.close()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/middleware/metrics.py DELETED
@@ -1,12 +0,0 @@
1
- from prometheus_fastapi_instrumentator import Instrumentator
2
-
3
- instrumentator = Instrumentator(
4
- should_group_status_codes=False,
5
- should_ignore_untemplated=True,
6
- should_respect_env_var=True,
7
- should_instrument_requests_inprogress=True,
8
- excluded_handlers=[".*admin.*", "/metrics"],
9
- env_var_name="ENABLE_METRICS",
10
- inprogress_name="inprogress",
11
- inprogress_labels=True,
12
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
api/models/__init__.py DELETED
File without changes
api/py.typed DELETED
File without changes
api/routes/__init__.py DELETED
File without changes
api/routes/predict.py DELETED
@@ -1,129 +0,0 @@
1
- import os
2
- import re
3
- import tempfile
4
- import time
5
- import uuid
6
-
7
- import pandas as pd
8
- from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
9
- from sqlalchemy.orm import Session
10
-
11
- from api.middleware.dependencies import get_db
12
- from api.models.db_models import AspectResult, BatchJob, Review
13
- from api.schemas.schemas import BatchJobResponse, PredictionResponse, ReviewInput
14
- from api.services.absa_pipeline import pipeline
15
- from api.tasks.batch_tasks import process_batch
16
-
17
- router = APIRouter()
18
-
19
-
20
- @router.post("/predict", response_model=PredictionResponse)
21
- async def predict(request: ReviewInput, db: Session = Depends(get_db)):
22
- try:
23
- time.time()
24
-
25
- # Inference
26
- prediction = pipeline.predict(request.text, request.language)
27
-
28
- # Save to DB
29
- db_review = Review(
30
- text=prediction.text,
31
- language=prediction.language,
32
- processing_time_ms=prediction.processing_time_ms,
33
- )
34
- db.add(db_review)
35
- db.commit()
36
- db.refresh(db_review)
37
-
38
- for asp in prediction.aspects:
39
- db_aspect = AspectResult(
40
- review_id=db_review.id,
41
- aspect=asp.aspect,
42
- sentiment=asp.sentiment,
43
- confidence=asp.confidence,
44
- start_pos=asp.start,
45
- end_pos=asp.end,
46
- )
47
- db.add(db_aspect)
48
- db.commit()
49
-
50
- return prediction
51
- except Exception:
52
- raise HTTPException(status_code=500, detail="Model inference failed. Please try again.")
53
-
54
-
55
- @router.post("/batch", response_model=BatchJobResponse)
56
- async def predict_batch(file: UploadFile = File(...), db: Session = Depends(get_db)):
57
- max_upload_size = 50 * 1024 * 1024 # 50MB
58
-
59
- if not file.filename or not file.filename.endswith(".csv"):
60
- raise HTTPException(status_code=422, detail="Only CSV files are allowed.")
61
-
62
- if file.content_type and file.content_type not in ("text/csv", "application/vnd.ms-excel", "text/plain", ""):
63
- raise HTTPException(status_code=422, detail="Invalid file type. CSV required.")
64
-
65
- try:
66
- content = await file.read()
67
- if len(content) > max_upload_size:
68
- raise HTTPException(status_code=422, detail="File exceeds 50MB maximum size.")
69
-
70
- # Create temp file to read
71
- with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmp:
72
- tmp.write(content)
73
- tmp_path = tmp.name
74
-
75
- # Validate CSV structure before processing
76
- try:
77
- df = pd.read_csv(tmp_path, nrows=1)
78
- except Exception:
79
- os.unlink(tmp_path)
80
- raise HTTPException(status_code=422, detail="Invalid CSV format.")
81
-
82
- df = pd.read_csv(tmp_path)
83
- if "text" not in df.columns:
84
- os.unlink(tmp_path)
85
- raise HTTPException(status_code=422, detail="CSV must contain a 'text' column.")
86
-
87
- if len(df) > 10000:
88
- os.unlink(tmp_path)
89
- raise HTTPException(status_code=422, detail="Max 10,000 rows allowed per batch.")
90
-
91
- job_id_obj = uuid.uuid4()
92
- job_id = str(job_id_obj)
93
- db_job = BatchJob(id=job_id_obj, status="queued", total=len(df), processed=0)
94
- db.add(db_job)
95
- db.commit()
96
-
97
- # Queue Celery task
98
- process_batch.delay(job_id, tmp_path)
99
-
100
- return BatchJobResponse(job_id=job_id, status="queued", total_reviews=len(df), processed=0)
101
- except HTTPException:
102
- raise
103
- except Exception:
104
- raise HTTPException(status_code=500, detail="Batch processing failed. Please try again.")
105
-
106
-
107
- @router.get("/status/{job_id}", response_model=BatchJobResponse)
108
- async def get_batch_status(job_id: str, db: Session = Depends(get_db)):
109
- if not re.match(r"^[a-fA-F0-9\-]{36}$", job_id):
110
- raise HTTPException(status_code=400, detail="Invalid job ID format")
111
- try:
112
- job_id_uuid = uuid.UUID(job_id)
113
- except ValueError:
114
- raise HTTPException(status_code=400, detail="Invalid job ID format")
115
- job = db.query(BatchJob).filter(BatchJob.id == job_id_uuid).first()
116
- if not job:
117
- raise HTTPException(status_code=404, detail="Job not found")
118
-
119
- result_url = None
120
- if job.status == "completed":
121
- result_url = f"/results/download/{job_id}"
122
-
123
- return BatchJobResponse(
124
- job_id=str(job.id),
125
- status=job.status,
126
- total_reviews=job.total,
127
- processed=job.processed,
128
- result_url=result_url,
129
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/routes/results.py DELETED
@@ -1,39 +0,0 @@
1
- import os
2
- import re
3
- from pathlib import Path
4
- from typing import Dict
5
-
6
- from fastapi import APIRouter, HTTPException
7
- from fastapi.responses import FileResponse
8
-
9
- router = APIRouter()
10
-
11
- _RESULTS_DIR = Path("data/results").resolve()
12
-
13
-
14
- @router.get("/health")
15
- async def health_check() -> Dict[str, str]:
16
- # Basic health check
17
- return {"status": "ok", "model": "loaded", "db": "connected"}
18
-
19
-
20
- @router.get("/info")
21
- async def get_info() -> Dict[str, str]:
22
- return {
23
- "model_name": "xlm-roberta-base-absa",
24
- "version": "1.0",
25
- "supported_languages": "en, hi",
26
- "max_batch_size": os.getenv("MAX_BATCH_SIZE", "10000"),
27
- }
28
-
29
-
30
- @router.get("/download/{job_id}")
31
- async def download_result(job_id: str):
32
- if not re.match(r"^[a-fA-F0-9\-]{36}$", job_id):
33
- raise HTTPException(status_code=400, detail="Invalid job ID format")
34
- resolved = (_RESULTS_DIR / f"{job_id}.csv").resolve()
35
- if not str(resolved).startswith(str(_RESULTS_DIR)):
36
- raise HTTPException(status_code=400, detail="Invalid job ID")
37
- if not resolved.exists():
38
- raise HTTPException(status_code=404, detail="Result file not found")
39
- return FileResponse(path=resolved, filename=f"absa_results_{job_id}.csv", media_type="text/csv")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
api/schemas/__init__.py DELETED
File without changes
api/services/__init__.py DELETED
File without changes
api/tasks/__init__.py DELETED
@@ -1,12 +0,0 @@
1
- import os
2
-
3
- from celery import Celery
4
-
5
- redis_url = os.getenv("REDIS_URL", "redis://localhost:6379/0")
6
-
7
- celery_app = Celery("absa_tasks", broker=redis_url, backend=redis_url.replace("/0", "/1"))
8
-
9
- celery_app.conf.update(
10
- task_serializer="json",
11
- result_expires=3600,
12
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
api/tasks/batch_tasks.py DELETED
@@ -1,132 +0,0 @@
1
- import csv
2
- import os
3
- from datetime import datetime, timezone
4
-
5
- import pandas as pd
6
-
7
- from api.middleware.dependencies import SessionLocal
8
- from api.models.db_models import AspectResult, BatchJob, Review
9
- from api.services.absa_pipeline import pipeline
10
- from api.tasks import celery_app
11
-
12
-
13
- @celery_app.task(bind=True)
14
- def process_batch(self, job_id: str, file_path: str):
15
- db = SessionLocal()
16
- try:
17
- job = db.query(BatchJob).filter(BatchJob.id == job_id).first()
18
- if not job:
19
- return
20
-
21
- job.status = "processing"
22
- db.commit()
23
-
24
- # Load CSV
25
- df = pd.read_csv(file_path)
26
- if "text" not in df.columns:
27
- raise ValueError("CSV must contain a 'text' column.")
28
-
29
- texts = df["text"].tolist()
30
- batch_size = 32
31
-
32
- results_dir = "data/results"
33
- os.makedirs(results_dir, exist_ok=True)
34
- result_file = f"{results_dir}/{job_id}.csv"
35
-
36
- processed_count = 0
37
-
38
- with open(result_file, "w", newline="", encoding="utf-8") as f:
39
- writer = csv.writer(f)
40
- writer.writerow(
41
- [
42
- "text",
43
- "language",
44
- "aspect",
45
- "sentiment",
46
- "confidence",
47
- "start_pos",
48
- "end_pos",
49
- "processing_time_ms",
50
- ]
51
- )
52
-
53
- for i in range(0, len(texts), batch_size):
54
- batch_texts = texts[i : i + batch_size]
55
- predictions = pipeline.predict_batch(batch_texts)
56
-
57
- for pred in predictions:
58
- # Save Review
59
- db_review = Review(
60
- text=pred.text,
61
- language=pred.language,
62
- processing_time_ms=pred.processing_time_ms,
63
- )
64
- db.add(db_review)
65
- db.commit()
66
- db.refresh(db_review)
67
-
68
- # Save Aspects & CSV
69
- for asp in pred.aspects:
70
- db_aspect = AspectResult(
71
- review_id=db_review.id,
72
- aspect=asp.aspect,
73
- sentiment=asp.sentiment,
74
- confidence=asp.confidence,
75
- start_pos=asp.start,
76
- end_pos=asp.end,
77
- )
78
- db.add(db_aspect)
79
- writer.writerow(
80
- [
81
- pred.text,
82
- pred.language,
83
- asp.aspect,
84
- asp.sentiment,
85
- asp.confidence,
86
- asp.start,
87
- asp.end,
88
- pred.processing_time_ms,
89
- ]
90
- )
91
-
92
- if not pred.aspects:
93
- writer.writerow(
94
- [
95
- pred.text,
96
- pred.language,
97
- "",
98
- "",
99
- "",
100
- "",
101
- "",
102
- pred.processing_time_ms,
103
- ]
104
- )
105
-
106
- db.commit()
107
- processed_count += len(batch_texts)
108
-
109
- if processed_count % 100 == 0 or processed_count == len(texts):
110
- job.processed = processed_count
111
- db.commit()
112
-
113
- job.status = "completed"
114
- job.completed_at = datetime.now(timezone.utc)
115
- db.commit()
116
-
117
- except Exception:
118
- job = db.query(BatchJob).filter(BatchJob.id == job_id).first()
119
- if job:
120
- job.status = "failed"
121
- db.commit()
122
- import logging
123
-
124
- logging.exception("Batch processing failed for job %s", job_id)
125
- finally:
126
- # Clean up temp file
127
- try:
128
- if file_path and os.path.exists(file_path):
129
- os.unlink(file_path)
130
- except OSError:
131
- pass
132
- db.close()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Single-file Gradio app for Multilingual ABSA.
2
+
3
+ Loads the ONNX model (INT8 → FP32) with a rule-based fallback, runs inference
4
+ via ``absa.pipeline.ABSAPipeline``, persists predictions to SQLite, and serves
5
+ a Gradio (gr.Blocks) UI. Run with ``python app.py``.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ import os
12
+ import sys
13
+ import time
14
+ from datetime import datetime, timezone
15
+ from pathlib import Path
16
+ from typing import Any
17
+
18
+ import gradio as gr
19
+ from sqlalchemy import Column, DateTime, Float, Integer, String, create_engine
20
+ from sqlalchemy.orm import declarative_base, sessionmaker
21
+
22
+ # Make the src-layout `absa` package importable when run directly
23
+ # (e.g. `python app.py`) without a prior `pip install -e .`. All `absa`
24
+ # imports below are lazy, so this bootstrap runs before any of them.
25
+ _SRC_DIR = Path(__file__).resolve().parent / "src"
26
+ if str(_SRC_DIR) not in sys.path:
27
+ sys.path.insert(0, str(_SRC_DIR))
28
+
29
+ logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
30
+ _logger = logging.getLogger("absa.app")
31
+
32
+ # ── SQLAlchemy / SQLite ───────────────────────────────────────────────────
33
+ DB_PATH = "absa.db"
34
+ engine = create_engine(
35
+ f"sqlite:///{DB_PATH}",
36
+ connect_args={"check_same_thread": False},
37
+ )
38
+ Base = declarative_base()
39
+ Session = sessionmaker(bind=engine)
40
+
41
+
42
+ def _utcnow() -> datetime:
43
+ return datetime.now(timezone.utc)
44
+
45
+
46
+ class Prediction(Base):
47
+ """One aspect-sentiment pair extracted from a single review."""
48
+
49
+ __tablename__ = "predictions"
50
+
51
+ id = Column(Integer, primary_key=True)
52
+ text = Column(String, nullable=False)
53
+ language = Column(String, nullable=False)
54
+ aspect = Column(String, nullable=False)
55
+ sentiment = Column(String, nullable=False)
56
+ confidence = Column(Float, nullable=False)
57
+ created_at = Column(DateTime, default=_utcnow)
58
+
59
+
60
+ Base.metadata.create_all(engine)
61
+
62
+ # ── Lazy, failure-tolerant model loading ──────────────────────────────────
63
+ # Module-level singleton (cached for the app lifetime). If the ONNX models
64
+ # are missing the pipeline degrades to the rule-based engine — never crashes.
65
+
66
+ DEFAULT_MODEL_PATH = Path(os.getenv("MODEL_PATH", "models/onnx"))
67
+
68
+
69
+ def _load_pipeline() -> Any:
70
+ """Import the ABSA pipeline lazily and attempt custom ONNX model load."""
71
+ try:
72
+ from absa.pipeline.absa_pipeline import ABSAPipeline
73
+ except Exception as exc: # pragma: no cover - import-time guard
74
+ _logger.error("Could not import ABSA pipeline: %s", exc)
75
+ raise
76
+
77
+ pipelin = ABSAPipeline()
78
+ try:
79
+ pipelin.load_models()
80
+ except Exception as exc:
81
+ _logger.warning("Custom model load failed (%s); using rule-based engine.", exc)
82
+ return pipelin
83
+
84
+
85
+ PIPELINE = _load_pipeline()
86
+
87
+
88
+ def _inference_mode() -> str:
89
+ """Report which engine is active: ONNX INT8 / ONNX FP32 / rule-based."""
90
+ if PIPELINE.aspect_model is not None:
91
+ if (DEFAULT_MODEL_PATH / "aspect_extraction_int8").exists():
92
+ return "ONNX INT8"
93
+ if (DEFAULT_MODEL_PATH / "aspect_extraction").exists():
94
+ return "ONNX FP32"
95
+ return "ONNX"
96
+ return "rule-based"
97
+
98
+
99
+ MODE = _inference_mode()
100
+
101
+
102
+ def get_count() -> int:
103
+ """Total predictions in SQLite."""
104
+ try:
105
+ session = Session()
106
+ return session.query(Prediction).count()
107
+ except Exception:
108
+ return 0
109
+ finally:
110
+ session.close()
111
+
112
+
113
+ def get_history_rows() -> list[list]:
114
+ """Return last 50 predictions as DataFrame rows."""
115
+ try:
116
+ session = Session()
117
+ rows = session.query(Prediction).order_by(Prediction.id.desc()).limit(50).all()
118
+ return [
119
+ [
120
+ r.created_at.strftime("%Y-%m-%d %H:%M") if r.created_at else "—",
121
+ r.language or "—",
122
+ r.aspect or "—",
123
+ r.sentiment or "—",
124
+ round(r.confidence, 3) if r.confidence else 0.0,
125
+ (r.text[:60] + "...") if r.text and len(r.text) > 60 else (r.text or "—"),
126
+ ]
127
+ for r in rows
128
+ ]
129
+ except Exception:
130
+ return []
131
+ finally:
132
+ session.close()
133
+
134
+
135
+ def get_history_md() -> str:
136
+ return f"Showing last 50 predictions · Total: **{get_count()}**"
137
+
138
+
139
+ def clear_history() -> tuple[str, list]:
140
+ """Wipe predictions table."""
141
+ try:
142
+ session = Session()
143
+ session.query(Prediction).delete()
144
+ session.commit()
145
+ except Exception:
146
+ pass
147
+ finally:
148
+ session.close()
149
+ return "History cleared · Total: **0**", []
150
+
151
+
152
+ def on_analyze(text: str) -> tuple[str, str, str, Any, list]:
153
+ """Run inference, save to DB, return formatted UI outputs."""
154
+ if not text or not text.strip():
155
+ return (
156
+ '<div class="meta-badges"><span class="badge">Detected Language: <strong>—</strong></span><span class="badge">Latency: <strong>—</strong></span></div>',
157
+ '<div class="summary-vis empty">Please enter a review to analyze.</div>',
158
+ '<div class="empty-state">No analysis yet.</div>',
159
+ gr.update(visible=False, value={})
160
+ )
161
+
162
+ start = time.time()
163
+ try:
164
+ response = PIPELINE.predict(text)
165
+ aspects = response.aspects if hasattr(response, "aspects") else response.get("aspects", [])
166
+ language = response.detected_language if hasattr(response, "detected_language") else response.get("detected_language", "unknown")
167
+ elapsed_ms = (time.time() - start) * 1000
168
+ except Exception as e:
169
+ return (
170
+ '<div class="meta-badges"><span class="badge">Detected Language: <strong>Error</strong></span><span class="badge">Latency: <strong>—</strong></span></div>',
171
+ '<div class="summary-vis empty">Error during analysis.</div>',
172
+ f'<div class="empty-state" style="color:#DC2626;">Unable to analyze this review: {str(e)[:120]}</div>',
173
+ gr.update(visible=False, value={})
174
+ )
175
+
176
+ lang_display = {
177
+ "en": "English", "english": "English",
178
+ "hi": "Hindi", "hindi": "Hindi",
179
+ "hinglish": "Hinglish", "hi-en": "Hinglish",
180
+ }.get(str(language).lower(), str(language).title())
181
+
182
+ meta_md = f'<div class="meta-badges"><span class="badge">Detected Language: <strong>{lang_display}</strong></span><span class="badge">Latency: <strong>{elapsed_ms:.0f} ms</strong></span></div>'
183
+
184
+ pos_count = neg_count = neu_count = 0
185
+ table_rows = ""
186
+ for a in aspects:
187
+ aspect_text = a.get("aspect", "") if isinstance(a, dict) else getattr(a, "aspect", "")
188
+ sentiment = a.get("sentiment", "neutral") if isinstance(a, dict) else getattr(a, "sentiment", "neutral")
189
+ confidence = float(a.get("confidence", 0.0) if isinstance(a, dict) else getattr(a, "confidence", 0.0))
190
+
191
+ if sentiment == "positive":
192
+ pos_count += 1
193
+ sent_color = "#16A34A"
194
+ sent_label = "Positive"
195
+ elif sentiment == "negative":
196
+ neg_count += 1
197
+ sent_color = "#DC2626"
198
+ sent_label = "Negative"
199
+ else:
200
+ neu_count += 1
201
+ sent_color = "#64748B"
202
+ sent_label = "Neutral"
203
+
204
+ conf_pct = int(confidence * 100)
205
+
206
+ table_rows += f"""
207
+ <tr>
208
+ <td class="aspect-col">{aspect_text}</td>
209
+ <td class="sentiment-col">
210
+ <span class="sent-dot" style="background-color: {sent_color};"></span>
211
+ <span style="color: {sent_color}; font-weight: 600;">{sent_label}</span>
212
+ </td>
213
+ <td class="conf-col">
214
+ <div class="conf-bar-bg"><div class="conf-bar-fill" style="width: {conf_pct}%;"></div></div>
215
+ <span class="conf-val">{conf_pct}%</span>
216
+ </td>
217
+ </tr>
218
+ """
219
+
220
+ if not aspects:
221
+ results_html = '<div class="empty-state">No aspects detected in this review.</div>'
222
+ else:
223
+ results_html = f"""
224
+ <table class="results-table">
225
+ <thead>
226
+ <tr>
227
+ <th>Aspect</th>
228
+ <th>Sentiment</th>
229
+ <th>Confidence</th>
230
+ </tr>
231
+ </thead>
232
+ <tbody>
233
+ {table_rows}
234
+ </tbody>
235
+ </table>
236
+ """
237
+
238
+ total = len(aspects)
239
+
240
+ # Visualization blocks
241
+ vis_pos = f'Positive <span class="vis-block pos">{"█" * pos_count}</span> {pos_count}' if pos_count else 'Positive <span class="vis-block empty-block"></span> 0'
242
+ vis_neg = f'Negative <span class="vis-block neg">{"█" * neg_count}</span> {neg_count}' if neg_count else 'Negative <span class="vis-block empty-block"></span> 0'
243
+ vis_neu = f'Neutral <span class="vis-block neu">{"█" * neu_count}</span> {neu_count}' if neu_count else 'Neutral <span class="vis-block empty-block"></span> 0'
244
+
245
+ summary_md = f"""
246
+ <div class="summary-vis">
247
+ <div class="summary-title">{total} Aspects</div>
248
+ <div class="vis-row">{vis_pos}</div>
249
+ <div class="vis-row">{vis_neg}</div>
250
+ <div class="vis-row">{vis_neu}</div>
251
+ </div>
252
+ """
253
+
254
+ # Save to SQLite
255
+ try:
256
+ session = Session()
257
+ for a in aspects:
258
+ aspect_text = a.get("aspect", "") if isinstance(a, dict) else getattr(a, "aspect", "")
259
+ sentiment = a.get("sentiment", "neutral") if isinstance(a, dict) else getattr(a, "sentiment", "neutral")
260
+ confidence = a.get("confidence", 0.0) if isinstance(a, dict) else getattr(a, "confidence", 0.0)
261
+ session.add(Prediction(
262
+ text=text,
263
+ language=lang_display,
264
+ aspect=aspect_text,
265
+ sentiment=sentiment,
266
+ confidence=float(confidence or 0.0),
267
+ ))
268
+ session.commit()
269
+ except Exception:
270
+ pass
271
+ finally:
272
+ session.close()
273
+
274
+ return (meta_md, summary_md, results_html, gr.update(visible=True, value=aspects))
275
+
276
+
277
+ # ── Gradio UI (gr.Blocks) ─────────────────────────────────────────────────
278
+
279
+ custom_theme = gr.themes.Soft(
280
+ primary_hue=gr.themes.colors.blue,
281
+ secondary_hue=gr.themes.colors.slate,
282
+ neutral_hue=gr.themes.colors.slate,
283
+ font=gr.themes.GoogleFont("Inter"),
284
+ ).set(
285
+ body_background_fill="#F8FAFC",
286
+ body_background_fill_dark="#F8FAFC",
287
+ body_text_color="#0F172A",
288
+ body_text_color_dark="#0F172A",
289
+ block_background_fill="#FFFFFF",
290
+ block_background_fill_dark="#FFFFFF",
291
+ block_border_color="#E2E8F0",
292
+ block_border_color_dark="#E2E8F0",
293
+ block_label_background_fill="#FFFFFF",
294
+ block_label_background_fill_dark="#FFFFFF",
295
+ block_label_text_color="#0F172A",
296
+ block_label_text_color_dark="#0F172A",
297
+ button_primary_background_fill="#2563EB",
298
+ button_primary_background_fill_dark="#2563EB",
299
+ button_primary_text_color="#FFFFFF",
300
+ button_primary_text_color_dark="#FFFFFF",
301
+ button_primary_border_color="#2563EB",
302
+ button_primary_border_color_dark="#2563EB",
303
+ button_secondary_background_fill="#FFFFFF",
304
+ button_secondary_background_fill_dark="#FFFFFF",
305
+ button_secondary_text_color="#0F172A",
306
+ button_secondary_text_color_dark="#0F172A",
307
+ button_secondary_border_color="#CBD5E1",
308
+ button_secondary_border_color_dark="#CBD5E1",
309
+ input_background_fill="#FFFFFF",
310
+ input_background_fill_dark="#FFFFFF",
311
+ input_border_color="#CBD5E1",
312
+ input_border_color_dark="#CBD5E1",
313
+ panel_background_fill="#FFFFFF",
314
+ panel_background_fill_dark="#FFFFFF",
315
+ table_even_background_fill="#F8FAFC",
316
+ table_even_background_fill_dark="#F8FAFC",
317
+ table_odd_background_fill="#FFFFFF",
318
+ table_odd_background_fill_dark="#FFFFFF",
319
+ table_border_color="#E2E8F0",
320
+ table_border_color_dark="#E2E8F0",
321
+ border_color_primary="#E2E8F0",
322
+ border_color_primary_dark="#E2E8F0",
323
+ color_accent_soft="#EFF6FF",
324
+ color_accent_soft_dark="#EFF6FF",
325
+ )
326
+
327
+ with gr.Blocks(title="Multilingual ABSA") as demo:
328
+
329
+ # TOP HEADER
330
+ with gr.Row(elem_classes="top-header"):
331
+ with gr.Column(scale=3, elem_classes="header-title-col"):
332
+ gr.Markdown("""
333
+ <div class="header-content">
334
+ <h1>Multilingual ABSA</h1>
335
+ <div class="header-subtitle">Aspect-Based Sentiment Analysis for English, Hindi, and Hinglish</div>
336
+ </div>
337
+ """)
338
+ with gr.Column(scale=2, elem_classes="header-metrics-col"):
339
+ gr.Markdown(f"""
340
+ <div class="header-metrics">
341
+ <div class="metric"><span class="m-label">MODE</span><span class="m-val">{MODE}</span></div>
342
+ <div class="metric"><span class="m-label">LANGUAGES</span><span class="m-val">English · Hindi · Hinglish</span></div>
343
+ <div class="metric"><span class="m-label">PREDICTIONS</span><span class="m-val">{get_count()}</span></div>
344
+ <div class="metric"><span class="m-label">STATUS</span><span class="m-val"><span class="status-dot">●</span> Ready</span></div>
345
+ </div>
346
+ """)
347
+
348
+ # WORKSPACE
349
+ with gr.Tabs(elem_classes="main-tabs"):
350
+ with gr.Tab("Workspace"):
351
+ with gr.Row(elem_classes="workspace-row"):
352
+
353
+ # LEFT PANEL
354
+ with gr.Column(scale=1, elem_classes="panel panel-left"):
355
+ gr.Markdown('<div class="section-title">Analyze Review</div><div class="section-sub">Enter a product review to identify aspects and their sentiment.</div>')
356
+
357
+ inp = gr.Textbox(
358
+ label="",
359
+ placeholder="Example: The battery life is amazing, but the camera quality is poor.",
360
+ lines=6,
361
+ max_lines=15,
362
+ elem_classes="review-input",
363
+ show_label=False,
364
+ )
365
+
366
+ btn = gr.Button("Analyze Review", variant="primary", elem_classes="analyze-btn")
367
+
368
+ gr.Markdown('<div class="section-title" style="margin-top: 32px; font-size: 0.85rem;">Examples</div>')
369
+ gr.Examples(
370
+ examples=[
371
+ ["The battery life is amazing but the camera quality is poor."],
372
+ ["बैटरी बहुत अच्छी है लेकिन कैमरा क्वालिटी खराब है।"],
373
+ ["Battery life mast hai lekin camera quality bahut bekar hai."],
374
+ ],
375
+ inputs=inp,
376
+ label=""
377
+ )
378
+
379
+ # RIGHT PANEL
380
+ with gr.Column(scale=1, elem_classes="panel panel-right"):
381
+ gr.Markdown('<div class="section-title">Analysis Results</div>')
382
+
383
+ meta_md = gr.Markdown('<div class="meta-badges"><span class="badge">Detected Language: <strong>Waiting</strong></span><span class="badge">Latency: <strong>—</strong></span></div>')
384
+ summary_md = gr.Markdown('<div class="summary-vis empty">Waiting for analysis...</div>')
385
+ results_html = gr.HTML('<div class="empty-state">No analysis yet.</div>')
386
+
387
+ with gr.Accordion("Raw Model Output", open=False, elem_classes="raw-accordion"):
388
+ json_out = gr.JSON(label="", visible=False, elem_classes="raw-json")
389
+
390
+ btn.click(
391
+ fn=lambda: (
392
+ '<div class="meta-badges"><span class="badge">Detected Language: <strong>Analyzing...</strong></span><span class="badge">Latency: <strong>—</strong></span></div>',
393
+ '<div class="summary-vis empty">Analyzing review...</div>',
394
+ '<div class="empty-state">Analyzing...</div>'
395
+ ),
396
+ outputs=[meta_md, summary_md, results_html]
397
+ ).then(
398
+ fn=on_analyze,
399
+ inputs=inp,
400
+ outputs=[meta_md, summary_md, results_html, json_out]
401
+ )
402
+
403
+ # HISTORY TAB
404
+ with gr.Tab("History"):
405
+ with gr.Row():
406
+ refresh_btn = gr.Button("Refresh Data", size="sm", variant="secondary")
407
+ clear_btn = gr.Button("Clear History", size="sm", variant="secondary")
408
+
409
+ history_df = gr.Dataframe(
410
+ headers=["Timestamp", "Language", "Aspect", "Sentiment", "Confidence", "Review Preview"],
411
+ datatype=["str", "str", "str", "str", "number", "str"],
412
+ value=get_history_rows(),
413
+ interactive=False,
414
+ wrap=True,
415
+ elem_classes="history-table"
416
+ )
417
+
418
+ # Now we can attach the `.then` to update history_df
419
+ btn.click(fn=lambda: None).then(fn=get_history_rows, outputs=history_df)
420
+
421
+ refresh_btn.click(fn=get_history_rows, outputs=history_df)
422
+ clear_btn.click(fn=clear_history, outputs=[history_df]).then(fn=get_history_rows, outputs=history_df)
423
+
424
+ custom_css = """
425
+ /* 60/30/10 Design System */
426
+
427
+ /* Layout & Base */
428
+ .gradio-container { max-width: 1200px !important; margin: auto; font-family: 'Inter', sans-serif; padding: 24px !important; }
429
+
430
+ /* Typography */
431
+ .section-title { font-size: 1.1rem; font-weight: 600; color: #0F172A; margin-bottom: 4px; }
432
+ .section-sub { font-size: 0.9rem; color: #64748B; margin-bottom: 16px; }
433
+
434
+ /* Top Header */
435
+ .top-header { border-bottom: 1px solid #E2E8F0; padding-bottom: 16px; margin-bottom: 24px; align-items: center; }
436
+ .header-content h1 { font-size: 1.6rem; font-weight: 600; color: #0F172A; margin: 0 0 4px 0; letter-spacing: -0.02em; }
437
+ .header-subtitle { font-size: 0.9rem; color: #64748B; }
438
+
439
+ /* Header Metrics */
440
+ .header-metrics { display: flex; gap: 24px; justify-content: flex-end; flex-wrap: wrap; }
441
+ .metric { display: flex; flex-direction: column; }
442
+ .m-label { font-size: 0.65rem; font-weight: 600; color: #64748B; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px; }
443
+ .m-val { font-size: 0.85rem; font-weight: 500; color: #0F172A; }
444
+ .status-dot { color: #16A34A; margin-right: 4px; }
445
+
446
+ /* Panels */
447
+ .workspace-row { gap: 32px !important; align-items: flex-start !important; }
448
+ .panel { background: #FFFFFF; border: 1px solid #E2E8F0; border-radius: 8px; padding: 24px; box-shadow: 0 1px 2px rgba(0,0,0,0.02); }
449
+
450
+ /* Review Input */
451
+ .review-input textarea { border: 1px solid #CBD5E1 !important; border-radius: 6px !important; padding: 12px !important; font-size: 0.95rem !important; line-height: 1.5 !important; background: #FFFFFF !important; color: #0F172A !important; transition: border-color 0.2s; box-shadow: none !important; }
452
+ .review-input textarea:focus { border-color: #2563EB !important; ring: 1px solid #2563EB !important; }
453
+ .analyze-btn { background: #2563EB !important; color: #FFFFFF !important; font-weight: 500 !important; border-radius: 6px !important; margin-top: 16px !important; padding: 10px 0 !important; border: none !important; transition: background 0.2s !important; }
454
+ .analyze-btn:hover { background: #1D4ED8 !important; }
455
+
456
+ /* Examples */
457
+ .compact-examples .gallery { gap: 8px !important; }
458
+ .compact-examples button { border: 1px solid #E2E8F0 !important; border-radius: 6px !important; padding: 8px 12px !important; font-size: 0.8rem !important; background: #F8FAFC !important; color: #475569 !important; text-align: left !important; }
459
+ .compact-examples button:hover { background: #F1F5F9 !important; border-color: #CBD5E1 !important; }
460
+
461
+ /* Meta Badges */
462
+ .meta-badges { display: flex; gap: 12px; margin-bottom: 24px; }
463
+ .badge { font-size: 0.75rem; background: #F1F5F9; color: #475569; padding: 4px 10px; border-radius: 4px; border: 1px solid #E2E8F0; }
464
+ .badge strong { color: #0F172A; font-weight: 600; margin-left: 4px; }
465
+
466
+ /* Summary Vis */
467
+ .summary-vis { margin-bottom: 24px; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.8rem; }
468
+ .summary-title { font-family: 'Inter', sans-serif; font-size: 0.9rem; font-weight: 600; color: #0F172A; margin-bottom: 12px; border-bottom: 1px solid #E2E8F0; padding-bottom: 8px; }
469
+ .vis-row { margin-bottom: 6px; display: flex; align-items: center; gap: 12px; color: #475569; }
470
+ .vis-block { letter-spacing: -1px; font-size: 0.7rem; }
471
+ .vis-block.pos { color: #16A34A; }
472
+ .vis-block.neg { color: #DC2626; }
473
+ .vis-block.neu { color: #64748B; }
474
+ .vis-block.empty-block { visibility: hidden; width: 10px; }
475
+ .summary-vis.empty { font-family: 'Inter', sans-serif; color: #64748B; font-style: italic; }
476
+
477
+ /* Results Table */
478
+ .results-table { width: 100%; border-collapse: collapse; margin-bottom: 16px; font-size: 0.85rem; }
479
+ .results-table th { text-align: left; padding: 8px 12px; border-bottom: 1px solid #E2E8F0; color: #64748B; font-weight: 600; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; }
480
+ .results-table td { padding: 12px; border-bottom: 1px solid #F1F5F9; color: #0F172A; }
481
+ .aspect-col { font-weight: 500; }
482
+ .sentiment-col { display: flex; align-items: center; gap: 6px; }
483
+ .sent-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
484
+
485
+ /* Confidence Bar */
486
+ .conf-col { min-width: 120px; }
487
+ .conf-bar-bg { width: 60px; height: 6px; background: #E2E8F0; border-radius: 3px; display: inline-block; vertical-align: middle; margin-right: 8px; overflow: hidden; }
488
+ .conf-bar-fill { height: 100%; background: #2563EB; border-radius: 3px; }
489
+ .conf-val { font-family: ui-monospace, monospace; font-size: 0.8rem; color: #475569; }
490
+
491
+ .empty-state { padding: 32px 0; text-align: center; color: #64748B; font-size: 0.9rem; border: 1px dashed #CBD5E1; border-radius: 6px; }
492
+
493
+ /* Raw Output Accordion */
494
+ .raw-accordion { margin-top: 24px !important; border: 1px solid #E2E8F0 !important; border-radius: 6px !important; overflow: hidden !important; background: #FFFFFF !important; }
495
+ .raw-accordion .label-wrap { padding: 12px 16px !important; font-size: 0.85rem !important; font-weight: 600 !important; color: #0F172A !important; background: #F8FAFC !important; border-bottom: 1px solid #E2E8F0 !important; }
496
+ .raw-accordion .raw-json { background: #0F172A !important; padding: 16px !important; margin: 0 !important; }
497
+ .raw-accordion .raw-json * { color: #F8FAFC !important; font-family: ui-monospace, SFMono-Regular, monospace !important; font-size: 0.8rem !important; }
498
+
499
+ /* History Table */
500
+ .history-table { border: 1px solid #E2E8F0 !important; border-radius: 8px !important; overflow: hidden !important; margin-top: 16px !important; }
501
+ .history-table th { background: #F8FAFC !important; color: #475569 !important; font-size: 0.75rem !important; text-transform: uppercase !important; font-weight: 600 !important; }
502
+
503
+ /* Mobile Stacking */
504
+ @media (max-width: 768px) {
505
+ .workspace-row { flex-direction: column !important; }
506
+ .panel { width: 100% !important; }
507
+ .header-metrics { justify-content: flex-start; margin-top: 16px; }
508
+ }
509
+ """
510
+
511
+ if __name__ == "__main__":
512
+ demo.launch(theme=custom_theme, css=custom_css)
coverage.xml CHANGED
@@ -1,728 +1,199 @@
1
  <?xml version="1.0" ?>
2
- <coverage version="7.14.0" timestamp="1786277891188" lines-valid="1482" lines-covered="432" line-rate="0.2915" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
3
  <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.14.0 -->
4
  <!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
5
  <sources>
6
  <source>/Users/theogengineer/Projects/Multilingual-Absa</source>
7
- <source>/Users/theogengineer/Projects/Multilingual-Absa/api</source>
8
  </sources>
9
  <packages>
10
- <package name="." line-rate="1" branch-rate="0" complexity="0">
11
- <classes>
12
- <class name="__init__.py" filename="__init__.py" complexity="0" line-rate="1" branch-rate="0">
13
- <methods/>
14
- <lines/>
15
- </class>
16
- <class name="main.py" filename="main.py" complexity="0" line-rate="1" branch-rate="0">
17
- <methods/>
18
- <lines>
19
- <line number="1" hits="1"/>
20
- <line number="2" hits="1"/>
21
- <line number="4" hits="1"/>
22
- <line number="5" hits="1"/>
23
- <line number="6" hits="1"/>
24
- <line number="7" hits="1"/>
25
- <line number="8" hits="1"/>
26
- <line number="9" hits="1"/>
27
- <line number="11" hits="1"/>
28
- <line number="13" hits="1"/>
29
- <line number="14" hits="1"/>
30
- <line number="15" hits="1"/>
31
- <line number="16" hits="1"/>
32
- <line number="17" hits="1"/>
33
- <line number="20" hits="1"/>
34
- <line number="21" hits="1"/>
35
- <line number="23" hits="1"/>
36
- <line number="24" hits="1"/>
37
- <line number="26" hits="1"/>
38
- <line number="27" hits="1"/>
39
- <line number="29" hits="1"/>
40
- <line number="31" hits="1"/>
41
- <line number="34" hits="1"/>
42
- <line number="36" hits="1"/>
43
- <line number="43" hits="1"/>
44
- <line number="44" hits="1"/>
45
- <line number="46" hits="1"/>
46
- <line number="53" hits="1"/>
47
- <line number="54" hits="1"/>
48
- <line number="56" hits="1"/>
49
- </lines>
50
- </class>
51
- </classes>
52
- </package>
53
- <package name="core" line-rate="1" branch-rate="0" complexity="0">
54
  <classes>
55
- <class name="__init__.py" filename="core/__init__.py" complexity="0" line-rate="1" branch-rate="0">
56
  <methods/>
57
  <lines/>
58
  </class>
59
  </classes>
60
  </package>
61
- <package name="middleware" line-rate="0.95" branch-rate="0" complexity="0">
62
  <classes>
63
- <class name="__init__.py" filename="middleware/__init__.py" complexity="0" line-rate="1" branch-rate="0">
64
  <methods/>
65
  <lines/>
66
  </class>
67
- <class name="dependencies.py" filename="middleware/dependencies.py" complexity="0" line-rate="0.9444" branch-rate="0">
68
  <methods/>
69
  <lines>
70
- <line number="1" hits="1"/>
71
- <line number="2" hits="1"/>
72
- <line number="3" hits="1"/>
73
- <line number="4" hits="1"/>
74
- <line number="6" hits="1"/>
75
- <line number="8" hits="1"/>
76
- <line number="10" hits="1"/>
77
  <line number="11" hits="0"/>
78
- <line number="16" hits="1"/>
79
- <line number="17" hits="1"/>
80
- <line number="18" hits="1"/>
81
- <line number="20" hits="1"/>
82
- <line number="21" hits="1"/>
83
- <line number="25" hits="1"/>
84
- <line number="26" hits="1"/>
85
- <line number="27" hits="1"/>
86
- <line number="28" hits="1"/>
87
- <line number="30" hits="1"/>
88
- </lines>
89
- </class>
90
- <class name="metrics.py" filename="middleware/metrics.py" complexity="0" line-rate="1" branch-rate="0">
91
- <methods/>
92
- <lines>
93
- <line number="1" hits="1"/>
94
- <line number="3" hits="1"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  </lines>
96
  </class>
97
- </classes>
98
- </package>
99
- <package name="routes" line-rate="0.6574" branch-rate="0" complexity="0">
100
- <classes>
101
- <class name="__init__.py" filename="routes/__init__.py" complexity="0" line-rate="1" branch-rate="0">
102
- <methods/>
103
- <lines/>
104
- </class>
105
- <class name="predict.py" filename="routes/predict.py" complexity="0" line-rate="0.6463" branch-rate="0">
106
  <methods/>
107
  <lines>
108
  <line number="1" hits="1"/>
109
  <line number="2" hits="1"/>
110
- <line number="3" hits="1"/>
111
- <line number="4" hits="1"/>
112
  <line number="5" hits="1"/>
113
- <line number="6" hits="1"/>
114
- <line number="7" hits="1"/>
115
- <line number="8" hits="1"/>
116
- <line number="10" hits="1"/>
117
- <line number="11" hits="1"/>
118
- <line number="12" hits="1"/>
119
- <line number="13" hits="1"/>
120
- <line number="14" hits="1"/>
121
- <line number="15" hits="1"/>
122
  <line number="18" hits="1"/>
123
  <line number="19" hits="1"/>
124
  <line number="20" hits="1"/>
125
- <line number="21" hits="1"/>
126
- <line number="24" hits="1"/>
127
- <line number="27" hits="1"/>
128
- <line number="32" hits="1"/>
129
- <line number="33" hits="1"/>
130
  <line number="34" hits="1"/>
131
- <line number="36" hits="1"/>
132
  <line number="37" hits="1"/>
133
- <line number="45" hits="1"/>
134
- <line number="46" hits="1"/>
 
 
 
 
135
  <line number="48" hits="1"/>
136
- <line number="49" hits="0"/>
137
- <line number="50" hits="0"/>
 
138
  <line number="53" hits="1"/>
139
- <line number="54" hits="1"/>
140
- <line number="55" hits="1"/>
141
- <line number="57" hits="1"/>
142
- <line number="58" hits="0"/>
143
  <line number="60" hits="1"/>
144
- <line number="61" hits="0"/>
145
  <line number="63" hits="1"/>
146
- <line number="64" hits="1"/>
147
- <line number="65" hits="1"/>
148
- <line number="66" hits="0"/>
149
- <line number="69" hits="1"/>
150
- <line number="70" hits="1"/>
151
  <line number="71" hits="1"/>
152
- <line number="74" hits="1"/>
153
- <line number="75" hits="1"/>
154
- <line number="76" hits="0"/>
155
- <line number="77" hits="0"/>
156
- <line number="78" hits="0"/>
157
- <line number="80" hits="1"/>
158
- <line number="81" hits="1"/>
159
- <line number="82" hits="0"/>
160
- <line number="83" hits="0"/>
161
  <line number="87" hits="1"/>
162
- <line number="88" hits="0"/>
163
- <line number="89" hits="0"/>
 
 
164
  <line number="93" hits="1"/>
165
  <line number="94" hits="1"/>
166
  <line number="95" hits="1"/>
167
  <line number="96" hits="1"/>
168
  <line number="97" hits="1"/>
169
- <line number="100" hits="1"/>
170
  <line number="102" hits="1"/>
171
- <line number="105" hits="0"/>
172
- <line number="106" hits="0"/>
 
173
  <line number="107" hits="0"/>
174
- <line number="108" hits="0"/>
175
- <line number="113" hits="1"/>
176
- <line number="114" hits="1"/>
177
- <line number="115" hits="0"/>
178
- <line number="116" hits="0"/>
179
- <line number="117" hits="0"/>
180
- <line number="118" hits="0"/>
181
- <line number="119" hits="0"/>
182
- <line number="120" hits="0"/>
183
- <line number="121" hits="0"/>
184
- <line number="122" hits="0"/>
185
- <line number="123" hits="0"/>
186
- <line number="125" hits="0"/>
187
- <line number="126" hits="0"/>
188
- <line number="127" hits="0"/>
189
- <line number="129" hits="0"/>
190
  </lines>
191
  </class>
192
- <class name="results.py" filename="routes/results.py" complexity="0" line-rate="0.6923" branch-rate="0">
193
  <methods/>
194
  <lines>
195
- <line number="1" hits="1"/>
196
- <line number="2" hits="1"/>
197
- <line number="3" hits="1"/>
198
- <line number="5" hits="1"/>
199
- <line number="8" hits="1"/>
200
- <line number="9" hits="1"/>
201
- <line number="11" hits="1"/>
202
- <line number="14" hits="1"/>
203
- <line number="15" hits="1"/>
204
- <line number="16" hits="1"/>
205
- <line number="23" hits="1"/>
206
- <line number="24" hits="1"/>
207
- <line number="25" hits="1"/>
208
- <line number="26" hits="1"/>
209
- <line number="27" hits="1"/>
210
- <line number="29" hits="1"/>
211
- <line number="31" hits="1"/>
212
- <line number="32" hits="1"/>
 
213
  <line number="33" hits="0"/>
214
- <line number="34" hits="0"/>
215
  <line number="35" hits="0"/>
216
- <line number="36" hits="0"/>
217
  <line number="37" hits="0"/>
218
- <line number="38" hits="0"/>
219
- <line number="39" hits="0"/>
220
- <line number="40" hits="0"/>
221
- </lines>
222
- </class>
223
- </classes>
224
- </package>
225
- <package name="schemas" line-rate="1" branch-rate="0" complexity="0">
226
- <classes>
227
- <class name="__init__.py" filename="schemas/__init__.py" complexity="0" line-rate="1" branch-rate="0">
228
- <methods/>
229
- <lines/>
230
- </class>
231
- <class name="db_models.py" filename="schemas/db_models.py" complexity="0" line-rate="1" branch-rate="0">
232
- <methods/>
233
- <lines>
234
- <line number="1" hits="1"/>
235
- <line number="2" hits="1"/>
236
- <line number="3" hits="1"/>
237
- <line number="4" hits="1"/>
238
- <line number="6" hits="1"/>
239
- <line number="9" hits="1"/>
240
- <line number="10" hits="1"/>
241
- <line number="12" hits="1"/>
242
- <line number="13" hits="1"/>
243
- <line number="14" hits="1"/>
244
- <line number="15" hits="1"/>
245
- <line number="18" hits="1"/>
246
- <line number="21" hits="1"/>
247
- <line number="22" hits="1"/>
248
- <line number="24" hits="1"/>
249
- <line number="25" hits="1"/>
250
- <line number="26" hits="1"/>
251
- <line number="27" hits="1"/>
252
- <line number="28" hits="1"/>
253
- <line number="29" hits="1"/>
254
- <line number="30" hits="1"/>
255
- <line number="33" hits="1"/>
256
- <line number="34" hits="1"/>
257
- <line number="36" hits="1"/>
258
- <line number="37" hits="1"/>
259
- <line number="38" hits="1"/>
260
- <line number="39" hits="1"/>
261
- <line number="40" hits="1"/>
262
- <line number="43" hits="1"/>
263
- </lines>
264
- </class>
265
- <class name="schemas.py" filename="schemas/schemas.py" complexity="0" line-rate="1" branch-rate="0">
266
- <methods/>
267
- <lines>
268
- <line number="1" hits="1"/>
269
- <line number="2" hits="1"/>
270
- <line number="5" hits="1"/>
271
- <line number="6" hits="1"/>
272
- <line number="7" hits="1"/>
273
- <line number="9" hits="1"/>
274
- <line number="12" hits="1"/>
275
- <line number="13" hits="1"/>
276
- <line number="14" hits="1"/>
277
- <line number="15" hits="1"/>
278
- <line number="16" hits="1"/>
279
- <line number="17" hits="1"/>
280
- <line number="19" hits="1"/>
281
- <line number="22" hits="1"/>
282
- <line number="23" hits="1"/>
283
- <line number="24" hits="1"/>
284
- <line number="25" hits="1"/>
285
- <line number="26" hits="1"/>
286
- <line number="27" hits="1"/>
287
- <line number="29" hits="1"/>
288
- <line number="32" hits="1"/>
289
- <line number="33" hits="1"/>
290
- <line number="34" hits="1"/>
291
- <line number="35" hits="1"/>
292
- <line number="36" hits="1"/>
293
- <line number="37" hits="1"/>
294
- <line number="39" hits="1"/>
295
- </lines>
296
- </class>
297
- </classes>
298
- </package>
299
- <package name="services" line-rate="0.6923" branch-rate="0" complexity="0">
300
- <classes>
301
- <class name="__init__.py" filename="services/__init__.py" complexity="0" line-rate="1" branch-rate="0">
302
- <methods/>
303
- <lines/>
304
- </class>
305
- <class name="absa_pipeline.py" filename="services/absa_pipeline.py" complexity="0" line-rate="0.6915" branch-rate="0">
306
- <methods/>
307
- <lines>
308
- <line number="13" hits="1"/>
309
- <line number="14" hits="1"/>
310
- <line number="15" hits="1"/>
311
- <line number="16" hits="1"/>
312
- <line number="17" hits="1"/>
313
- <line number="18" hits="1"/>
314
- <line number="20" hits="1"/>
315
- <line number="22" hits="1"/>
316
- <line number="23" hits="1"/>
317
- <line number="26" hits="1"/>
318
- <line number="27" hits="1"/>
319
- <line number="31" hits="1"/>
320
- <line number="33" hits="1"/>
321
- <line number="34" hits="0"/>
322
- <line number="35" hits="0"/>
323
- <line number="36" hits="0"/>
324
- <line number="38" hits="0"/>
325
- <line number="39" hits="0"/>
326
- <line number="40" hits="0"/>
327
- <line number="44" hits="1"/>
328
- <line number="151" hits="1"/>
329
- <line number="256" hits="1"/>
330
- <line number="346" hits="1"/>
331
- <line number="424" hits="1"/>
332
- <line number="448" hits="1"/>
333
- <line number="466" hits="1"/>
334
- <line number="472" hits="1"/>
335
- <line number="479" hits="1"/>
336
- <line number="481" hits="1"/>
337
- <line number="482" hits="1"/>
338
- <line number="485" hits="1"/>
339
- <line number="490" hits="1"/>
340
- <line number="491" hits="1"/>
341
- <line number="492" hits="1"/>
342
- <line number="493" hits="1"/>
343
- <line number="494" hits="1"/>
344
- <line number="496" hits="1"/>
345
- <line number="497" hits="1"/>
346
- <line number="499" hits="1"/>
347
- <line number="501" hits="1"/>
348
- <line number="502" hits="1"/>
349
- <line number="503" hits="1"/>
350
- <line number="505" hits="1"/>
351
- <line number="506" hits="1"/>
352
- <line number="507" hits="1"/>
353
- <line number="508" hits="0"/>
354
- <line number="510" hits="1"/>
355
- <line number="511" hits="1"/>
356
- <line number="512" hits="1"/>
357
- <line number="515" hits="1"/>
358
- <line number="517" hits="1"/>
359
- <line number="518" hits="1"/>
360
- <line number="519" hits="1"/>
361
- <line number="520" hits="1"/>
362
- <line number="521" hits="1"/>
363
- <line number="522" hits="1"/>
364
- <line number="523" hits="1"/>
365
- <line number="524" hits="1"/>
366
- <line number="525" hits="1"/>
367
- <line number="526" hits="1"/>
368
- <line number="527" hits="0"/>
369
- <line number="533" hits="1"/>
370
- <line number="534" hits="1"/>
371
- <line number="535" hits="1"/>
372
- <line number="536" hits="1"/>
373
- <line number="537" hits="1"/>
374
- <line number="538" hits="1"/>
375
- <line number="539" hits="1"/>
376
- <line number="541" hits="1"/>
377
- <line number="542" hits="1"/>
378
- <line number="549" hits="1"/>
379
- <line number="551" hits="1"/>
380
- <line number="552" hits="1"/>
381
- <line number="553" hits="1"/>
382
- <line number="555" hits="1"/>
383
- <line number="556" hits="0"/>
384
- <line number="557" hits="0"/>
385
- <line number="558" hits="0"/>
386
- <line number="559" hits="0"/>
387
- <line number="562" hits="0"/>
388
- <line number="565" hits="0"/>
389
- <line number="566" hits="0"/>
390
- <line number="567" hits="0"/>
391
- <line number="569" hits="1"/>
392
- <line number="570" hits="1"/>
393
- <line number="571" hits="1"/>
394
- <line number="572" hits="1"/>
395
- <line number="573" hits="1"/>
396
- <line number="574" hits="1"/>
397
- <line number="575" hits="1"/>
398
- <line number="577" hits="1"/>
399
- <line number="578" hits="0"/>
400
- <line number="579" hits="0"/>
401
- <line number="580" hits="0"/>
402
- <line number="581" hits="0"/>
403
- <line number="582" hits="0"/>
404
- <line number="583" hits="0"/>
405
- <line number="584" hits="0"/>
406
- <line number="585" hits="0"/>
407
- <line number="587" hits="1"/>
408
- <line number="588" hits="1"/>
409
- <line number="590" hits="1"/>
410
- <line number="592" hits="1"/>
411
- <line number="593" hits="1"/>
412
- <line number="594" hits="1"/>
413
- <line number="595" hits="1"/>
414
- <line number="597" hits="1"/>
415
- <line number="598" hits="0"/>
416
- <line number="600" hits="1"/>
417
- <line number="602" hits="1"/>
418
- <line number="610" hits="1"/>
419
- <line number="611" hits="0"/>
420
- <line number="615" hits="1"/>
421
- <line number="616" hits="0"/>
422
- <line number="617" hits="0"/>
423
- <line number="618" hits="0"/>
424
- <line number="619" hits="0"/>
425
- <line number="620" hits="0"/>
426
- <line number="621" hits="0"/>
427
- <line number="622" hits="0"/>
428
- <line number="624" hits="0"/>
429
- <line number="625" hits="0"/>
430
- <line number="626" hits="0"/>
431
- <line number="627" hits="0"/>
432
- <line number="632" hits="0"/>
433
- <line number="633" hits="0"/>
434
- <line number="634" hits="0"/>
435
- <line number="635" hits="0"/>
436
- <line number="636" hits="0"/>
437
- <line number="637" hits="0"/>
438
- <line number="638" hits="0"/>
439
- <line number="639" hits="0"/>
440
- <line number="640" hits="0"/>
441
- <line number="641" hits="0"/>
442
- <line number="643" hits="0"/>
443
- <line number="644" hits="0"/>
444
- <line number="645" hits="0"/>
445
- <line number="646" hits="0"/>
446
- <line number="647" hits="0"/>
447
- <line number="649" hits="0"/>
448
- <line number="650" hits="0"/>
449
- <line number="651" hits="0"/>
450
- <line number="658" hits="0"/>
451
- <line number="659" hits="0"/>
452
- <line number="660" hits="0"/>
453
- <line number="661" hits="0"/>
454
- <line number="662" hits="0"/>
455
- <line number="671" hits="0"/>
456
- <line number="675" hits="1"/>
457
- <line number="676" hits="1"/>
458
- <line number="677" hits="1"/>
459
- <line number="678" hits="1"/>
460
- <line number="681" hits="1"/>
461
- <line number="682" hits="1"/>
462
- <line number="686" hits="1"/>
463
- <line number="687" hits="1"/>
464
- <line number="689" hits="1"/>
465
- <line number="690" hits="1"/>
466
- <line number="694" hits="1"/>
467
- <line number="695" hits="1"/>
468
- <line number="696" hits="1"/>
469
- <line number="698" hits="1"/>
470
- <line number="701" hits="1"/>
471
- <line number="702" hits="1"/>
472
- <line number="703" hits="1"/>
473
- <line number="705" hits="1"/>
474
- <line number="706" hits="1"/>
475
- <line number="715" hits="1"/>
476
- <line number="717" hits="1"/>
477
- <line number="723" hits="1"/>
478
- <line number="724" hits="1"/>
479
- <line number="726" hits="1"/>
480
- <line number="727" hits="1"/>
481
- <line number="729" hits="1"/>
482
- <line number="730" hits="1"/>
483
- <line number="731" hits="1"/>
484
- <line number="732" hits="1"/>
485
- <line number="733" hits="1"/>
486
- <line number="734" hits="1"/>
487
- <line number="735" hits="1"/>
488
- <line number="736" hits="0"/>
489
- <line number="737" hits="1"/>
490
- <line number="738" hits="1"/>
491
- <line number="739" hits="1"/>
492
- <line number="741" hits="1"/>
493
- <line number="742" hits="1"/>
494
- <line number="744" hits="1"/>
495
- <line number="746" hits="1"/>
496
- <line number="747" hits="1"/>
497
- <line number="749" hits="1"/>
498
- <line number="750" hits="1"/>
499
- <line number="751" hits="1"/>
500
- <line number="753" hits="1"/>
501
- <line number="754" hits="1"/>
502
- <line number="755" hits="1"/>
503
- <line number="756" hits="1"/>
504
- <line number="757" hits="1"/>
505
- <line number="758" hits="1"/>
506
- <line number="760" hits="1"/>
507
- <line number="761" hits="1"/>
508
- <line number="764" hits="1"/>
509
- </lines>
510
- </class>
511
- <class name="lang_service.py" filename="services/lang_service.py" complexity="0" line-rate="0.7" branch-rate="0">
512
- <methods/>
513
- <lines>
514
- <line number="1" hits="1"/>
515
- <line number="2" hits="1"/>
516
- <line number="5" hits="1"/>
517
- <line number="6" hits="1"/>
518
- <line number="10" hits="1"/>
519
- <line number="11" hits="1"/>
520
- <line number="12" hits="1"/>
521
- <line number="13" hits="0"/>
522
- <line number="15" hits="1"/>
523
- <line number="16" hits="1"/>
524
- <line number="17" hits="0"/>
525
- <line number="18" hits="0"/>
526
- <line number="19" hits="0"/>
527
- <line number="20" hits="0"/>
528
- <line number="22" hits="0"/>
529
- <line number="25" hits="1"/>
530
- <line number="26" hits="1"/>
531
- <line number="27" hits="1"/>
532
- <line number="28" hits="1"/>
533
- <line number="31" hits="1"/>
534
- </lines>
535
- </class>
536
- </classes>
537
- </package>
538
- <package name="src.absa" line-rate="1" branch-rate="0" complexity="0">
539
- <classes>
540
- <class name="__init__.py" filename="src/absa/__init__.py" complexity="0" line-rate="1" branch-rate="0">
541
- <methods/>
542
- <lines/>
543
- </class>
544
- </classes>
545
- </package>
546
- <package name="src.absa.data" line-rate="0.2" branch-rate="0" complexity="0">
547
- <classes>
548
- <class name="__init__.py" filename="src/absa/data/__init__.py" complexity="0" line-rate="1" branch-rate="0">
549
- <methods/>
550
- <lines/>
551
- </class>
552
- <class name="augmentation.py" filename="src/absa/data/augmentation.py" complexity="0" line-rate="0" branch-rate="0">
553
- <methods/>
554
- <lines>
555
- <line number="6" hits="0"/>
556
- <line number="7" hits="0"/>
557
- <line number="8" hits="0"/>
558
- <line number="9" hits="0"/>
559
- <line number="10" hits="0"/>
560
- <line number="11" hits="0"/>
561
- <line number="12" hits="0"/>
562
- <line number="14" hits="0"/>
563
- <line number="17" hits="0"/>
564
- <line number="18" hits="0"/>
565
- <line number="19" hits="0"/>
566
- <line number="20" hits="0"/>
567
- <line number="21" hits="0"/>
568
- <line number="23" hits="0"/>
569
- <line number="24" hits="0"/>
570
- <line number="26" hits="0"/>
571
- <line number="27" hits="0"/>
572
- <line number="29" hits="0"/>
573
- <line number="30" hits="0"/>
574
- <line number="31" hits="0"/>
575
- <line number="32" hits="0"/>
576
- <line number="33" hits="0"/>
577
- <line number="35" hits="0"/>
578
- <line number="36" hits="0"/>
579
- <line number="39" hits="0"/>
580
- <line number="42" hits="0"/>
581
- <line number="45" hits="0"/>
582
- <line number="46" hits="0"/>
583
- <line number="47" hits="0"/>
584
- <line number="48" hits="0"/>
585
- <line number="50" hits="0"/>
586
- <line number="51" hits="0"/>
587
- <line number="53" hits="0"/>
588
- <line number="54" hits="0"/>
589
- <line number="55" hits="0"/>
590
- <line number="56" hits="0"/>
591
- <line number="57" hits="0"/>
592
- <line number="60" hits="0"/>
593
- <line number="61" hits="0"/>
594
- <line number="64" hits="0"/>
595
- <line number="65" hits="0"/>
596
- <line number="67" hits="0"/>
597
- <line number="69" hits="0"/>
598
- <line number="70" hits="0"/>
599
- <line number="73" hits="0"/>
600
- <line number="74" hits="0"/>
601
- <line number="75" hits="0"/>
602
- <line number="76" hits="0"/>
603
- <line number="77" hits="0"/>
604
- <line number="78" hits="0"/>
605
- <line number="79" hits="0"/>
606
- <line number="80" hits="0"/>
607
- <line number="81" hits="0"/>
608
- <line number="82" hits="0"/>
609
- <line number="83" hits="0"/>
610
- <line number="84" hits="0"/>
611
- <line number="86" hits="0"/>
612
- <line number="88" hits="0"/>
613
- <line number="89" hits="0"/>
614
- <line number="92" hits="0"/>
615
- <line number="93" hits="0"/>
616
- <line number="94" hits="0"/>
617
- <line number="95" hits="0"/>
618
- <line number="96" hits="0"/>
619
- <line number="98" hits="0"/>
620
- <line number="101" hits="0"/>
621
- <line number="102" hits="0"/>
622
- <line number="103" hits="0"/>
623
- <line number="104" hits="0"/>
624
- <line number="105" hits="0"/>
625
- <line number="108" hits="0"/>
626
- <line number="109" hits="0"/>
627
- </lines>
628
- </class>
629
- <class name="bio_tagger.py" filename="src/absa/data/bio_tagger.py" complexity="0" line-rate="0.9362" branch-rate="0">
630
- <methods/>
631
- <lines>
632
- <line number="1" hits="1"/>
633
- <line number="2" hits="1"/>
634
- <line number="5" hits="1"/>
635
- <line number="16" hits="1"/>
636
- <line number="18" hits="1"/>
637
- <line number="19" hits="1"/>
638
- <line number="20" hits="1"/>
639
- <line number="23" hits="1"/>
640
- <line number="36" hits="1"/>
641
- <line number="39" hits="1"/>
642
- <line number="41" hits="1"/>
643
- <line number="42" hits="1"/>
644
- <line number="43" hits="1"/>
645
- <line number="45" hits="1"/>
646
- <line number="46" hits="1"/>
647
- <line number="49" hits="1"/>
648
- <line number="50" hits="1"/>
649
- <line number="52" hits="1"/>
650
- <line number="53" hits="1"/>
651
- <line number="54" hits="1"/>
652
- <line number="55" hits="1"/>
653
- <line number="58" hits="1"/>
654
- <line number="61" hits="1"/>
655
- <line number="66" hits="1"/>
656
- <line number="69" hits="1"/>
657
- <line number="73" hits="1"/>
658
- <line number="75" hits="0"/>
659
- <line number="77" hits="1"/>
660
- <line number="79" hits="1"/>
661
- <line number="82" hits="1"/>
662
- <line number="93" hits="1"/>
663
- <line number="94" hits="1"/>
664
- <line number="96" hits="1"/>
665
- <line number="97" hits="1"/>
666
- <line number="98" hits="1"/>
667
- <line number="99" hits="1"/>
668
- <line number="100" hits="1"/>
669
- <line number="101" hits="1"/>
670
- <line number="102" hits="1"/>
671
- <line number="103" hits="1"/>
672
- <line number="106" hits="0"/>
673
- <line number="108" hits="1"/>
674
- <line number="109" hits="1"/>
675
- <line number="110" hits="1"/>
676
- <line number="112" hits="1"/>
677
- <line number="113" hits="0"/>
678
- <line number="115" hits="1"/>
679
- </lines>
680
- </class>
681
- <class name="dataset.py" filename="src/absa/data/dataset.py" complexity="0" line-rate="0" branch-rate="0">
682
- <methods/>
683
- <lines>
684
- <line number="1" hits="0"/>
685
- <line number="2" hits="0"/>
686
- <line number="3" hits="0"/>
687
- <line number="4" hits="0"/>
688
- <line number="5" hits="0"/>
689
- <line number="6" hits="0"/>
690
- <line number="9" hits="0"/>
691
- <line number="10" hits="0"/>
692
- <line number="11" hits="0"/>
693
- <line number="13" hits="0"/>
694
- <line number="14" hits="0"/>
695
- <line number="16" hits="0"/>
696
- <line number="17" hits="0"/>
697
- <line number="19" hits="0"/>
698
- <line number="25" hits="0"/>
699
- <line number="26" hits="0"/>
700
- <line number="27" hits="0"/>
701
- <line number="28" hits="0"/>
702
- <line number="29" hits="0"/>
703
- <line number="31" hits="0"/>
704
- <line number="33" hits="0"/>
705
- <line number="35" hits="0"/>
706
- <line number="39" hits="0"/>
707
- <line number="40" hits="0"/>
708
  <line number="41" hits="0"/>
709
  <line number="42" hits="0"/>
710
  <line number="43" hits="0"/>
711
  <line number="44" hits="0"/>
712
  <line number="45" hits="0"/>
 
713
  <line number="47" hits="0"/>
714
- <line number="48" hits="0"/>
715
  <line number="49" hits="0"/>
716
  <line number="50" hits="0"/>
717
  <line number="51" hits="0"/>
718
  <line number="52" hits="0"/>
719
- <line number="61" hits="0"/>
720
- <line number="67" hits="0"/>
721
- <line number="68" hits="0"/>
 
722
  <line number="70" hits="0"/>
723
- <line number="71" hits="0"/>
724
- <line number="74" hits="0"/>
725
- <line number="75" hits="0"/>
 
726
  </lines>
727
  </class>
728
  <class name="hf_dataset.py" filename="src/absa/data/hf_dataset.py" complexity="0" line-rate="0" branch-rate="0">
@@ -731,47 +202,45 @@
731
  <line number="1" hits="0"/>
732
  <line number="2" hits="0"/>
733
  <line number="3" hits="0"/>
734
- <line number="4" hits="0"/>
735
  <line number="5" hits="0"/>
736
  <line number="6" hits="0"/>
737
  <line number="7" hits="0"/>
738
  <line number="8" hits="0"/>
739
  <line number="9" hits="0"/>
740
  <line number="11" hits="0"/>
741
- <line number="14" hits="0"/>
742
- <line number="15" hits="0"/>
743
  <line number="16" hits="0"/>
744
  <line number="17" hits="0"/>
745
  <line number="18" hits="0"/>
746
  <line number="19" hits="0"/>
747
  <line number="20" hits="0"/>
748
  <line number="21" hits="0"/>
749
- <line number="24" hits="0"/>
 
750
  <line number="26" hits="0"/>
751
- <line number="27" hits="0"/>
752
  <line number="29" hits="0"/>
753
- <line number="30" hits="0"/>
754
  <line number="31" hits="0"/>
755
  <line number="32" hits="0"/>
 
756
  <line number="34" hits="0"/>
757
- <line number="35" hits="0"/>
758
  <line number="37" hits="0"/>
759
- <line number="44" hits="0"/>
760
- <line number="47" hits="0"/>
761
  <line number="49" hits="0"/>
762
- <line number="50" hits="0"/>
763
  <line number="52" hits="0"/>
764
- <line number="53" hits="0"/>
765
  <line number="54" hits="0"/>
 
766
  <line number="56" hits="0"/>
767
- <line number="57" hits="0"/>
768
  <line number="58" hits="0"/>
 
769
  <line number="60" hits="0"/>
770
- <line number="61" hits="0"/>
771
  <line number="63" hits="0"/>
772
- <line number="71" hits="0"/>
773
- <line number="74" hits="0"/>
774
- <line number="75" hits="0"/>
775
  <line number="76" hits="0"/>
776
  <line number="77" hits="0"/>
777
  <line number="78" hits="0"/>
@@ -779,118 +248,120 @@
779
  <line number="80" hits="0"/>
780
  <line number="81" hits="0"/>
781
  <line number="82" hits="0"/>
 
782
  <line number="84" hits="0"/>
783
- <line number="85" hits="0"/>
784
- <line number="88" hits="0"/>
785
- <line number="89" hits="0"/>
786
  <line number="90" hits="0"/>
787
  <line number="91" hits="0"/>
788
- <line number="94" hits="0"/>
789
- <line number="95" hits="0"/>
790
  <line number="96" hits="0"/>
791
- <line number="99" hits="0"/>
792
- <line number="100" hits="0"/>
 
793
  <line number="102" hits="0"/>
794
- <line number="107" hits="0"/>
795
- <line number="111" hits="0"/>
796
- <line number="112" hits="0"/>
797
  <line number="114" hits="0"/>
798
- <line number="115" hits="0"/>
799
- <line number="121" hits="0"/>
800
- <line number="122" hits="0"/>
801
  <line number="123" hits="0"/>
802
  <line number="124" hits="0"/>
803
  <line number="125" hits="0"/>
804
  <line number="126" hits="0"/>
 
805
  <line number="128" hits="0"/>
806
- <line number="136" hits="0"/>
807
- <line number="141" hits="0"/>
808
- <line number="142" hits="0"/>
809
- <line number="147" hits="0"/>
810
- <line number="150" hits="0"/>
 
811
  <line number="153" hits="0"/>
 
812
  <line number="157" hits="0"/>
813
- <line number="159" hits="0"/>
814
- <line number="167" hits="0"/>
 
815
  <line number="175" hits="0"/>
816
  <line number="178" hits="0"/>
817
  <line number="179" hits="0"/>
818
- <line number="182" hits="0"/>
819
- <line number="183" hits="0"/>
820
  </lines>
821
  </class>
822
  <class name="hindi_loader.py" filename="src/absa/data/hindi_loader.py" complexity="0" line-rate="0" branch-rate="0">
823
  <methods/>
824
  <lines>
825
  <line number="1" hits="0"/>
826
- <line number="2" hits="0"/>
827
  <line number="3" hits="0"/>
828
  <line number="4" hits="0"/>
829
- <line number="7" hits="0"/>
830
  <line number="8" hits="0"/>
831
  <line number="9" hits="0"/>
832
  <line number="10" hits="0"/>
833
  <line number="11" hits="0"/>
834
- <line number="13" hits="0"/>
835
- <line number="15" hits="0"/>
836
  <line number="16" hits="0"/>
837
- <line number="18" hits="0"/>
 
 
838
  <line number="21" hits="0"/>
839
  <line number="22" hits="0"/>
840
  <line number="23" hits="0"/>
841
  <line number="24" hits="0"/>
842
- <line number="25" hits="0"/>
843
  <line number="27" hits="0"/>
844
  <line number="28" hits="0"/>
845
  <line number="29" hits="0"/>
846
  <line number="30" hits="0"/>
847
- <line number="31" hits="0"/>
848
- <line number="33" hits="0"/>
849
  <line number="35" hits="0"/>
850
  <line number="36" hits="0"/>
851
- <line number="37" hits="0"/>
852
- <line number="39" hits="0"/>
853
- <line number="41" hits="0"/>
854
- <line number="43" hits="0"/>
855
  <line number="49" hits="0"/>
856
- <line number="50" hits="0"/>
857
  <line number="52" hits="0"/>
858
- <line number="53" hits="0"/>
859
  <line number="56" hits="0"/>
860
- <line number="57" hits="0"/>
861
  </lines>
862
  </class>
863
  <class name="lang_detect.py" filename="src/absa/data/lang_detect.py" complexity="0" line-rate="0.9643" branch-rate="0">
864
  <methods/>
865
  <lines>
866
  <line number="1" hits="1"/>
867
- <line number="2" hits="1"/>
868
  <line number="3" hits="1"/>
869
  <line number="5" hits="1"/>
870
- <line number="8" hits="1"/>
871
  <line number="10" hits="1"/>
872
- <line number="11" hits="1"/>
873
  <line number="12" hits="1"/>
874
- <line number="15" hits="1"/>
875
- <line number="24" hits="1"/>
876
- <line number="25" hits="0"/>
877
- <line number="27" hits="1"/>
878
- <line number="28" hits="1"/>
879
  <line number="29" hits="1"/>
 
880
  <line number="31" hits="1"/>
881
- <line number="32" hits="1"/>
882
  <line number="33" hits="1"/>
883
  <line number="34" hits="1"/>
 
884
  <line number="36" hits="1"/>
885
- <line number="37" hits="1"/>
886
  <line number="39" hits="1"/>
887
  <line number="41" hits="1"/>
888
- <line number="42" hits="1"/>
889
  <line number="44" hits="1"/>
890
- <line number="45" hits="1"/>
891
  <line number="46" hits="1"/>
892
  <line number="47" hits="1"/>
 
893
  <line number="49" hits="1"/>
 
894
  </lines>
895
  </class>
896
  <class name="preprocess.py" filename="src/absa/data/preprocess.py" complexity="0" line-rate="0" branch-rate="0">
@@ -898,20 +369,20 @@
898
  <lines>
899
  <line number="1" hits="0"/>
900
  <line number="2" hits="0"/>
901
- <line number="3" hits="0"/>
902
- <line number="6" hits="0"/>
903
- <line number="8" hits="0"/>
904
  <line number="9" hits="0"/>
905
- <line number="12" hits="0"/>
906
- <line number="15" hits="0"/>
907
- <line number="18" hits="0"/>
908
- <line number="21" hits="0"/>
909
- <line number="24" hits="0"/>
910
  <line number="25" hits="0"/>
911
- <line number="28" hits="0"/>
912
- <line number="31" hits="0"/>
913
  <line number="32" hits="0"/>
914
- <line number="34" hits="0"/>
 
915
  </lines>
916
  </class>
917
  <class name="transliterate.py" filename="src/absa/data/transliterate.py" complexity="0" line-rate="0" branch-rate="0">
@@ -927,21 +398,21 @@
927
  <line number="11" hits="0"/>
928
  <line number="12" hits="0"/>
929
  <line number="13" hits="0"/>
 
930
  <line number="18" hits="0"/>
931
- <line number="20" hits="0"/>
932
  <line number="21" hits="0"/>
933
- <line number="23" hits="0"/>
934
- <line number="24" hits="0"/>
 
935
  <line number="27" hits="0"/>
936
  <line number="28" hits="0"/>
937
- <line number="29" hits="0"/>
938
- <line number="30" hits="0"/>
939
  <line number="33" hits="0"/>
 
 
940
  <line number="39" hits="0"/>
941
- <line number="40" hits="0"/>
942
- <line number="44" hits="0"/>
943
- <line number="45" hits="0"/>
944
- <line number="47" hits="0"/>
945
  </lines>
946
  </class>
947
  </classes>
@@ -957,83 +428,83 @@
957
  <lines>
958
  <line number="5" hits="0"/>
959
  <line number="6" hits="0"/>
960
- <line number="7" hits="0"/>
961
  <line number="8" hits="0"/>
962
  <line number="9" hits="0"/>
963
- <line number="11" hits="0"/>
964
  <line number="12" hits="0"/>
965
- <line number="14" hits="0"/>
966
  <line number="15" hits="0"/>
967
  <line number="16" hits="0"/>
968
  <line number="17" hits="0"/>
969
- <line number="20" hits="0"/>
970
  <line number="21" hits="0"/>
971
- <line number="24" hits="0"/>
972
  <line number="25" hits="0"/>
973
  <line number="26" hits="0"/>
974
  <line number="27" hits="0"/>
975
- <line number="29" hits="0"/>
976
- <line number="31" hits="0"/>
977
  <line number="32" hits="0"/>
978
  <line number="33" hits="0"/>
 
 
979
  <line number="37" hits="0"/>
980
  <line number="38" hits="0"/>
981
  <line number="39" hits="0"/>
982
- <line number="40" hits="0"/>
983
  <line number="42" hits="0"/>
984
- <line number="43" hits="0"/>
985
- <line number="45" hits="0"/>
986
  <line number="47" hits="0"/>
987
  <line number="48" hits="0"/>
988
- <line number="49" hits="0"/>
989
- <line number="51" hits="0"/>
990
  <line number="54" hits="0"/>
991
  <line number="55" hits="0"/>
992
  <line number="56" hits="0"/>
993
  <line number="57" hits="0"/>
994
- <line number="58" hits="0"/>
995
  <line number="60" hits="0"/>
996
  <line number="61" hits="0"/>
997
- <line number="62" hits="0"/>
998
  <line number="64" hits="0"/>
999
- <line number="65" hits="0"/>
1000
- <line number="67" hits="0"/>
1001
  <line number="70" hits="0"/>
1002
  <line number="71" hits="0"/>
1003
- <line number="72" hits="0"/>
1004
  <line number="74" hits="0"/>
1005
- <line number="75" hits="0"/>
1006
- <line number="81" hits="0"/>
1007
  <line number="83" hits="0"/>
1008
  <line number="84" hits="0"/>
1009
  <line number="85" hits="0"/>
1010
- <line number="88" hits="0"/>
1011
- <line number="91" hits="0"/>
1012
- <line number="98" hits="0"/>
1013
- <line number="99" hits="0"/>
1014
- <line number="100" hits="0"/>
 
1015
  <line number="103" hits="0"/>
 
 
1016
  <line number="106" hits="0"/>
 
 
 
1017
  <line number="112" hits="0"/>
1018
  <line number="113" hits="0"/>
1019
- <line number="116" hits="0"/>
1020
  <line number="117" hits="0"/>
1021
  <line number="118" hits="0"/>
 
 
 
 
1022
  <line number="123" hits="0"/>
1023
  <line number="124" hits="0"/>
1024
- <line number="125" hits="0"/>
1025
- <line number="126" hits="0"/>
1026
- <line number="130" hits="0"/>
1027
- <line number="134" hits="0"/>
1028
- <line number="135" hits="0"/>
1029
- <line number="136" hits="0"/>
1030
- <line number="137" hits="0"/>
1031
- <line number="138" hits="0"/>
1032
- <line number="139" hits="0"/>
1033
- <line number="140" hits="0"/>
1034
- <line number="141" hits="0"/>
1035
- <line number="144" hits="0"/>
1036
- <line number="145" hits="0"/>
1037
  </lines>
1038
  </class>
1039
  <class name="cross_lingual_eval.py" filename="src/absa/evaluation/cross_lingual_eval.py" complexity="0" line-rate="0" branch-rate="0">
@@ -1041,70 +512,70 @@
1041
  <lines>
1042
  <line number="1" hits="0"/>
1043
  <line number="2" hits="0"/>
1044
- <line number="3" hits="0"/>
1045
  <line number="4" hits="0"/>
1046
- <line number="10" hits="0"/>
1047
- <line number="11" hits="0"/>
1048
- <line number="13" hits="0"/>
1049
- <line number="16" hits="0"/>
1050
  <line number="17" hits="0"/>
1051
  <line number="18" hits="0"/>
1052
  <line number="19" hits="0"/>
1053
  <line number="20" hits="0"/>
1054
  <line number="21" hits="0"/>
1055
  <line number="22" hits="0"/>
1056
- <line number="25" hits="0"/>
1057
  <line number="26" hits="0"/>
1058
- <line number="29" hits="0"/>
1059
  <line number="30" hits="0"/>
1060
- <line number="32" hits="0"/>
1061
  <line number="33" hits="0"/>
1062
- <line number="36" hits="0"/>
 
 
1063
  <line number="38" hits="0"/>
1064
- <line number="39" hits="0"/>
1065
  <line number="41" hits="0"/>
1066
- <line number="44" hits="0"/>
1067
- <line number="48" hits="0"/>
1068
- <line number="50" hits="0"/>
 
 
1069
  <line number="59" hits="0"/>
1070
- <line number="60" hits="0"/>
1071
  <line number="62" hits="0"/>
1072
  <line number="64" hits="0"/>
 
1073
  <line number="66" hits="0"/>
1074
- <line number="67" hits="0"/>
1075
  <line number="69" hits="0"/>
1076
  <line number="70" hits="0"/>
1077
  <line number="71" hits="0"/>
1078
- <line number="73" hits="0"/>
1079
  <line number="74" hits="0"/>
1080
- <line number="75" hits="0"/>
1081
- <line number="76" hits="0"/>
1082
  <line number="77" hits="0"/>
 
1083
  <line number="79" hits="0"/>
 
1084
  <line number="82" hits="0"/>
1085
- <line number="85" hits="0"/>
 
1086
  <line number="86" hits="0"/>
1087
- <line number="87" hits="0"/>
1088
  <line number="89" hits="0"/>
1089
- <line number="90" hits="0"/>
1090
- <line number="91" hits="0"/>
1091
  <line number="93" hits="0"/>
1092
- <line number="95" hits="0"/>
1093
- <line number="100" hits="0"/>
 
 
1094
  <line number="104" hits="0"/>
1095
  <line number="105" hits="0"/>
1096
  <line number="107" hits="0"/>
1097
  <line number="108" hits="0"/>
1098
  <line number="109" hits="0"/>
1099
- <line number="115" hits="0"/>
1100
- <line number="116" hits="0"/>
1101
- <line number="118" hits="0"/>
1102
- <line number="119" hits="0"/>
1103
- <line number="120" hits="0"/>
1104
  <line number="122" hits="0"/>
1105
- <line number="123" hits="0"/>
1106
- <line number="132" hits="0"/>
1107
- <line number="133" hits="0"/>
1108
  </lines>
1109
  </class>
1110
  <class name="final_eval.py" filename="src/absa/evaluation/final_eval.py" complexity="0" line-rate="0" branch-rate="0">
@@ -1145,7 +616,6 @@
1145
  <line number="1" hits="0"/>
1146
  <line number="2" hits="0"/>
1147
  <line number="3" hits="0"/>
1148
- <line number="4" hits="0"/>
1149
  <line number="5" hits="0"/>
1150
  <line number="6" hits="0"/>
1151
  <line number="7" hits="0"/>
@@ -1153,283 +623,409 @@
1153
  <line number="9" hits="0"/>
1154
  <line number="10" hits="0"/>
1155
  <line number="11" hits="0"/>
1156
- <line number="14" hits="0"/>
1157
- <line number="15" hits="0"/>
1158
  <line number="16" hits="0"/>
1159
  <line number="17" hits="0"/>
1160
  <line number="18" hits="0"/>
1161
  <line number="19" hits="0"/>
1162
  <line number="20" hits="0"/>
1163
  <line number="21" hits="0"/>
1164
- <line number="24" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1165
  <line number="37" hits="0"/>
1166
  <line number="38" hits="0"/>
1167
  <line number="40" hits="0"/>
1168
- <line number="41" hits="0"/>
1169
  <line number="42" hits="0"/>
1170
  <line number="44" hits="0"/>
1171
  <line number="45" hits="0"/>
1172
  <line number="46" hits="0"/>
1173
- <line number="47" hits="0"/>
1174
  <line number="48" hits="0"/>
1175
- <line number="51" hits="0"/>
1176
  <line number="52" hits="0"/>
1177
  <line number="53" hits="0"/>
 
 
1178
  <line number="57" hits="0"/>
 
 
1179
  <line number="60" hits="0"/>
1180
  <line number="63" hits="0"/>
1181
- <line number="66" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1182
  <line number="70" hits="0"/>
1183
- <line number="71" hits="0"/>
1184
- <line number="73" hits="0"/>
1185
- <line number="74" hits="0"/>
1186
- <line number="76" hits="0"/>
1187
- <line number="79" hits="0"/>
1188
- <line number="80" hits="0"/>
1189
  <line number="85" hits="0"/>
1190
- <line number="86" hits="0"/>
1191
- <line number="87" hits="0"/>
1192
- <line number="90" hits="0"/>
1193
  <line number="91" hits="0"/>
1194
  <line number="92" hits="0"/>
 
1195
  <line number="95" hits="0"/>
1196
  <line number="96" hits="0"/>
1197
- <line number="97" hits="0"/>
1198
  <line number="99" hits="0"/>
 
 
1199
  <line number="106" hits="0"/>
 
 
 
1200
  <line number="118" hits="0"/>
1201
  <line number="119" hits="0"/>
1202
- <line number="120" hits="0"/>
1203
  <line number="121" hits="0"/>
1204
- <line number="122" hits="0"/>
1205
- <line number="125" hits="0"/>
 
1206
  <line number="133" hits="0"/>
 
 
1207
  <line number="136" hits="0"/>
1208
- <line number="137" hits="0"/>
1209
- <line number="138" hits="0"/>
1210
- <line number="140" hits="0"/>
1211
  <line number="143" hits="0"/>
1212
- <line number="144" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1213
  </lines>
1214
  </class>
1215
- <class name="export_onnx.py" filename="src/absa/models/export_onnx.py" complexity="0" line-rate="0" branch-rate="0">
1216
  <methods/>
1217
  <lines>
1218
- <line number="6" hits="0"/>
 
1219
  <line number="8" hits="0"/>
1220
  <line number="9" hits="0"/>
1221
- <line number="14" hits="0"/>
1222
- <line number="16" hits="0"/>
1223
- <line number="17" hits="0"/>
1224
- <line number="18" hits="0"/>
1225
- <line number="19" hits="0"/>
1226
- <line number="22" hits="0"/>
1227
  <line number="25" hits="0"/>
 
1228
  <line number="27" hits="0"/>
1229
- <line number="28" hits="0"/>
1230
  <line number="30" hits="0"/>
1231
  <line number="31" hits="0"/>
1232
  <line number="32" hits="0"/>
 
1233
  <line number="37" hits="0"/>
1234
  <line number="38" hits="0"/>
 
1235
  <line number="41" hits="0"/>
1236
  <line number="42" hits="0"/>
1237
- <line number="46" hits="0"/>
1238
- <line number="48" hits="0"/>
 
 
1239
  <line number="50" hits="0"/>
1240
- <line number="51" hits="0"/>
1241
- <line number="52" hits="0"/>
1242
  <line number="54" hits="0"/>
1243
  <line number="55" hits="0"/>
 
1244
  <line number="58" hits="0"/>
1245
  <line number="59" hits="0"/>
1246
  <line number="60" hits="0"/>
1247
- <line number="62" hits="0"/>
1248
  <line number="63" hits="0"/>
1249
  <line number="64" hits="0"/>
1250
  <line number="65" hits="0"/>
1251
- <line number="66" hits="0"/>
 
1252
  <line number="69" hits="0"/>
 
 
 
 
1253
  <line number="77" hits="0"/>
 
 
 
 
1254
  <line number="85" hits="0"/>
1255
  <line number="86" hits="0"/>
1256
- </lines>
1257
- </class>
1258
- <class name="train_aspect_extraction.py" filename="src/absa/models/train_aspect_extraction.py" complexity="0" line-rate="0" branch-rate="0">
1259
- <methods/>
1260
- <lines>
1261
- <line number="1" hits="0"/>
1262
- <line number="2" hits="0"/>
1263
- <line number="3" hits="0"/>
1264
- <line number="4" hits="0"/>
1265
- <line number="12" hits="0"/>
1266
- <line number="13" hits="0"/>
1267
- <line number="15" hits="0"/>
1268
- <line number="18" hits="0"/>
1269
- <line number="27" hits="0"/>
1270
- <line number="28" hits="0"/>
1271
- <line number="30" hits="0"/>
1272
- <line number="32" hits="0"/>
1273
- <line number="36" hits="0"/>
1274
- <line number="42" hits="0"/>
1275
- <line number="46" hits="0"/>
1276
- <line number="49" hits="0"/>
1277
- <line number="56" hits="0"/>
1278
- <line number="57" hits="0"/>
1279
- <line number="59" hits="0"/>
1280
- <line number="60" hits="0"/>
1281
- <line number="61" hits="0"/>
1282
- <line number="63" hits="0"/>
1283
- <line number="64" hits="0"/>
1284
- <line number="66" hits="0"/>
1285
- <line number="67" hits="0"/>
1286
- <line number="74" hits="0"/>
1287
- <line number="76" hits="0"/>
1288
  <line number="92" hits="0"/>
1289
- <line number="102" hits="0"/>
1290
- <line number="103" hits="0"/>
1291
- <line number="105" hits="0"/>
1292
  <line number="106" hits="0"/>
1293
- <line number="107" hits="0"/>
1294
- <line number="109" hits="0"/>
1295
- <line number="110" hits="0"/>
1296
- <line number="111" hits="0"/>
1297
  <line number="115" hits="0"/>
1298
- <line number="122" hits="0"/>
 
 
 
 
1299
  <line number="125" hits="0"/>
 
1300
  <line number="128" hits="0"/>
1301
  <line number="129" hits="0"/>
 
 
 
 
 
 
 
1302
  </lines>
1303
  </class>
1304
- <class name="train_joint_absa.py" filename="src/absa/models/train_joint_absa.py" complexity="0" line-rate="0" branch-rate="0">
1305
  <methods/>
1306
  <lines>
1307
  <line number="5" hits="0"/>
1308
- <line number="6" hits="0"/>
1309
  <line number="7" hits="0"/>
1310
  <line number="8" hits="0"/>
1311
- <line number="16" hits="0"/>
1312
- <line number="17" hits="0"/>
1313
- <line number="18" hits="0"/>
1314
- <line number="19" hits="0"/>
1315
- <line number="23" hits="0"/>
1316
  <line number="24" hits="0"/>
1317
- <line number="26" hits="0"/>
 
1318
  <line number="29" hits="0"/>
1319
  <line number="30" hits="0"/>
1320
  <line number="31" hits="0"/>
1321
- <line number="32" hits="0"/>
1322
- <line number="33" hits="0"/>
1323
  <line number="34" hits="0"/>
1324
  <line number="35" hits="0"/>
1325
- <line number="38" hits="0"/>
 
1326
  <line number="39" hits="0"/>
1327
- <line number="40" hits="0"/>
1328
- <line number="41" hits="0"/>
1329
  <line number="42" hits="0"/>
1330
- <line number="44" hits="0"/>
1331
- <line number="45" hits="0"/>
1332
- <line number="48" hits="0"/>
1333
  <line number="51" hits="0"/>
1334
  <line number="53" hits="0"/>
 
1335
  <line number="55" hits="0"/>
1336
- <line number="69" hits="0"/>
1337
- <line number="73" hits="0"/>
 
 
 
 
 
 
 
 
1338
  <line number="85" hits="0"/>
1339
- <line number="86" hits="0"/>
1340
- <line number="89" hits="0"/>
1341
- <line number="92" hits="0"/>
1342
- <line number="93" hits="0"/>
1343
- <line number="95" hits="0"/>
1344
- <line number="96" hits="0"/>
1345
- <line number="97" hits="0"/>
1346
- <line number="100" hits="0"/>
1347
  <line number="101" hits="0"/>
1348
- <line number="102" hits="0"/>
1349
- <line number="107" hits="0"/>
1350
- <line number="110" hits="0"/>
1351
- <line number="116" hits="0"/>
1352
  <line number="118" hits="0"/>
1353
  <line number="119" hits="0"/>
1354
- <line number="120" hits="0"/>
1355
  <line number="122" hits="0"/>
1356
- <line number="131" hits="0"/>
1357
- <line number="132" hits="0"/>
1358
- <line number="133" hits="0"/>
1359
- <line number="134" hits="0"/>
1360
- <line number="135" hits="0"/>
1361
- <line number="136" hits="0"/>
1362
- <line number="137" hits="0"/>
1363
- <line number="140" hits="0"/>
1364
- <line number="142" hits="0"/>
1365
- <line number="143" hits="0"/>
1366
- <line number="146" hits="0"/>
1367
- <line number="154" hits="0"/>
1368
- <line number="156" hits="0"/>
1369
- <line number="159" hits="0"/>
1370
- <line number="160" hits="0"/>
1371
- <line number="162" hits="0"/>
1372
- <line number="164" hits="0"/>
1373
- <line number="167" hits="0"/>
1374
- <line number="168" hits="0"/>
1375
- <line number="169" hits="0"/>
1376
- <line number="170" hits="0"/>
1377
- <line number="172" hits="0"/>
1378
- <line number="173" hits="0"/>
1379
- <line number="174" hits="0"/>
1380
- <line number="178" hits="0"/>
1381
- <line number="195" hits="0"/>
1382
- <line number="196" hits="0"/>
1383
- <line number="198" hits="0"/>
1384
- <line number="200" hits="0"/>
1385
- <line number="205" hits="0"/>
1386
- <line number="206" hits="0"/>
1387
- <line number="209" hits="0"/>
1388
- <line number="210" hits="0"/>
1389
  </lines>
1390
  </class>
1391
- <class name="train_multilingual.py" filename="src/absa/models/train_multilingual.py" complexity="0" line-rate="0" branch-rate="0">
1392
  <methods/>
1393
  <lines>
 
 
 
1394
  <line number="5" hits="0"/>
1395
  <line number="6" hits="0"/>
1396
  <line number="7" hits="0"/>
1397
- <line number="15" hits="0"/>
1398
- <line number="16" hits="0"/>
1399
  <line number="17" hits="0"/>
1400
- <line number="18" hits="0"/>
1401
  <line number="20" hits="0"/>
1402
- <line number="23" hits="0"/>
1403
- <line number="24" hits="0"/>
1404
- <line number="25" hits="0"/>
1405
- <line number="26" hits="0"/>
1406
  <line number="29" hits="0"/>
1407
  <line number="30" hits="0"/>
1408
- <line number="31" hits="0"/>
1409
- <line number="35" hits="0"/>
1410
- <line number="36" hits="0"/>
1411
- <line number="37" hits="0"/>
1412
- <line number="39" hits="0"/>
1413
- <line number="40" hits="0"/>
1414
- <line number="41" hits="0"/>
1415
- <line number="42" hits="0"/>
1416
- <line number="43" hits="0"/>
1417
- <line number="44" hits="0"/>
1418
  <line number="46" hits="0"/>
1419
- <line number="49" hits="0"/>
1420
- <line number="54" hits="0"/>
 
 
 
 
1421
  <line number="55" hits="0"/>
1422
  <line number="56" hits="0"/>
1423
- <line number="57" hits="0"/>
1424
- <line number="59" hits="0"/>
1425
  <line number="60" hits="0"/>
1426
- <line number="61" hits="0"/>
1427
- <line number="64" hits="0"/>
1428
  <line number="65" hits="0"/>
1429
- <line number="68" hits="0"/>
1430
- <line number="70" hits="0"/>
1431
- <line number="71" hits="0"/>
1432
  <line number="72" hits="0"/>
 
1433
  <line number="75" hits="0"/>
1434
  <line number="76" hits="0"/>
1435
  <line number="77" hits="0"/>
@@ -1438,153 +1034,331 @@
1438
  <line number="81" hits="0"/>
1439
  <line number="83" hits="0"/>
1440
  <line number="84" hits="0"/>
1441
- <line number="86" hits="0"/>
1442
- <line number="88" hits="0"/>
1443
- <line number="89" hits="0"/>
1444
- <line number="90" hits="0"/>
1445
  <line number="92" hits="0"/>
1446
- <line number="93" hits="0"/>
1447
- <line number="97" hits="0"/>
1448
- <line number="99" hits="0"/>
1449
  <line number="111" hits="0"/>
1450
- <line number="120" hits="0"/>
1451
- <line number="121" hits="0"/>
1452
- <line number="123" hits="0"/>
1453
- <line number="124" hits="0"/>
1454
  <line number="128" hits="0"/>
1455
  <line number="129" hits="0"/>
1456
- <line number="130" hits="0"/>
1457
  <line number="131" hits="0"/>
 
1458
  <line number="133" hits="0"/>
1459
- <line number="134" hits="0"/>
1460
  <line number="135" hits="0"/>
1461
  <line number="136" hits="0"/>
1462
- <line number="138" hits="0"/>
1463
- <line number="139" hits="0"/>
1464
  <line number="140" hits="0"/>
 
 
1465
  <line number="143" hits="0"/>
1466
- <line number="144" hits="0"/>
 
 
 
 
 
 
 
1467
  </lines>
1468
  </class>
1469
- <class name="train_qlora.py" filename="src/absa/models/train_qlora.py" complexity="0" line-rate="0" branch-rate="0">
 
 
 
 
 
 
 
 
1470
  <methods/>
1471
  <lines>
1472
- <line number="5" hits="0"/>
1473
- <line number="6" hits="0"/>
1474
- <line number="7" hits="0"/>
1475
- <line number="16" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1476
  <line number="17" hits="0"/>
1477
  <line number="18" hits="0"/>
1478
- <line number="19" hits="0"/>
1479
- <line number="20" hits="0"/>
1480
- <line number="23" hits="0"/>
1481
  <line number="26" hits="0"/>
1482
- <line number="27" hits="0"/>
1483
  <line number="28" hits="0"/>
1484
  <line number="29" hits="0"/>
1485
  <line number="30" hits="0"/>
1486
- <line number="33" hits="0"/>
1487
- <line number="34" hits="0"/>
1488
  <line number="35" hits="0"/>
1489
  <line number="36" hits="0"/>
1490
  <line number="38" hits="0"/>
 
 
1491
  <line number="41" hits="0"/>
1492
  <line number="42" hits="0"/>
 
 
 
1493
  <line number="48" hits="0"/>
1494
- <line number="49" hits="0"/>
 
1495
  <line number="52" hits="0"/>
 
1496
  <line number="54" hits="0"/>
1497
  <line number="55" hits="0"/>
1498
- <line number="56" hits="0"/>
1499
- <line number="63" hits="0"/>
1500
- <line number="71" hits="0"/>
1501
- <line number="72" hits="0"/>
1502
- <line number="76" hits="0"/>
1503
- <line number="77" hits="0"/>
1504
- <line number="78" hits="0"/>
1505
- <line number="79" hits="0"/>
1506
- <line number="81" hits="0"/>
1507
- <line number="83" hits="0"/>
1508
- <line number="84" hits="0"/>
1509
- <line number="88" hits="0"/>
1510
- <line number="90" hits="0"/>
1511
- <line number="104" hits="0"/>
1512
- <line number="114" hits="0"/>
1513
- <line number="115" hits="0"/>
1514
- <line number="117" hits="0"/>
1515
- <line number="118" hits="0"/>
1516
- <line number="121" hits="0"/>
1517
- <line number="122" hits="0"/>
1518
- <line number="125" hits="0"/>
1519
- <line number="128" hits="0"/>
1520
- <line number="129" hits="0"/>
1521
  </lines>
1522
  </class>
1523
- <class name="train_sentiment.py" filename="src/absa/models/train_sentiment.py" complexity="0" line-rate="0" branch-rate="0">
1524
  <methods/>
1525
  <lines>
1526
- <line number="1" hits="0"/>
1527
- <line number="2" hits="0"/>
1528
- <line number="3" hits="0"/>
1529
- <line number="4" hits="0"/>
1530
- <line number="5" hits="0"/>
1531
- <line number="13" hits="0"/>
 
1532
  <line number="14" hits="0"/>
1533
- <line number="16" hits="0"/>
 
 
1534
  <line number="19" hits="0"/>
1535
- <line number="28" hits="0"/>
1536
- <line number="29" hits="0"/>
1537
- <line number="31" hits="0"/>
1538
- <line number="32" hits="0"/>
1539
- <line number="35" hits="0"/>
1540
- <line number="44" hits="0"/>
1541
- <line number="45" hits="0"/>
1542
- <line number="46" hits="0"/>
1543
- <line number="47" hits="0"/>
1544
- <line number="49" hits="0"/>
1545
- <line number="50" hits="0"/>
1546
- <line number="51" hits="0"/>
1547
- <line number="52" hits="0"/>
1548
- <line number="54" hits="0"/>
1549
- <line number="55" hits="0"/>
1550
- <line number="59" hits="0"/>
1551
- <line number="61" hits="0"/>
1552
- <line number="63" hits="0"/>
1553
- <line number="66" hits="0"/>
1554
- <line number="73" hits="0"/>
1555
- <line number="74" hits="0"/>
1556
- <line number="76" hits="0"/>
1557
- <line number="77" hits="0"/>
1558
- <line number="78" hits="0"/>
1559
- <line number="80" hits="0"/>
1560
- <line number="81" hits="0"/>
1561
- <line number="83" hits="0"/>
1562
- <line number="84" hits="0"/>
1563
- <line number="91" hits="0"/>
1564
- <line number="93" hits="0"/>
1565
- <line number="110" hits="0"/>
1566
- <line number="111" hits="0"/>
1567
- <line number="113" hits="0"/>
1568
- <line number="116" hits="0"/>
1569
- <line number="118" hits="0"/>
1570
- <line number="129" hits="0"/>
1571
- <line number="130" hits="0"/>
1572
- <line number="132" hits="0"/>
1573
- <line number="133" hits="0"/>
1574
- <line number="134" hits="0"/>
1575
- <line number="136" hits="0"/>
1576
- <line number="137" hits="0"/>
1577
- <line number="138" hits="0"/>
1578
- <line number="141" hits="0"/>
1579
- <line number="142" hits="0"/>
1580
- <line number="143" hits="0"/>
1581
- <line number="144" hits="0"/>
1582
- <line number="146" hits="0"/>
1583
- <line number="153" hits="0"/>
1584
- <line number="159" hits="0"/>
1585
- <line number="160" hits="0"/>
1586
- <line number="163" hits="0"/>
1587
- <line number="164" hits="0"/>
1588
  </lines>
1589
  </class>
1590
  </classes>
@@ -1600,33 +1374,33 @@
1600
  <lines>
1601
  <line number="1" hits="0"/>
1602
  <line number="2" hits="0"/>
1603
- <line number="3" hits="0"/>
1604
- <line number="6" hits="0"/>
1605
  <line number="7" hits="0"/>
1606
- <line number="10" hits="0"/>
1607
- <line number="13" hits="0"/>
1608
- <line number="15" hits="0"/>
1609
  <line number="16" hits="0"/>
1610
- <line number="19" hits="0"/>
1611
- <line number="37" hits="0"/>
1612
- <line number="39" hits="0"/>
1613
  <line number="40" hits="0"/>
1614
  <line number="41" hits="0"/>
1615
- <line number="43" hits="0"/>
1616
  <line number="44" hits="0"/>
1617
  <line number="45" hits="0"/>
1618
  <line number="46" hits="0"/>
1619
- <line number="48" hits="0"/>
1620
- <line number="52" hits="0"/>
1621
- <line number="55" hits="0"/>
 
 
 
1622
  <line number="68" hits="0"/>
1623
- <line number="70" hits="0"/>
1624
  <line number="71" hits="0"/>
1625
- <line number="72" hits="0"/>
1626
- <line number="74" hits="0"/>
1627
  <line number="81" hits="0"/>
1628
- <line number="82" hits="0"/>
1629
- <line number="84" hits="0"/>
1630
  </lines>
1631
  </class>
1632
  </classes>
@@ -1661,88 +1435,5 @@
1661
  </class>
1662
  </classes>
1663
  </package>
1664
- <package name="tasks" line-rate="0.2174" branch-rate="0" complexity="0">
1665
- <classes>
1666
- <class name="__init__.py" filename="tasks/__init__.py" complexity="0" line-rate="1" branch-rate="0">
1667
- <methods/>
1668
- <lines>
1669
- <line number="1" hits="1"/>
1670
- <line number="2" hits="1"/>
1671
- <line number="4" hits="1"/>
1672
- <line number="6" hits="1"/>
1673
- <line number="10" hits="1"/>
1674
- </lines>
1675
- </class>
1676
- <class name="batch_tasks.py" filename="tasks/batch_tasks.py" complexity="0" line-rate="0.1562" branch-rate="0">
1677
- <methods/>
1678
- <lines>
1679
- <line number="1" hits="1"/>
1680
- <line number="2" hits="1"/>
1681
- <line number="3" hits="1"/>
1682
- <line number="4" hits="1"/>
1683
- <line number="5" hits="1"/>
1684
- <line number="6" hits="1"/>
1685
- <line number="7" hits="1"/>
1686
- <line number="8" hits="1"/>
1687
- <line number="11" hits="1"/>
1688
- <line number="12" hits="1"/>
1689
- <line number="13" hits="0"/>
1690
- <line number="14" hits="0"/>
1691
- <line number="15" hits="0"/>
1692
- <line number="16" hits="0"/>
1693
- <line number="17" hits="0"/>
1694
- <line number="19" hits="0"/>
1695
- <line number="20" hits="0"/>
1696
- <line number="23" hits="0"/>
1697
- <line number="24" hits="0"/>
1698
- <line number="25" hits="0"/>
1699
- <line number="27" hits="0"/>
1700
- <line number="28" hits="0"/>
1701
- <line number="30" hits="0"/>
1702
- <line number="31" hits="0"/>
1703
- <line number="32" hits="0"/>
1704
- <line number="34" hits="0"/>
1705
- <line number="36" hits="0"/>
1706
- <line number="37" hits="0"/>
1707
- <line number="38" hits="0"/>
1708
- <line number="51" hits="0"/>
1709
- <line number="52" hits="0"/>
1710
- <line number="53" hits="0"/>
1711
- <line number="55" hits="0"/>
1712
- <line number="57" hits="0"/>
1713
- <line number="62" hits="0"/>
1714
- <line number="63" hits="0"/>
1715
- <line number="64" hits="0"/>
1716
- <line number="67" hits="0"/>
1717
- <line number="68" hits="0"/>
1718
- <line number="76" hits="0"/>
1719
- <line number="77" hits="0"/>
1720
- <line number="90" hits="0"/>
1721
- <line number="91" hits="0"/>
1722
- <line number="104" hits="0"/>
1723
- <line number="105" hits="0"/>
1724
- <line number="107" hits="0"/>
1725
- <line number="108" hits="0"/>
1726
- <line number="109" hits="0"/>
1727
- <line number="111" hits="0"/>
1728
- <line number="112" hits="0"/>
1729
- <line number="113" hits="0"/>
1730
- <line number="115" hits="0"/>
1731
- <line number="116" hits="0"/>
1732
- <line number="117" hits="0"/>
1733
- <line number="118" hits="0"/>
1734
- <line number="119" hits="0"/>
1735
- <line number="120" hits="0"/>
1736
- <line number="121" hits="0"/>
1737
- <line number="124" hits="0"/>
1738
- <line number="125" hits="0"/>
1739
- <line number="126" hits="0"/>
1740
- <line number="127" hits="0"/>
1741
- <line number="128" hits="0"/>
1742
- <line number="129" hits="0"/>
1743
- </lines>
1744
- </class>
1745
- </classes>
1746
- </package>
1747
  </packages>
1748
  </coverage>
 
1
  <?xml version="1.0" ?>
2
+ <coverage version="7.14.0" timestamp="1786377350829" lines-valid="1253" lines-covered="245" line-rate="0.1955" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
3
  <!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.14.0 -->
4
  <!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
5
  <sources>
6
  <source>/Users/theogengineer/Projects/Multilingual-Absa</source>
 
7
  </sources>
8
  <packages>
9
+ <package name="src.absa" line-rate="1" branch-rate="0" complexity="0">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  <classes>
11
+ <class name="__init__.py" filename="src/absa/__init__.py" complexity="0" line-rate="1" branch-rate="0">
12
  <methods/>
13
  <lines/>
14
  </class>
15
  </classes>
16
  </package>
17
+ <package name="src.absa.data" line-rate="0.2" branch-rate="0" complexity="0">
18
  <classes>
19
+ <class name="__init__.py" filename="src/absa/data/__init__.py" complexity="0" line-rate="1" branch-rate="0">
20
  <methods/>
21
  <lines/>
22
  </class>
23
+ <class name="augmentation.py" filename="src/absa/data/augmentation.py" complexity="0" line-rate="0" branch-rate="0">
24
  <methods/>
25
  <lines>
26
+ <line number="6" hits="0"/>
27
+ <line number="7" hits="0"/>
28
+ <line number="8" hits="0"/>
29
+ <line number="9" hits="0"/>
 
 
 
30
  <line number="11" hits="0"/>
31
+ <line number="12" hits="0"/>
32
+ <line number="13" hits="0"/>
33
+ <line number="15" hits="0"/>
34
+ <line number="18" hits="0"/>
35
+ <line number="19" hits="0"/>
36
+ <line number="20" hits="0"/>
37
+ <line number="21" hits="0"/>
38
+ <line number="22" hits="0"/>
39
+ <line number="24" hits="0"/>
40
+ <line number="25" hits="0"/>
41
+ <line number="27" hits="0"/>
42
+ <line number="28" hits="0"/>
43
+ <line number="30" hits="0"/>
44
+ <line number="31" hits="0"/>
45
+ <line number="32" hits="0"/>
46
+ <line number="33" hits="0"/>
47
+ <line number="34" hits="0"/>
48
+ <line number="36" hits="0"/>
49
+ <line number="37" hits="0"/>
50
+ <line number="38" hits="0"/>
51
+ <line number="39" hits="0"/>
52
+ <line number="42" hits="0"/>
53
+ <line number="43" hits="0"/>
54
+ <line number="44" hits="0"/>
55
+ <line number="45" hits="0"/>
56
+ <line number="47" hits="0"/>
57
+ <line number="48" hits="0"/>
58
+ <line number="50" hits="0"/>
59
+ <line number="51" hits="0"/>
60
+ <line number="52" hits="0"/>
61
+ <line number="53" hits="0"/>
62
+ <line number="54" hits="0"/>
63
+ <line number="57" hits="0"/>
64
+ <line number="58" hits="0"/>
65
+ <line number="61" hits="0"/>
66
+ <line number="62" hits="0"/>
67
+ <line number="64" hits="0"/>
68
+ <line number="66" hits="0"/>
69
+ <line number="67" hits="0"/>
70
+ <line number="70" hits="0"/>
71
+ <line number="71" hits="0"/>
72
+ <line number="72" hits="0"/>
73
+ <line number="73" hits="0"/>
74
+ <line number="74" hits="0"/>
75
+ <line number="75" hits="0"/>
76
+ <line number="76" hits="0"/>
77
+ <line number="77" hits="0"/>
78
+ <line number="78" hits="0"/>
79
+ <line number="79" hits="0"/>
80
+ <line number="80" hits="0"/>
81
+ <line number="81" hits="0"/>
82
+ <line number="83" hits="0"/>
83
+ <line number="85" hits="0"/>
84
+ <line number="86" hits="0"/>
85
+ <line number="89" hits="0"/>
86
+ <line number="90" hits="0"/>
87
+ <line number="91" hits="0"/>
88
+ <line number="92" hits="0"/>
89
+ <line number="93" hits="0"/>
90
+ <line number="95" hits="0"/>
91
+ <line number="98" hits="0"/>
92
+ <line number="99" hits="0"/>
93
+ <line number="100" hits="0"/>
94
+ <line number="101" hits="0"/>
95
+ <line number="102" hits="0"/>
96
+ <line number="105" hits="0"/>
97
+ <line number="106" hits="0"/>
98
  </lines>
99
  </class>
100
+ <class name="bio_tagger.py" filename="src/absa/data/bio_tagger.py" complexity="0" line-rate="0.9362" branch-rate="0">
 
 
 
 
 
 
 
 
101
  <methods/>
102
  <lines>
103
  <line number="1" hits="1"/>
104
  <line number="2" hits="1"/>
 
 
105
  <line number="5" hits="1"/>
106
+ <line number="16" hits="1"/>
 
 
 
 
 
 
 
 
107
  <line number="18" hits="1"/>
108
  <line number="19" hits="1"/>
109
  <line number="20" hits="1"/>
110
+ <line number="23" hits="1"/>
 
 
 
 
111
  <line number="34" hits="1"/>
 
112
  <line number="37" hits="1"/>
113
+ <line number="39" hits="1"/>
114
+ <line number="40" hits="1"/>
115
+ <line number="41" hits="1"/>
116
+ <line number="43" hits="1"/>
117
+ <line number="44" hits="1"/>
118
+ <line number="47" hits="1"/>
119
  <line number="48" hits="1"/>
120
+ <line number="50" hits="1"/>
121
+ <line number="51" hits="1"/>
122
+ <line number="52" hits="1"/>
123
  <line number="53" hits="1"/>
124
+ <line number="56" hits="1"/>
125
+ <line number="59" hits="1"/>
 
 
126
  <line number="60" hits="1"/>
 
127
  <line number="63" hits="1"/>
128
+ <line number="67" hits="1"/>
129
+ <line number="69" hits="0"/>
 
 
 
130
  <line number="71" hits="1"/>
131
+ <line number="73" hits="1"/>
132
+ <line number="76" hits="1"/>
 
 
 
 
 
 
 
133
  <line number="87" hits="1"/>
134
+ <line number="88" hits="1"/>
135
+ <line number="90" hits="1"/>
136
+ <line number="91" hits="1"/>
137
+ <line number="92" hits="1"/>
138
  <line number="93" hits="1"/>
139
  <line number="94" hits="1"/>
140
  <line number="95" hits="1"/>
141
  <line number="96" hits="1"/>
142
  <line number="97" hits="1"/>
143
+ <line number="100" hits="0"/>
144
  <line number="102" hits="1"/>
145
+ <line number="103" hits="1"/>
146
+ <line number="104" hits="1"/>
147
+ <line number="106" hits="1"/>
148
  <line number="107" hits="0"/>
149
+ <line number="109" hits="1"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  </lines>
151
  </class>
152
+ <class name="dataset.py" filename="src/absa/data/dataset.py" complexity="0" line-rate="0" branch-rate="0">
153
  <methods/>
154
  <lines>
155
+ <line number="1" hits="0"/>
156
+ <line number="2" hits="0"/>
157
+ <line number="4" hits="0"/>
158
+ <line number="6" hits="0"/>
159
+ <line number="7" hits="0"/>
160
+ <line number="8" hits="0"/>
161
+ <line number="11" hits="0"/>
162
+ <line number="12" hits="0"/>
163
+ <line number="13" hits="0"/>
164
+ <line number="15" hits="0"/>
165
+ <line number="16" hits="0"/>
166
+ <line number="18" hits="0"/>
167
+ <line number="19" hits="0"/>
168
+ <line number="21" hits="0"/>
169
+ <line number="27" hits="0"/>
170
+ <line number="28" hits="0"/>
171
+ <line number="29" hits="0"/>
172
+ <line number="30" hits="0"/>
173
+ <line number="31" hits="0"/>
174
  <line number="33" hits="0"/>
 
175
  <line number="35" hits="0"/>
 
176
  <line number="37" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  <line number="41" hits="0"/>
178
  <line number="42" hits="0"/>
179
  <line number="43" hits="0"/>
180
  <line number="44" hits="0"/>
181
  <line number="45" hits="0"/>
182
+ <line number="46" hits="0"/>
183
  <line number="47" hits="0"/>
 
184
  <line number="49" hits="0"/>
185
  <line number="50" hits="0"/>
186
  <line number="51" hits="0"/>
187
  <line number="52" hits="0"/>
188
+ <line number="53" hits="0"/>
189
+ <line number="54" hits="0"/>
190
+ <line number="63" hits="0"/>
191
+ <line number="69" hits="0"/>
192
  <line number="70" hits="0"/>
193
+ <line number="72" hits="0"/>
194
+ <line number="73" hits="0"/>
195
+ <line number="76" hits="0"/>
196
+ <line number="77" hits="0"/>
197
  </lines>
198
  </class>
199
  <class name="hf_dataset.py" filename="src/absa/data/hf_dataset.py" complexity="0" line-rate="0" branch-rate="0">
 
202
  <line number="1" hits="0"/>
203
  <line number="2" hits="0"/>
204
  <line number="3" hits="0"/>
 
205
  <line number="5" hits="0"/>
206
  <line number="6" hits="0"/>
207
  <line number="7" hits="0"/>
208
  <line number="8" hits="0"/>
209
  <line number="9" hits="0"/>
210
  <line number="11" hits="0"/>
211
+ <line number="13" hits="0"/>
 
212
  <line number="16" hits="0"/>
213
  <line number="17" hits="0"/>
214
  <line number="18" hits="0"/>
215
  <line number="19" hits="0"/>
216
  <line number="20" hits="0"/>
217
  <line number="21" hits="0"/>
218
+ <line number="22" hits="0"/>
219
+ <line number="23" hits="0"/>
220
  <line number="26" hits="0"/>
221
+ <line number="28" hits="0"/>
222
  <line number="29" hits="0"/>
 
223
  <line number="31" hits="0"/>
224
  <line number="32" hits="0"/>
225
+ <line number="33" hits="0"/>
226
  <line number="34" hits="0"/>
227
+ <line number="36" hits="0"/>
228
  <line number="37" hits="0"/>
229
+ <line number="39" hits="0"/>
230
+ <line number="46" hits="0"/>
231
  <line number="49" hits="0"/>
232
+ <line number="51" hits="0"/>
233
  <line number="52" hits="0"/>
 
234
  <line number="54" hits="0"/>
235
+ <line number="55" hits="0"/>
236
  <line number="56" hits="0"/>
 
237
  <line number="58" hits="0"/>
238
+ <line number="59" hits="0"/>
239
  <line number="60" hits="0"/>
240
+ <line number="62" hits="0"/>
241
  <line number="63" hits="0"/>
242
+ <line number="65" hits="0"/>
243
+ <line number="73" hits="0"/>
 
244
  <line number="76" hits="0"/>
245
  <line number="77" hits="0"/>
246
  <line number="78" hits="0"/>
 
248
  <line number="80" hits="0"/>
249
  <line number="81" hits="0"/>
250
  <line number="82" hits="0"/>
251
+ <line number="83" hits="0"/>
252
  <line number="84" hits="0"/>
253
+ <line number="86" hits="0"/>
254
+ <line number="87" hits="0"/>
 
255
  <line number="90" hits="0"/>
256
  <line number="91" hits="0"/>
257
+ <line number="92" hits="0"/>
258
+ <line number="93" hits="0"/>
259
  <line number="96" hits="0"/>
260
+ <line number="97" hits="0"/>
261
+ <line number="98" hits="0"/>
262
+ <line number="101" hits="0"/>
263
  <line number="102" hits="0"/>
264
+ <line number="104" hits="0"/>
265
+ <line number="109" hits="0"/>
266
+ <line number="113" hits="0"/>
267
  <line number="114" hits="0"/>
268
+ <line number="116" hits="0"/>
269
+ <line number="117" hits="0"/>
 
270
  <line number="123" hits="0"/>
271
  <line number="124" hits="0"/>
272
  <line number="125" hits="0"/>
273
  <line number="126" hits="0"/>
274
+ <line number="127" hits="0"/>
275
  <line number="128" hits="0"/>
276
+ <line number="130" hits="0"/>
277
+ <line number="138" hits="0"/>
278
+ <line number="143" hits="0"/>
279
+ <line number="144" hits="0"/>
280
+ <line number="149" hits="0"/>
281
+ <line number="152" hits="0"/>
282
  <line number="153" hits="0"/>
283
+ <line number="155" hits="0"/>
284
  <line number="157" hits="0"/>
285
+ <line number="165" hits="0"/>
286
+ <line number="173" hits="0"/>
287
+ <line number="174" hits="0"/>
288
  <line number="175" hits="0"/>
289
  <line number="178" hits="0"/>
290
  <line number="179" hits="0"/>
 
 
291
  </lines>
292
  </class>
293
  <class name="hindi_loader.py" filename="src/absa/data/hindi_loader.py" complexity="0" line-rate="0" branch-rate="0">
294
  <methods/>
295
  <lines>
296
  <line number="1" hits="0"/>
 
297
  <line number="3" hits="0"/>
298
  <line number="4" hits="0"/>
299
+ <line number="5" hits="0"/>
300
  <line number="8" hits="0"/>
301
  <line number="9" hits="0"/>
302
  <line number="10" hits="0"/>
303
  <line number="11" hits="0"/>
304
+ <line number="12" hits="0"/>
305
+ <line number="14" hits="0"/>
306
  <line number="16" hits="0"/>
307
+ <line number="17" hits="0"/>
308
+ <line number="19" hits="0"/>
309
+ <line number="20" hits="0"/>
310
  <line number="21" hits="0"/>
311
  <line number="22" hits="0"/>
312
  <line number="23" hits="0"/>
313
  <line number="24" hits="0"/>
314
+ <line number="26" hits="0"/>
315
  <line number="27" hits="0"/>
316
  <line number="28" hits="0"/>
317
  <line number="29" hits="0"/>
318
  <line number="30" hits="0"/>
319
+ <line number="32" hits="0"/>
320
+ <line number="34" hits="0"/>
321
  <line number="35" hits="0"/>
322
  <line number="36" hits="0"/>
323
+ <line number="38" hits="0"/>
324
+ <line number="40" hits="0"/>
325
+ <line number="42" hits="0"/>
326
+ <line number="48" hits="0"/>
327
  <line number="49" hits="0"/>
328
+ <line number="51" hits="0"/>
329
  <line number="52" hits="0"/>
330
+ <line number="55" hits="0"/>
331
  <line number="56" hits="0"/>
 
332
  </lines>
333
  </class>
334
  <class name="lang_detect.py" filename="src/absa/data/lang_detect.py" complexity="0" line-rate="0.9643" branch-rate="0">
335
  <methods/>
336
  <lines>
337
  <line number="1" hits="1"/>
 
338
  <line number="3" hits="1"/>
339
  <line number="5" hits="1"/>
340
+ <line number="7" hits="1"/>
341
  <line number="10" hits="1"/>
 
342
  <line number="12" hits="1"/>
343
+ <line number="13" hits="1"/>
344
+ <line number="14" hits="1"/>
345
+ <line number="17" hits="1"/>
346
+ <line number="26" hits="1"/>
347
+ <line number="27" hits="0"/>
348
  <line number="29" hits="1"/>
349
+ <line number="30" hits="1"/>
350
  <line number="31" hits="1"/>
 
351
  <line number="33" hits="1"/>
352
  <line number="34" hits="1"/>
353
+ <line number="35" hits="1"/>
354
  <line number="36" hits="1"/>
355
+ <line number="38" hits="1"/>
356
  <line number="39" hits="1"/>
357
  <line number="41" hits="1"/>
358
+ <line number="43" hits="1"/>
359
  <line number="44" hits="1"/>
 
360
  <line number="46" hits="1"/>
361
  <line number="47" hits="1"/>
362
+ <line number="48" hits="1"/>
363
  <line number="49" hits="1"/>
364
+ <line number="51" hits="1"/>
365
  </lines>
366
  </class>
367
  <class name="preprocess.py" filename="src/absa/data/preprocess.py" complexity="0" line-rate="0" branch-rate="0">
 
369
  <lines>
370
  <line number="1" hits="0"/>
371
  <line number="2" hits="0"/>
372
+ <line number="4" hits="0"/>
373
+ <line number="7" hits="0"/>
 
374
  <line number="9" hits="0"/>
375
+ <line number="10" hits="0"/>
376
+ <line number="13" hits="0"/>
377
+ <line number="16" hits="0"/>
378
+ <line number="19" hits="0"/>
379
+ <line number="22" hits="0"/>
380
  <line number="25" hits="0"/>
381
+ <line number="26" hits="0"/>
382
+ <line number="29" hits="0"/>
383
  <line number="32" hits="0"/>
384
+ <line number="33" hits="0"/>
385
+ <line number="35" hits="0"/>
386
  </lines>
387
  </class>
388
  <class name="transliterate.py" filename="src/absa/data/transliterate.py" complexity="0" line-rate="0" branch-rate="0">
 
398
  <line number="11" hits="0"/>
399
  <line number="12" hits="0"/>
400
  <line number="13" hits="0"/>
401
+ <line number="16" hits="0"/>
402
  <line number="18" hits="0"/>
403
+ <line number="19" hits="0"/>
404
  <line number="21" hits="0"/>
405
+ <line number="22" hits="0"/>
406
+ <line number="25" hits="0"/>
407
+ <line number="26" hits="0"/>
408
  <line number="27" hits="0"/>
409
  <line number="28" hits="0"/>
410
+ <line number="31" hits="0"/>
 
411
  <line number="33" hits="0"/>
412
+ <line number="34" hits="0"/>
413
+ <line number="38" hits="0"/>
414
  <line number="39" hits="0"/>
415
+ <line number="41" hits="0"/>
 
 
 
416
  </lines>
417
  </class>
418
  </classes>
 
428
  <lines>
429
  <line number="5" hits="0"/>
430
  <line number="6" hits="0"/>
 
431
  <line number="8" hits="0"/>
432
  <line number="9" hits="0"/>
433
+ <line number="10" hits="0"/>
434
  <line number="12" hits="0"/>
435
+ <line number="13" hits="0"/>
436
  <line number="15" hits="0"/>
437
  <line number="16" hits="0"/>
438
  <line number="17" hits="0"/>
439
+ <line number="18" hits="0"/>
440
  <line number="21" hits="0"/>
441
+ <line number="22" hits="0"/>
442
  <line number="25" hits="0"/>
443
  <line number="26" hits="0"/>
444
  <line number="27" hits="0"/>
445
+ <line number="28" hits="0"/>
446
+ <line number="30" hits="0"/>
447
  <line number="32" hits="0"/>
448
  <line number="33" hits="0"/>
449
+ <line number="34" hits="0"/>
450
+ <line number="36" hits="0"/>
451
  <line number="37" hits="0"/>
452
  <line number="38" hits="0"/>
453
  <line number="39" hits="0"/>
454
+ <line number="41" hits="0"/>
455
  <line number="42" hits="0"/>
456
+ <line number="44" hits="0"/>
457
+ <line number="46" hits="0"/>
458
  <line number="47" hits="0"/>
459
  <line number="48" hits="0"/>
460
+ <line number="50" hits="0"/>
461
+ <line number="53" hits="0"/>
462
  <line number="54" hits="0"/>
463
  <line number="55" hits="0"/>
464
  <line number="56" hits="0"/>
465
  <line number="57" hits="0"/>
466
+ <line number="59" hits="0"/>
467
  <line number="60" hits="0"/>
468
  <line number="61" hits="0"/>
469
+ <line number="63" hits="0"/>
470
  <line number="64" hits="0"/>
471
+ <line number="66" hits="0"/>
472
+ <line number="69" hits="0"/>
473
  <line number="70" hits="0"/>
474
  <line number="71" hits="0"/>
475
+ <line number="73" hits="0"/>
476
  <line number="74" hits="0"/>
477
+ <line number="80" hits="0"/>
478
+ <line number="82" hits="0"/>
479
  <line number="83" hits="0"/>
480
  <line number="84" hits="0"/>
481
  <line number="85" hits="0"/>
482
+ <line number="86" hits="0"/>
483
+ <line number="93" hits="0"/>
484
+ <line number="94" hits="0"/>
485
+ <line number="95" hits="0"/>
486
+ <line number="96" hits="0"/>
487
+ <line number="97" hits="0"/>
488
  <line number="103" hits="0"/>
489
+ <line number="104" hits="0"/>
490
+ <line number="105" hits="0"/>
491
  <line number="106" hits="0"/>
492
+ <line number="107" hits="0"/>
493
+ <line number="110" hits="0"/>
494
+ <line number="111" hits="0"/>
495
  <line number="112" hits="0"/>
496
  <line number="113" hits="0"/>
497
+ <line number="115" hits="0"/>
498
  <line number="117" hits="0"/>
499
  <line number="118" hits="0"/>
500
+ <line number="119" hits="0"/>
501
+ <line number="120" hits="0"/>
502
+ <line number="121" hits="0"/>
503
+ <line number="122" hits="0"/>
504
  <line number="123" hits="0"/>
505
  <line number="124" hits="0"/>
506
+ <line number="127" hits="0"/>
507
+ <line number="128" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
508
  </lines>
509
  </class>
510
  <class name="cross_lingual_eval.py" filename="src/absa/evaluation/cross_lingual_eval.py" complexity="0" line-rate="0" branch-rate="0">
 
512
  <lines>
513
  <line number="1" hits="0"/>
514
  <line number="2" hits="0"/>
 
515
  <line number="4" hits="0"/>
516
+ <line number="5" hits="0"/>
517
+ <line number="6" hits="0"/>
518
+ <line number="7" hits="0"/>
519
+ <line number="14" hits="0"/>
520
  <line number="17" hits="0"/>
521
  <line number="18" hits="0"/>
522
  <line number="19" hits="0"/>
523
  <line number="20" hits="0"/>
524
  <line number="21" hits="0"/>
525
  <line number="22" hits="0"/>
526
+ <line number="23" hits="0"/>
527
  <line number="26" hits="0"/>
528
+ <line number="27" hits="0"/>
529
  <line number="30" hits="0"/>
530
+ <line number="31" hits="0"/>
531
  <line number="33" hits="0"/>
532
+ <line number="34" hits="0"/>
533
+ <line number="35" hits="0"/>
534
+ <line number="37" hits="0"/>
535
  <line number="38" hits="0"/>
536
+ <line number="40" hits="0"/>
537
  <line number="41" hits="0"/>
538
+ <line number="43" hits="0"/>
539
+ <line number="45" hits="0"/>
540
+ <line number="54" hits="0"/>
541
+ <line number="55" hits="0"/>
542
+ <line number="57" hits="0"/>
543
  <line number="59" hits="0"/>
544
+ <line number="61" hits="0"/>
545
  <line number="62" hits="0"/>
546
  <line number="64" hits="0"/>
547
+ <line number="65" hits="0"/>
548
  <line number="66" hits="0"/>
549
+ <line number="68" hits="0"/>
550
  <line number="69" hits="0"/>
551
  <line number="70" hits="0"/>
552
  <line number="71" hits="0"/>
553
+ <line number="72" hits="0"/>
554
  <line number="74" hits="0"/>
 
 
555
  <line number="77" hits="0"/>
556
+ <line number="78" hits="0"/>
557
  <line number="79" hits="0"/>
558
+ <line number="80" hits="0"/>
559
  <line number="82" hits="0"/>
560
+ <line number="83" hits="0"/>
561
+ <line number="84" hits="0"/>
562
  <line number="86" hits="0"/>
563
+ <line number="88" hits="0"/>
564
  <line number="89" hits="0"/>
 
 
565
  <line number="93" hits="0"/>
566
+ <line number="94" hits="0"/>
567
+ <line number="96" hits="0"/>
568
+ <line number="97" hits="0"/>
569
+ <line number="98" hits="0"/>
570
  <line number="104" hits="0"/>
571
  <line number="105" hits="0"/>
572
  <line number="107" hits="0"/>
573
  <line number="108" hits="0"/>
574
  <line number="109" hits="0"/>
575
+ <line number="111" hits="0"/>
576
+ <line number="112" hits="0"/>
577
+ <line number="121" hits="0"/>
 
 
578
  <line number="122" hits="0"/>
 
 
 
579
  </lines>
580
  </class>
581
  <class name="final_eval.py" filename="src/absa/evaluation/final_eval.py" complexity="0" line-rate="0" branch-rate="0">
 
616
  <line number="1" hits="0"/>
617
  <line number="2" hits="0"/>
618
  <line number="3" hits="0"/>
 
619
  <line number="5" hits="0"/>
620
  <line number="6" hits="0"/>
621
  <line number="7" hits="0"/>
 
623
  <line number="9" hits="0"/>
624
  <line number="10" hits="0"/>
625
  <line number="11" hits="0"/>
626
+ <line number="13" hits="0"/>
 
627
  <line number="16" hits="0"/>
628
  <line number="17" hits="0"/>
629
  <line number="18" hits="0"/>
630
  <line number="19" hits="0"/>
631
  <line number="20" hits="0"/>
632
  <line number="21" hits="0"/>
633
+ <line number="22" hits="0"/>
634
+ <line number="23" hits="0"/>
635
+ <line number="26" hits="0"/>
636
+ <line number="39" hits="0"/>
637
+ <line number="40" hits="0"/>
638
+ <line number="42" hits="0"/>
639
+ <line number="43" hits="0"/>
640
+ <line number="44" hits="0"/>
641
+ <line number="46" hits="0"/>
642
+ <line number="47" hits="0"/>
643
+ <line number="48" hits="0"/>
644
+ <line number="49" hits="0"/>
645
+ <line number="50" hits="0"/>
646
+ <line number="53" hits="0"/>
647
+ <line number="54" hits="0"/>
648
+ <line number="55" hits="0"/>
649
+ <line number="59" hits="0"/>
650
+ <line number="62" hits="0"/>
651
+ <line number="65" hits="0"/>
652
+ <line number="66" hits="0"/>
653
+ <line number="68" hits="0"/>
654
+ <line number="69" hits="0"/>
655
+ <line number="71" hits="0"/>
656
+ <line number="72" hits="0"/>
657
+ <line number="74" hits="0"/>
658
+ <line number="77" hits="0"/>
659
+ <line number="78" hits="0"/>
660
+ <line number="81" hits="0"/>
661
+ <line number="82" hits="0"/>
662
+ <line number="83" hits="0"/>
663
+ <line number="86" hits="0"/>
664
+ <line number="87" hits="0"/>
665
+ <line number="88" hits="0"/>
666
+ <line number="91" hits="0"/>
667
+ <line number="92" hits="0"/>
668
+ <line number="93" hits="0"/>
669
+ <line number="95" hits="0"/>
670
+ <line number="98" hits="0"/>
671
+ <line number="110" hits="0"/>
672
+ <line number="111" hits="0"/>
673
+ <line number="112" hits="0"/>
674
+ <line number="113" hits="0"/>
675
+ <line number="114" hits="0"/>
676
+ <line number="117" hits="0"/>
677
+ <line number="125" hits="0"/>
678
+ <line number="128" hits="0"/>
679
+ <line number="129" hits="0"/>
680
+ <line number="130" hits="0"/>
681
+ <line number="132" hits="0"/>
682
+ <line number="135" hits="0"/>
683
+ <line number="136" hits="0"/>
684
+ </lines>
685
+ </class>
686
+ <class name="export_onnx.py" filename="src/absa/models/export_onnx.py" complexity="0" line-rate="0" branch-rate="0">
687
+ <methods/>
688
+ <lines>
689
+ <line number="6" hits="0"/>
690
+ <line number="8" hits="0"/>
691
+ <line number="9" hits="0"/>
692
+ <line number="14" hits="0"/>
693
+ <line number="16" hits="0"/>
694
+ <line number="17" hits="0"/>
695
+ <line number="18" hits="0"/>
696
+ <line number="19" hits="0"/>
697
+ <line number="22" hits="0"/>
698
+ <line number="23" hits="0"/>
699
+ <line number="25" hits="0"/>
700
+ <line number="26" hits="0"/>
701
+ <line number="28" hits="0"/>
702
+ <line number="29" hits="0"/>
703
+ <line number="30" hits="0"/>
704
+ <line number="35" hits="0"/>
705
+ <line number="36" hits="0"/>
706
  <line number="37" hits="0"/>
707
  <line number="38" hits="0"/>
708
  <line number="40" hits="0"/>
 
709
  <line number="42" hits="0"/>
710
  <line number="44" hits="0"/>
711
  <line number="45" hits="0"/>
712
  <line number="46" hits="0"/>
 
713
  <line number="48" hits="0"/>
714
+ <line number="49" hits="0"/>
715
  <line number="52" hits="0"/>
716
  <line number="53" hits="0"/>
717
+ <line number="54" hits="0"/>
718
+ <line number="56" hits="0"/>
719
  <line number="57" hits="0"/>
720
+ <line number="58" hits="0"/>
721
+ <line number="59" hits="0"/>
722
  <line number="60" hits="0"/>
723
  <line number="63" hits="0"/>
724
+ <line number="71" hits="0"/>
725
+ <line number="79" hits="0"/>
726
+ <line number="80" hits="0"/>
727
+ </lines>
728
+ </class>
729
+ <class name="train_aspect_extraction.py" filename="src/absa/models/train_aspect_extraction.py" complexity="0" line-rate="0" branch-rate="0">
730
+ <methods/>
731
+ <lines>
732
+ <line number="1" hits="0"/>
733
+ <line number="3" hits="0"/>
734
+ <line number="4" hits="0"/>
735
+ <line number="5" hits="0"/>
736
+ <line number="6" hits="0"/>
737
+ <line number="7" hits="0"/>
738
+ <line number="16" hits="0"/>
739
+ <line number="19" hits="0"/>
740
+ <line number="28" hits="0"/>
741
+ <line number="29" hits="0"/>
742
+ <line number="31" hits="0"/>
743
+ <line number="33" hits="0"/>
744
+ <line number="37" hits="0"/>
745
+ <line number="43" hits="0"/>
746
+ <line number="47" hits="0"/>
747
+ <line number="50" hits="0"/>
748
+ <line number="57" hits="0"/>
749
+ <line number="58" hits="0"/>
750
+ <line number="60" hits="0"/>
751
+ <line number="61" hits="0"/>
752
+ <line number="62" hits="0"/>
753
+ <line number="64" hits="0"/>
754
+ <line number="65" hits="0"/>
755
+ <line number="67" hits="0"/>
756
+ <line number="68" hits="0"/>
757
+ <line number="75" hits="0"/>
758
+ <line number="77" hits="0"/>
759
+ <line number="93" hits="0"/>
760
+ <line number="103" hits="0"/>
761
+ <line number="104" hits="0"/>
762
+ <line number="106" hits="0"/>
763
+ <line number="107" hits="0"/>
764
+ <line number="108" hits="0"/>
765
+ <line number="110" hits="0"/>
766
+ <line number="111" hits="0"/>
767
+ <line number="112" hits="0"/>
768
+ <line number="116" hits="0"/>
769
+ <line number="117" hits="0"/>
770
+ <line number="119" hits="0"/>
771
+ <line number="122" hits="0"/>
772
+ <line number="123" hits="0"/>
773
+ <line number="126" hits="0"/>
774
+ <line number="127" hits="0"/>
775
+ </lines>
776
+ </class>
777
+ <class name="train_joint_absa.py" filename="src/absa/models/train_joint_absa.py" complexity="0" line-rate="0" branch-rate="0">
778
+ <methods/>
779
+ <lines>
780
+ <line number="5" hits="0"/>
781
+ <line number="6" hits="0"/>
782
+ <line number="7" hits="0"/>
783
+ <line number="9" hits="0"/>
784
+ <line number="10" hits="0"/>
785
+ <line number="11" hits="0"/>
786
+ <line number="12" hits="0"/>
787
+ <line number="13" hits="0"/>
788
+ <line number="14" hits="0"/>
789
+ <line number="22" hits="0"/>
790
+ <line number="27" hits="0"/>
791
+ <line number="30" hits="0"/>
792
+ <line number="31" hits="0"/>
793
+ <line number="32" hits="0"/>
794
+ <line number="33" hits="0"/>
795
+ <line number="34" hits="0"/>
796
+ <line number="35" hits="0"/>
797
+ <line number="36" hits="0"/>
798
+ <line number="39" hits="0"/>
799
+ <line number="40" hits="0"/>
800
+ <line number="41" hits="0"/>
801
+ <line number="42" hits="0"/>
802
+ <line number="43" hits="0"/>
803
+ <line number="45" hits="0"/>
804
+ <line number="46" hits="0"/>
805
+ <line number="49" hits="0"/>
806
+ <line number="52" hits="0"/>
807
+ <line number="54" hits="0"/>
808
+ <line number="56" hits="0"/>
809
  <line number="70" hits="0"/>
810
+ <line number="72" hits="0"/>
811
+ <line number="84" hits="0"/>
 
 
 
 
812
  <line number="85" hits="0"/>
813
+ <line number="88" hits="0"/>
 
 
814
  <line number="91" hits="0"/>
815
  <line number="92" hits="0"/>
816
+ <line number="94" hits="0"/>
817
  <line number="95" hits="0"/>
818
  <line number="96" hits="0"/>
 
819
  <line number="99" hits="0"/>
820
+ <line number="100" hits="0"/>
821
+ <line number="101" hits="0"/>
822
  <line number="106" hits="0"/>
823
+ <line number="109" hits="0"/>
824
+ <line number="115" hits="0"/>
825
+ <line number="117" hits="0"/>
826
  <line number="118" hits="0"/>
827
  <line number="119" hits="0"/>
 
828
  <line number="121" hits="0"/>
829
+ <line number="130" hits="0"/>
830
+ <line number="131" hits="0"/>
831
+ <line number="132" hits="0"/>
832
  <line number="133" hits="0"/>
833
+ <line number="134" hits="0"/>
834
+ <line number="135" hits="0"/>
835
  <line number="136" hits="0"/>
836
+ <line number="139" hits="0"/>
837
+ <line number="141" hits="0"/>
838
+ <line number="142" hits="0"/>
839
  <line number="143" hits="0"/>
840
+ <line number="149" hits="0"/>
841
+ <line number="151" hits="0"/>
842
+ <line number="154" hits="0"/>
843
+ <line number="155" hits="0"/>
844
+ <line number="157" hits="0"/>
845
+ <line number="159" hits="0"/>
846
+ <line number="162" hits="0"/>
847
+ <line number="163" hits="0"/>
848
+ <line number="164" hits="0"/>
849
+ <line number="165" hits="0"/>
850
+ <line number="167" hits="0"/>
851
+ <line number="168" hits="0"/>
852
+ <line number="169" hits="0"/>
853
+ <line number="171" hits="0"/>
854
+ <line number="188" hits="0"/>
855
+ <line number="189" hits="0"/>
856
+ <line number="191" hits="0"/>
857
+ <line number="193" hits="0"/>
858
+ <line number="196" hits="0"/>
859
+ <line number="197" hits="0"/>
860
+ <line number="200" hits="0"/>
861
+ <line number="201" hits="0"/>
862
  </lines>
863
  </class>
864
+ <class name="train_multilingual.py" filename="src/absa/models/train_multilingual.py" complexity="0" line-rate="0" branch-rate="0">
865
  <methods/>
866
  <lines>
867
+ <line number="5" hits="0"/>
868
+ <line number="7" hits="0"/>
869
  <line number="8" hits="0"/>
870
  <line number="9" hits="0"/>
871
+ <line number="10" hits="0"/>
872
+ <line number="11" hits="0"/>
873
+ <line number="12" hits="0"/>
874
+ <line number="21" hits="0"/>
875
+ <line number="24" hits="0"/>
 
876
  <line number="25" hits="0"/>
877
+ <line number="26" hits="0"/>
878
  <line number="27" hits="0"/>
 
879
  <line number="30" hits="0"/>
880
  <line number="31" hits="0"/>
881
  <line number="32" hits="0"/>
882
+ <line number="36" hits="0"/>
883
  <line number="37" hits="0"/>
884
  <line number="38" hits="0"/>
885
+ <line number="40" hits="0"/>
886
  <line number="41" hits="0"/>
887
  <line number="42" hits="0"/>
888
+ <line number="43" hits="0"/>
889
+ <line number="44" hits="0"/>
890
+ <line number="45" hits="0"/>
891
+ <line number="47" hits="0"/>
892
  <line number="50" hits="0"/>
893
+ <line number="53" hits="0"/>
 
894
  <line number="54" hits="0"/>
895
  <line number="55" hits="0"/>
896
+ <line number="56" hits="0"/>
897
  <line number="58" hits="0"/>
898
  <line number="59" hits="0"/>
899
  <line number="60" hits="0"/>
 
900
  <line number="63" hits="0"/>
901
  <line number="64" hits="0"/>
902
  <line number="65" hits="0"/>
903
+ <line number="67" hits="0"/>
904
+ <line number="68" hits="0"/>
905
  <line number="69" hits="0"/>
906
+ <line number="72" hits="0"/>
907
+ <line number="73" hits="0"/>
908
+ <line number="74" hits="0"/>
909
+ <line number="76" hits="0"/>
910
  <line number="77" hits="0"/>
911
+ <line number="78" hits="0"/>
912
+ <line number="80" hits="0"/>
913
+ <line number="81" hits="0"/>
914
+ <line number="83" hits="0"/>
915
  <line number="85" hits="0"/>
916
  <line number="86" hits="0"/>
917
+ <line number="87" hits="0"/>
918
+ <line number="89" hits="0"/>
919
+ <line number="90" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
920
  <line number="92" hits="0"/>
921
+ <line number="94" hits="0"/>
 
 
922
  <line number="106" hits="0"/>
 
 
 
 
923
  <line number="115" hits="0"/>
924
+ <line number="116" hits="0"/>
925
+ <line number="118" hits="0"/>
926
+ <line number="119" hits="0"/>
927
+ <line number="123" hits="0"/>
928
+ <line number="124" hits="0"/>
929
  <line number="125" hits="0"/>
930
+ <line number="126" hits="0"/>
931
  <line number="128" hits="0"/>
932
  <line number="129" hits="0"/>
933
+ <line number="130" hits="0"/>
934
+ <line number="131" hits="0"/>
935
+ <line number="133" hits="0"/>
936
+ <line number="134" hits="0"/>
937
+ <line number="135" hits="0"/>
938
+ <line number="138" hits="0"/>
939
+ <line number="139" hits="0"/>
940
  </lines>
941
  </class>
942
+ <class name="train_qlora.py" filename="src/absa/models/train_qlora.py" complexity="0" line-rate="0" branch-rate="0">
943
  <methods/>
944
  <lines>
945
  <line number="5" hits="0"/>
 
946
  <line number="7" hits="0"/>
947
  <line number="8" hits="0"/>
948
+ <line number="9" hits="0"/>
949
+ <line number="10" hits="0"/>
950
+ <line number="11" hits="0"/>
951
+ <line number="12" hits="0"/>
952
+ <line number="13" hits="0"/>
953
  <line number="24" hits="0"/>
954
+ <line number="27" hits="0"/>
955
+ <line number="28" hits="0"/>
956
  <line number="29" hits="0"/>
957
  <line number="30" hits="0"/>
958
  <line number="31" hits="0"/>
 
 
959
  <line number="34" hits="0"/>
960
  <line number="35" hits="0"/>
961
+ <line number="36" hits="0"/>
962
+ <line number="37" hits="0"/>
963
  <line number="39" hits="0"/>
 
 
964
  <line number="42" hits="0"/>
965
+ <line number="43" hits="0"/>
966
+ <line number="49" hits="0"/>
967
+ <line number="50" hits="0"/>
968
  <line number="51" hits="0"/>
969
  <line number="53" hits="0"/>
970
+ <line number="54" hits="0"/>
971
  <line number="55" hits="0"/>
972
+ <line number="62" hits="0"/>
973
+ <line number="70" hits="0"/>
974
+ <line number="71" hits="0"/>
975
+ <line number="75" hits="0"/>
976
+ <line number="76" hits="0"/>
977
+ <line number="77" hits="0"/>
978
+ <line number="78" hits="0"/>
979
+ <line number="80" hits="0"/>
980
+ <line number="82" hits="0"/>
981
+ <line number="83" hits="0"/>
982
  <line number="85" hits="0"/>
983
+ <line number="87" hits="0"/>
 
 
 
 
 
 
 
984
  <line number="101" hits="0"/>
985
+ <line number="111" hits="0"/>
986
+ <line number="112" hits="0"/>
987
+ <line number="114" hits="0"/>
988
+ <line number="115" hits="0"/>
989
  <line number="118" hits="0"/>
990
  <line number="119" hits="0"/>
 
991
  <line number="122" hits="0"/>
992
+ <line number="125" hits="0"/>
993
+ <line number="126" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
994
  </lines>
995
  </class>
996
+ <class name="train_sentiment.py" filename="src/absa/models/train_sentiment.py" complexity="0" line-rate="0" branch-rate="0">
997
  <methods/>
998
  <lines>
999
+ <line number="1" hits="0"/>
1000
+ <line number="3" hits="0"/>
1001
+ <line number="4" hits="0"/>
1002
  <line number="5" hits="0"/>
1003
  <line number="6" hits="0"/>
1004
  <line number="7" hits="0"/>
1005
+ <line number="8" hits="0"/>
 
1006
  <line number="17" hits="0"/>
 
1007
  <line number="20" hits="0"/>
 
 
 
 
1008
  <line number="29" hits="0"/>
1009
  <line number="30" hits="0"/>
1010
+ <line number="32" hits="0"/>
1011
+ <line number="33" hits="0"/>
1012
+ <line number="36" hits="0"/>
1013
+ <line number="45" hits="0"/>
 
 
 
 
 
 
1014
  <line number="46" hits="0"/>
1015
+ <line number="47" hits="0"/>
1016
+ <line number="48" hits="0"/>
1017
+ <line number="50" hits="0"/>
1018
+ <line number="51" hits="0"/>
1019
+ <line number="52" hits="0"/>
1020
+ <line number="53" hits="0"/>
1021
  <line number="55" hits="0"/>
1022
  <line number="56" hits="0"/>
1023
+ <line number="58" hits="0"/>
 
1024
  <line number="60" hits="0"/>
1025
+ <line number="62" hits="0"/>
 
1026
  <line number="65" hits="0"/>
 
 
 
1027
  <line number="72" hits="0"/>
1028
+ <line number="73" hits="0"/>
1029
  <line number="75" hits="0"/>
1030
  <line number="76" hits="0"/>
1031
  <line number="77" hits="0"/>
 
1034
  <line number="81" hits="0"/>
1035
  <line number="83" hits="0"/>
1036
  <line number="84" hits="0"/>
 
 
 
 
1037
  <line number="92" hits="0"/>
1038
+ <line number="94" hits="0"/>
 
 
1039
  <line number="111" hits="0"/>
1040
+ <line number="112" hits="0"/>
1041
+ <line number="114" hits="0"/>
1042
+ <line number="115" hits="0"/>
1043
+ <line number="117" hits="0"/>
1044
  <line number="128" hits="0"/>
1045
  <line number="129" hits="0"/>
 
1046
  <line number="131" hits="0"/>
1047
+ <line number="132" hits="0"/>
1048
  <line number="133" hits="0"/>
 
1049
  <line number="135" hits="0"/>
1050
  <line number="136" hits="0"/>
1051
+ <line number="137" hits="0"/>
 
1052
  <line number="140" hits="0"/>
1053
+ <line number="141" hits="0"/>
1054
+ <line number="142" hits="0"/>
1055
  <line number="143" hits="0"/>
1056
+ <line number="145" hits="0"/>
1057
+ <line number="146" hits="0"/>
1058
+ <line number="148" hits="0"/>
1059
+ <line number="151" hits="0"/>
1060
+ <line number="157" hits="0"/>
1061
+ <line number="158" hits="0"/>
1062
+ <line number="161" hits="0"/>
1063
+ <line number="162" hits="0"/>
1064
  </lines>
1065
  </class>
1066
+ </classes>
1067
+ </package>
1068
+ <package name="src.absa.pipeline" line-rate="0.5815" branch-rate="0" complexity="0">
1069
+ <classes>
1070
+ <class name="__init__.py" filename="src/absa/pipeline/__init__.py" complexity="0" line-rate="1" branch-rate="0">
1071
+ <methods/>
1072
+ <lines/>
1073
+ </class>
1074
+ <class name="absa_pipeline.py" filename="src/absa/pipeline/absa_pipeline.py" complexity="0" line-rate="0.6318" branch-rate="0">
1075
  <methods/>
1076
  <lines>
1077
+ <line number="13" hits="1"/>
1078
+ <line number="14" hits="1"/>
1079
+ <line number="15" hits="1"/>
1080
+ <line number="16" hits="1"/>
1081
+ <line number="17" hits="1"/>
1082
+ <line number="18" hits="1"/>
1083
+ <line number="20" hits="1"/>
1084
+ <line number="22" hits="1"/>
1085
+ <line number="23" hits="1"/>
1086
+ <line number="26" hits="1"/>
1087
+ <line number="27" hits="1"/>
1088
+ <line number="31" hits="0"/>
1089
+ <line number="33" hits="0"/>
1090
+ <line number="34" hits="1"/>
1091
+ <line number="35" hits="1"/>
1092
+ <line number="36" hits="1"/>
1093
+ <line number="38" hits="0"/>
1094
+ <line number="39" hits="1"/>
1095
+ <line number="40" hits="1"/>
1096
+ <line number="44" hits="1"/>
1097
+ <line number="151" hits="1"/>
1098
+ <line number="256" hits="1"/>
1099
+ <line number="346" hits="1"/>
1100
+ <line number="424" hits="1"/>
1101
+ <line number="448" hits="1"/>
1102
+ <line number="466" hits="1"/>
1103
+ <line number="472" hits="1"/>
1104
+ <line number="479" hits="1"/>
1105
+ <line number="481" hits="1"/>
1106
+ <line number="482" hits="1"/>
1107
+ <line number="485" hits="1"/>
1108
+ <line number="490" hits="1"/>
1109
+ <line number="491" hits="1"/>
1110
+ <line number="492" hits="1"/>
1111
+ <line number="493" hits="1"/>
1112
+ <line number="494" hits="1"/>
1113
+ <line number="496" hits="1"/>
1114
+ <line number="497" hits="1"/>
1115
+ <line number="499" hits="1"/>
1116
+ <line number="501" hits="1"/>
1117
+ <line number="502" hits="1"/>
1118
+ <line number="503" hits="1"/>
1119
+ <line number="505" hits="1"/>
1120
+ <line number="506" hits="1"/>
1121
+ <line number="507" hits="1"/>
1122
+ <line number="508" hits="0"/>
1123
+ <line number="510" hits="1"/>
1124
+ <line number="511" hits="1"/>
1125
+ <line number="512" hits="1"/>
1126
+ <line number="515" hits="1"/>
1127
+ <line number="517" hits="1"/>
1128
+ <line number="518" hits="1"/>
1129
+ <line number="519" hits="1"/>
1130
+ <line number="520" hits="1"/>
1131
+ <line number="521" hits="1"/>
1132
+ <line number="522" hits="1"/>
1133
+ <line number="523" hits="1"/>
1134
+ <line number="524" hits="1"/>
1135
+ <line number="525" hits="1"/>
1136
+ <line number="526" hits="1"/>
1137
+ <line number="527" hits="0"/>
1138
+ <line number="533" hits="1"/>
1139
+ <line number="534" hits="1"/>
1140
+ <line number="535" hits="1"/>
1141
+ <line number="536" hits="1"/>
1142
+ <line number="537" hits="1"/>
1143
+ <line number="538" hits="1"/>
1144
+ <line number="539" hits="1"/>
1145
+ <line number="541" hits="1"/>
1146
+ <line number="542" hits="1"/>
1147
+ <line number="549" hits="1"/>
1148
+ <line number="551" hits="0"/>
1149
+ <line number="552" hits="0"/>
1150
+ <line number="553" hits="0"/>
1151
+ <line number="555" hits="0"/>
1152
+ <line number="556" hits="0"/>
1153
+ <line number="557" hits="0"/>
1154
+ <line number="558" hits="0"/>
1155
+ <line number="559" hits="0"/>
1156
+ <line number="562" hits="0"/>
1157
+ <line number="565" hits="0"/>
1158
+ <line number="566" hits="0"/>
1159
+ <line number="567" hits="0"/>
1160
+ <line number="569" hits="0"/>
1161
+ <line number="570" hits="0"/>
1162
+ <line number="571" hits="0"/>
1163
+ <line number="572" hits="0"/>
1164
+ <line number="573" hits="0"/>
1165
+ <line number="574" hits="0"/>
1166
+ <line number="575" hits="0"/>
1167
+ <line number="577" hits="0"/>
1168
+ <line number="578" hits="0"/>
1169
+ <line number="579" hits="0"/>
1170
+ <line number="580" hits="0"/>
1171
+ <line number="581" hits="0"/>
1172
+ <line number="582" hits="0"/>
1173
+ <line number="583" hits="0"/>
1174
+ <line number="584" hits="0"/>
1175
+ <line number="585" hits="0"/>
1176
+ <line number="587" hits="0"/>
1177
+ <line number="588" hits="0"/>
1178
+ <line number="590" hits="0"/>
1179
+ <line number="592" hits="1"/>
1180
+ <line number="593" hits="1"/>
1181
+ <line number="594" hits="1"/>
1182
+ <line number="595" hits="1"/>
1183
+ <line number="597" hits="1"/>
1184
+ <line number="598" hits="0"/>
1185
+ <line number="600" hits="1"/>
1186
+ <line number="602" hits="1"/>
1187
+ <line number="610" hits="1"/>
1188
+ <line number="611" hits="0"/>
1189
+ <line number="615" hits="1"/>
1190
+ <line number="616" hits="0"/>
1191
+ <line number="617" hits="0"/>
1192
+ <line number="618" hits="0"/>
1193
+ <line number="619" hits="0"/>
1194
+ <line number="620" hits="0"/>
1195
+ <line number="621" hits="0"/>
1196
+ <line number="622" hits="0"/>
1197
+ <line number="624" hits="0"/>
1198
+ <line number="625" hits="0"/>
1199
+ <line number="626" hits="0"/>
1200
+ <line number="627" hits="0"/>
1201
+ <line number="632" hits="0"/>
1202
+ <line number="633" hits="0"/>
1203
+ <line number="634" hits="0"/>
1204
+ <line number="635" hits="0"/>
1205
+ <line number="636" hits="0"/>
1206
+ <line number="637" hits="0"/>
1207
+ <line number="638" hits="0"/>
1208
+ <line number="639" hits="0"/>
1209
+ <line number="640" hits="0"/>
1210
+ <line number="641" hits="0"/>
1211
+ <line number="643" hits="0"/>
1212
+ <line number="644" hits="0"/>
1213
+ <line number="645" hits="0"/>
1214
+ <line number="646" hits="0"/>
1215
+ <line number="647" hits="0"/>
1216
+ <line number="649" hits="0"/>
1217
+ <line number="650" hits="0"/>
1218
+ <line number="651" hits="0"/>
1219
+ <line number="658" hits="0"/>
1220
+ <line number="659" hits="0"/>
1221
+ <line number="660" hits="0"/>
1222
+ <line number="661" hits="0"/>
1223
+ <line number="662" hits="0"/>
1224
+ <line number="671" hits="0"/>
1225
+ <line number="675" hits="1"/>
1226
+ <line number="676" hits="1"/>
1227
+ <line number="677" hits="1"/>
1228
+ <line number="678" hits="1"/>
1229
+ <line number="681" hits="1"/>
1230
+ <line number="682" hits="1"/>
1231
+ <line number="686" hits="1"/>
1232
+ <line number="687" hits="1"/>
1233
+ <line number="689" hits="1"/>
1234
+ <line number="690" hits="1"/>
1235
+ <line number="694" hits="1"/>
1236
+ <line number="695" hits="1"/>
1237
+ <line number="696" hits="1"/>
1238
+ <line number="698" hits="1"/>
1239
+ <line number="701" hits="1"/>
1240
+ <line number="702" hits="1"/>
1241
+ <line number="703" hits="1"/>
1242
+ <line number="705" hits="1"/>
1243
+ <line number="706" hits="1"/>
1244
+ <line number="715" hits="1"/>
1245
+ <line number="717" hits="1"/>
1246
+ <line number="723" hits="1"/>
1247
+ <line number="724" hits="1"/>
1248
+ <line number="726" hits="1"/>
1249
+ <line number="727" hits="1"/>
1250
+ <line number="729" hits="1"/>
1251
+ <line number="730" hits="1"/>
1252
+ <line number="731" hits="1"/>
1253
+ <line number="732" hits="1"/>
1254
+ <line number="733" hits="1"/>
1255
+ <line number="734" hits="1"/>
1256
+ <line number="735" hits="1"/>
1257
+ <line number="736" hits="0"/>
1258
+ <line number="737" hits="1"/>
1259
+ <line number="738" hits="1"/>
1260
+ <line number="739" hits="1"/>
1261
+ <line number="741" hits="1"/>
1262
+ <line number="742" hits="1"/>
1263
+ <line number="744" hits="1"/>
1264
+ <line number="746" hits="1"/>
1265
+ <line number="747" hits="1"/>
1266
+ <line number="749" hits="1"/>
1267
+ <line number="750" hits="1"/>
1268
+ <line number="751" hits="1"/>
1269
+ <line number="753" hits="1"/>
1270
+ <line number="754" hits="1"/>
1271
+ <line number="755" hits="1"/>
1272
+ <line number="756" hits="1"/>
1273
+ <line number="757" hits="1"/>
1274
+ <line number="758" hits="1"/>
1275
+ <line number="760" hits="1"/>
1276
+ <line number="761" hits="1"/>
1277
+ <line number="764" hits="1"/>
1278
+ </lines>
1279
+ </class>
1280
+ <class name="db_models.py" filename="src/absa/pipeline/db_models.py" complexity="0" line-rate="0" branch-rate="0">
1281
+ <methods/>
1282
+ <lines>
1283
+ <line number="8" hits="0"/>
1284
+ <line number="10" hits="0"/>
1285
+ <line number="11" hits="0"/>
1286
+ <line number="13" hits="0"/>
1287
+ <line number="14" hits="0"/>
1288
  <line number="17" hits="0"/>
1289
  <line number="18" hits="0"/>
1290
+ <line number="21" hits="0"/>
1291
+ <line number="22" hits="0"/>
1292
+ <line number="25" hits="0"/>
1293
  <line number="26" hits="0"/>
 
1294
  <line number="28" hits="0"/>
1295
  <line number="29" hits="0"/>
1296
  <line number="30" hits="0"/>
1297
+ <line number="31" hits="0"/>
1298
+ <line number="32" hits="0"/>
1299
  <line number="35" hits="0"/>
1300
  <line number="36" hits="0"/>
1301
  <line number="38" hits="0"/>
1302
+ <line number="39" hits="0"/>
1303
+ <line number="40" hits="0"/>
1304
  <line number="41" hits="0"/>
1305
  <line number="42" hits="0"/>
1306
+ <line number="43" hits="0"/>
1307
+ <line number="44" hits="0"/>
1308
+ <line number="47" hits="0"/>
1309
  <line number="48" hits="0"/>
1310
+ <line number="50" hits="0"/>
1311
+ <line number="51" hits="0"/>
1312
  <line number="52" hits="0"/>
1313
+ <line number="53" hits="0"/>
1314
  <line number="54" hits="0"/>
1315
  <line number="55" hits="0"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1316
  </lines>
1317
  </class>
1318
+ <class name="lang_service.py" filename="src/absa/pipeline/lang_service.py" complexity="0" line-rate="0.7" branch-rate="0">
1319
  <methods/>
1320
  <lines>
1321
+ <line number="1" hits="1"/>
1322
+ <line number="3" hits="1"/>
1323
+ <line number="6" hits="1"/>
1324
+ <line number="7" hits="1"/>
1325
+ <line number="11" hits="1"/>
1326
+ <line number="12" hits="1"/>
1327
+ <line number="13" hits="1"/>
1328
  <line number="14" hits="0"/>
1329
+ <line number="16" hits="1"/>
1330
+ <line number="17" hits="1"/>
1331
+ <line number="18" hits="0"/>
1332
  <line number="19" hits="0"/>
1333
+ <line number="20" hits="0"/>
1334
+ <line number="21" hits="0"/>
1335
+ <line number="23" hits="0"/>
1336
+ <line number="26" hits="1"/>
1337
+ <line number="27" hits="1"/>
1338
+ <line number="28" hits="1"/>
1339
+ <line number="29" hits="1"/>
1340
+ <line number="32" hits="1"/>
1341
+ </lines>
1342
+ </class>
1343
+ <class name="schemas.py" filename="src/absa/pipeline/schemas.py" complexity="0" line-rate="1" branch-rate="0">
1344
+ <methods/>
1345
+ <lines>
1346
+ <line number="1" hits="1"/>
1347
+ <line number="3" hits="1"/>
1348
+ <line number="6" hits="1"/>
1349
+ <line number="7" hits="1"/>
1350
+ <line number="8" hits="1"/>
1351
+ <line number="9" hits="1"/>
1352
+ <line number="10" hits="1"/>
1353
+ <line number="11" hits="1"/>
1354
+ <line number="13" hits="1"/>
1355
+ <line number="16" hits="1"/>
1356
+ <line number="17" hits="1"/>
1357
+ <line number="18" hits="1"/>
1358
+ <line number="19" hits="1"/>
1359
+ <line number="20" hits="1"/>
1360
+ <line number="21" hits="1"/>
1361
+ <line number="23" hits="1"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1362
  </lines>
1363
  </class>
1364
  </classes>
 
1374
  <lines>
1375
  <line number="1" hits="0"/>
1376
  <line number="2" hits="0"/>
1377
+ <line number="4" hits="0"/>
 
1378
  <line number="7" hits="0"/>
1379
+ <line number="8" hits="0"/>
1380
+ <line number="11" hits="0"/>
1381
+ <line number="14" hits="0"/>
1382
  <line number="16" hits="0"/>
1383
+ <line number="17" hits="0"/>
1384
+ <line number="20" hits="0"/>
1385
+ <line number="38" hits="0"/>
1386
  <line number="40" hits="0"/>
1387
  <line number="41" hits="0"/>
1388
+ <line number="42" hits="0"/>
1389
  <line number="44" hits="0"/>
1390
  <line number="45" hits="0"/>
1391
  <line number="46" hits="0"/>
1392
+ <line number="47" hits="0"/>
1393
+ <line number="49" hits="0"/>
1394
+ <line number="51" hits="0"/>
1395
+ <line number="54" hits="0"/>
1396
+ <line number="65" hits="0"/>
1397
+ <line number="67" hits="0"/>
1398
  <line number="68" hits="0"/>
1399
+ <line number="69" hits="0"/>
1400
  <line number="71" hits="0"/>
1401
+ <line number="78" hits="0"/>
1402
+ <line number="79" hits="0"/>
1403
  <line number="81" hits="0"/>
 
 
1404
  </lines>
1405
  </class>
1406
  </classes>
 
1435
  </class>
1436
  </classes>
1437
  </package>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1438
  </packages>
1439
  </coverage>
data/.gitignore DELETED
@@ -1 +0,0 @@
1
- /raw
 
 
data/demo/demo_single_reviews.txt DELETED
@@ -1,5 +0,0 @@
1
- The phone has an amazing screen but the battery life is terrible.
2
- I absolutely love the camera quality on this device.
3
- फोन की बैटरी अच्छी है लेकिन कैमरा बेकार है
4
- खाना बहुत स्वादिष्ट था, पर सर्विस थोड़ी स्लो थी
5
- Design mast hai par price bahut high hai
 
 
 
 
 
 
data/demo/sample_reviews.csv DELETED
@@ -1,21 +0,0 @@
1
- text,language
2
- "The phone has an amazing screen but the battery life is terrible.",en
3
- "I absolutely love the camera quality on this device.",en
4
- "Shipping was very fast, but the customer service was useless when I had a question.",en
5
- "The laptop keyboard feels incredibly cheap, though it runs fast.",en
6
- "Amazing food, terrible atmosphere.",en
7
- "Best purchase I made this year. High quality materials.",en
8
- "The speakers are loud but the bass is non-existent.",en
9
- "Wait staff was friendly, food was completely cold.",en
10
- "I like the design but the software has too many bugs.",en
11
- "Great value for money, highly recommended.",en
12
- "फोन की बैटरी अच्छी है लेकिन कैमरा बेकार है",hi
13
- "मुझे इस लैपटॉप की स्क्रीन बहुत पसंद आई",hi
14
- "डिलीवरी बहुत लेट थी और पैकिंग भी खराब थी",hi
15
- "खाना बहुत स्वादिष्ट था, पर सर्विस थोड़ी स्लो थी",hi
16
- "यह प्रोडक्ट पैसे की बर्बादी है",hi
17
- "Design mast hai par price bahut high hai",hinglish
18
- "Screen quality ekdum awesome hai bhai",hinglish
19
- "Customer support ne help nahi ki, very bad experience",hinglish
20
- "Look and feel to accha hai but performance thik thak hai",hinglish
21
- "Battery drain jaldi hota hai, overall not good",hinglish
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/models/lid.176.ftz DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:8f3472cfe8738a7b6099e8e999c3cbfae0dcd15696aac7d7738a8039db603e83
3
- size 938013
 
 
 
 
data/raw.dvc DELETED
@@ -1,6 +0,0 @@
1
- outs:
2
- - md5: 0d10b4997c93bd1bce4a9d53a6e4748e.dir
3
- size: 7943297
4
- nfiles: 21
5
- hash: md5
6
- path: raw
 
 
 
 
 
 
 
data/tokenized/absa_cls_dataset/dataset_dict.json DELETED
@@ -1 +0,0 @@
1
- {"splits": ["train", "validation", "test"]}
 
 
data/tokenized/absa_cls_dataset/test/data-00000-of-00001.arrow DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:1eb8d8230357e82431b68c2226770b209f0a61fe34425c0fd037b17f913a028c
3
- size 101864
 
 
 
 
data/tokenized/absa_cls_dataset/test/dataset_info.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "citation": "",
3
- "description": "",
4
- "features": {
5
- "label": {
6
- "dtype": "int64",
7
- "_type": "Value"
8
- },
9
- "input_ids": {
10
- "feature": {
11
- "dtype": "int32",
12
- "_type": "Value"
13
- },
14
- "_type": "Sequence"
15
- },
16
- "attention_mask": {
17
- "feature": {
18
- "dtype": "int8",
19
- "_type": "Value"
20
- },
21
- "_type": "Sequence"
22
- }
23
- },
24
- "homepage": "",
25
- "license": ""
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_cls_dataset/test/state.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "_data_files": [
3
- {
4
- "filename": "data-00000-of-00001.arrow"
5
- }
6
- ],
7
- "_fingerprint": "b686d9c13fd54a9d",
8
- "_format_columns": null,
9
- "_format_kwargs": {},
10
- "_format_type": null,
11
- "_output_all_columns": false,
12
- "_split": null
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_cls_dataset/train/data-00000-of-00001.arrow DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:74827f37b8915b4946a33e030d5833d109bfcf9d9d847edf54fd830fe33a0a3d
3
- size 808112
 
 
 
 
data/tokenized/absa_cls_dataset/train/dataset_info.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "citation": "",
3
- "description": "",
4
- "features": {
5
- "label": {
6
- "dtype": "int64",
7
- "_type": "Value"
8
- },
9
- "input_ids": {
10
- "feature": {
11
- "dtype": "int32",
12
- "_type": "Value"
13
- },
14
- "_type": "Sequence"
15
- },
16
- "attention_mask": {
17
- "feature": {
18
- "dtype": "int8",
19
- "_type": "Value"
20
- },
21
- "_type": "Sequence"
22
- }
23
- },
24
- "homepage": "",
25
- "license": ""
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_cls_dataset/train/state.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "_data_files": [
3
- {
4
- "filename": "data-00000-of-00001.arrow"
5
- }
6
- ],
7
- "_fingerprint": "59c1808a1a0be248",
8
- "_format_columns": null,
9
- "_format_kwargs": {},
10
- "_format_type": null,
11
- "_output_all_columns": false,
12
- "_split": null
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_cls_dataset/validation/data-00000-of-00001.arrow DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:a9da21b3401a16a246766047cda0695dcf07ef7d3c7eb64804ed9f59f0746f08
3
- size 105136
 
 
 
 
data/tokenized/absa_cls_dataset/validation/dataset_info.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "citation": "",
3
- "description": "",
4
- "features": {
5
- "label": {
6
- "dtype": "int64",
7
- "_type": "Value"
8
- },
9
- "input_ids": {
10
- "feature": {
11
- "dtype": "int32",
12
- "_type": "Value"
13
- },
14
- "_type": "Sequence"
15
- },
16
- "attention_mask": {
17
- "feature": {
18
- "dtype": "int8",
19
- "_type": "Value"
20
- },
21
- "_type": "Sequence"
22
- }
23
- },
24
- "homepage": "",
25
- "license": ""
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_cls_dataset/validation/state.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "_data_files": [
3
- {
4
- "filename": "data-00000-of-00001.arrow"
5
- }
6
- ],
7
- "_fingerprint": "a33b9cfd2402e633",
8
- "_format_columns": null,
9
- "_format_kwargs": {},
10
- "_format_type": null,
11
- "_output_all_columns": false,
12
- "_split": null
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_ner_dataset/dataset_dict.json DELETED
@@ -1 +0,0 @@
1
- {"splits": ["train", "validation", "test"]}
 
 
data/tokenized/absa_ner_dataset/test/data-00000-of-00001.arrow DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e1ec218e3b5b0c88fd86358c8e87f44709510cff43c41a81dac98274ce4eb0e7
3
- size 141712
 
 
 
 
data/tokenized/absa_ner_dataset/test/dataset_info.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "citation": "",
3
- "description": "",
4
- "features": {
5
- "input_ids": {
6
- "feature": {
7
- "dtype": "int32",
8
- "_type": "Value"
9
- },
10
- "_type": "Sequence"
11
- },
12
- "attention_mask": {
13
- "feature": {
14
- "dtype": "int8",
15
- "_type": "Value"
16
- },
17
- "_type": "Sequence"
18
- },
19
- "labels": {
20
- "feature": {
21
- "dtype": "int64",
22
- "_type": "Value"
23
- },
24
- "_type": "Sequence"
25
- }
26
- },
27
- "homepage": "",
28
- "license": ""
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_ner_dataset/test/state.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "_data_files": [
3
- {
4
- "filename": "data-00000-of-00001.arrow"
5
- }
6
- ],
7
- "_fingerprint": "0fa99b895566c7b5",
8
- "_format_columns": null,
9
- "_format_kwargs": {},
10
- "_format_type": null,
11
- "_output_all_columns": false,
12
- "_split": null
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_ner_dataset/train/data-00000-of-00001.arrow DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:76c719d76d95127fc82691bbe1455e988c0c593fcdd510f270deac3e625cb929
3
- size 1101368
 
 
 
 
data/tokenized/absa_ner_dataset/train/dataset_info.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "citation": "",
3
- "description": "",
4
- "features": {
5
- "input_ids": {
6
- "feature": {
7
- "dtype": "int32",
8
- "_type": "Value"
9
- },
10
- "_type": "Sequence"
11
- },
12
- "attention_mask": {
13
- "feature": {
14
- "dtype": "int8",
15
- "_type": "Value"
16
- },
17
- "_type": "Sequence"
18
- },
19
- "labels": {
20
- "feature": {
21
- "dtype": "int64",
22
- "_type": "Value"
23
- },
24
- "_type": "Sequence"
25
- }
26
- },
27
- "homepage": "",
28
- "license": ""
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_ner_dataset/train/state.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "_data_files": [
3
- {
4
- "filename": "data-00000-of-00001.arrow"
5
- }
6
- ],
7
- "_fingerprint": "535b22b0ddf3661d",
8
- "_format_columns": null,
9
- "_format_kwargs": {},
10
- "_format_type": null,
11
- "_output_all_columns": false,
12
- "_split": null
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_ner_dataset/validation/data-00000-of-00001.arrow DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:f94a6981561bcaa124a70fb560b93e355e57df287e9e721a2e6e887b6689b236
3
- size 144312
 
 
 
 
data/tokenized/absa_ner_dataset/validation/dataset_info.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "citation": "",
3
- "description": "",
4
- "features": {
5
- "input_ids": {
6
- "feature": {
7
- "dtype": "int32",
8
- "_type": "Value"
9
- },
10
- "_type": "Sequence"
11
- },
12
- "attention_mask": {
13
- "feature": {
14
- "dtype": "int8",
15
- "_type": "Value"
16
- },
17
- "_type": "Sequence"
18
- },
19
- "labels": {
20
- "feature": {
21
- "dtype": "int64",
22
- "_type": "Value"
23
- },
24
- "_type": "Sequence"
25
- }
26
- },
27
- "homepage": "",
28
- "license": ""
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/tokenized/absa_ner_dataset/validation/state.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "_data_files": [
3
- {
4
- "filename": "data-00000-of-00001.arrow"
5
- }
6
- ],
7
- "_fingerprint": "caedb7425c742cc1",
8
- "_format_columns": null,
9
- "_format_kwargs": {},
10
- "_format_type": null,
11
- "_output_all_columns": false,
12
- "_split": null
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docker/Dockerfile DELETED
@@ -1,42 +0,0 @@
1
- # Stage 1: Builder
2
- FROM python:3.11-slim AS builder
3
-
4
- WORKDIR /app
5
- COPY pyproject.toml .
6
- COPY src ./src
7
- COPY api ./api
8
-
9
- RUN apt-get update && apt-get install -y --no-install-recommends \
10
- build-essential \
11
- git \
12
- && rm -rf /var/lib/apt/lists/*
13
-
14
- RUN pip install --no-cache-dir --prefix=/install .
15
-
16
- # Stage 2: Runtime
17
- FROM python:3.11-slim
18
-
19
- WORKDIR /app
20
-
21
- # Copy dependencies
22
- COPY --from=builder /install /usr/local
23
-
24
- # Copy application code
25
- COPY api /app/api
26
- COPY src /app/src
27
- COPY scripts /app/scripts
28
- COPY docker /app/docker
29
- COPY .env.example /app/.env.example
30
- # .env is injected via docker-compose environment vars — no need to COPY it
31
-
32
- ENV PYTHONPATH=/app/src
33
-
34
- # Add a non-root user
35
- RUN adduser --disabled-password --gecos "" absauser \
36
- && chown -R absauser /app
37
-
38
- USER absauser
39
-
40
- EXPOSE 8000
41
-
42
- CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docker/Dockerfile.prod DELETED
@@ -1,19 +0,0 @@
1
- FROM python:3.11-slim as builder
2
- WORKDIR /app
3
- COPY pyproject.toml .
4
- COPY src ./src
5
- COPY api ./api
6
- RUN pip install --no-cache-dir .
7
-
8
- FROM python:3.11-slim as runtime
9
- WORKDIR /app
10
- COPY --from=builder /usr/local/lib/python3.11 /usr/local/lib/python3.11
11
- COPY --from=builder /usr/local/bin /usr/local/bin
12
- COPY api/ ./api/
13
- COPY src/ ./src/
14
- ENV PYTHONPATH=/app/src
15
- ENV MODEL_SOURCE=huggingface_hub
16
- RUN useradd -m appuser && chown -R appuser /app
17
- USER appuser
18
- EXPOSE 8000
19
- CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docker/docker-compose.prod.yml DELETED
@@ -1,16 +0,0 @@
1
- version: "3.9"
2
- services:
3
- api:
4
- image: ghcr.io/YOUR_USERNAME/multilingual-absa/api:latest
5
- restart: always
6
- environment:
7
- - LOG_LEVEL=WARNING
8
- deploy:
9
- resources:
10
- limits:
11
- memory: 2G
12
- worker:
13
- image: ghcr.io/YOUR_USERNAME/multilingual-absa/api:latest
14
- command: celery -A api.tasks.batch_tasks worker --loglevel=warning
15
- restart: always
16
-