Astraea: WA family-law multi-agent site (Flask + Ollama semantic RAG)

This commit is contained in:
drjones
2026-09-04 22:33:38 -07:00
commit 913edc0951
9 changed files with 1027 additions and 0 deletions

60
README.md Normal file
View File

@@ -0,0 +1,60 @@
# Astraea ⚖️
A constellation of **Washington State family-law specialist agents**, backed by a local
Ollama semantic-RAG pipeline. Eight specialists, each grounded in its own cited corpus of
Washington law (RCW), answer questions with inline citations — never from thin air.
> For educational purposes only — not legal advice.
## The eight specialists
| Agent | Domain | Primary source |
|---|---|---|
| 🧭 Navigator | Court process, residency, intake, routing | RCW 26.09 (overview) |
| ⚖️ Divorce & Dissolution | No-fault dissolution, legal separation, the 90-day wait | RCW 26.09 |
| 🧒 Child Custody & Parenting | Parenting plans, best-interest factors, relocation | RCW 26.09 / 26.10 |
| 💵 Child Support | Income-shares model, the economic table | RCW 26.19 |
| 🕊️ Spousal Maintenance | Maintenance factors & duration | RCW 26.09.090 |
| 🏠 Property & Debt | Community vs. separate property, division | RCW 26.16 / 26.09.080 |
| 🛡️ Protection Orders | DV, anti-harassment, ERPO | RCW 7.105 |
| 🤝 Mediation & ADR | Mandatory mediation, settlement, collaborative law | RCW 26.09.015 |
## Architecture
```
Flask (gunicorn + nginx) Ollama host (nightmare, RTX 4080 SUPER)
app.py ── /api/chat ──────────► granite4.2 (RAG answer, think:false, num_ctx<=16K)
rag.py ── embed + retrieve ───► nomic-embed-text-v2-moe (semantic embeddings)
agents.py (8 specialist defs)
books/*.md (8 cited WA-law corpora, chunked -> embedded -> index.json)
```
The RAG engine chunks each book on heading + sentence boundaries, embeds every chunk with
`nomic-embed-text-v2-moe`, and retrieves the top-5 by cosine similarity. The answer model
(`granite4.2`) is an instruction-follower that answers strictly from the retrieved context
and says so when the answer isn't in the corpus.
## Deploy (Proxmox LXC)
```bash
# On CT 150 "astraea" (10.30.20.160)
/opt/astraea/venv/bin/gunicorn --workers 2 --threads 4 --bind 0.0.0.0:5000 --timeout 240 app:app
# systemd: astraea.service · nginx: /etc/nginx/sites-enabled/astraea (80 -> 5000)
```
Redeploy: `tar czf /tmp/a.tar.gz app.py rag.py agents.py templates/ && scp → proxmox → pct push 150 → extract → systemctl restart astraea`.
Reindex (after editing a book): `curl -X POST http://<ct>:5000/api/reindex` (or restart the
service). The vector index is cached at `/opt/astraea/index.json` and rebuilt only when a
book changes.
## API
- `GET /api/agents` — list specialists
- `POST /api/chat` — `{agent_id, message, history?}` → `{answer, citations, grounded, latency_ms}`
- `GET /api/health` — agent count + index status
- `POST /api/reindex` — rebuild the vector index
## Public
https://astraea.thetempleofdoom.com (Cloudflare fleet tunnel `1aeb1ac0` → 10.30.20.160:80)