Skip to main content

Water Conflict Classifier

SetFit-based multi-label text classifier for identifying water-related conflict events in news headlines.

This folder contains the package source code. For usage instructions with the published package, see the PyPI page.

Project: Experimental research supporting the Pacific Institute's Water Conflict Chronology
Developer: Baobab Tech
License: CC BY-NC 4.0 (Non-Commercial)
PyPI Package: water-conflict-classifier


Package Installation & Usage

Install from PyPI:

pip install water-conflict-classifier

Use the trained model:

from setfit import SetFitModel

model = SetFitModel.from_pretrained("baobabtech/water-conflict-classifier")
predictions = model.predict(["Military group attack workers at dam"])
# Returns: [[1, 1, 1]]  # [Trigger, Casualty, Weapon]

The rest of this README is for developers who want to train their own model or modify the package.

Frugal AI: Training with Limited Data

This classifier demonstrates an intentional approach to building AI systems with limited data using SetFit - a framework for few-shot learning with sentence transformers. Rather than defaulting to massive language models (GPT, Claude, or 100B+ parameter models) for simple classification tasks, we fine-tune small, efficient models (e.g., BAAI/bge-small-en-v1.5 with ~33M parameters) on a focused dataset.

Why this matters: The industry has normalized using trillion-parameter models to classify headlines, answer simple questions, or categorize text - tasks that don't require world knowledge, reasoning, or generative capabilities. This is computationally wasteful and environmentally costly. A properly fine-tuned small model can achieve comparable or better accuracy while using a fraction of the compute resources.

Our approach:

  • Train on ~2,000 examples (few-shot learning with SetFit)
  • Deploy small parameter models (e.g., ~33M params) vs. 100B-1T parameter alternatives
  • Achieve specialized task performance without the overhead of general-purpose LLMs
  • Reduce inference costs and latency by orders of magnitude

This is not about avoiding large models altogether - they're invaluable for complex reasoning tasks. But for targeted classification problems with labeled data, fine-tuning remains the professional, responsible choice.

Package Structure

This is the source code for the water-conflict-classifier Python package, published to PyPI.

classifier/
├── __init__.py                         # Package marker
├── data_prep.py                        # Data loading (for training-ready datasets)
├── training_logic.py                   # Core training logic (fixed hyperparameters)
├── training_logic_optuna.py            # Optuna hyperparameter search training
├── evaluation.py                       # Model evaluation & metrics
├── model_card.py                       # Model card generation
├── versioning.py                       # Experiment tracking & versioning
├── evals_upload.py                     # Upload evaluation results to HF
├── train_setfit_headline_classifier.py # Local training script
├── pyproject.toml                      # Package configuration
├── setup.py                            # Build configuration
└── README.md                           # This file

Note: Scripts that use this package (like cloud training with HF Jobs and dataset preparation) are in the ../scripts/ folder.


Local Training

Train on your own hardware with local data files.

Setup

  1. Install the package in development mode:
uv pip install -e .
# or with regular pip:
pip install -e .

This installs the modules (data_prep, training_logic, etc.) so they can be imported.

  1. Prepare training data:

Training data should be in ../data/:

  • ../data/positives.csv - Water conflict headlines with labels
  • ../data/negatives.csv - Non-water conflict headlines

Build negatives (if needed) - see the scripts README:

cd ../scripts
python fetch_serpapi_negatives.py
uv run generate_synthetic_negatives.py --calls 140
uv run verify_negatives.py ../data/real_headlines.csv ../data/synthetic_headlines.csv ../data/hard_negatives.csv
uv run build_negatives.py
  1. Train:
python train_setfit_headline_classifier.py

Model saved to ./water-conflict-classifier/


Cloud Training

For training on HuggingFace Jobs (managed GPUs):

  1. Prepare training dataset: Use ../scripts/prepare_training_dataset.py to preprocess, balance, and upload training-ready data to HF Hub
  2. Train model: Two options:
    • ../scripts/train_on_hf.py - Standard training with fixed hyperparameters
    • ../scripts/train_on_hf_optuna.py - Optuna hyperparameter search (finds optimal settings automatically)

Optuna training searches on a small sample (~200 examples) for speed, then trains the final model on full data with best hyperparameters. Results are logged to the HF evals dataset for comparison.

See the scripts README for complete workflow.


Publishing to PyPI

See PUBLISHING.md for complete instructions on building and publishing the package.


Data Sources

The training data combines:

  • Positive Examples: Water conflict headlines from Pacific Institute Water Conflict Chronology
  • Negative Examples: As many as positives, about half real Google News titles (via SerpApi) and half synthetic headlines generated with Claude Haiku 5.5, all checked by an LLM judge:
    1. Hard Negatives (~35%): Water-related news that is not conflict (utilities, infrastructure, floods and droughts, research, cooperation, water sports) to prevent false positives
    2. Other Negatives (~65%): Conflict and security news with no water role, plus general news
  • Held-out Negatives: 300 real + 300 synthetic negatives never used in training; the false positive rate on each shows whether the model keys on synthetic style

Hard Negatives Strategy

Without hard negatives, the model learns "water mentioned → conflict" instead of "water + violence → conflict". Hard negatives are water-related headlines that lack violence or conflict:

  • Water infrastructure projects (dams, treatment plants)
  • Scientific water research and technology
  • Water conservation initiatives and conferences
  • Environmental water management

These are tagged with priority_sample=True in the dataset and are ALWAYS included in training (never diluted by sampling). This ensures the model correctly distinguishes peaceful water news from actual water conflicts.

Resources


License

Copyright © 2025 Baobab Tech

This project is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.

You are free to use, share, and adapt this work for non-commercial purposes with appropriate attribution to Baobab Tech. For commercial licensing inquiries, please contact Baobab Tech.

Metadata

Release files for water-conflict-classifier 0.1.23

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for water-conflict-classifier 0.1.23
File Size Uploaded Provenance
water_conflict_classifier-0.1.23.tar.gz 27.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for water-conflict-classifier 0.1.23
File Interpreter ABI Platform
water_conflict_classifier-0.1.23-py3-none-any.whl Python 3 none any Details

Total release size: 54.5 kB

Release files / water_conflict_classifier-0.1.23.tar.gz

Download URL water_conflict_classifier-0.1.23.tar.gz
Size 27.6 kB
Tags Source
SHA-256 checksum
How to use checksums
13c4fcdc05f93fe4bb3e4008e5deebe6aafda891a2c827e0d063f6763ba81b39
BLAKE2b-256 checksum
How to use checksums
2f740f186e3c9b0de343ed577042e24c192bb61c1a198b6ebc1cc0db0007298b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / water_conflict_classifier-0.1.23-py3-none-any.whl

Download URL water_conflict_classifier-0.1.23-py3-none-any.whl
Size 26.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d58f70a3482b58c660cda98bf87d9a196669fc0e4a155c0a89d97134b8707052
BLAKE2b-256 checksum
How to use checksums
2749f1be3625e79e1b0387810c7df6142fbe3e8aad162c70289f1fb91ef9c619
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for water-conflict-classifier 0.1.23

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page