wsh-rag
Ask natural-language questions about Singapore Workplace Safety and Health (WSH) PDFs — locally indexed, Claude-powered, with inline citations.
wsh-rag is a small command-line tool that points at a folder of PDFs — the WSH Act, MOM Codes of Practice, bizSAFE materials, your collected Risk Assessments — builds a local vector index, and answers natural-language questions about them with inline citations back to the source file and page.
It's built for safety officers, employers, and bizSAFE candidates who routinely need to look up obligations under Singapore's Workplace Safety and Health regime and want answers traced back to the underlying paragraph.
Install
pip install wsh-rag
# or, recommended for CLI tools:
pipx install wsh-rag
Requires Python 3.11+.
Quickstart
export ANTHROPIC_API_KEY=sk-ant-...
wsh-rag index ./my-wsh-pdfs
wsh-rag ask "What are an employer's duties under the WSH Act?" \
--folder ./my-wsh-pdfs
That's it. The first index run will download the embedding model (~130 MB, one-time). Subsequent indexes and asks are fast and run entirely on your machine — only the final answering step calls the Claude API.
What you'll see
╭──────────────────────── ANSWER ────────────────────────╮
│ Under the Workplace Safety and Health Act, every │
│ employer must take reasonably practicable measures to │
│ ensure the safety and health of employees at work [F1].│
│ This includes conducting risk assessments before any │
│ work activity that may pose a risk [F2][F3], and │
│ maintaining records of those assessments for at least │
│ three years [F2]. │
╰────────────────────────────────────────────────────────╯
┏━━━━━━━━━━━━━━━━ SOURCES ━━━━━━━━━━━━━━━━━━━━━┓
┃ Tag │ File │ Page ┃
┠───────┼─────────────────────────────┼────────┨
┃ F1 │ WSH_Act_2006.pdf │ 14 ┃
┃ F2 │ COP_Risk_Management.pdf │ 8 ┃
┃ F3 │ COP_Risk_Management.pdf │ 12 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
Only chunks the model actually cited appear in the Sources table. The [F1] markers stay in the answer so you can trace each claim back to a row.
How it works
PDFs ─▶ pymupdf ─▶ page-bounded chunker ─▶ bge-small embeddings
│
▼
LanceDB (file-based)
│
question ─▶ query embedding ─▶ top-k retrieval ─────┘
│
▼
Claude Sonnet 4.6 (with prompt caching)
│
▼
cited answer + Sources table
Notable choices, briefly:
- Page-bounded chunks — each chunk has exactly one source page, so citations stay precise.
- Local embeddings —
BAAI/bge-small-en-v1.5runs on your machine, no embedding API cost. - Prompt caching — the system prompt and retrieved context are cached on the Anthropic side, so re-asking against the same context within ~5 minutes runs at a heavy discount.
- Sources show only what was cited — if the model invented an
[F9], the marker stays in the answer (so you can spot it) but the table only lists the real ones.
Configuration
| Env var | Purpose |
|---|---|
ANTHROPIC_API_KEY |
Required for wsh-rag ask. Get one at https://console.anthropic.com/. |
wsh-rag index <folder>
| Flag | Default | Notes |
|---|---|---|
--chunk-tokens |
800 | Tokens per chunk. |
--overlap |
100 | Token overlap between adjacent chunks (within a page). |
--embed-model |
BAAI/bge-small-en-v1.5 |
Any sentence-transformers model. Changing this requires re-indexing. |
wsh-rag ask "<question>"
| Flag | Default | Notes |
|---|---|---|
--folder / -f |
. |
Folder containing the .wsh-rag/ index. |
--top-k / -k |
5 | Chunks retrieved as context. |
--model |
claude-sonnet-4-6 |
Anthropic model id. |
--max-tokens |
1500 | Max tokens in the answer. |
--embed-model |
BAAI/bge-small-en-v1.5 |
Must match what you used at index time. |
Where the index lives
wsh-rag writes its index to <folder>/.wsh-rag/ — sibling to the PDFs you indexed. It's safe to delete (rm -rf .wsh-rag) and trivially re-buildable. Add this to your .gitignore:
.wsh-rag/
Singapore WSH context
This tool is built around the kinds of documents the Singapore Ministry of Manpower (MOM) and the Workplace Safety and Health Council publish:
- The Workplace Safety and Health Act (and its subsidiary regulations)
- Codes of Practice (e.g. CP on Risk Management, CP on Working Safely at Heights)
- bizSAFE training materials and audit checklists
- MOM advisories and circulars
- Your own Risk Assessments and Safe Work Procedures
The system prompt instructs Claude to refuse to speculate when the provided context doesn't cover a question — important because WSH guidance is precise and small wording differences matter legally.
Disclaimer:
wsh-ragis not a substitute for legal advice. Always cite the source PDF, not this tool's output, when reporting or making compliance decisions.
Limitations (v0.1.0)
- No incremental re-indexing —
wsh-rag indexalways does a full rebuild. - No interactive chat REPL — every
askis one-shot. - English text only.
- Scanned PDFs need OCR (not bundled). If
wsh-rag indexwarns that a PDF produced no extractable text, it's likely scanned. - One vector backend (LanceDB), one LLM provider (Anthropic Claude).
Roadmap
- Hash-based incremental re-indexing (only re-embed changed PDFs)
- Hybrid retrieval (BM25 + vector) for better recall on specific clause numbers
- Interactive
wsh-rag chatREPL with multi-turn context - Optional OCR via tesseract for scanned PDFs
Development
git clone https://github.com/LogiqlyAI/wsh-rag
cd wsh-rag
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
ruff check . && ruff format --check .
pytest
The integration test in tests/test_cli.py mocks the Anthropic client and uses a tiny reportlab-generated PDF, so the suite runs offline and without an API key.
License
MIT.
wsh-rag itself is MIT-licensed. Note that PyMuPDF, used for PDF parsing, is AGPL-licensed — wsh-rag only depends on it at runtime, so distributing wsh-rag under MIT is fine, but downstream users embedding wsh-rag should be aware of PyMuPDF's terms.
Acknowledgements
- Anthropic Claude for answer synthesis and prompt caching
- BAAI's
bge-small-en-v1.5for local retrieval embeddings - LanceDB for the file-based vector store
- PyMuPDF for fast PDF text extraction
- The Singapore Workplace Safety and Health Council and MOM for publishing the underlying guidance documents this tool is designed for
Metadata
Release files for wsh-rag 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wsh_rag-0.1.0.tar.gz | 19.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wsh_rag-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.4 kB
Release files / wsh_rag-0.1.0.tar.gz
| Download URL | wsh_rag-0.1.0.tar.gz |
|---|---|
| Size | 19.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bd25a5da7d6cc35b228e499ff5e54bccdf3f5867fbaf6f04d80051a4490a7f93
|
|
BLAKE2b-256 checksum How to use checksums |
a6ab81823469a5d6eb768a1c09e777fdba1b8f63acb9dc41f208d2f776cd4316
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 25, 2026.
Transparency logRelease files / wsh_rag-0.1.0-py3-none-any.whl
| Download URL | wsh_rag-0.1.0-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
711ec91a3798e4217dd75bd981a2e6c9e76d89281de9e93753d92ee46b849a7a
|
|
BLAKE2b-256 checksum How to use checksums |
46c6608fe130ff2bb3de233b1897516c237f38a5ec8cb90e8df33de28a387ca9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 25, 2026.
Transparency log