103 lines
4.8 KiB
Markdown
103 lines
4.8 KiB
Markdown
# Timmy the Talking Turd
|
|
|
|
A working mobile-first bowel diary with an optional **photo-first AI assist**: “Your intelligent pooping pal.”
|
|
|
|
- [Product roadmap and live Gitea epic map](ROADMAP.md)
|
|
- [Product and safety boundary](PRODUCT.md)
|
|
- [Self-hosted stool-vision decision](research/SELF-HOSTED-STOOL-VISION.md)
|
|
|
|
## Build a gated review release
|
|
|
|
```bash
|
|
python3 scripts/build_release.py
|
|
```
|
|
|
|
The builder clones the committed `main` tree into an isolated directory, runs unit/security and both mobile acceptance suites, audits dependencies, checks syntax and secrets, excludes model weights and sensitive/generated media, and writes a checksummed archive plus `manifest.json` under `/root/timmy-releases/`. It refuses dirty or non-`main` source trees.
|
|
|
|
## Run with the self-hosted open-weight path
|
|
|
|
```bash
|
|
npm install
|
|
|
|
git clone --depth 1 https://github.com/ggml-org/llama.cpp /root/model-spikes/llama.cpp
|
|
cmake -S /root/model-spikes/llama.cpp -B /root/model-spikes/llama.cpp/build -DCMAKE_BUILD_TYPE=Release
|
|
cmake --build /root/model-spikes/llama.cpp/build -j4 --target llama-server
|
|
|
|
hf download ggml-org/SmolVLM2-2.2B-Instruct-GGUF \
|
|
SmolVLM2-2.2B-Instruct-Q4_K_M.gguf \
|
|
mmproj-SmolVLM2-2.2B-Instruct-Q8_0.gguf \
|
|
--local-dir /root/model-spikes/models/smolvlm2-2.2b
|
|
|
|
TIMMY_MODEL_PORT=8080 scripts/run_selfhost_smolvlm.sh
|
|
|
|
# In another terminal
|
|
TIMMY_VISION_PROFILE=selfhost npm start
|
|
# open http://localhost:4173
|
|
```
|
|
|
|
The selected bootstrap model is `SmolVLM2-2.2B-Instruct` using the official Apache-2.0 GGUF conversion. The default self-hosted endpoint is loopback-only at `http://127.0.0.1:8080/v1`. Override paths, host, port, threads, model ID, or endpoint with the `TIMMY_MODEL_*` and `TIMMY_VISION_*` environment variables.
|
|
|
|
## Run with a hosted provider
|
|
|
|
```bash
|
|
hermes proxy start --provider nous --host 127.0.0.1 --port 8645
|
|
npm start
|
|
```
|
|
|
|
Hosted remains the default compatibility profile. To make it explicit, set `TIMMY_VISION_PROFILE=hosted`. Credentials stay server-side:
|
|
|
|
```bash
|
|
TIMMY_VISION_BASE_URL=https://your-openai-compatible-provider/v1 \
|
|
TIMMY_VISION_API_KEY=... \
|
|
TIMMY_VISION_MODEL=your-vision-model \
|
|
npm start
|
|
```
|
|
|
|
Set `TIMMY_VISION_ENABLED=0` to disable uploads and retain manual-only operation.
|
|
|
|
## Verify
|
|
|
|
```bash
|
|
npm test
|
|
npm run test:ui # server required on port 4173
|
|
npm run test:photo # mocked positive suggestion through the real browser UX
|
|
npm audit --audit-level=high
|
|
```
|
|
|
|
## What works
|
|
|
|
- Photo-first camera/file capture
|
|
- Client-side image compression before transfer
|
|
- Explicit consent before one-time provider analysis
|
|
- Structured AI suggestions for **visible Bristol form and color only**
|
|
- Confidence display, low-confidence abstention, and user confirmation
|
|
- Urgency, discomfort, notes, and symptoms remain strictly user-reported
|
|
- Manual logging that never uploads
|
|
- Red-flag symptom escalation
|
|
- Local browser ledger, calendar, pattern summary, JSON portability, and delete-all
|
|
- Installable/offline PWA shell for the manual and saved-ledger paths
|
|
|
|
## What is deliberately not faked
|
|
|
|
The positive photo-prefill interface is covered by a deterministic provider fixture. A live self-hosted SmolVLM2-2.2B model was exercised against a CC-licensed real Type 4 stool photograph. It accepted the content and identified stool, but predicted the wrong type with low confidence; Timmy correctly abstained. **The open model removes provider moderation from the path, but its Bristol accuracy is not clinically established.**
|
|
|
|
Timmy does not diagnose disease, identify bleeding, infer pain/urgency, recommend treatment, or clear foods. The selected VLM is a bootstrap worker, not the final classifier. See [research/SELF-HOSTED-STOOL-VISION.md](research/SELF-HOSTED-STOOL-VISION.md) for the measured receipts, hardware gate, consented-data pipeline, specialist-classifier plan, and sources.
|
|
|
|
## Architecture
|
|
|
|
```text
|
|
Browser PWA
|
|
├── app.js photo-first UX, local persistence, compression
|
|
├── src/domain.js tested health/safety and summary rules
|
|
├── src/analysis.js strict AI schema, validation, visual-only merge
|
|
├── server.mjs static server + bounded /api/analyze route
|
|
├── src/vision-service.js server-side OpenAI-compatible provider adapter
|
|
├── src/vision-config.js hosted/self-hosted profiles and readiness probe
|
|
├── scripts/run_selfhost_smolvlm.sh
|
|
├── scripts/ingest_training_photo.py
|
|
├── localStorage saved ledger and attached photos
|
|
└── llama.cpp / hosted API selected per server-side profile
|
|
```
|
|
|
|
The server accepts JPEG/PNG/WebP data URLs up to 4 MB, uses a bounded 60-second hosted or 120-second self-hosted timeout, never accepts an API key from browser input, does not write inference images to disk, and returns only validated visual suggestions. The separate dataset ingester runs only for explicit, consented contributions.
|