An open-source, Italian-first AI assistant stack: a FastAPI backend, a streaming chat UI, a RAG pipeline, tool use, and Pippo — an autonomous AI character that has to survive on 100 €/month.
Project status: active work in progress. The API, the survival simulation and the tool layer are working and tested. The LLM layer is provider-based (Ollama / Groq / WebLLM / local transformers): bring any model you like, Pippo supplies the personality, the memory and the survival loop.
- Chat backend (FastAPI) with
/chatand/chat/stream, conversation history, RAG context and automatic tool routing - Pippo survival simulation — a budget tracker played as a life-or-death game: vital status, expenses, income, simulated freelance actions, earnings opportunities, activity log and deactivation when the budget collapses
- Grounded personality — Pippo's real budget state (remaining, daily budget, top categories, vital status) is injected into the system prompt, so the model speaks about its actual situation
- AI advice with a rules fallback —
/budget/adviceuses the configured LLM when one is reachable, otherwise the built-in survival heuristics - RAG with ChromaDB and multilingual embeddings, plus document ingest endpoint
- Tools: web search (DuckDuckGo), calculator (safe AST evaluator that understands "128 per 56"), Italian Wikipedia, weather, news, date/time, unit conversion
- Multiple LLM providers: Ollama (local), transformers (local GPU/CPU), WebLLM (in-browser via WebGPU) and Groq (free API key) — selectable from the UI
- Modern chat UI: streaming responses, Markdown rendering, conversation search, JSON export/import, keyboard shortcuts, dark mode, voice input, mobile-first layout
- Pippo survival UI: terminal-style dashboard with vital badge, action cards with simulated outcomes, earnings sources and activity log
- Autonomous life mode: Pippo doesn't wait to be asked — he greets you first, then eats, tries to earn and narrates his own survival in first person, on his own clock (works with WebLLM, Groq or the local API — his voice and state are identical in every mode)
┌───────────────────────────────────────────────────────────┐
│ Frontend (static, no build step) │
│ - frontend/index.html chat UI (Groq/WebLLM/API) │
│ - frontend/budget_tracker.html Pippo survival dashboard │
├───────────────────────────────────────────────────────────┤
│ API gateway (FastAPI, api/main.py) │
│ - /chat, /chat/stream grounded prompts + tools │
│ - /budget/* survival simulation │
│ - /rag/ingest vector store writes │
├───────────────────────────────────────────────────────────┤
│ Services │
│ - api/services/tools.py web, calc, wiki, meteo… │
│ - api/services/rag_service.py ChromaDB + embeddings │
│ - api/services/budget_tracker.py Pippo state machine │
├───────────────────────────────────────────────────────────┤
│ LLM engines: Ollama · transformers · WebLLM · Groq │
└───────────────────────────────────────────────────────────┘
- Python 3.11+ (3.12 recommended for training)
- 16 GB RAM minimum
- macOS / Linux / Windows
# 1. Install Ollama and pull a model
brew install --cask ollama
ollama pull llama3.1:8b
# 2. Clone and configure
git clone https://github.com/jeaders/Italian-LLM.git
cd Italian-LLM
cp .env.example .env
# 3. In .env
# USE_OLLAMA=true
# OLLAMA_URL=http://localhost:11434
# OLLAMA_MODEL=llama3.1:8b
# 4. Start the API (it also serves the frontend)
make inference
# API + UI: http://localhost:8000/docs and http://localhost:8000/app
# Dashboard: http://localhost:8000/app/budget_tracker.html
# 5. Open the UI
open http://localhost:8000/appOne command gives you everything on a single origin: chat, Pippo's autonomous survival and the
budget dashboard. make inference uses .venv/bin/python when the virtualenv exists, so no
python vs python3 ambiguity (on macOS the bare python command usually doesn't exist).
To serve only the static files instead (e.g. on another port), use:
python3 -m http.server 3000 --directory frontend # then open http://localhost:3000git clone https://github.com/jeaders/Italian-LLM.git
cd Italian-LLM
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
uvicorn api.main:app --reload --port 8000
open frontend/index.htmlWithout a local model the API still runs: chat answers with a clear "model unavailable" message, tools, RAG and the whole Pippo simulation keep working.
Pippo is the heart of this project: an Italian AI character whose only goal is to stay alive on 100 € per month. The simulation is real state, not decoration:
- Vital status:
alive→warning→danger→critical→dead, driven by the remaining budget (deactivation below −20 €) - Expenses and income are tracked per calendar month; when the month rolls over the previous
month is archived to
historyand the budget restarts clean - Survival actions (microtasks, freelance, tutoring, transcription…) have a simulated outcome, a cost and an urgency that scales with how close Pippo is to deactivation. A deactivated Pippo cannot act: recover income or reset the month
- Grounded chat: Pippo's system prompt includes his live state (remaining, spent, income, daily budget, days left, top categories), so he complains about his budget, not a generic one
- Advice:
GET /budget/adviceasks the LLM when one is configured, otherwise uses the built-in survival heuristics (tip_source: "ai" | "rules"in the response)
The point of the project is not to ask Pippo questions — it's to watch him try to stay alive:
- Pippo lives on the server: a background loop advances his life every
PIPPO_TICK_SECONDS(default 20s,PIPPO_AUTONOMOUS=falseto disable). He eats (max 2 meals/day), attempts the most urgent earning action for his situation (max 3/day) and small flavour events happen — whether or not anyone is watching. - When you open the chat, Pippo speaks first: he introduces himself with his real numbers, then narrates his life as it happens through whichever provider you selected (WebLLM, Groq, local API) — same system prompt and same live state in every mode.
- Every 6 narrations he switches to a reflection: weekly or monthly balance of his survival plus concrete ideas to improve it (spending too much on food? transport? actions failing?).
- The dashboard (
/app/budget_tracker.html) is a read-only window on his life: Oggi (meals, decisions, money in/out), Settimana (daily bars, averages vs the 3.33 €/day target), Mese (per-category breakdown, end-of-month projection, survival stats) plus the live feed of what he is doing right now. There are no buttons to press: the decisions are his. - Anti-hallucination guard: if the model invents euro amounts that are not in his real state, the narration is replaced by the deterministic version of the same events.
Base URL: http://localhost:8000 — interactive docs at /docs.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check and active backend |
GET |
/tools |
Available tools and their parameters |
POST |
/chat |
Synchronous chat (RAG, tools, Pippo state) |
POST |
/chat/stream |
Streaming chat |
GET |
/conversations/{id} |
Conversation history |
DELETE |
/conversations/{id} |
Delete a conversation |
POST |
/rag/ingest |
Add documents to the vector store |
POST |
/budget/expenses |
Record an expense |
POST |
/budget/income |
Record income |
GET |
/budget/status |
Budget status and alerts |
GET |
/budget/advice |
Survival advice (AI or rules) |
GET |
/budget/vital-status |
Pippo's vital status |
GET |
/budget/actions |
Available survival actions |
POST |
/budget/actions/{action_id} |
Perform a survival action |
GET |
/budget/earnings |
Earning opportunity catalogue |
GET |
/budget/activity-log |
Recent activity log |
GET |
/budget/deactivation |
Deactivation risk and recovery info |
POST |
/budget/reset |
Reset the month ({"confirm": true}) |
GET |
/pippo/prompt |
Pippo's system prompt (shared by every provider) |
GET |
/pippo/intro |
First-contact prompt + fallback text |
POST |
/pippo/tick |
Advance Pippo's autonomous life: events, state, narration prompt |
GET |
/pippo/feed |
Recent autonomous events, newest first |
GET |
/pippo/report |
Survival aggregates (?scope=day|week|month) |
GET |
/pippo/reflection |
Reflection prompt + fallback (?scope=day|week|month) |
GET |
/pippo/loop |
Autonomous loop status |
POST |
/pippo/complete |
Complete a narration prompt server-side (local provider) |
Example:
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "Quanto fa 128 per 56?", "use_rag": false, "use_web_search": false}'
curl http://localhost:8000/budget/vital-status
curl -X POST http://localhost:8000/budget/actions/microtaskCopy .env.example to .env:
| Variable | Default | Meaning |
|---|---|---|
USE_OLLAMA |
false |
Use Ollama as the LLM backend |
OLLAMA_URL |
http://localhost:11434 |
Ollama base URL |
OLLAMA_MODEL |
llama3.1:8b |
Default model |
OLLAMA_CHAT_MODEL |
— | Optional separate chat model |
MODEL_NAME |
mistralai/Mistral-7B-v0.3 |
transformers model (when not using Ollama) |
EMBEDDING_MODEL |
sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 |
RAG embeddings |
CHROMA_DB_PATH |
./data/embeddings/chroma |
Vector store location |
PIPPO_AUTONOMOUS |
true |
Background loop that keeps Pippo alive without being asked |
PIPPO_TICK_SECONDS |
20 |
Seconds between autonomous ticks |
The chat UI also supports Groq and WebLLM directly in the browser (no backend needed) — see
frontend/index.html.
make test # or: python -m pytest tests/ -v24 tests covering the API surface, the budget simulation (reset, month rollover, deactivation), tool routing, the safe calculator and Pippo's autonomous loop (daily limits, deactivation).
| Target | Notes |
|---|---|
| Docker | docker-compose up --build serves the API; open the frontend pages from frontend/ |
| Fly.io | flyctl launch && flyctl deploy |
| HuggingFace Spaces | Gradio/Streamlit entrypoints in frontend/ and space/ |
| Netlify (static) | Publishes frontend/ with no build step. Chat works standalone (Groq/WebLLM), but Pippo's autonomous life needs the API: either proxy /budget/*, /pippo/* and /chat to a public backend (commented example in netlify.toml), or set the backend URL in Settings → Backend Pippo (API). Note: the Pippo dashboard calls /budget/* on its own origin, so it needs the API served from the same origin (or a proxy) too. |
The API is a plain FastAPI app — publish it anywhere, then connect the frontend:
# Fly.io example (Dockerfile and requirements.txt are in deploy/)
flyctl launch --dockerfile deploy/Dockerfile --region fra # no deploy yet
flyctl volumes create pippo_data --size 1 --region fra
flyctl deploy
# mount the volume on /app/data so data/budget/budget_tracker.json survives restarts
# (add [mounts] destination = "/app/data" to the generated fly.toml)Then pick one of:
- Netlify proxy: uncomment the redirects in
netlify.tomlwith your backend host — same-origin, no CORS, works for the dashboard too. - Frontend setting: open the site → ⚙️ Impostazioni → Backend Pippo (API) →
https://your-app.fly.dev. Saved inlocalStorage, and?api=<url>works too.
Without a reachable backend, Pippo still introduces himself and explains how to start the API — he just can't eat, earn or narrate his life.
Italian-LLM/
├── api/
│ ├── main.py # FastAPI app: chat, tools, budget endpoints
│ └── services/
│ ├── tools.py # web search, calculator, wikipedia, weather, news…
│ ├── pippo_brain.py # Pippo's autonomous survival loop and narration prompts
│ ├── rag_service.py # ChromaDB + embeddings
│ └── budget_tracker.py # Pippo survival state machine
├── frontend/
│ ├── index.html # chat UI (Groq / WebLLM / local API)
│ └── budget_tracker.html # Pippo survival dashboard
├── training/ # LoRA/QLoRA pipeline and configs (incl. Pippo SFT)
├── data/ # datasets and runtime state
├── tests/ # pytest suite
├── deploy/ # Docker and deployment files
└── Makefile # make inference / train-pippo / test / …
- Daily limits in the survival loop (max 2 meals, 3 earning actions per day)
- Time-based cooldowns between actions
- SQLite persistence for conversations (today: in-memory, lost on restart)
- Multi-user budgets (today: single shared budget file)
- Release a trained Pippo adapter (the survival SFT config already exists)
- Real token streaming for the local transformers backend
Issues and pull requests are welcome. See CONTRIBUTING.md.
MIT — see LICENSE.
- Hugging Face for the training ecosystem
- Ollama for local inference
- ChromaDB and sentence-transformers for RAG
- Groq and WebLLM for browser/fast inference options
- The Italian AI community
⭐ If you like the project, leave a star on GitHub!
Made with ❤️ in Italy 🇮🇹 by jeaders