deploy: update Space from deploy_preflight --push
Browse files
.codeboarding/logs/wrapper-server.log
CHANGED
|
@@ -122,3 +122,12 @@ INFO: 127.0.0.1:44498 - "GET /health HTTP/1.1" 200 OK
|
|
| 122 |
[stderr] 2026-06-14 04:57:18 INFO [watchfiles.main:308] 2 changes detected
|
| 123 |
[stderr] 2026-06-14 04:57:18 WARNING [codeboarding_pro.analysis_controller:506] Skipping incremental update: full analysis artifacts not ready yet
|
| 124 |
[stderr] 2026-06-14 04:57:18 INFO [codeboarding_pro.analysis_controller:314] No cached analysis results; skipping health report
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
[stderr] 2026-06-14 04:57:18 INFO [watchfiles.main:308] 2 changes detected
|
| 123 |
[stderr] 2026-06-14 04:57:18 WARNING [codeboarding_pro.analysis_controller:506] Skipping incremental update: full analysis artifacts not ready yet
|
| 124 |
[stderr] 2026-06-14 04:57:18 INFO [codeboarding_pro.analysis_controller:314] No cached analysis results; skipping health report
|
| 125 |
+
[stderr] 2026-06-14 04:58:20 INFO [watchfiles.main:308] 1 change detected
|
| 126 |
+
[stderr] 2026-06-14 04:58:20 WARNING [codeboarding_pro.analysis_controller:506] Skipping incremental update: full analysis artifacts not ready yet
|
| 127 |
+
[stderr] 2026-06-14 04:58:20 INFO [codeboarding_pro.analysis_controller:314] No cached analysis results; skipping health report
|
| 128 |
+
[stderr] 2026-06-14 05:02:51 INFO [watchfiles.main:308] 1 change detected
|
| 129 |
+
[stderr] 2026-06-14 05:02:51 WARNING [codeboarding_pro.analysis_controller:506] Skipping incremental update: full analysis artifacts not ready yet
|
| 130 |
+
[stderr] 2026-06-14 05:02:51 INFO [codeboarding_pro.analysis_controller:314] No cached analysis results; skipping health report
|
| 131 |
+
[stderr] 2026-06-14 05:03:14 INFO [watchfiles.main:308] 1 change detected
|
| 132 |
+
[stderr] 2026-06-14 05:03:15 WARNING [codeboarding_pro.analysis_controller:506] Skipping incremental update: full analysis artifacts not ready yet
|
| 133 |
+
[stderr] 2026-06-14 05:03:15 INFO [codeboarding_pro.analysis_controller:314] No cached analysis results; skipping health report
|
core/llm.py
CHANGED
|
@@ -14,6 +14,8 @@ import json
|
|
| 14 |
import os
|
| 15 |
|
| 16 |
MODEL = os.environ.get("CHIEF_ENGINEER_MODEL", "gemma4:e4b")
|
|
|
|
|
|
|
| 17 |
|
| 18 |
# Backend select. Default "ollama" keeps local/recording behavior IDENTICAL.
|
| 19 |
# Set CHIEF_ENGINEER_BACKEND=zerogpu ONLY on the published Space (see
|
|
@@ -37,6 +39,13 @@ def _zerogpu():
|
|
| 37 |
return None
|
| 38 |
|
| 39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
def _forced_offline() -> bool:
|
| 41 |
"""Force the deterministic fallback path regardless of any daemon/backend.
|
| 42 |
Read dynamically (not cached) so tests can toggle it. Used by the offline
|
|
@@ -51,6 +60,8 @@ def is_available() -> bool:
|
|
| 51 |
zg = _zerogpu()
|
| 52 |
if zg is not None:
|
| 53 |
return zg.is_available()
|
|
|
|
|
|
|
| 54 |
if ollama is None:
|
| 55 |
return False
|
| 56 |
try:
|
|
@@ -64,6 +75,8 @@ def backend_status() -> str:
|
|
| 64 |
zg = _zerogpu()
|
| 65 |
if zg is not None:
|
| 66 |
return zg.backend_status()
|
|
|
|
|
|
|
| 67 |
return (f"<span style='color:var(--ao-green);'>●</span> live · {MODEL} (local Ollama)"
|
| 68 |
if is_available() else
|
| 69 |
f"<span style='color:var(--ao-yellow);'>●</span> offline fallback · "
|
|
@@ -73,7 +86,8 @@ def backend_status() -> str:
|
|
| 73 |
def warm_up() -> str:
|
| 74 |
"""Pay the model's cold start now (off-camera), so the first real BUILD is fast.
|
| 75 |
On ZeroGPU this enters the GPU window and loads the model; on Ollama/fallback it is
|
| 76 |
-
a cheap no-op.
|
|
|
|
| 77 |
zg = _zerogpu()
|
| 78 |
if zg is not None:
|
| 79 |
try:
|
|
@@ -89,13 +103,30 @@ def chat_json(system: str, user: str, temperature: float = 0.4) -> dict | None:
|
|
| 89 |
return None
|
| 90 |
zg = _zerogpu()
|
| 91 |
if zg is not None:
|
| 92 |
-
# ANY ZeroGPU failure (quota exhausted, model load, OOM, timeout) must fall
|
| 93 |
-
# back to the deterministic advisor — never surface "Error" on the Space.
|
| 94 |
-
# This is what keeps the "demo never crashes" guarantee true in production.
|
| 95 |
try:
|
| 96 |
return zg.chat_json(system, user, temperature)
|
| 97 |
except Exception:
|
| 98 |
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
if not is_available():
|
| 100 |
return None
|
| 101 |
try:
|
|
|
|
| 14 |
import os
|
| 15 |
|
| 16 |
MODEL = os.environ.get("CHIEF_ENGINEER_MODEL", "gemma4:e4b")
|
| 17 |
+
MODAL_API_URL = os.environ.get("CHIEF_ENGINEER_MODAL_URL",
|
| 18 |
+
"https://kylebrodeur--microfactory-node-inference-serve.modal.run/v1/chat/completions")
|
| 19 |
|
| 20 |
# Backend select. Default "ollama" keeps local/recording behavior IDENTICAL.
|
| 21 |
# Set CHIEF_ENGINEER_BACKEND=zerogpu ONLY on the published Space (see
|
|
|
|
| 39 |
return None
|
| 40 |
|
| 41 |
|
| 42 |
+
def _modal_api():
|
| 43 |
+
"""Lazily check if Modal API backend is selected."""
|
| 44 |
+
if BACKEND != "modal":
|
| 45 |
+
return None
|
| 46 |
+
return True # Modal API is always available (HTTP endpoint)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
def _forced_offline() -> bool:
|
| 50 |
"""Force the deterministic fallback path regardless of any daemon/backend.
|
| 51 |
Read dynamically (not cached) so tests can toggle it. Used by the offline
|
|
|
|
| 60 |
zg = _zerogpu()
|
| 61 |
if zg is not None:
|
| 62 |
return zg.is_available()
|
| 63 |
+
if _modal_api():
|
| 64 |
+
return True
|
| 65 |
if ollama is None:
|
| 66 |
return False
|
| 67 |
try:
|
|
|
|
| 75 |
zg = _zerogpu()
|
| 76 |
if zg is not None:
|
| 77 |
return zg.backend_status()
|
| 78 |
+
if _modal_api():
|
| 79 |
+
return f"<span style='color:var(--ao-green);'>●</span> live · Modal API (remote GPU)"
|
| 80 |
return (f"<span style='color:var(--ao-green);'>●</span> live · {MODEL} (local Ollama)"
|
| 81 |
if is_available() else
|
| 82 |
f"<span style='color:var(--ao-yellow);'>●</span> offline fallback · "
|
|
|
|
| 86 |
def warm_up() -> str:
|
| 87 |
"""Pay the model's cold start now (off-camera), so the first real BUILD is fast.
|
| 88 |
On ZeroGPU this enters the GPU window and loads the model; on Ollama/fallback it is
|
| 89 |
+
a cheap no-op. On Modal API it's a no-op (Modal handles its own warm-up).
|
| 90 |
+
Returns the (post-load) backend status. Never raises."""
|
| 91 |
zg = _zerogpu()
|
| 92 |
if zg is not None:
|
| 93 |
try:
|
|
|
|
| 103 |
return None
|
| 104 |
zg = _zerogpu()
|
| 105 |
if zg is not None:
|
|
|
|
|
|
|
|
|
|
| 106 |
try:
|
| 107 |
return zg.chat_json(system, user, temperature)
|
| 108 |
except Exception:
|
| 109 |
return None
|
| 110 |
+
if _modal_api():
|
| 111 |
+
try:
|
| 112 |
+
import urllib.request
|
| 113 |
+
body = json.dumps({
|
| 114 |
+
"messages": [{"role": "user", "content": f"{system}\n\n{user}"}],
|
| 115 |
+
"max_tokens": 512,
|
| 116 |
+
"temperature": temperature,
|
| 117 |
+
}).encode()
|
| 118 |
+
req = urllib.request.Request(MODAL_API_URL, data=body,
|
| 119 |
+
headers={"Content-Type": "application/json"})
|
| 120 |
+
with urllib.request.urlopen(req, timeout=120) as resp:
|
| 121 |
+
data = json.loads(resp.read())
|
| 122 |
+
text = data["choices"][0]["message"]["content"].strip()
|
| 123 |
+
if text.startswith("```"):
|
| 124 |
+
text = text.strip("`").lstrip()
|
| 125 |
+
if text[:4].lower() == "json":
|
| 126 |
+
text = text[4:]
|
| 127 |
+
return json.loads(text)
|
| 128 |
+
except Exception:
|
| 129 |
+
return None
|
| 130 |
if not is_available():
|
| 131 |
return None
|
| 132 |
try:
|
learn/finetune/activity.jsonl
CHANGED
|
@@ -31,3 +31,5 @@
|
|
| 31 |
{"timestamp":"2026-06-14T05:55:00-05:00","action":"serving","event":"all_three_complete","details":"All three serving items implemented: 1) gguf_pipeline_modal.py for Ollama GGUF on Modal, 2) modal_serve.py for Modal inference API, 3) core/llm_zerogpu_lora.py + app.py backend for Gradio model switcher. UI placement deferred to other agent per user request."}
|
| 32 |
{"timestamp":"2026-06-14T06:00:00-05:00","action":"serving","event":"modal_api_deployed","details":"Modal inference API deployed successfully at https://kylebrodeur--microfactory-node-inference-serve.modal.run. Image built in 71s, app deployed in 75s."}
|
| 33 |
{"timestamp":"2026-06-14T06:10:00-05:00","action":"deploy","event":"space_updated","details":"Deploy preflight 10/10 green. Pushed to build-small-hackathon/microfactory-lab. Factory reboot triggered. Space rebuilding. Note: Gradio warns about build_job arg count (model_choice has default, UI agent will wire dropdown)."}
|
|
|
|
|
|
|
|
|
| 31 |
{"timestamp":"2026-06-14T05:55:00-05:00","action":"serving","event":"all_three_complete","details":"All three serving items implemented: 1) gguf_pipeline_modal.py for Ollama GGUF on Modal, 2) modal_serve.py for Modal inference API, 3) core/llm_zerogpu_lora.py + app.py backend for Gradio model switcher. UI placement deferred to other agent per user request."}
|
| 32 |
{"timestamp":"2026-06-14T06:00:00-05:00","action":"serving","event":"modal_api_deployed","details":"Modal inference API deployed successfully at https://kylebrodeur--microfactory-node-inference-serve.modal.run. Image built in 71s, app deployed in 75s."}
|
| 33 |
{"timestamp":"2026-06-14T06:10:00-05:00","action":"deploy","event":"space_updated","details":"Deploy preflight 10/10 green. Pushed to build-small-hackathon/microfactory-lab. Factory reboot triggered. Space rebuilding. Note: Gradio warns about build_job arg count (model_choice has default, UI agent will wire dropdown)."}
|
| 34 |
+
{"timestamp":"2026-06-14T06:30:00-05:00","action":"serving","event":"gguf_both_launched","details":"Killed old v2-only GGUF run. Launched both v2 and v3 GGUF pipelines in parallel with distinct --name flags (microfactory-node-v2, microfactory-node-v3-qat). Reusing cached llama.cpp image — no rebuild."}
|
| 35 |
+
{"timestamp":"2026-06-14T06:30:00-05:00","action":"deploy","event":"space_v3_default","details":"Space now defaults to LoRA v3 (QAT E4B) — best training loss (1.75), best quantization quality. Pre-warmed at startup. Model options: v3 → v2 → Base → Modal API."}
|
learn/finetune/gguf_pipeline_modal.py
CHANGED
|
@@ -45,7 +45,7 @@ if modal is not None:
|
|
| 45 |
"accelerate>=0.34", "huggingface_hub")
|
| 46 |
)
|
| 47 |
|
| 48 |
-
# CPU image for llama.cpp
|
| 49 |
cpu_image = (
|
| 50 |
modal.Image.debian_slim(python_version="3.12")
|
| 51 |
.apt_install("git", "build-essential", "cmake")
|
|
|
|
| 45 |
"accelerate>=0.34", "huggingface_hub")
|
| 46 |
)
|
| 47 |
|
| 48 |
+
# CPU image for GGUF conversion — llama.cpp pre-built in the image (reused across runs)
|
| 49 |
cpu_image = (
|
| 50 |
modal.Image.debian_slim(python_version="3.12")
|
| 51 |
.apt_install("git", "build-essential", "cmake")
|