slamos/bc-test
Bottlecap Newline Fixer
An ML service for fixing newline placement in English text. It takes text with broken newlines (e.g. copied from PDFs) and reconstructs proper paragraph and line breaks using fine-tuned transformer models.
Live app: https://slamos-bc-test.hf.space/
Report: report.pdf
Setup
Install dependencies
make installEnvironment variables
Create a .env file in the project root:
HF_TOKEN=<your-huggingface-token> # Required for downloading Wikipedia dataset
WB_TOKEN=<your-wandb-token> # Required for training (W&B logging)
BETTERSTACK_SOURCE_TOKEN=<your-token> # Optional, for API request loggingData
Download pre-built data (recommended)
The full processed dataset is available as a zip on Google Drive. This skips all download/preprocess/split steps:
make download_dataThis downloads and extracts data.zip into the data/ folder.
Google Drive link: data.zip
Download datasets from source
Alternatively, you can build the data from scratch:
make download_tedseg # TED segmentation dataset
make download_pubmed k=100 # PubMed samples (default 100)
make download_wikipedia k=100 # Wikipedia samples (default 100, requires HF_TOKEN)Preprocess
make preprocess_all # All datasets at once
# Or individually:
make preprocess_pubmed
make preprocess_wikipedia
make preprocess_gutenberg
make preprocess_tedSentence splitting
make sentence_split_all # All datasets
# Or individually:
make sentence_split_gutenberg
make sentence_split_pubmed
make sentence_split_wikipedia
make sentence_split_recipes
make sentence_split_tedBuild pairs
make create_recipes # Create recipes dataset
make build_recipes_pairs # Build sentence pairsTraining
Training arguments
Run training
make train_distilbert
make train_bert
make train_deberta
make train_all # Train all three modelsOr directly:
python -m src.models.train --model bert --epochs 5 --batch_size 16 --lr 1e-5Export and upload models
make export_distilbert # Export checkpoint to ONNX
make export_all # Export all models
make upload_distilbert # Push to HuggingFace Hub
make upload_all # Upload all modelsDownload pre-trained models
make download_distilbert
make download_bert
make download_deberta
make download_all # Download all models from HF HubInference
CLI inference
make inference_distilbert # Interactive CLI (from HF Hub)
make inference_bert
make inference_deberta
make inference_local_distilbert # From local checkpoints
make inference_local_bert
make inference_local_debertaInference arguments
API
Running the service locally
make run-be # FastAPI backend on port 8000
make run-fe # Streamlit frontendEndpoints
When deployed on HF Spaces, the API is available under the /api prefix:
When running locally, endpoints are available at http://localhost:8000/api/ (same /api prefix).
Example requests
Health check:
curl https://slamos-bc-test.hf.space/api/healthResponse:
{
"status": "ok",
"available_models": ["bert", "distilbert", "deberta"]
}Fix newlines (single model):
curl -X POST https://slamos-bc-test.hf.space/api/fix-newlines \
-H "Content-Type: application/json" \
-d '{"text": "This is a sentence that\nw\nas broken acr\noss lines."}'Response:
{
"fixed_text": "This is a sentence that was broken across lines.",
"model_used": "bert"
}Fix newlines (all models):
curl -X POST https://slamos-bc-test.hf.space/api/fix-newlines-all-models \
-H "Content-Type: application/json" \
-d '{"text": "This is a sentence that\nw\nas broken acr\noss lines."}'Response:
{
"results": [
{
"model_name": "bert",
"fixed_text": "This is a sentence that was broken across lines."
},
{
"model_name": "distilbert",
"fixed_text": "This is a sentence that was broken across lines."
},
{
"model_name": "deberta",
"fixed_text": "This is a sentence that was broken across lines.."
}
]
}Testing
make test-api # Test API endpoints
make test-dataset # Test dataset utilities
make test-pipelines # Test inference pipelines
make test-all # Run all testsCleanup
make clean # Remove checkpoint and plot directoriesModels
The three fine-tuned models are hosted on HuggingFace:
Each model classifies sentence pairs into three boundary types:
- SAME_PARAGRAPH — sentences belong to the same paragraph (join with space)
- NEW_PARAGRAPH — new paragraph boundary (join with
\n\n) - NEWLINE — line break within a paragraph (join with
\n)
