Spaces:
Running
Running
| 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. | |