fugee / README.md
helmo's picture
List HF username @helmo (solo team)
c668df0 verified
|
Raw
History Blame Contribute Delete
9.93 kB
---
title: Fugee
emoji: 🏠
colorFrom: green
colorTo: yellow
sdk: gradio
sdk_version: 6.15.2
app_file: app/app.py
pinned: false
license: mit
short_description: Agentic AI guidance for displaced people, on a small LLM
tags:
- track:backyard
- sponsor:openai
- sponsor:modal
- achievement:offbrand
- achievement:llama
---
<!-- The block above is Hugging Face Space metadata (required for the Space to
build). The hackathon submission tool appends track/badge tags to it. -->
<div align="center">
# 🏠 Fugee
**Safe guidance for people on the move.**
An agentic AI assistant for displaced people, asylum seekers, and refugees β€”
powered by a small LLM, the **LFM2.5 8B-parameter** model.
πŸŽ₯ **[Watch the demo](https://www.youtube.com/watch?v=PYGzJZj7LfM)** Β· πŸ“£ **[Launch post](https://x.com/heldernoid/status/2066252940940067178)** Β· πŸ’» **[GitHub](https://github.com/heldernoid/fugee)**
πŸ‘€ **Team (solo):** [@helmo](https://huggingface.co/helmo)
</div>
---
## What it is
Fugee conducts a calm, structured, multilingual interview, reasons about the
person's situation against international refugee law (the 1951 Refugee
Convention and the 1969 AU Convention), recommends realistic destination
countries, and generates a personalised documentation package they can download
and edit.
It is a **single-process Gradio web app** backed by a **pure-Python agent loop**
(`agent/loop.py`, ported from pi-agent-core's patterns) and the **`lfm2.5:8b`**
model served by Ollama. No Node.js, no microservices, no external database.
> **This Space** runs the Gradio UI on free CPU and calls the LLM (`lfm2.5:8b`)
> and embeddings (`nomic-embed-text`) on a GPU **Ollama** endpoint hosted on
> [Modal](https://modal.com) β€” so the same code and the same small model run
> unchanged, just on rented GPU. See [`deploy/DEPLOY.md`](deploy/DEPLOY.md).
The design point: *a genuinely useful agentic product running on a small model.*
The interview is fully **deterministic** (fixed questions and controls,
hand-translated into 10 languages) and the LLM is used only where it adds real
intelligence β€” the legal **assessment**, the document **drafting**, and the
spoken-back **review summary**.
### The five phases
1. **Intake** β€” language selection + a calm welcome.
2. **Interview** β€” a fixed, deterministic question flow (current/origin country,
what happened, persecution grounds, danger, documents, languages, goals).
3. **Assessment** β€” the agent reasons openly about the case: classifies it
(refugee / broader protection / statelessness / economic), names the
Convention ground, gauges risk, and ranks destinations. Grounded in curated
country data and the UNHCR Handbook & Guidelines (RAG) β€” **not** the open web.
4. **Recommendations** β€” 2–3 country cards with real UNHCR/processing data and a
step-by-step roadmap. Economic (non-protection) cases get honest **work-route**
guidance instead of a doomed asylum claim.
5. **Documents** β€” an LLM-drafted, editable **Word (.docx) + PDF** package,
branded and laid out with bundled fonts (fully offline).
---
## Requirements
- **Python β‰₯ 3.10**
- **[Ollama](https://ollama.com)** running somewhere you can reach (local or LAN),
with:
- **`lfm2.5:8b`** β€” the tool-calling instruct model the app uses, and
- **`nomic-embed-text`** (used to build the UNHCR-guidelines search index).
- A few hundred MB of disk for the Python deps and the (regenerable) RAG index.
> No Node.js / npm anywhere β€” Fugee is pure Python.
---
## Quick start
```bash
# 1. Clone and enter the repo
cd fugee
# 2. Create a virtualenv and install deps (uv recommended; plain venv also fine)
uv venv && source .venv/bin/activate # or: python -m venv .venv && source .venv/bin/activate
uv pip install -r requirements.txt # or: pip install -r requirements.txt
# 3. Configure the model + host
cp .env.example .env
# then edit .env: set OLLAMA_HOST and MODEL_ID to what your Ollama actually has
# 4. Pull the models on your Ollama host (skip any you already have)
ollama pull lfm2.5:8b # or your chosen ≀32B instruct model
ollama pull nomic-embed-text # embeddings for the guidelines RAG index
# 5. Build the UNHCR-guidelines search index (one-time; regenerable, gitignored)
python data/scripts/build_guidelines_index.py
# 6. Run the app
python app/app.py
```
Open **http://localhost:7860** in a browser. (The server binds `0.0.0.0:7860`, so
it's reachable from other machines on your network too.)
### Configuration (`.env`)
Read at startup by `app/config.py` (no `python-dotenv` dependency):
| Variable | Meaning | Example |
|-----------------|----------------------------------------------------------------|---------|
| `OLLAMA_HOST` | Base URL of the Ollama server (local, LAN, or Modal endpoint) | `http://127.0.0.1:11434` |
| `MODEL_ID` | The single ≀32B tool-calling instruct model for the whole app | `lfm2.5:8b` |
| `MODEL_PROVIDER`| `ollama` (default) or a litellm provider name | `ollama` |
| `NUM_CTX` | Ollama context window β€” keep large; the small default truncates the assessment prompt | `16384` |
| `MODAL_KEY` / `MODAL_SECRET` | Proxy-auth headers when `OLLAMA_HOST` is a protected Modal endpoint (hosted demo only) | β€” |
> **One model, no fallback.** The hackathon build deliberately uses a single
> small model end to end. `web_search` is **disabled** β€” the assessment is
> grounded only in sources we control (curated country data + UNHCR guidelines),
> so no Tavily key is required.
---
## Live demo: Hugging Face Space + Modal
The deployed demo splits into two pieces so it runs **free** and **fast** without
changing the app or the model:
```
HF Space (free CPU, Gradio) Modal (GPU, Ollama)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” HTTPS β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ app/app.py + curated data β”‚ ───────▢ β”‚ ollama serve β”‚
β”‚ + guidelines RAG (cosine) β”‚ proxy β”‚ β€’ lfm2.5:8b (assessment) β”‚
β”‚ OLLAMA_HOST β†’ Modal URL β”‚ auth β”‚ β€’ nomic-embed-text (RAG) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
The Space sets `OLLAMA_HOST` to the Modal endpoint and sends the proxy-auth
headers (`agent/ollama_auth.py`); everything else is identical to local. Full,
copy-pasteable steps β€” create the Space, deploy Modal, set secrets, upload the
RAG index β€” are in **[`deploy/DEPLOY.md`](deploy/DEPLOY.md)**.
---
## Project layout
```
fugee/
β”œβ”€β”€ agent/ # Pure-Python agent loop + tools
β”‚ β”œβ”€β”€ loop.py # while-loop, typed events, hooks, steering (ported from pi)
β”‚ β”œβ”€β”€ drafting.py # LLM document drafting
β”‚ └── tools/ # country_lookup, asylum_stats, guideline_search, doc_generator
β”œβ”€β”€ app/ # Gradio application
β”‚ β”œβ”€β”€ app.py # entrypoint β€” `python app/app.py`
β”‚ β”œβ”€β”€ phases/ # intake / interview / assessment / recommendations / documents
β”‚ β”œβ”€β”€ interview_script.py # fixed questions + 10-language translations
β”‚ β”œβ”€β”€ state/session.py # forward-only interview state machine
β”‚ └── prompts/ # system / assessment prompts (Markdown)
β”œβ”€β”€ data/scripts/ # UNHCR data pipeline + guidelines RAG index builder
β”œβ”€β”€ specs/ # PLAN.md, ARCHITECTURE.md, ISSUES.md, curated country data
β”‚ └── data/countries.json # authoritative country reference (signatories + non-signatories)
β”œβ”€β”€ tests/ # unit / integration (no model) + e2e (real model)
β”œβ”€β”€ DESIGN.md # design tokens (authoritative)
β”œβ”€β”€ mockup.html # visual reference for every phase
β”œβ”€β”€ CLAUDE.md # agent working rules for this repo
└── requirements.txt
```
---
## Running the tests
```bash
# Fast: pure logic + phase integration (no model needed)
pytest tests/unit tests/integration -v
# End-to-end with a real model (needs Ollama + your MODEL_ID)
pytest tests/e2e -v
```
Testing philosophy: unit tests stub only at the network boundary; E2E uses real
model calls. Tools never fabricate data β€” a failed lookup surfaces an error
rather than inventing one.
---
## Languages
English Β· FranΓ§ais Β· EspaΓ±ol Β· PortuguΓͺs Β· Ψ§Ω„ΨΉΨ±Ψ¨ΩŠΨ© Β· ΰ€Ήΰ€Ώΰ€¨ΰ₯ΰ€¦ΰ₯€ Β· δΈ­ζ–‡ Β· ζ—₯本θͺž Β· ν•œκ΅­μ–΄ Β· Русский
The interview questions, options, and chrome are hand-translated for all ten.
---
## For contributors / agents
- **`CLAUDE.md`** β€” the single source of truth for how to work in this repo
(critical rules, design authority, sign-off gates). Read it first.
- **`DESIGN.md` + `mockup.html`** β€” authoritative for every visual decision.
- **`specs/ISSUES.md`** β€” hard-won gotchas and their real fixes (e.g. the Gradio
`CheckboxGroup` reveal bug). Read before touching the interview UI or the
assessment/recommendation logic β€” it will save you a long debugging loop.
- **`specs/ARCHITECTURE.md` / `specs/PLAN.md`** β€” system design and phased plan.
---
## Status & disclaimer
Built for the **Hugging Face Build Small Hackathon (June 2026)**. Quality bar:
demo-ready, real-user-usable.
Fugee provides **guidance, not legal advice**. It helps a person understand and
prepare; it is not a substitute for a qualified immigration lawyer or an accredited
adviser. It is deliberately honest about what does and does not qualify for
protection β€” wrong output is worse than no output.