argus-lens 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. argus_lens-0.1.0/.env.example +13 -0
  2. argus_lens-0.1.0/.github/workflows/ci.yml +56 -0
  3. argus_lens-0.1.0/.github/workflows/release.yml +69 -0
  4. argus_lens-0.1.0/.gitignore +12 -0
  5. argus_lens-0.1.0/Dockerfile +13 -0
  6. argus_lens-0.1.0/Dockerfile.gpu-base +12 -0
  7. argus_lens-0.1.0/LICENSE +21 -0
  8. argus_lens-0.1.0/Makefile +46 -0
  9. argus_lens-0.1.0/PKG-INFO +245 -0
  10. argus_lens-0.1.0/README.md +180 -0
  11. argus_lens-0.1.0/build-docker.sh +16 -0
  12. argus_lens-0.1.0/docker-compose.yaml +22 -0
  13. argus_lens-0.1.0/pyproject.toml +81 -0
  14. argus_lens-0.1.0/src/argus_lens/__init__.py +21 -0
  15. argus_lens-0.1.0/src/argus_lens/_version.py +24 -0
  16. argus_lens-0.1.0/src/argus_lens/assembly/__init__.py +1 -0
  17. argus_lens-0.1.0/src/argus_lens/assembly/classifier.py +59 -0
  18. argus_lens-0.1.0/src/argus_lens/assembly/composer.py +162 -0
  19. argus_lens-0.1.0/src/argus_lens/assembly/filtering.py +234 -0
  20. argus_lens-0.1.0/src/argus_lens/assembly/noise.py +54 -0
  21. argus_lens-0.1.0/src/argus_lens/assembly/token_budget.py +59 -0
  22. argus_lens-0.1.0/src/argus_lens/assembly/training.py +261 -0
  23. argus_lens-0.1.0/src/argus_lens/assembly/variants.py +90 -0
  24. argus_lens-0.1.0/src/argus_lens/assembly/zeroshot.py +68 -0
  25. argus_lens-0.1.0/src/argus_lens/backends/__init__.py +1 -0
  26. argus_lens-0.1.0/src/argus_lens/backends/base.py +148 -0
  27. argus_lens-0.1.0/src/argus_lens/backends/blip2.py +90 -0
  28. argus_lens-0.1.0/src/argus_lens/backends/florence2.py +129 -0
  29. argus_lens-0.1.0/src/argus_lens/backends/hf_inference.py +76 -0
  30. argus_lens-0.1.0/src/argus_lens/backends/hybrid.py +64 -0
  31. argus_lens-0.1.0/src/argus_lens/backends/nvidia_nim.py +88 -0
  32. argus_lens-0.1.0/src/argus_lens/backends/openai.py +87 -0
  33. argus_lens-0.1.0/src/argus_lens/backends/replicate.py +69 -0
  34. argus_lens-0.1.0/src/argus_lens/backends/wd14.py +172 -0
  35. argus_lens-0.1.0/src/argus_lens/cli.py +134 -0
  36. argus_lens-0.1.0/src/argus_lens/engine.py +407 -0
  37. argus_lens-0.1.0/src/argus_lens/exporters/__init__.py +32 -0
  38. argus_lens-0.1.0/src/argus_lens/exporters/csv_export.py +33 -0
  39. argus_lens-0.1.0/src/argus_lens/exporters/json_export.py +30 -0
  40. argus_lens-0.1.0/src/argus_lens/exporters/text.py +21 -0
  41. argus_lens-0.1.0/src/argus_lens/registry.py +179 -0
  42. argus_lens-0.1.0/src/argus_lens/retry.py +116 -0
  43. argus_lens-0.1.0/src/argus_lens/server.py +166 -0
  44. argus_lens-0.1.0/src/argus_lens/types.py +332 -0
  45. argus_lens-0.1.0/tests/__init__.py +0 -0
  46. argus_lens-0.1.0/tests/conftest.py +1 -0
  47. argus_lens-0.1.0/tests/test_assembly.py +462 -0
  48. argus_lens-0.1.0/tests/test_url_loading.py +89 -0
