CI and images / lint (push) Successful in 3s
CI and images / extension-version (push) Successful in 3s
extension / lint (push) Successful in 16s
CI and images / frontend-build (push) Successful in 19s
CI and images / backend-lint-and-test (push) Successful in 31s
CI and images / integration (push) Successful in 2m22s
CI and images / sign-extension (push) Successful in 3s
CI and images / build-web (push) Successful in 3m7s
CI and images / smoke-web (push) Successful in 59s
CI and images / build-agent (push) Successful in 6m41s
CI and images / promote (push) Successful in 2s
Agent: - The image ran PyPI's CUDA-13 torch 2.14 and onnxruntime-gpu 1.30 on a CUDA 12.9 cudnn-runtime base. requirements.txt had silently replaced the Dockerfile's torch 2.6+cu124, because ultralytics pulls torchvision, which pulls its own torch. That left ~3 GB of base libraries and a ~3 GB torch nothing loaded: 10 GB compressed. - Now: an nvidia/cuda 13.0.3 `base` image, with torch and torchvision installed together from cu130. CUDA and cuDNN come from the nvidia-* pip packages; onnxruntime-gpu declares its [cuda,cudnn] extras. - fc_agent/accel.py preloads those libraries for onnxruntime. It then logs, and reports in /status, whether torch and the ONNX CUDA provider actually got the GPU, since both fall back to the CPU silently. Web image: - Drop opencv-python-headless and onnxruntime, plus the opencv-only apt libs. Both have been listed since the scaffold and nothing in backend/ imports them. - torch/torchvision move to 2.14/0.29, and the unexplained caps are lifted (rule 154). Redis: 8-alpine in both compose files and both CI service containers. That gives an AGPLv3 licence option, where 7.4 was RSAL/SSPL only. The client moves to >=8.1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LVjrnpQjRgHdvq95rASoiR
73 lines
3.1 KiB
Markdown
73 lines
3.1 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:13.0.3-base-ubuntu24.04 nvidia-smi
|
|
# the header's CUDA version must be 13.0 or later (driver 580+)
|
|
```
|
|
|
|
## 1. Get a token
|
|
In FC: **Settings → Tagging → GPU agent → Generate token** (or Rotate). Copy it.
|
|
|
|
## 2. Pull (CI publishes it alongside the web image)
|
|
```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.
|