disco-zero / tools /live.py
rfick's picture
Squash history: one commit holding the current files
4b23c8f
Raw History Blame Contribute Delete
4.24 kB
"""The live Space through its Gradio API: the configuration's first preset at SNR 30 with the tissue panel's defaults,
then a custom two-shell protocol on the configuration's first timing class; prints the headline, the timings and the
seconds the worker spent on the packs' responses the page had not cached and, with ``--stream``, every stage update as it
arrives; downloads the figures and files to ``$LIVE_OUT``. ``--config`` is the configuration the Space serves
(``DISCO_CONFIG``: ``config.toml`` for the DiSCo Spaces, ``brain.toml`` for ``rfick/brain-zero``): the inputs are
built from its source's panel, presets and knobs, not spelled here.
python tools/live.py [space] [--config brain.toml] [--stream] [--preset NAME] [--no-ladder] [--knob CHOICE]
"""
import argparse
import os
import sys
import time
def main():
ap = argparse.ArgumentParser()
ap.add_argument("space", nargs="?", default="rfick/disco")
ap.add_argument("--config", default=os.environ.get("DISCO_CONFIG", "config.toml"), help="the configuration in space/ the Space serves")
ap.add_argument("--stream", action="store_true", help="print every stage update as it arrives")
ap.add_argument("--preset", action="append", help="an acquisition to run (default: the first preset, then custom shells)")
ap.add_argument("--no-ladder", action="store_true", help="skip the explorer's tier ladder (the shortest GPU reservation)")
ap.add_argument("--knob", default=None, help="B: the same run with this knob changed (a choice of the page's dropdown)")
a = ap.parse_args()
os.environ["DISCO_CONFIG"] = a.config # before the page module reads its configuration
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from gradio_client import Client
from huggingface_hub import get_token
from space import app as A, pipeline as P, sources
cfg = P.config()
S = sources.source_class(cfg)
panel = S.panel(cfg)
defaults = {c.name: c.value for row in panel.rows for c in row}
tc = S.tracking_controls(cfg)
shapes = list(S.shapes_of(cfg))
physics = [defaults[name] for name in panel.fields]
def inputs(preset, *, knob, n_keys=1, ladder=True):
shells = [True, shapes[0], 1000, 30, 12.0, 24.0, 53.5, True, shapes[0], 3000, 45, 8.0, 20.0, 53.5,
False, shapes[0], 3000, 90, 17.0, 30.0, 53.5, False, shapes[0], 6000, 60, 17.0, 30.0, 53.5]
return [preset, 2, True, 30, tc["density"][2], tc["max_angle"][2], tc["step"][2], 0, None, knob, A.IDEAL, n_keys, ladder, *physics, *shells]
c = Client(a.space, token=get_token(), verbose=False, download_files=os.environ.get("LIVE_OUT", "/tmp/disco-live"), httpx_kwargs={"timeout": 900})
for preset in a.preset or (S.presets(cfg)[0], A.CUSTOM):
t0 = time.perf_counter()
args = inputs(preset, knob=a.knob or A.NO_KNOB, ladder=not a.no_ladder)
print(f"{preset}: the client's own estimate {A.estimated_seconds(*args)} s (the page's cache is not known here; the Space prices "
f"the responses it has not cached on top)", flush=True)
job = c.submit(*args, api_name="/run_pipeline")
seen = 0
while a.stream and not job.done():
outs = job.outputs()
for o in outs[seen:]:
print(f" +{time.perf_counter() - t0:5.1f} s: {str(o[1])[:100]}", flush=True)
seen = len(outs)
time.sleep(1)
out = job.result()
print(f"{preset}: {time.perf_counter() - t0:.1f} s wall; result received at unix {time.time():.1f}", flush=True)
named = dict(zip([n for n in A.OUTPUTS if n not in ("result", "b_row")], out)) # the API returns neither the gr.State nor the gr.Row
print(named["headline"]); print(named["timings"])
rows = named["timings"]["data"] if isinstance(named["timings"], dict) else named["timings"]
responses = [r[1] for r in rows if r[0] == A.RESPONSES_ROW]
print(f"the packs' responses on the worker: {responses[0] if responses else 'none (the source prepares nothing)'} s", flush=True)
print("tck", named["tck"], "volumes", named["volumes"], flush=True)
if __name__ == "__main__":
main()