fix: call Modal directly from the canonical Space

#6
by thangvip - opened
README.md CHANGED
@@ -113,11 +113,10 @@ hackathon's 32B total limit.
113
  - **Training:** the MiniCPM and FLUX adapters, validation runs, and deployment
114
  experiments used Modal.
115
 
116
- Text and image inference scale independently. The canonical hackathon Space
117
- serves the custom interface and streams NDJSON progress. Because organization
118
- members cannot manage that Space's secrets, it forwards generation requests to
119
- the owner-controlled CPU orchestrator, which HMAC-signs calls to the two Modal
120
- services. No credential is stored in the public repository.
121
 
122
  ## Published Artifacts
123
 
 
113
  - **Training:** the MiniCPM and FLUX adapters, validation runs, and deployment
114
  experiments used Modal.
115
 
116
+ Text and image inference scale independently. The canonical hackathon Space is
117
+ a CPU orchestrator: it serves the custom interface, validates requests, streams
118
+ NDJSON progress, and HMAC-signs calls directly to the two Modal services. No
119
+ credential is stored in the public repository.
 
120
 
121
  ## Published Artifacts
122
 
docs/build-small-hackathon-article.md CHANGED
@@ -133,10 +133,9 @@ animals, so the visual variety felt smaller than the style menu suggested.
133
 
134
  ## Modal as the GPU Layer
135
 
136
- The canonical organization Space serves the custom interface and streams the
137
- API response. Since organization members cannot manage its secrets, it forwards
138
- generation requests to an owner-controlled CPU Space that holds the HMAC
139
- credential. Text and image workloads then run on separate Modal applications:
140
 
141
  - MiniCPM4.1-8B on an A100 40GB endpoint
142
  - FLUX.1-schnell plus the four style adapters on an A100 80GB endpoint
@@ -147,9 +146,8 @@ model from evicting the other and lets each service scale to zero
147
  independently. The public repository contains no credentials.
148
 
149
  Modal was also used for adapter training, validation grids, GGUF smoke tests,
150
- and deployment experiments. The runtime bridge signs requests with HMAC, and
151
- the organization Space preserves the NDJSON stream so a long generation
152
- remains visibly alive through both Hugging Face hops.
153
 
154
  ## Codex as an Engineering Partner
155
 
 
133
 
134
  ## Modal as the GPU Layer
135
 
136
+ The canonical organization Space serves the custom interface, validates
137
+ requests, and streams the API response. It holds an HMAC credential as a
138
+ private Space secret and calls two separate Modal applications directly:
 
139
 
140
  - MiniCPM4.1-8B on an A100 40GB endpoint
141
  - FLUX.1-schnell plus the four style adapters on an A100 80GB endpoint
 
146
  independently. The public repository contains no credentials.
147
 
148
  Modal was also used for adapter training, validation grids, GGUF smoke tests,
149
+ and deployment experiments. The organization Space signs requests with HMAC
150
+ and preserves the NDJSON stream so a long generation remains visibly alive.
 
151
 
152
  ## Codex as an Engineering Partner
153
 
src/compliment_forest/config.py CHANGED
@@ -64,11 +64,6 @@ class AppConfig(BaseModel):
64
  def from_env(cls) -> AppConfig:
65
  trace_path = os.getenv("CF_TRACE_PATH")
66
  hosted_space = bool(os.getenv("SPACE_ID"))
67
- submission_upstream = (
68
- "https://thangvip-compliment-forest.hf.space"
69
- if os.getenv("SPACE_ID") == "build-small-hackathon/compliment-forest"
70
- else None
71
- )
72
  default_text_backend = "transformers" if hosted_space else "demo"
73
  default_image_backend = "zerogpu" if hosted_space else "demo"
74
  return cls(
@@ -104,7 +99,7 @@ class AppConfig(BaseModel):
104
  modal_image_endpoint=os.getenv("CF_MODAL_IMAGE_ENDPOINT"),
105
  modal_music_endpoint=os.getenv("CF_MODAL_MUSIC_ENDPOINT"),
106
  modal_signing_key=(os.getenv("CF_MODAL_SIGNING_KEY") or os.getenv("HF_TOKEN")),
107
- upstream_space_url=os.getenv("CF_UPSTREAM_SPACE_URL") or submission_upstream,
108
  local_files_only=os.getenv("CF_LOCAL_FILES_ONLY", "0") == "1",
109
  default_seed=int(os.getenv("CF_DEFAULT_SEED", "3407")),
110
  default_style=os.getenv("CF_DEFAULT_STYLE", "surprise"),
 
64
  def from_env(cls) -> AppConfig:
65
  trace_path = os.getenv("CF_TRACE_PATH")
66
  hosted_space = bool(os.getenv("SPACE_ID"))
 
 
 
 
 
67
  default_text_backend = "transformers" if hosted_space else "demo"
68
  default_image_backend = "zerogpu" if hosted_space else "demo"
69
  return cls(
 
99
  modal_image_endpoint=os.getenv("CF_MODAL_IMAGE_ENDPOINT"),
100
  modal_music_endpoint=os.getenv("CF_MODAL_MUSIC_ENDPOINT"),
101
  modal_signing_key=(os.getenv("CF_MODAL_SIGNING_KEY") or os.getenv("HF_TOKEN")),
102
+ upstream_space_url=os.getenv("CF_UPSTREAM_SPACE_URL"),
103
  local_files_only=os.getenv("CF_LOCAL_FILES_ONLY", "0") == "1",
104
  default_seed=int(os.getenv("CF_DEFAULT_SEED", "3407")),
105
  default_style=os.getenv("CF_DEFAULT_STYLE", "surprise"),