multimodalart HF Staff commited on
Commit
1ccbe3f
·
verified ·
1 Parent(s): 9c16554

Fall back to an anonymous conditioner call when the forwarded ZeroGPU token is refused

Browse files
Files changed (2) hide show
  1. README.md +12 -8
  2. app.py +26 -1
README.md CHANGED
@@ -162,14 +162,18 @@ one-time `PIPE.to("cuda")` is inside the first row's 339 s and does not reappear
162
 
163
  Two cards are booked per request: this Space's denoise loop and the conditioner's forward. ZeroGPU attributes a
164
  booking to the `X-IP-Token` header of the request that triggered it, so this Space forwards the caller's token to the
165
- conditioner (`gradio_client.Client(..., headers={"X-IP-Token": ...})`, from the `gr.Request` gradio injects — the UI
166
- path and the `/generate` API path alike). One user's request then bills as one request across both halves, the way it
167
- would if this were a single Space, and no org token is ever spent on it.
168
-
169
- A caller the router cannot attribute an unauthenticated API call falls back to the conditioner's IP-based quota,
170
- whose ceiling is 120 credits. An `xlarge` booking costs **twice** its seconds there, so the conditioner keeps its
171
- reservation at 60 s (120 credits) for an encode; asking it to upsample a prompt books 120 s (240 credits) and needs a
172
- forwarded token.
 
 
 
 
173
 
174
  ## Secrets
175
 
 
162
 
163
  Two cards are booked per request: this Space's denoise loop and the conditioner's forward. ZeroGPU attributes a
164
  booking to the `X-IP-Token` header of the request that triggered it, so this Space forwards the caller's token to the
165
+ conditioner (`gradio_client.Client(..., headers={"X-IP-Token": ...})`, off the `gr.Request` gradio injects — the UI
166
+ path and the `/generate` API path alike). When ZeroGPU honours it, one user's request bills as one request across both
167
+ halves and no org token is spent on it.
168
+
169
+ It is best effort, though: ZeroGPU answers `401` for a proxy token it will not honour, which `spaces` surfaces as
170
+ `Expired ZeroGPU proxy token`, and a token minted for one Space arriving at another is exactly that case on the API
171
+ path. So a refused token falls back to calling the conditioner with no token at all, on an IP-based quota.
172
+
173
+ That fallback is a working path rather than a degraded one, because the conditioner is sized for it. An unattributed
174
+ caller may book at most 120 credits at a time and an `xlarge` booking costs **twice** its seconds, i.e. 60 s — so the
175
+ conditioner books the encode (45 s) and a prompt upsample (60 s) as **two separate calls**, each under the ceiling,
176
+ where one combined booking would be refused outright.
177
 
178
  ## Secrets
179
 
app.py CHANGED
@@ -210,6 +210,30 @@ def ip_token_of(request) -> str | None:
210
  return token
211
 
212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  def encode_remote(prompt, image_path, last_image_path, canvas, num_frames, rewrite_prompt=False, ip_token=None):
214
  """Ask the conditioner Space for `prompt_embeds` + `text_token_tags`. Off this Space's GPU time entirely.
215
 
@@ -221,7 +245,8 @@ def encode_remote(prompt, image_path, last_image_path, canvas, num_frames, rewri
221
  from gradio_client import handle_file
222
  from safetensors import safe_open
223
 
224
- path, plan = conditioner(ip_token).predict(
 
225
  prompt=prompt,
226
  image_path=handle_file(image_path) if image_path else None,
227
  last_image_path=handle_file(last_image_path) if last_image_path else None,
 
210
  return token
211
 
212
 
213
+ LOG_TAG = "gen"
214
+
215
+
216
+ def call_conditioner(ip_token, **arguments):
217
+ """One conditioner call, on the caller's ZeroGPU identity when that is accepted and anonymously when it is not.
218
+
219
+ Forwarding is best effort. ZeroGPU's `/schedule` answers `401` for a proxy token it will not honour — which is
220
+ what a token minted for *this* Space looks like when it arrives at the conditioner — and `spaces` surfaces that as
221
+ `Expired ZeroGPU proxy token`. So the forwarded call is tried first, and a rejected token falls back to no token
222
+ at all rather than failing the request. The conditioner's own bookings are sized to fit the unattributed ceiling,
223
+ so the fallback is a working path and not a degraded one.
224
+ """
225
+ api_name = arguments.pop("api_name")
226
+ if ip_token is not None:
227
+ try:
228
+ return conditioner(ip_token).predict(**arguments, api_name=api_name)
229
+ except Exception as error:
230
+ if "proxy token" not in str(error):
231
+ raise
232
+ print(f"[{LOG_TAG}] the forwarded ZeroGPU token was refused ({error}); retrying anonymously", flush=True)
233
+ CLIENTS.pop(ip_token, None)
234
+ return conditioner(None).predict(**arguments, api_name=api_name)
235
+
236
+
237
  def encode_remote(prompt, image_path, last_image_path, canvas, num_frames, rewrite_prompt=False, ip_token=None):
238
  """Ask the conditioner Space for `prompt_embeds` + `text_token_tags`. Off this Space's GPU time entirely.
239
 
 
245
  from gradio_client import handle_file
246
  from safetensors import safe_open
247
 
248
+ path, plan = call_conditioner(
249
+ ip_token,
250
  prompt=prompt,
251
  image_path=handle_file(image_path) if image_path else None,
252
  last_image_path=handle_file(last_image_path) if last_image_path else None,