614b6bc52a
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ttrj5P7upUTueSfoJcxEqa
72 lines
3.0 KiB
Markdown
72 lines
3.0 KiB
Markdown
# FabledCurator GPU agent
|
|
|
|
A desktop-GPU worker that embeds characters (CCIP) + figure crops for
|
|
FabledCurator. It talks to FC **only over HTTP** — it leases jobs, fetches image
|
|
pixels, runs the models on your GPU, and posts results back. Your FC database and
|
|
Redis stay private; the agent never touches them.
|
|
|
|
You run it when you want a burst and stop it to reclaim the card.
|
|
|
|
## 0. Host prerequisite — NVIDIA Container Toolkit
|
|
Docker needs the toolkit to hand the GPU to a container (else: *"could not select
|
|
device driver nvidia with capabilities [[gpu]]"*). On Arch/CachyOS:
|
|
```sh
|
|
sudo pacman -S nvidia-container-toolkit
|
|
sudo nvidia-ctk runtime configure --runtime=docker
|
|
sudo systemctl restart docker
|
|
# verify:
|
|
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
|
|
```
|
|
|
|
## 1. Get a token
|
|
In FC: **Settings → Tagging → GPU agent → Generate token** (or Rotate). Copy it.
|
|
|
|
## 2. Pull (CI publishes it alongside the web/ml images)
|
|
```sh
|
|
docker pull git.fabledsword.com/bvandeusen/fabledcurator-agent:latest
|
|
```
|
|
> Local build for development instead: `docker build -t fc-gpu-agent agent/`
|
|
|
|
## 3. Run (on the machine with the GPU)
|
|
```sh
|
|
docker run --rm --gpus all -p 8770:8770 \
|
|
-e FC_URL=http://curator.traefik.internal \
|
|
-e FC_TOKEN=<paste-the-token> \
|
|
-v fc-agent-models:/models \
|
|
git.fabledsword.com/bvandeusen/fabledcurator-agent:latest
|
|
```
|
|
Then open <http://localhost:8770> — the control page. Click **Start** to begin
|
|
draining the queue; **Pause**/**Stop** to yield the GPU. The `-v fc-agent-models`
|
|
volume caches the downloaded ONNX models so restarts are fast.
|
|
|
|
Kick off a backfill from FC (**GPU agent card → Queue character embedding**), then
|
|
watch the queue counts on the control page (or FC's card) drain.
|
|
|
|
## Config (env)
|
|
| var | default | meaning |
|
|
|---|---|---|
|
|
| `FC_URL` | `http://localhost:8000` | FC base URL |
|
|
| `FC_TOKEN` | — | the bearer token (required) |
|
|
| `AGENT_ID` | `desktop-agent` | identifies this agent's leases |
|
|
| `BATCH_SIZE` | `4` | jobs leased per round (still processed one at a time) |
|
|
| `CCIP_MODEL` | imgutils default | CCIP model name |
|
|
| `DETECTOR_LEVEL` | `m` | person-detector size: `n` < `s` < `m` < `x` |
|
|
| `POLL_IDLE_SECONDS` | `10` | wait between empty leases |
|
|
|
|
## ⚠️ Verify on first run
|
|
This part can't be CI-tested (no GPU/models in CI), so confirm against your
|
|
installed `dghs-imgutils` (`pip show dghs-imgutils`) — see `fc_agent/models.py`:
|
|
- `imgutils.detect.detect_person(image, level=...)` returns
|
|
`[((x0,y0,x1,y1), label, score), ...]`.
|
|
- `imgutils.metrics.ccip_extract_feature(image, model=...)` returns a vector
|
|
(768-d for caformer). If you want the F1-0.94 variant, set
|
|
`CCIP_MODEL=ccip-caformer_b36-24` (verify the exact string in imgutils).
|
|
|
|
If FC's matcher under/over-fires, tune the cosine threshold in
|
|
`backend/app/services/ml/ccip.py` (`DEFAULT_SIM_THRESHOLD`) and use
|
|
`GET /api/ccip/overview` + `/api/ccip/images/<id>` to spot-check.
|
|
|
|
## CPU fallback
|
|
Swap `onnxruntime-gpu` → `onnxruntime` in `requirements.txt` and drop `--gpus all`
|
|
to grind it slowly on the server instead. Same agent, no card.
|