Skip to content

Latest commit

 

History

History
151 lines (118 loc) · 6.57 KB

CONTRIBUTING.md

File metadata and controls

151 lines (118 loc) · 6.57 KB

Contributing to Complaint Router NLP

Thanks for taking the time to contribute. This is a notebook-driven NLP / ML project — the guidelines below keep it reproducible, reviewable, and runnable on modest hardware.

Table of contents

Ways to contribute

  • Bug reports and fixes — pipeline breakage, wrong metrics, data-loading edge cases, memory blow-ups.
  • Features from the roadmap — calibrated probabilities, sub-routers for the non-Loans lanes, a DistilBERT baseline, packaging route_complaint() as a CLI, CI.
  • Documentation — clearer explanations, diagrams, worked examples.
  • Performance / memory improvements — the notebooks are deliberately written to run on a laptop; keep it that way.

Ground rules

  1. The notebooks are the source of truth. There is no separate library — each NN_name.ipynb is self-contained and reads the artifacts written by the notebooks before it (00 → 05).
  2. A clean "Restart & Run All" must pass, top to bottom, on the complaint-router-venv kernel.
  3. One concern per pull request. A metrics change and a feature change are two PRs.
  4. Be honest about results. If a change lowers a score, say so and explain the trade-off. Numbers in the README must match a real run.

Development setup

Full instructions are in the README Quickstart. In short:

python -m venv .venv
.venv\Scripts\activate            # Windows  •  source .venv/bin/activate  elsewhere
pip install -r requirements.txt
python -m nltk.downloader punkt punkt_tab stopwords wordnet omw-1.4 \
    averaged_perceptron_tagger averaged_perceptron_tagger_eng vader_lexicon
python -m ipykernel install --user --name complaint-router-venv \
    --display-name complaint-router-venv

00_fetch_data pulls the raw data once; every later run reuses data/raw/ because the default is FORCE_REFETCH = False. 01's lemmatization is cached (data/processed/lemma_cache.parquet), so re-running it after a config change is seconds.

Working on the notebooks

  • Edit cells directly. Match the surrounding style — short comments, snake_case, scikit-learn idioms.
  • Keep configuration in the clearly-marked config cell near the top of each notebook (MAX_PER_LANE, MERGE_* switches, USE_CHAR_NGRAMS, the C grid, N_TOPICS, …). Don't scatter magic numbers through the code.
  • Every non-trivial code cell should be preceded by a markdown header that says what it does.
  • If you add a slow step, cache it — follow the lemma_cache.parquet pattern in 01 (key by complaint_id, only compute the misses, persist).
  • Prefer adding a toggle (USE_X = False) over hard-swapping behaviour, so reviewers can A/B it.

Reproducibility & the artifact contract

  • Preserve RANDOM_SEED = 42 and the stratified 70 / 15 / 15 split.
  • Never tune on the test split. Choose hyper-parameters on validation only; report test once, at the end.
  • If you change what a notebook writes to data/processed/ or models/, you must also update:
    • every downstream notebook that reads it, and
    • the Intermediate artifacts and Configuration knobs tables in the README.
  • Metrics: report per-class and macro / weighted roll-ups. For a router, per-lane recall is the headline — a model that silently drops a lane can still post high accuracy.

Testing your changes

Run the notebook you touched and everything downstream:

jupyter nbconvert --to notebook --execute --inplace \
  --ExecutePreprocessor.timeout=3600 \
  --ExecutePreprocessor.kernel_name=complaint-router-venv \
  notebooks/05_classification.ipynb
  • A change to 01 needs 01 → 05. A change to 05 needs only 05.
  • On a memory-constrained machine, run notebooks one at a time (see README Troubleshooting) — a six-notebook loop can be killed mid-run.
  • Confirm the notebook has no error outputs and the committed cell outputs match the committed code.

Coding style

  • Python: PEP 8, ~100-column lines, f-strings, type hints on non-trivial helpers.
  • Vectorized pandas / numpy over Python loops.
  • Every plot gets a title, axis labels, and a legend where relevant, and must be legible in a rendered notebook.

Commit & pull-request conventions

  • Imperative, present-tense subjects: add char n-gram union to 02, fix stale row-count label in 05, cache lemmatization in 01.
  • One logical change per commit where practical.
  • PR description: what changed, why, and the before / after numbers if a metric moved — paste the relevant cell output.
  • Re-run the affected notebooks so committed outputs match committed code. Plots are fine to keep; strip multi-MB embedded data blobs.

What NOT to commit

  • data/ (raw, processed, caches) and models/*.joblib — all regenerable, all git-ignored.
  • .venv/, __pycache__/, *.log, editor/IDE files.
  • Notebook outputs containing large embedded binary data.
  • Any real personal data — the CFPB narratives are already redacted (XXXX); keep it that way and never add un-redacted text.

Good first issues

From the README Roadmap:

  • Wrap the prod estimator in CalibratedClassifierCV so confidence is a real p(lane).
  • Add sub-routers for the Reporting & Collections and Banking & Payments lanes.
  • Package route_complaint() as an importable module + python -m complaint_router "<text>".
  • A tiny fixture sample + a GitHub Actions nbconvert --execute smoke test.
  • pyLDAvis interactive topic view in 04.

Reporting bugs

Open an issue with:

  • what you ran (notebook + cell),
  • the full traceback,
  • OS / Python version / pip freeze (or at least scikit-learn, pandas, numpy versions),
  • free-RAM figure if it looks like an out-of-memory kill.

Code of Conduct

Be respectful and assume good faith. Keep discussion technical and constructive. Harassment or discrimination of any kind is not tolerated; maintainers may remove comments, commits, or contributors that violate this.