kylebrodeur commited on
Commit
8faa5bd
·
verified ·
1 Parent(s): 22fe767

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. Returns the (post-load) backend status. Never raises."""
 
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 build + GGUF conversion
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")