@@ -0,0 +1,13 @@
1
+ # ── Cloud backend credentials ────────────────────────────────────────
2
+ # API key for cloud backends (OpenAI, Replicate, HuggingFace Inference, NVIDIA NIM).
3
+ # Only needed when using a cloud-based backend.
4
+ ARGUS_API_KEY=
5
+
6
+ # ── Local model paths ────────────────────────────────────────────────
7
+ # WD14 ONNX model directory. If unset, defaults to ~/.cache/wd14_tagger/
8
+ # and auto-downloads from HuggingFace on first use.
9
+ WD14_MODEL_DIR=/home/smk/.cache/wd14_tagger
10
+
11
+ # HuggingFace cache directory for transformer models (Florence-2, BLIP-2).
12
+ # Defaults to ~/.cache/huggingface if unset. These auto-download on first use.
13
+ HF_HOME=/home/smk/.cache/huggingface
@@ -0,0 +1,56 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ lint:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+ - run: pip install ruff
22
+ - run: ruff check src/ tests/
23
+ - run: ruff format --check src/ tests/
24
+
25
+ test:
26
+ runs-on: ubuntu-latest
27
+ strategy:
28
+ matrix:
29
+ python-version: ["3.11", "3.12"]
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ with:
33
+ fetch-depth: 0
34
+ - uses: actions/setup-python@v5
35
+ with:
36
+ python-version: ${{ matrix.python-version }}
37
+ - run: pip install -e ".[dev]"
38
+ - run: pytest --tb=short -q
39
+
40
+ build:
41
+ runs-on: ubuntu-latest
42
+ needs: [lint, test]
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ with:
46
+ fetch-depth: 0
47
+ - uses: actions/setup-python@v5
48
+ with:
49
+ python-version: "3.12"
50
+ - run: pip install build
51
+ - run: python -m build
52
+ - uses: actions/upload-artifact@v4
53
+ with:
54
+ name: dist
55
+ path: dist/
56
+ retention-days: 14
@@ -0,0 +1,69 @@
1
+ name: Release to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions:
8
+ contents: read
9
+ id-token: write
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+ - run: pip install build
22
+ - run: python -m build
23
+ - uses: actions/upload-artifact@v4
24
+ with:
25
+ name: dist
26
+ path: dist/
27
+
28
+ test-install:
29
+ runs-on: ubuntu-latest
30
+ needs: build
31
+ strategy:
32
+ matrix:
33
+ python-version: ["3.11", "3.12"]
34
+ steps:
35
+ - uses: actions/download-artifact@v4
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+ - uses: actions/setup-python@v5
40
+ with:
41
+ python-version: ${{ matrix.python-version }}
42
+ - name: Install wheel and smoke-test import
43
+ run: |
44
+ pip install dist/*.whl
45
+ python -c "from argus_lens import ArgusLens, __version__; print(f'argus-lens {__version__} OK')"
46
+
47
+ publish-testpypi:
48
+ runs-on: ubuntu-latest
49
+ needs: test-install
50
+ environment: testpypi
51
+ steps:
52
+ - uses: actions/download-artifact@v4
53
+ with:
54
+ name: dist
55
+ path: dist/
56
+ - uses: pypa/gh-action-pypi-publish@release/v1
57
+ with:
58
+ repository-url: https://test.pypi.org/legacy/
59
+
60
+ publish-pypi:
61
+ runs-on: ubuntu-latest
62
+ needs: publish-testpypi
63
+ environment: pypi
64
+ steps:
65
+ - uses: actions/download-artifact@v4
66
+ with:
67
+ name: dist
68
+ path: dist/
69
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ .eggs/
8
+ *.egg
9
+ .env
10
+ .ruff_cache/
11
+ .pytest_cache/
12
+ .mypy_cache/
@@ -0,0 +1,13 @@
1
+ FROM gpu_base
2
+
3
+ WORKDIR /app
4
+
5
+ COPY dist/*.whl /tmp/wheels/
6
+ RUN --mount=type=cache,target=/root/.cache/pip \
7
+ set -- /tmp/wheels/*.whl && \
8
+ pip install --upgrade pip && \
9
+ pip install "$1[server,local,openai,replicate]" && \
10
+ rm -rf /tmp/wheels
11
+
12
+ EXPOSE 8080
13
+ CMD ["argus-lens", "serve", "--port", "8080", "--cors"]
@@ -0,0 +1,12 @@
1
+ FROM nvidia/cuda:12.4.1-runtime-ubuntu22.04
2
+
3
+ ENV DEBIAN_FRONTEND=noninteractive \
4
+ PYTHONUNBUFFERED=1
5
+
6
+ RUN apt-get update && apt-get install -y --no-install-recommends \
7
+ python3.11 python3.11-dev python3.11-venv python3-pip git curl g++ build-essential \
8
+ libgl1 libglib2.0-0 libxcb1 libsm6 libxext6 libxrender1 && \
9
+ rm -rf /var/lib/apt/lists/*
10
+
11
+ RUN python3.11 -m venv /opt/venv
12
+ ENV PATH="/opt/venv/bin:$PATH"
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dragonhound
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,46 @@
1
+ .DEFAULT_GOAL := help
2
+ DIST := dist
3
+
4
+ .PHONY: help install dev lint fmt test build clean smoke check
5
+
6
+ help: ## Show this help
7
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
8
+ awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-12s\033[0m %s\n", $$1, $$2}'
9
+
10
+ install: ## Editable install (core deps only)
11
+ pip install -e .
12
+
13
+ dev: ## Editable install with dev + cli extras
14
+ pip install -e ".[dev,cli]"
15
+
16
+ lint: ## Run ruff linter
17
+ ruff check src/ tests/
18
+
19
+ fmt: ## Auto-format with ruff
20
+ ruff format src/ tests/
21
+ ruff check --fix src/ tests/
22
+
23
+ test: ## Run pytest
24
+ pytest --tb=short -q
25
+
26
+ build: clean ## Build sdist + wheel into dist/
27
+ python -m build
28
+ @echo ""
29
+ @ls -lh $(DIST)/
30
+ @echo ""
31
+ @echo "Wheel: $$(ls $(DIST)/*.whl)"
32
+
33
+ clean: ## Remove build artifacts
34
+ rm -rf $(DIST) build src/*.egg-info src/argus_lens/*.egg-info
35
+
36
+ smoke: build ## Build wheel, install in tmp venv, smoke-test import
37
+ $(eval TMPVENV := $(shell mktemp -d))
38
+ python -m venv $(TMPVENV)
39
+ $(TMPVENV)/bin/pip install --quiet $(DIST)/*.whl
40
+ $(TMPVENV)/bin/python -c \
41
+ "from argus_lens import ArgusLens, __version__; print(f'argus-lens {__version__} OK')"
42
+ rm -rf $(TMPVENV)
43
+
44
+ check: lint test build ## Full local CI: lint + test + build
45
+ @echo ""
46
+ @echo "All checks passed."
@@ -0,0 +1,245 @@
1
+ Metadata-Version: 2.4
2
+ Name: argus-lens
3
+ Version: 0.1.0
4
+ Summary: Structured image captioning for training and generation
5
+ Project-URL: Repository, https://github.com/smk762/argus-lens
6
+ Author: smk762
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Keywords: blip,captioning,diffusion,florence,image,lora,training,wd14
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Classifier: Topic :: Scientific/Engineering :: Image Recognition
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: httpx>=0.27
22
+ Requires-Dist: pillow>=10.0
23
+ Requires-Dist: structlog>=24.0
24
+ Provides-Extra: all
25
+ Requires-Dist: fastapi>=0.110; extra == 'all'
26
+ Requires-Dist: numpy>=1.24; extra == 'all'
27
+ Requires-Dist: onnxruntime>=1.16; extra == 'all'
28
+ Requires-Dist: openai>=1.30; extra == 'all'
29
+ Requires-Dist: replicate>=0.25; extra == 'all'
30
+ Requires-Dist: rich>=13.0; extra == 'all'
31
+ Requires-Dist: torch>=2.1; extra == 'all'
32
+ Requires-Dist: transformers>=4.46; extra == 'all'
33
+ Requires-Dist: typer>=0.12; extra == 'all'
34
+ Requires-Dist: uvicorn>=0.27; extra == 'all'
35
+ Provides-Extra: cli
36
+ Requires-Dist: rich>=13.0; extra == 'cli'
37
+ Requires-Dist: typer>=0.12; extra == 'cli'
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
40
+ Requires-Dist: pytest>=8.0; extra == 'dev'
41
+ Requires-Dist: ruff>=0.5; extra == 'dev'
42
+ Provides-Extra: local
43
+ Requires-Dist: numpy>=1.24; extra == 'local'
44
+ Requires-Dist: onnxruntime>=1.16; extra == 'local'
45
+ Requires-Dist: torch>=2.1; extra == 'local'
46
+ Requires-Dist: transformers>=4.46; extra == 'local'
47
+ Provides-Extra: openai
48
+ Requires-Dist: openai>=1.30; extra == 'openai'
49
+ Provides-Extra: replicate
50
+ Requires-Dist: replicate>=0.25; extra == 'replicate'
51
+ Provides-Extra: server
52
+ Requires-Dist: fastapi>=0.110; extra == 'server'
53
+ Requires-Dist: python-multipart>=0.0.7; extra == 'server'
54
+ Requires-Dist: uvicorn>=0.27; extra == 'server'
55
+ Provides-Extra: torch
56
+ Requires-Dist: torch>=2.1; extra == 'torch'
57
+ Requires-Dist: transformers>=4.46; extra == 'torch'
58
+ Provides-Extra: wd14
59
+ Requires-Dist: numpy>=1.24; extra == 'wd14'
60
+ Requires-Dist: onnxruntime>=1.16; extra == 'wd14'
61
+ Provides-Extra: wd14-gpu
62
+ Requires-Dist: numpy>=1.24; extra == 'wd14-gpu'
63
+ Requires-Dist: onnxruntime-gpu>=1.16; extra == 'wd14-gpu'
64
+ Description-Content-Type: text/markdown
65
+
66
+ # Argus Lens
67
+
68
+ Structured image captioning for training and generation.
69
+
70
+ ## Quick Start
71
+
72
+ ```bash
73
+ pip install argus-lens[openai]
74
+ ```
75
+
76
+ ```python
77
+ from argus_lens import ArgusLens
78
+
79
+ engine = ArgusLens(backend="openai", api_key="sk-...")
80
+ result = engine.caption("photo.jpg", trigger_word="sks_person")
81
+
82
+ print(result.final_caption)
83
+ print(result.caption_variants["training"])
84
+ print(result.caption_variants["zeroshot"])
85
+ ```
86
+
87
+ ## Features
88
+
89
+ - **Multi-model backends**: WD14, Florence-2 (local GPU/CPU) + OpenAI, HuggingFace, Replicate, NVIDIA NIM (cloud API)
90
+ - **Structured captions**: Category-bucketed variants (identity, wardrobe, pose, setting, lighting, action)
91
+ - **Training-optimised**: Tiered tag protection, omission cycles, CLIP/T5 token budgets, identity suppression
92
+ - **Zero-shot variant**: Identity-first, prose-preferred captions for generation without LoRA
93
+ - **Hybrid pipelines**: Mix local + cloud backends (e.g. WD14 tags + GPT-4o prose)
94
+ - **Backend-aware budgets**: Automatic token limits for SDXL (60), Flux (200), SD3 (200)
95
+ - **CLI + Server**: Command-line tool and optional FastAPI micro-server
96
+ - **Export formats**: `.txt` sidecars, JSON, JSONL, CSV
97
+
98
+ ## Installation
99
+
100
+ pip handles all Python dependencies through extras. Pick the extras that match your use case:
101
+
102
+ ```bash
103
+ # Assembly engine only (no model deps)
104
+ pip install argus-lens
105
+
106
+ # Local backends (GPU inference)
107
+ pip install argus-lens[local] # WD14 + Florence-2
108
+ pip install argus-lens[wd14] # WD14 only (CPU, no torch)
109
+ pip install argus-lens[torch] # Florence-2 only
110
+
111
+ # Cloud backends (no GPU needed)
112
+ pip install argus-lens[openai] # GPT-4o vision
113
+ pip install argus-lens[replicate] # Replicate API
114
+
115
+ # Server (FastAPI + uvicorn)
116
+ pip install argus-lens[server,local,openai]
117
+
118
+ # Everything
119
+ pip install argus-lens[all]
120
+ ```
121
+
122
+ If you're adding argus-lens to an existing project, just add e.g. `argus-lens[openai]` to your `requirements.txt` -- pip resolves all transitive deps automatically.
123
+
124
+ ### System dependencies for local GPU backends
125
+
126
+ Cloud-only users (`[openai]`, `[replicate]`) need no system packages -- skip this section.
127
+
128
+ Local backends (`[local]`, `[wd14]`, `[torch]`) require system libraries for image processing and (optionally) CUDA for GPU acceleration. On Ubuntu/Debian:
129
+
130
+ ```bash
131
+ sudo apt install -y \
132
+ libgl1 libglib2.0-0 libxcb1 libsm6 libxext6 libxrender1
133
+ ```
134
+
135
+ For GPU inference, you also need:
136
+
137
+ - NVIDIA GPU drivers (check with `nvidia-smi`)
138
+ - CUDA runtime (the `Dockerfile.gpu-base` in this repo uses `nvidia/cuda:12.4.1-runtime-ubuntu22.04` as a reference)
139
+ - NVIDIA Container Toolkit (for Docker deployment only)
140
+
141
+ If you already have torch and CUDA working in your environment, you're set -- the pip extras handle the rest.
142
+
143
+ ## Usage
144
+
145
+ ### Python API
146
+
147
+ Import and use directly in your code. This is the primary interface.
148
+
149
+ ```python
150
+ from argus_lens import ArgusLens
151
+
152
+ # Cloud backend -- works anywhere, no GPU
153
+ engine = ArgusLens(backend="openai", api_key="sk-...")
154
+ result = engine.caption("photo.jpg", trigger_word="sks_person")
155
+
156
+ # Local backend -- needs torch + GPU/CPU
157
+ engine = ArgusLens(backend="hybrid")
158
+ result = engine.caption("photo.jpg", trigger_word="sks_person")
159
+
160
+ # Batch processing
161
+ results = engine.caption_directory("./images/", output_format="txt")
162
+ ```
163
+
164
+ ### CLI
165
+
166
+ ```bash
167
+ # Caption a single image
168
+ argus-lens caption photo.jpg --trigger sks_person --backend openai
169
+
170
+ # Caption a directory, output as txt sidecars
171
+ argus-lens caption ./images/ --format txt --backend hybrid
172
+
173
+ # List available backends
174
+ argus-lens backends
175
+ ```
176
+
177
+ ### HTTP Server
178
+
179
+ Run the built-in FastAPI server for frontend consumers (e.g. [argus-vision-demo](https://github.com/smk762/argus-vision-demo)):
180
+
181
+ ```bash
182
+ pip install argus-lens[server,local]
183
+ argus-lens serve --cors --port 8080
184
+ ```
185
+
186
+ Endpoints:
187
+
188
+ - `POST /caption` -- multipart file upload
189
+ - `POST /caption/url` -- JSON body with image URL
190
+ - `POST /caption/batch` -- multiple file upload
191
+ - `POST /caption/stream` -- NDJSON streaming for batch
192
+ - `GET /backends` -- list available backends
193
+
194
+ ### Docker
195
+
196
+ For fresh hosts or isolated deployment with GPU passthrough. No pip install needed on the host.
197
+
198
+ ```bash
199
+ # Build and run
200
+ ./build-docker.sh
201
+ docker compose up
202
+ ```
203
+
204
+ This builds a CUDA 12.4 base image, installs all extras into it, and runs `argus-lens serve` on port 8080.
205
+
206
+ #### Configuration
207
+
208
+ Copy or create a `.env` file for the Docker deployment:
209
+
210
+ | Variable | Default | Description |
211
+ |---|---|---|
212
+ | `ARGUS_BACKEND` | `hybrid` | Captioning backend (`hybrid`, `wd14`, `florence2`, `openai`, etc.) |
213
+ | `ARGUS_API_KEY` | -- | API key for cloud backends |
214
+ | `ARGUS_PORT` | `8080` | Host port for the server |
215
+ | `WD14_MODEL_DIR` | `~/.cache/wd14_tagger/` | WD14 ONNX model directory (auto-downloads on first use) |
216
+ | `HF_HOME` | `~/.cache/huggingface` | HuggingFace model cache (auto-downloads on first use) |
217
+ | `HF_TRUST_REMOTE_CODE` | `false` | Only needed for legacy `microsoft/Florence-2-*` weights. See [Security](#security) |
218
+
219
+ #### GPU prerequisites
220
+
221
+ ```bash
222
+ # Verify NVIDIA driver
223
+ nvidia-smi
224
+
225
+ # Install container toolkit (if not already)
226
+ sudo apt install nvidia-container-toolkit
227
+ sudo nvidia-ctk runtime configure --runtime=docker
228
+ sudo systemctl restart docker
229
+ ```
230
+
231
+ #### Model caching
232
+
233
+ The `docker-compose.yaml` bind-mounts `~/.cache/wd14_tagger` and `~/.cache/huggingface` from the host so models persist across container rebuilds. Models auto-download on first use if not already cached.
234
+
235
+ ## Security
236
+
237
+ ### `trust_remote_code` and Florence-2
238
+
239
+ By default, the Florence-2 backend uses [`florence-community/Florence-2-base`](https://huggingface.co/florence-community/Florence-2-base) weights which are natively supported in `transformers` -- no `trust_remote_code` needed.
240
+
241
+ The legacy [`microsoft/Florence-2-base`](https://huggingface.co/microsoft/Florence-2-base) weights require `HF_TRUST_REMOTE_CODE=true`, which executes arbitrary Python from the model repository at load time. Only enable this for models you trust. WD14 uses a static ONNX model and never runs remote code.
242
+
243
+ ## License
244
+
245
+ MIT
@@ -0,0 +1,180 @@
1
+ # Argus Lens
2
+
3
+ Structured image captioning for training and generation.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ pip install argus-lens[openai]
9
+ ```
10
+
11
+ ```python
12
+ from argus_lens import ArgusLens
13
+
14
+ engine = ArgusLens(backend="openai", api_key="sk-...")
15
+ result = engine.caption("photo.jpg", trigger_word="sks_person")
16
+
17
+ print(result.final_caption)
18
+ print(result.caption_variants["training"])
19
+ print(result.caption_variants["zeroshot"])
20
+ ```
21
+
22
+ ## Features
23
+
24
+ - **Multi-model backends**: WD14, Florence-2 (local GPU/CPU) + OpenAI, HuggingFace, Replicate, NVIDIA NIM (cloud API)
25
+ - **Structured captions**: Category-bucketed variants (identity, wardrobe, pose, setting, lighting, action)
26
+ - **Training-optimised**: Tiered tag protection, omission cycles, CLIP/T5 token budgets, identity suppression
27
+ - **Zero-shot variant**: Identity-first, prose-preferred captions for generation without LoRA
28
+ - **Hybrid pipelines**: Mix local + cloud backends (e.g. WD14 tags + GPT-4o prose)
29
+ - **Backend-aware budgets**: Automatic token limits for SDXL (60), Flux (200), SD3 (200)
30
+ - **CLI + Server**: Command-line tool and optional FastAPI micro-server
31
+ - **Export formats**: `.txt` sidecars, JSON, JSONL, CSV
32
+
33
+ ## Installation
34
+
35
+ pip handles all Python dependencies through extras. Pick the extras that match your use case:
36
+
37
+ ```bash
38
+ # Assembly engine only (no model deps)
39
+ pip install argus-lens
40
+
41
+ # Local backends (GPU inference)
42
+ pip install argus-lens[local] # WD14 + Florence-2
43
+ pip install argus-lens[wd14] # WD14 only (CPU, no torch)
44
+ pip install argus-lens[torch] # Florence-2 only
45
+
46
+ # Cloud backends (no GPU needed)
47
+ pip install argus-lens[openai] # GPT-4o vision
48
+ pip install argus-lens[replicate] # Replicate API
49
+
50
+ # Server (FastAPI + uvicorn)
51
+ pip install argus-lens[server,local,openai]
52
+
53
+ # Everything
54
+ pip install argus-lens[all]
55
+ ```
56
+
57
+ If you're adding argus-lens to an existing project, just add e.g. `argus-lens[openai]` to your `requirements.txt` -- pip resolves all transitive deps automatically.
58
+
59
+ ### System dependencies for local GPU backends
60
+
61
+ Cloud-only users (`[openai]`, `[replicate]`) need no system packages -- skip this section.
62
+
63
+ Local backends (`[local]`, `[wd14]`, `[torch]`) require system libraries for image processing and (optionally) CUDA for GPU acceleration. On Ubuntu/Debian:
64
+
65
+ ```bash
66
+ sudo apt install -y \
67
+ libgl1 libglib2.0-0 libxcb1 libsm6 libxext6 libxrender1
68
+ ```
69
+
70
+ For GPU inference, you also need:
71
+
72
+ - NVIDIA GPU drivers (check with `nvidia-smi`)
73
+ - CUDA runtime (the `Dockerfile.gpu-base` in this repo uses `nvidia/cuda:12.4.1-runtime-ubuntu22.04` as a reference)
74
+ - NVIDIA Container Toolkit (for Docker deployment only)
75
+
76
+ If you already have torch and CUDA working in your environment, you're set -- the pip extras handle the rest.
77
+
78
+ ## Usage
79
+
80
+ ### Python API
81
+
82
+ Import and use directly in your code. This is the primary interface.
83
+
84
+ ```python
85
+ from argus_lens import ArgusLens
86
+
87
+ # Cloud backend -- works anywhere, no GPU
88
+ engine = ArgusLens(backend="openai", api_key="sk-...")
89
+ result = engine.caption("photo.jpg", trigger_word="sks_person")
90
+
91
+ # Local backend -- needs torch + GPU/CPU
92
+ engine = ArgusLens(backend="hybrid")
93
+ result = engine.caption("photo.jpg", trigger_word="sks_person")
94
+
95
+ # Batch processing
96
+ results = engine.caption_directory("./images/", output_format="txt")
97
+ ```
98
+
99
+ ### CLI
100
+
101
+ ```bash
102
+ # Caption a single image
103
+ argus-lens caption photo.jpg --trigger sks_person --backend openai
104
+
105
+ # Caption a directory, output as txt sidecars
106
+ argus-lens caption ./images/ --format txt --backend hybrid
107
+
108
+ # List available backends
109
+ argus-lens backends
110
+ ```
111
+
112
+ ### HTTP Server
113
+
114
+ Run the built-in FastAPI server for frontend consumers (e.g. [argus-vision-demo](https://github.com/smk762/argus-vision-demo)):
115
+
116
+ ```bash
117
+ pip install argus-lens[server,local]
118
+ argus-lens serve --cors --port 8080
119
+ ```
120
+
121
+ Endpoints:
122
+
123
+ - `POST /caption` -- multipart file upload
124
+ - `POST /caption/url` -- JSON body with image URL
125
+ - `POST /caption/batch` -- multiple file upload
126
+ - `POST /caption/stream` -- NDJSON streaming for batch
127
+ - `GET /backends` -- list available backends
128
+
129
+ ### Docker
130
+
131
+ For fresh hosts or isolated deployment with GPU passthrough. No pip install needed on the host.
132
+
133
+ ```bash
134
+ # Build and run
135
+ ./build-docker.sh
136
+ docker compose up
137
+ ```
138
+
139
+ This builds a CUDA 12.4 base image, installs all extras into it, and runs `argus-lens serve` on port 8080.
140
+
141
+ #### Configuration
142
+
143
+ Copy or create a `.env` file for the Docker deployment:
144
+
145
+ | Variable | Default | Description |
146
+ |---|---|---|
147
+ | `ARGUS_BACKEND` | `hybrid` | Captioning backend (`hybrid`, `wd14`, `florence2`, `openai`, etc.) |
148
+ | `ARGUS_API_KEY` | -- | API key for cloud backends |
149
+ | `ARGUS_PORT` | `8080` | Host port for the server |
150
+ | `WD14_MODEL_DIR` | `~/.cache/wd14_tagger/` | WD14 ONNX model directory (auto-downloads on first use) |
151
+ | `HF_HOME` | `~/.cache/huggingface` | HuggingFace model cache (auto-downloads on first use) |
152
+ | `HF_TRUST_REMOTE_CODE` | `false` | Only needed for legacy `microsoft/Florence-2-*` weights. See [Security](#security) |
153
+
154
+ #### GPU prerequisites
155
+
156
+ ```bash
157
+ # Verify NVIDIA driver
158
+ nvidia-smi
159
+
160
+ # Install container toolkit (if not already)
161
+ sudo apt install nvidia-container-toolkit
162
+ sudo nvidia-ctk runtime configure --runtime=docker
163
+ sudo systemctl restart docker
164
+ ```
165
+
166
+ #### Model caching
167
+
168
+ The `docker-compose.yaml` bind-mounts `~/.cache/wd14_tagger` and `~/.cache/huggingface` from the host so models persist across container rebuilds. Models auto-download on first use if not already cached.
169
+
170
+ ## Security
171
+
172
+ ### `trust_remote_code` and Florence-2
173
+
174
+ By default, the Florence-2 backend uses [`florence-community/Florence-2-base`](https://huggingface.co/florence-community/Florence-2-base) weights which are natively supported in `transformers` -- no `trust_remote_code` needed.
175
+
176
+ The legacy [`microsoft/Florence-2-base`](https://huggingface.co/microsoft/Florence-2-base) weights require `HF_TRUST_REMOTE_CODE=true`, which executes arbitrary Python from the model repository at load time. Only enable this for models you trust. WD14 uses a static ONNX model and never runs remote code.
177
+
178
+ ## License
179
+
180
+ MIT
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+
6
+ echo "==> Building wheel..."
7
+ cd "${SCRIPT_DIR}"
8
+ python -m build
9
+
10
+ echo "==> Building gpu_base image..."
11
+ docker build -t gpu_base -f Dockerfile.gpu-base .
12
+
13
+ echo "==> Building argus-lens server image..."
14
+ docker compose build "$@"
15
+
16
+ echo "==> Done. Run: docker compose up"