MyPal / README.md
KhaledSalehKL1's picture
Add demo, repo, and X links to Space README
c07408a verified
|
Raw
History Blame Contribute Delete
4.3 kB
---
title: MyPal (9XAIPal)
emoji: πŸ“š
colorFrom: blue
colorTo: indigo
sdk: docker
app_port: 7860
pinned: false
license: mit
---
# 9XAIPal β€” local-first reading companion
Single-container Hugging Face Space deployment. A plain FastAPI app (`app.py`)
mounts the real 9XAIPal backend API at `/api/v1` and serves the compiled React
UI at `/` (SPA with client-side routing) β€” all on port `7860`.
## Layout
| Path | Purpose |
| ----------------- | -------------------------------------------------- |
| `app.py` | FastAPI entrypoint (API + SPA, port 7860) |
| `Dockerfile` | Builds the image; bakes in the Ollama embedder |
| `start.sh` | Boot script: Redis, Ollama, then supervisord (API + Celery worker + optional local Postgres) |
| `supervisord.conf`| Process supervisor config: keeps API + worker alive |
| `requirements.txt`| Python dependencies |
| `app/` | 9XAIPal backend package |
| `dist/` | Compiled React UI |
## Links
- **YouTube Demo Video:** [https://youtu.be/m-uIaNKOOrk?si=4FpcZtlKJwZpPJnz](https://youtu.be/m-uIaNKOOrk?si=4FpcZtlKJwZpPJnz)
- **GitHub Repository:** [https://github.com/Khaled-Saleh-KL1/9XAIPal](https://github.com/Khaled-Saleh-KL1/9XAIPal)
- **X (Twitter) Post:** [https://x.com/KL1_Suii/status/2066237932713775393?s=20](https://x.com/KL1_Suii/status/2066237932713775393?s=20)
## Configuration (set as Space **Secrets / Variables**)
All config is read from environment variables β€” **no `.env` file is bundled**.
Set these under *Settings β†’ Variables and secrets*:
- `OLLAMA_BASE_URL`, `OLLAMA_API_KEY` β€” chat/VLM backend (Ollama Cloud)
- `CHAT_MODEL`, `VLM_MODEL` β€” **must match an exact tag served by your
`OLLAMA_BASE_URL`**. If the endpoint lists `gemma4:31b` and not
`gemma4:31b-cloud`, set `CHAT_MODEL=gemma4:31b` and `VLM_MODEL=gemma4:31b`.
- `EMBEDDING_PROVIDER=ollama`, `EMBEDDING_BASE_URL=http://localhost:11434`,
`EMBEDDING_MODEL=qwen3-embedding` β€” embeddings run on the **in-container**
Ollama (the 31B chat model lives on Ollama Cloud, which hosts no embedding
models, so a small embedding model is baked into the image and served locally)
- `HF_TOKEN` / `HUGGING_FACE_HUB_TOKEN` β€” model-weight downloads
- **Database** β€” `POSTGRES_HOST`, `POSTGRES_PORT`, `POSTGRES_DB`,
`POSTGRES_USER`, `POSTGRES_PASSWORD`, `PGSSLMODE=require`. The Space container
disk is **ephemeral**, so this deployment points at an **external managed
Postgres** (Supabase, with `pgvector`) so uploaded papers persist across
restarts/rebuilds. Use Supabase's **session-mode connection pooler** host
(`aws-0-<region>.pooler.supabase.com:5432`, user `postgres.<project-ref>`) β€”
the direct `db.<ref>.supabase.co` host is IPv6-only and unreachable from the
IPv4-only Space container.
- (optional) `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `GEMINI_API_KEY` / … for cloud fallback
> Note: `start.sh` boots Redis and an in-container Ollama (for embeddings), then
> launches `supervisord` to keep the FastAPI app **and a Celery worker** alive.
> PostgreSQL runs **externally** (managed) whenever `POSTGRES_HOST` is set to a
> non-local host β€” the bundled in-container Postgres is started only as a fallback
> for local/no-external-DB runs, and its data is ephemeral. Redis here is just an
> ephemeral cache/queue.
>
> **PDF extraction:** the image enables the PyMuPDF text-only fallback by default
> (`ALLOW_PYMUPDF_FALLBACK=1`) so uploads process immediately without baking
> several gigabytes of MinerU + torch into the image. For higher-fidelity output
> (OCR, tables, equations, figures), install `mineru[pipeline]>=3.2.0`, `torch`,
> `torchvision`, and `scipy>=1.17.1` in `requirements.txt` and set
> `ALLOW_PYMUPDF_FALLBACK=0` (or unset) in the Space variables.
>
> **Self-healing:** the container has a Docker `HEALTHCHECK` on `/healthz` and an
> in-app watchdog that detects stuck ingestion jobs. If a paper hangs in
> `queued` / `extracting` / `chunking` / `embedding` / `summarizing` for too long,
> the watchdog revokes the stuck Celery task, cleans up partial state, and
> re-dispatches the job so processing completes.