inside-out / README.md
peteryej's picture
Fix Space config: merge duplicate README frontmatter blocks
d1e8e99
|
Raw
History Blame Contribute Delete
6.66 kB
---
title: Inside Out
emoji: πŸ’¬
colorFrom: yellow
colorTo: purple
sdk: gradio
sdk_version: 6.16.0
app_file: app.py
pinned: false
license: apache-2.0
short_description: Let your emotions speak for you
tags:
- track:wood
- sponsor:openai
- sponsor:nvidia
- achievement:offgrid
- achievement:offbrand
- achievement:llama
- achievement:sharing
- achievement:fieldnotes
---
# Inside Out β€” Chat with Your Emotions 🌟
A warm little Gradio app, inspired by Pixar's *Inside Out*, where a cast of
emotion agents chime in on whatever is on your mind. It isn't an advice bot β€”
it's a gentle mirror that helps you **notice and name what you're really
feeling**.
πŸ“£ Featured on X: [@QuicklyLearnIt](https://x.com/QuicklyLearnIt/status/2066334265336570107?s=20)
You type a message. A handful of emotions light up and respond, each in their
own distinct voice, followed by a soft reflection inviting you to notice which
feeling rings most true. You can also **tap any emotion chip** at the top to
invite that one to speak up directly.
## The cast
Powered by multiple agents β€” one per emotion (from *Inside Out* and *Inside
Out 2*):
✨ Joy Β· πŸ’™ Sadness Β· 😨 Fear Β· πŸ”₯ Anger Β· 🀒 Disgust Β· 🧑 Anxiety Β· πŸ’š Envy Β·
πŸ˜” Boredom Β· 😳 Embarrassment
For each message, an **orchestrator agent** decides which 2–4 emotions would
naturally speak up, those emotion agents respond **in parallel**, and a final
**reflection agent** helps you make sense of the mix. The emotion chips along
the top double as buttons: tap one and that single emotion chimes in on the
conversation so far.
## Try saying…
Not sure where to start? These exercise different emotional mixes:
- "I have a big exam tomorrow and I haven't studied enough."
- "My best friend got the promotion I was hoping for and I don't know how to feel."
- "I just sent an email to my whole team with an embarrassing typo in it."
- "I moved to a new city and I feel really lonely here."
- "I finally finished a project I've been working on for months!"
- "Lately everything just feels gray and pointless."
- "My roommate keeps leaving dirty dishes everywhere and I'm so done."
- "I got into the program I applied for but now I'm terrified I'll fail."
- "Is it normal to feel happy and sad at the same time?"
- "I have talked about the issue with my wife a few time and we can't reach an agreement. i don't know what to do now."
## Run it
```bash
pip install -r requirements.txt
python app.py # open http://localhost:7860
```
Configuration is read from the environment, and a local **`.env`** file is
loaded automatically if present (via `python-dotenv`):
```bash
# .env (real shell environment variables take precedence)
HF_TOKEN=hf_... # enables model-generated replies
GOOGLE_CLIENT_ID=... # optional, enables Google sign-in
GOOGLE_CLIENT_SECRET=...
GOOGLE_ALLOWED_DOMAIN=example.com # optional, restrict to one Workspace domain
SESSION_SECRET=change-me
SHOW_LOGIN=true # optional, shows the login sidebar
```
- **`HF_TOKEN`** lets the model (set by `HF_MODEL` in `app.py`, currently
`google/gemma-4-26B-A4B-it`) generate the emotion responses. Without it the
app still runs in a lightweight **offline demo mode** (keyword-based
responses), so you can always see the experience. Pick a regular *instruct*
model β€” a reasoning/"thinking" model returns its answer in a separate
`reasoning` field and leaves `content` empty, which falls back to demo lines.
On startup the app logs `HF_TOKEN present: True/False` (boolean only, never
the value) so you can confirm the token reached the app β€” handy in Space logs.
- **Google sign-in** is required when `GOOGLE_CLIENT_ID` and
`GOOGLE_CLIENT_SECRET` are set; otherwise the app runs as an open local demo.
### Hot reload (dev)
```bash
DEV=1 python app.py # uvicorn watches the source and reloads on save
```
### Local serving with llama.cpp
Set **`LOCAL_SERVING=true`** to run entirely on your own machine β€” the app then
talks to a local [llama.cpp](https://github.com/ggml-org/llama.cpp) server
(OpenAI-compatible) instead of the hosted HF Inference API, and **no `HF_TOKEN`
is needed**.
```bash
LOCAL_SERVING=true python app.py
```
On startup the app **auto-discovers a local GGUF** for `HF_MODEL` under
`~/models` (override with `LOCAL_MODELS_DIR`, or pin an exact file with
`LOCAL_MODEL_PATH`) and **launches `llama-server` for you** β€” no separate
terminal needed. It reuses an already-running server if one is up, and shuts
its own down on exit. A 30B-A3B / 26B-A4B model at ~4-bit fits a 24 GB GPU.
Prefer to run the server yourself? Just start it first and the app will reuse it:
```bash
llama-server -m /path/to/model.gguf --jinja --reasoning-budget 0 \
-ngl 99 -c 8192 --port 8088
```
- **Reasoning models:** `USE_REASONING` defaults to **`false`**, which serves the
model with `--reasoning-budget 0` so it answers directly. Many models (Gemma 4,
Nemotron, Qwen3…) otherwise default to a "thinking" mode that leaves `content`
empty and falls back to demo lines. Set `USE_REASONING=true` to let the model
think β€” the agent layer then strips the `<think>…</think>` chain-of-thought
from replies (and uses larger token budgets so the answer is reached).
- Override the endpoint with `LOCAL_LLM_BASE_URL` (default
`http://localhost:8088/v1`), the llama.cpp binary with `LLAMA_SERVER_BIN`, and
the reported model name with `LOCAL_LLM_MODEL`. The startup log shows
`serving=local-llama.cpp | reasoning=off` so you can confirm the active backend.
## How it works
| File | Purpose |
|-----------------|--------------------------------------------------------------------|
| `app.py` | Gradio UI β€” theme/CSS, emotion chip-buttons, chat + chime callbacks, FastAPI mount and optional Google OAuth. |
| `agents.py` | Orchestrator, per-emotion agents (run in parallel), and the closing reflection. |
| `emotions.py` | Each emotion's display name, persona, color, and emoji. |
The Gradio UI is mounted onto a FastAPI app via `gr.mount_gradio_app`, which is
where the custom theme/CSS and the Google OAuth routes are wired in. Model calls
go through Hugging Face's chat-completion API; recent conversation (up to the
last 100 turns) is fed back to the agents as readable context.
## A gentle note
This is a playful tool for self-reflection, **not** a substitute for
professional mental-health support. If you're struggling, please reach out to
someone you trust or a qualified professional.