Files
astraea/README.md
drjones 9f9d812320 Astraea v1.0 — multi-agent WA family-law assistant
Eight specialist agents over a 16-book verified WA law corpus (RAG with citations),
per-user document vault, WA court-form PDF auto-fill, comms missions with DV
safety guard, no-KYC auth, TTS. Self-hosted: Flask + SQLite + Ollama, stdlib-only RAG.

Includes README, LICENSE (MIT + not-legal-advice notice), DEPLOY runbook, .gitignore.
2026-09-07 18:49:32 -07:00

195 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ⚖️ Astraea — Self-Hosted AI Family-Law Assistant for Washington State
> **Eight specialist AI agents. Grounded in verified Washington law. Your documents never leave your network.**
Astraea is a self-hosted, multi-agent legal information assistant focused on Washington State family law: divorce, custody, child support, maintenance, property division, protection orders, and mediation. It combines retrieval-augmented generation (RAG) over a curated library of state-specific legal references with tool-calling LLM agents, PDF form auto-fill, per-user document vaults, and optional Twilio/SMTP communications — all running on your own hardware with your own models.
**Live instance:** https://astraea.thetempleofdoom.com
---
## Why Astraea
People going through divorce or custody battles face three problems: lawyers are expensive, court forms are intimidating, and generic chatbots hallucinate the law. Astraea attacks all three:
1. **Grounded answers, not vibes.** Every agent answers from a curated book library (185KB of verified WA-law reference material citing RCW chapters, controlling case law like *In re Marriage of Littlefield*, and WashingtonLawHelp.org). Responses carry citations back to the source chunks.
2. **Specialists, not one generic bot.** Eight agents, each with its own system prompt, book subset, and focus — from the intake Navigator to the Protection Orders specialist with built-in DV-safety guardrails.
3. **Self-hosted and private.** Runs on a Proxmox LXC container, talks to a LAN Ollama server, and stores everything in a local SQLite database. No cloud APIs, no data leaving your network.
> ⚠️ **Not legal advice.** Astraea is an educational and organizational tool. It does not replace a licensed Washington attorney. This notice is embedded in the product, the agents' system prompts, and every source book.
## The Eight Specialists
| Agent | Focus |
|---|---|
| 🧭 **Navigator** | Intake — where to start, which specialist next, the overall WA process |
| ⚖️ **Divorce & Dissolution** | No-fault dissolution, legal separation, the 90-day wait, decrees |
| 🧒 **Child Custody & Parenting** | Parenting plans, best-interest factors, relocation, nonparental custody |
| 💰 **Child Support** | Washington's economic table, imputation, deviations |
| 🤝 **Spousal Maintenance** | Alimony factors, duration, modification |
| 🏠 **Property & Debt** | Characterization, fair-and-equitable division, QDROs |
| 🛡️ **Protection** | Protection orders, no-contact orders, DV safety planning |
| 🕊️ **Mediation & ADR** | Mediation, arbitration, collaborative law, settlement strategy |
## Feature Highlights
- **Multi-agent RAG chat** — stdlib-only vector engine (embeddings via Ollama, cosine retrieval, cached disk index, incremental rebuild when a book changes)
- **Per-user document vault** — upload filings/correspondence/evidence; text extracted (PDF/DOCX/TXT), chunked, embedded, and retrieved as `[USER DOC]` context in chats
- **PDF form auto-fill** — 10+ Washington court form packets (FL All-Cases series) with field detection (`detect_fields.py` + `pymupdf` overlay) and LLM-assisted mapping from your case facts
- **Document generation** — declarations, letters, timelines generated from your case context
- **Comms missions with DV safety guard** — Twilio SMS/voice + SMTP email with a hard block on contacting anyone protected by a no-contact/protection order, plus formal message templates
- **No-KYC auth** — username/password only, per-user profiles with an "About Me" context system, 12 professional avatars
- **Text-to-speech** — every answer speakable via edge-tts
- **Conversation memory** — per-agent persisted history in SQLite
- **Zero cloud dependencies** — Flask + SQLite + Ollama; the RAG engine is pure stdlib (urllib + json + math)
## Architecture
```
┌─────────────────────────────────────────┐
Browser ──HTTPS──▶│ nginx (TLS termination, fleet tunnel) │
└───────────────┬─────────────────────────┘
│ :5000
┌───────────────▼───────────────┐
│ Astraea (Flask + gunicorn) │
│ ├─ agents.py 8 specialists │
│ ├─ rag.py vector engine │
│ ├─ store.py SQLite DAL │
│ ├─ userdocs.py doc vault │
│ ├─ forms.py PDF autofill │
│ ├─ comms.py Twilio/SMTP │
│ └─ tts.py edge-tts │
└───────────────┬───────────────┘
│ LAN
┌───────────────▼───────────────┐
│ Ollama host (GPU) │
│ ├─ qwen3.8fast orchestrator │
│ ├─ ornith-1.5:9b fallback │
│ └─ nomic-embed embeddings │
└───────────────────────────────┘
```
**Repo layout**
```
├── app.py # Flask app: routes, chat orchestration, uploads (757 lines)
├── agents.py # The 8 specialist definitions (system prompts, book subsets)
├── rag.py # Stdlib-only RAG: chunk → embed → cosine retrieve → cite
├── store.py # SQLite: users, sessions, profiles, settings, messages, files
├── documents.py # Generated-document engine
├── detect_fields.py # PDF form field detection (pymupdf)
├── forms.py # Court-form fill + overlay endpoints
├── comms.py # Twilio SMS/voice + SMTP, no-contact safety guard
├── tts.py # edge-tts speech synthesis
├── userdocs.py # Per-user document vault ingestion
├── books/ # 16 curated WA family-law reference books (the RAG corpus)
├── templates/ # Landing page + app SPA (vanilla JS, no build step)
├── static/ # Assets
├── astraea.service # systemd unit (gunicorn, 2 workers × 4 threads)
├── astraea-nginx.conf # nginx site config
└── benchmark_models.py # Model-selection benchmark harness
```
## Quick Start
### Requirements
- Python 3.11+ (3.9 works with minor tweaks — stdlib-only core)
- An [Ollama](https://ollama.com) server reachable on your LAN with:
- `qwen3.8fast` (or any tool-calling model) — orchestrator
- `ornith-1.5:9b` (or any reliable instruct model) — fallback
- `nomic-embed-text-v2-moe` — embeddings
- Optional: `pymupdf` for PDF form filling, `edge-tts` for speech
### Install
```bash
git clone http://10.30.20.149:3000/drjones/astraea.git
cd astraea
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
pip install pymupdf edge-tts # optional features
```
### Configure
Point the agents at your Ollama host in `agents.py`:
```python
OLLAMA_URL = "http://your-ollama-host:11434"
RAG_MODEL = "qwen3.8fast" # tool-calling orchestrator
GENERAL_MODEL = "ornith-1.5:9b" # fallback
EMBED_MODEL = "nomic-embed-text-v2-moe"
```
The vector index builds on first boot (background thread) and caches to `index.json`.
### Run
```bash
python app.py # dev, port 5000
# or production:
gunicorn --workers 2 --threads 4 --bind 0.0.0.0:5000 --timeout 240 app:app
```
Register a user, answer the About-Me prompts (this becomes silent context for every agent), and start with the **Navigator**.
### Deploy on Proxmox LXC (how we run it)
```bash
pct create 150 local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst \
--hostname astraea --memory 2048 --cores 2 \
--net0 name=eth0,bridge=vmbr0,ip=10.30.20.160/24,gw=10.30.20.1 \
--rootfs poolmaster:8 --unprivileged 1
pct start 150
# then: install python3-venv, clone, pip install, cp astraea.service /etc/systemd/system/
systemctl enable --now astraea
```
nginx TLS termination + Cloudflare Tunnel gives the public URL. See `astraea-nginx.conf`.
## The RAG Corpus
`books/` contains 16 reference books (~185KB) written as structured Markdown, each with inline citations to RCW statutes, Washington case law, and WashingtonLawHelp.org:
- `divorce-dissolution.md` + 3 case-law companions (characterization, division, maintenance)
- `custody-parenting.md`, `parentage.md`, `guardianship.md`
- `child-support.md`, `spousal-maintenance.md`, `property-debt.md`
- `protection-orders.md`, `mediation-adr.md`, `modification-enforcement.md`
- `overview-intake.md`, `committed-relationships.md`, `adoption.md`
The index is chunked at ~1200 chars, embedded once, and rebuilt incrementally per-book on change. Retrieval returns top-k chunks as `[SOURCE n]` blocks the agent must cite.
## Safety Design
- **Not-legal-advice notice** in the product UI, agent system prompts, and every book header
- **No-contact safety guard** (`comms.py`): if a user's profile indicates a protection/no-contact order is in effect, outbound Twilio/SMTP actions toward the protected party are hard-blocked with a safety message
- **No-KYC by design**: no emails, no phone numbers required at signup; users stay anonymous
- **Local-only data**: uploads, chats, and profiles live in one SQLite file on your container
## Known Limitations & Roadmap
- [ ] **Password hashing is unsalted SHA-256** — needs bcrypt/argon2 with a transparent re-hash-on-login migration (next security release)
- [ ] Session tokens don't expire — add TTL + refresh
- [ ] No rate limiting on auth/chat endpoints
- [ ] Single-node SQLite — Postgres adapter for multi-user scale
- [ ] Books cover WA only — contributions for other states welcome (keep the citation format!)
- [ ] Streaming responses (currently full-answer)
## Operations
```bash
systemctl status astraea # service health
curl localhost:5000/api/health # app health + index status
curl -X POST localhost:5000/api/reindex # force full RAG rebuild
```
Database backup: `cp astraea.db astraea.db.bak-$(date +%F)` — everything (users, chats, vault metadata) is in that one file. Uploads live in `uploads/`.
## Credits
Built by [drjones](https://github.com/drjonesxxx1) on a Proxmox homelab with local Ollama models — no cloud APIs were harmed.
---
*Licensed under MIT — see [LICENSE](LICENSE). Legal reference material is educational, cites public sources, and is not legal advice.*