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

11 KiB
Raw Blame History

⚖️ 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 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

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:

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

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)

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

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 on a Proxmox homelab with local Ollama models — no cloud APIs were harmed.


Licensed under MIT — see LICENSE. Legal reference material is educational, cites public sources, and is not legal advice.