MSGEncrypted commited on
Commit
a0b2364
Β·
1 Parent(s): 6d86316

init plan

Browse files
.cursor/plans/uv_monorepo_init_d9207227.plan.md ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: uv monorepo init
3
+ overview: Bootstrap a uv workspace monorepo from scratch with a Gradio HF Space app and a swappable local inference library (llama-cpp-python default, transformers optional), aligned with [Build Small Hackathon](https://huggingface.co/build-small-hackathon) constraints.
4
+ todos:
5
+ - id: uv-workspace
6
+ content: Run uv init at root + apps/gradio-space + libs/inference; configure workspace members, sources, and uv.lock
7
+ status: pending
8
+ - id: inference-lib
9
+ content: Implement inference Protocol, llama_cpp backend, transformers backend (optional extra), and factory with env-based switching
10
+ status: pending
11
+ - id: gradio-app
12
+ content: Create minimal Gradio chat app in apps/gradio-space wired to inference lib
13
+ status: pending
14
+ - id: hf-space
15
+ content: Add Dockerfile, Space README YAML, .env.example, download_model script, and root README with dev/hackathon docs
16
+ status: pending
17
+ - id: verify
18
+ content: Run uv sync, local Gradio smoke test, and confirm imports/backends work
19
+ status: pending
20
+ isProject: false
21
+ ---
22
+
23
+ # uv Monorepo + Gradio + Local Llama Inference
24
+
25
+ ## Context
26
+
27
+ - Repo today: only [`README.md`](README.md) β€” greenfield setup.
28
+ - Your choices: **generic track scaffold**, **abstract inference with llama-cpp default**.
29
+ - Hackathon hard rules: Gradio app on HF Space, models **≀ 32B**, demo video + social post by **June 15, 2026**.
30
+
31
+ ## Target layout
32
+
33
+ ```text
34
+ small-model-hackathon/
35
+ β”œβ”€β”€ pyproject.toml # workspace root + shared dev tooling
36
+ β”œβ”€β”€ uv.lock
37
+ β”œβ”€β”€ .python-version # 3.12
38
+ β”œβ”€β”€ .gitignore
39
+ β”œβ”€β”€ Dockerfile # HF Space (Docker SDK) β€” builds whole workspace
40
+ β”œβ”€β”€ README.md # dev + hackathon checklist
41
+ β”œβ”€β”€ apps/
42
+ β”‚ └── gradio-space/
43
+ β”‚ β”œβ”€β”€ pyproject.toml
44
+ β”‚ β”œβ”€β”€ README.md # HF Space card YAML (title, sdk, hardware hints)
45
+ β”‚ └── src/gradio_space/
46
+ β”‚ β”œβ”€β”€ __init__.py
47
+ β”‚ └── app.py # Gradio UI entrypoint
48
+ β”œβ”€β”€ libs/
49
+ β”‚ └── inference/
50
+ β”‚ β”œβ”€β”€ pyproject.toml
51
+ β”‚ └── src/inference/
52
+ β”‚ β”œβ”€β”€ __init__.py
53
+ β”‚ β”œβ”€β”€ base.py # Protocol / ABC
54
+ β”‚ β”œβ”€β”€ llama_cpp.py # default backend (GGUF)
55
+ β”‚ β”œβ”€β”€ transformers.py # optional HF backend
56
+ β”‚ └── factory.py # INFERENCE_BACKEND env switch
57
+ └── scripts/
58
+ └── download_model.py # pull GGUF from Hub to local cache
59
+ ```
60
+
61
+ ```mermaid
62
+ flowchart LR
63
+ subgraph app [apps/gradio-space]
64
+ GradioUI[app.py]
65
+ end
66
+ subgraph lib [libs/inference]
67
+ Factory[factory.py]
68
+ LlamaCpp[llama_cpp.py]
69
+ Transformers[transformers.py]
70
+ end
71
+ GradioUI --> Factory
72
+ Factory -->|default| LlamaCpp
73
+ Factory -->|optional| Transformers
74
+ LlamaCpp --> GGUF[Local GGUF file]
75
+ Transformers --> HFModel[HF weights via transformers]
76
+ ```
77
+
78
+ ## 1. Initialize uv workspace
79
+
80
+ Run from repo root:
81
+
82
+ ```bash
83
+ uv init --name small-model-hackathon
84
+ uv init --package apps/gradio-space
85
+ uv init --package libs/inference
86
+ ```
87
+
88
+ Configure root [`pyproject.toml`](pyproject.toml):
89
+
90
+ - `[tool.uv.workspace]` with `members = ["apps/*", "libs/*"]`
91
+ - Root depends on both workspace packages so `uv sync` installs everything:
92
+ - `dependencies = ["gradio-space", "inference"]`
93
+ - `[tool.uv.sources]` mapping each to `{ workspace = true }`
94
+ - Shared dev deps at root: `ruff`, `pytest` (optional but lightweight)
95
+ - `requires-python = ">=3.12"` (matches your installed Python 3.12.9)
96
+
97
+ Lock and install:
98
+
99
+ ```bash
100
+ uv lock
101
+ uv sync --all-packages
102
+ ```
103
+
104
+ ## 2. `libs/inference` β€” swappable local backends
105
+
106
+ **Core interface** in `base.py`:
107
+
108
+ ```python
109
+ class InferenceBackend(Protocol):
110
+ def load(self) -> None: ...
111
+ def generate(self, prompt: str, *, max_tokens: int = 512, temperature: float = 0.7) -> str: ...
112
+ def chat(self, messages: list[dict[str, str]], **kwargs) -> str: ...
113
+ ```
114
+
115
+ **Default backend β€” `llama_cpp.py`**
116
+
117
+ - Dependency: `llama-cpp-python` (CPU build by default; GPU variant documented for local/CUDA Spaces)
118
+ - Load GGUF via env config:
119
+ - `MODEL_PATH` β€” local file path, or
120
+ - `MODEL_REPO` + `MODEL_FILE` β€” download from Hugging Face Hub at startup (`huggingface_hub.hf_hub_download`)
121
+ - Suggested default model for dev: `Qwen/Qwen2.5-3B-Instruct-GGUF` with a specific `.gguf` quant (well under 32B; laptop-friendly)
122
+
123
+ **Optional backend β€” `transformers.py`**
124
+
125
+ - Dependencies kept in an optional extra: `inference[transformers]` β†’ `transformers`, `torch`, `accelerate`
126
+ - Same public methods; loads `AutoModelForCausalLM` + `AutoTokenizer` from `MODEL_ID`
127
+ - Heavier; useful if you later fine-tune and publish on Hub
128
+
129
+ **Factory β€” `factory.py`**
130
+
131
+ - `INFERENCE_BACKEND=llama_cpp|transformers` (default `llama_cpp`)
132
+ - Lazy singleton so model loads once on first request (important for Gradio cold start)
133
+
134
+ ## 3. `apps/gradio-space` β€” minimal chat UI
135
+
136
+ **Dependencies:** `gradio`, `inference` (workspace)
137
+
138
+ **`app.py` skeleton:**
139
+
140
+ - `gr.ChatInterface` or simple `Blocks` with textbox + chat history
141
+ - On startup: call `get_backend().load()` with a status message if model missing
142
+ - Wire `chat()` to the inference backend
143
+ - Expose `demo.launch()` guarded by `if __name__ == "__main__"`
144
+
145
+ **Run locally:**
146
+
147
+ ```bash
148
+ uv run --package gradio-space python -m gradio_space.app
149
+ # or: uv run --package gradio-space gradio apps/gradio-space/src/gradio_space/app.py
150
+ ```
151
+
152
+ **Env template** (`.env.example` at root):
153
+
154
+ ```bash
155
+ INFERENCE_BACKEND=llama_cpp
156
+ MODEL_REPO=Qwen/Qwen2.5-3B-Instruct-GGUF
157
+ MODEL_FILE=qwen2.5-3b-instruct-q4_k_m.gguf
158
+ N_CTX=4096
159
+ N_GPU_LAYERS=0
160
+ ```
161
+
162
+ ## 4. HF Space deployment (monorepo-friendly)
163
+
164
+ Use **Docker SDK** at repo root ([HF Docker Spaces docs](https://huggingface.co/docs/hub/en/spaces-sdks-docker)) so the whole workspace ships together.
165
+
166
+ **Root `Dockerfile` (outline):**
167
+
168
+ - Base: `python:3.12-slim`
169
+ - Install `uv` via official installer
170
+ - `COPY` monorepo, `uv sync --frozen --no-dev --package gradio-space`
171
+ - Run as UID 1000 (HF requirement)
172
+ - `EXPOSE 7860`
173
+ - `CMD ["uv", "run", "--package", "gradio-space", "python", "-m", "gradio_space.app"]`
174
+
175
+ **`apps/gradio-space/README.md`** β€” Space card frontmatter:
176
+
177
+ ```yaml
178
+ ---
179
+ title: <Your App Name>
180
+ emoji: ...
181
+ colorFrom: ...
182
+ colorTo: ...
183
+ sdk: docker
184
+ app_port: 7860
185
+ pinned: false
186
+ license: apache-2.0
187
+ ---
188
+ ```
189
+
190
+ When creating the Space under [build-small-hackathon](https://huggingface.co/build-small-hackathon):
191
+
192
+ 1. New Space β†’ SDK: Docker β†’ link this repo
193
+ 2. Hardware: start **CPU basic** for llama-cpp dev; upgrade to GPU Space if you offload layers
194
+ 3. Add Space secrets/env vars for `MODEL_REPO`, `MODEL_FILE`, etc.
195
+ 4. Optionally attach a **Storage Bucket** if you cache large GGUF files persistently
196
+
197
+ ## 5. Repo hygiene
198
+
199
+ **[`.gitignore`](.gitignore):** `.venv/`, `__pycache__/`, `.env`, `models/`, `*.gguf`, `.ruff_cache/`, `.pytest_cache/`
200
+
201
+ **[`README.md`](README.md)** sections:
202
+
203
+ - Prerequisites: `uv`, Python 3.12
204
+ - Quick start: sync, download model script, run Gradio locally
205
+ - Monorepo commands cheat sheet (`uv add --package ...`, `uv run --package ...`)
206
+ - Hackathon checklist: track choice, Space link, demo video, social post, badge targets (Off-the-Grid, Llama Champion, etc.)
207
+
208
+ **[`scripts/download_model.py`](scripts/download_model.py):** small CLI using `huggingface_hub` to fetch the configured GGUF into `./models/` for offline dev.
209
+
210
+ ## 6. Verification checklist (post-init)
211
+
212
+ | Step | Command / check |
213
+ |------|-----------------|
214
+ | Workspace resolves | `uv sync --all-packages` succeeds |
215
+ | Import chain | `uv run python -c "from inference.factory import get_backend"` |
216
+ | Gradio boots | `uv run --package gradio-space python -m gradio_space.app` β†’ localhost:7860 |
217
+ | Backend switch | `INFERENCE_BACKEND=transformers` fails gracefully until extra installed |
218
+ | Docker build | `docker build -t hackathon-space .` (optional local smoke test) |
219
+
220
+ ## Out of scope for this init (pick up later)
221
+
222
+ - Track-specific product logic (Backyard AI vs Thousand Token Wood)
223
+ - Fine-tuning pipeline / custom model publish
224
+ - Custom UI via `gr.Server` (Off-Brand badge)
225
+ - Agent traces dataset upload (Sharing is Caring badge)
226
+ - CI/GitHub Actions
227
+
228
+ ## Key design decisions
229
+
230
+ | Decision | Rationale |
231
+ |----------|-----------|
232
+ | uv workspace with `apps/` + `libs/` | Clean separation; Gradio app stays thin; inference reusable |
233
+ | llama-cpp default | Matches "Off the Grid" + "Llama Champion" badges; runs on laptop CPU |
234
+ | transformers as optional extra | Keeps default install light; swap via env when needed |
235
+ | Docker Space at repo root | Standard pattern for monorepos on HF (see [eu-ai-act example](https://huggingface.co/spaces/MCP-1st-Birthday/eu-ai-act-compliance-agent/blob/main/Dockerfile)) |
236
+ | Qwen2.5-3B-Instruct GGUF default | Small, capable, llama.cpp-compatible, well under 32B cap |