Spaces:
Sleeping
Sleeping
File size: 9,150 Bytes
dc7468e 3741d5c dc7468e 3741d5c 8ec8113 dc7468e 758d461 dc7468e 4ee7c6a cafaeed 8ec8113 dc7468e 6ec6311 dc7468e 4ee7c6a cafaeed 72ab5f3 dc7468e 8ec8113 dc7468e 8ec8113 dc7468e b3eac77 dc7468e b3eac77 6ec6311 8ec8113 758d461 dc7468e 758d461 4ee7c6a 758d461 dc7468e 4ee7c6a dc7468e 4ee7c6a 758d461 dc7468e 4ee7c6a dc7468e 758d461 dc7468e 8ec8113 758d461 dc7468e 758d461 3741d5c 758d461 dc7468e 3741d5c 39743d5 dc7468e 3741d5c 6ec6311 758d461 6ec6311 6c26a3c 758d461 dc7468e 3741d5c 758d461 4ee7c6a b3eac77 dc7468e 758d461 6ec6311 4ee7c6a 6ec6311 dc7468e a0d6c1d 4ee7c6a a0d6c1d dc7468e 4ee7c6a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | """Kalanos HF Space: bounded numeric audits and published assessment examples."""
import json
import logging
import tempfile
import os
from concurrent.futures import ThreadPoolExecutor
from html import escape
from urllib.parse import quote
from pathlib import Path
import gradio as gr
import requests
from cards import CSS, card_payload, grader_intro, header, kpis, render, section, share_strip
from quick_grade import parse_ref, quick_grade
from usage import track
CSS += '\n#k-card-markdown .custom-button-label { font-size:0; } #k-card-markdown .custom-button-label::before { content:"⧉"; font-size:18px; }'
# ZeroGPU compatibility shim. If the Space is ever scheduled on ZeroGPU hardware,
# its startup check kills the container unless at least one @spaces.GPU function
# exists ("No @spaces.GPU function detected during startup"). This app is CPU-only
# (the audit runs in a subprocess); the no-op below only satisfies that check.
# `spaces` is absent locally, so the import is guarded.
try:
import spaces
@spaces.GPU
def _zerogpu_warmup():
return 'ok'
except Exception:
pass
KALANOS_API = os.environ.get('KALANOS_API', 'https://hub.kalanos.ai').rstrip('/')
FEATURED = ('lerobot/aloha_static_towel', 'lerobot/pusht', 'lerobot/aloha_sim_insertion_human')
def published(ref):
try:
response = requests.get(f'{KALANOS_API}/d/hf/{quote(ref, safe="/")}/hf-card.json', timeout=12)
if response.status_code == 200:
return response.json()
except (requests.RequestException, ValueError):
pass
return None
def examples():
with ThreadPoolExecutor(max_workers=3) as pool:
payloads = [p for p in pool.map(published, FEATURED) if p]
head = section('Featured dataset reports')
if not payloads:
return head + '<div class="k-html"><p class="k-small k-muted">Featured reports are unavailable right now. You can still grade a public dataset above.</p></div>'
return head + '<div class="k-html">' + kpis(payloads) + '<div class="k-cards">' + ''.join(render(p) for p in payloads) + '</div></div>'
def _one(html):
return f'<div class="k-html"><div class="k-cards" style="grid-template-columns:minmax(0,1fr);max-width:420px">{html}</div></div>' if html else ''
def _ok(msg):
return f'<span class="k-ok">{escape(msg)}</span>'
def _err(msg):
return f'<span class="k-error" role="alert">{escape(msg)}</span>'
def _result(html, markdown, status, state):
"""Outputs for [out, card_text, card_acc, status, report_state]; the Markdown panel only appears with a result."""
return html, markdown, gr.update(visible=bool(markdown)), status, state
def dataset_exists(ref):
"""True/False from the public HF API; None if HF could not be reached."""
try:
r = requests.head(f'https://huggingface.co/api/datasets/{quote(ref, safe="/")}', timeout=10, allow_redirects=True)
except requests.RequestException:
return None
if r.status_code == 200:
return True
if r.status_code in (401, 403, 404):
return False
return None
NOT_FOUND = '{ref} was not found on Hugging Face, or it is private/gated. Check the org/name and try a public dataset.'
def run(ref):
try:
ref = parse_ref(ref)
except ValueError as exc:
return _result('', '', _err(str(exc)), None)
track('hf_audit_started')
try:
# Always run fresh. Existing published reports never short-circuit grading.
card = quick_grade(ref)
payload = card_payload(card, KALANOS_API)
result = _result(render(payload, published=False, detailed=True), payload['markdown'], _ok('Quick audit complete. Video: not assessed.'), card)
track('hf_audit_completed')
return result
except ValueError as exc:
track('hf_audit_failed')
return _result('', '', _err(str(exc)), None)
except Exception:
track('hf_audit_failed')
logging.exception('Quick audit failed')
if dataset_exists(ref) is False:
return _result('', '', _err(NOT_FOUND.format(ref=ref)), None)
return _result('', '', _err('The audit could not complete. Check it is a public LeRobot v2/v3 dataset within the Space limits, or run the CLI.'), None)
def lookup(ref):
try:
ref = parse_ref(ref)
except ValueError as exc:
return _result('', '', _err(str(exc)), None)
payload = published(ref)
if payload:
return _result(render(payload, detailed=True), payload['markdown'], _ok('Stored assessment shown with its recorded date and scope. Grade dataset runs a fresh audit.'), payload)
if dataset_exists(ref) is False:
return _result('', '', _err(NOT_FOUND.format(ref=ref)), None)
return _result('', '', _err(f'No published report for {ref} on Kalanos Hub yet. Grade dataset runs a fresh quick audit.'), None)
def download_assessment(card):
"""Gradio serves this session's converted assessment and expires cached files."""
if card is None:
return gr.update(value=None, visible=False)
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', prefix='kalanos-assessment-', delete=False) as file:
json.dump(card, file, indent=2, ensure_ascii=False)
download.temp_files.add(file.name)
return gr.update(value=file.name, visible=True)
# Publishing from the Space is intentionally disabled. The publisher upserts
# reports by slug alone (hf/<org>/<name>), so a visitor's quick audit submitted
# with a personal CLI key would replace the registry's full report for that
# dataset. Re-enable once /api/reports scopes slug conflicts by tenant.
# Until then: copy the HF card Markdown, or publish from the CLI.
with gr.Blocks(title='Kalanos · Robotics Dataset Quality', delete_cache=(600, 600)) as demo:
gr.HTML(header(KALANOS_API))
with gr.Column(elem_classes='k-grader'):
gr.HTML(grader_intro())
with gr.Row():
ref_in = gr.Textbox(label='Public HF dataset', placeholder='lerobot/pusht', scale=4, show_label=False, container=False)
go = gr.Button('Grade dataset', variant='primary', scale=1, elem_classes='k-primary')
# Secondary action stays clear; report cards themselves use compact icons.
lookup_btn = gr.Button('View published report', scale=1, elem_classes='k-secondary')
status = gr.HTML('', elem_classes='k-status')
report_state = gr.State(None, time_to_live=600)
download = gr.DownloadButton('Download assessment JSON (compact)', visible=False)
report_state.change(download_assessment, inputs=report_state, outputs=download)
out = gr.HTML()
with gr.Accordion('HF card Markdown', open=False, elem_classes='k-accordion', visible=False) as card_acc:
copy_card = gr.Button('Copy HF dataset card', size='sm', render=False)
card_text = gr.Code(language='markdown', label='Copy into your existing dataset README', interactive=False, buttons=[copy_card], elem_id='k-card-markdown')
copy_card.click(fn=None, inputs=card_text, outputs=None, queue=False,
js="async (markdown) => { await window.kalanosUsage?.copy(markdown, document.querySelector('#k-card-markdown .custom-button')); }")
card_acc.expand(fn=None, queue=False, js="() => { window.kalanosUsage?.emit('hf_card_previewed'); }")
featured = gr.HTML(section('Featured dataset reports'))
demo.load(examples, outputs=featured)
outputs = [out, card_text, card_acc, status, report_state]
go.click(run, inputs=ref_in, outputs=outputs, concurrency_limit=1, concurrency_id='audit')
ref_in.submit(run, inputs=ref_in, outputs=outputs, concurrency_limit=1, concurrency_id='audit')
lookup_btn.click(lookup, inputs=ref_in, outputs=outputs)
gr.HTML(share_strip(KALANOS_API))
gr.HTML('<p class="k-small k-muted">Anonymous activity counts help improve this demo. Dataset names and card contents are not included.</p>')
THEME = gr.themes.Base(
primary_hue=gr.themes.colors.slate, neutral_hue=gr.themes.colors.stone,
font=[gr.themes.GoogleFont('IBM Plex Sans'), 'sans-serif'],
font_mono=[gr.themes.GoogleFont('IBM Plex Mono'), 'monospace'],
).set(body_background_fill='#f2efe6', body_text_color='#202622', block_radius='0px', button_large_radius='3px',
input_radius='3px', input_background_fill='#ffffff', input_border_color='#d2d3cb')
# Light-only: Gradio adds `.dark` to <body> from the viewer's system setting (or
# ?__theme=dark); every surface here is pinned light, so dark text variables would
# produce light-on-light text. Remove the class at load and keep it off.
FORCE_LIGHT_JS = '''() => {
const off = () => { document.body.classList.remove('dark'); document.documentElement.classList.remove('dark'); };
off(); new MutationObserver(off).observe(document.body, { attributes: true, attributeFilter: ['class'] });
}'''
FORCE_LIGHT_HEAD = '<meta name="color-scheme" content="light">'
APP_JS = FORCE_LIGHT_JS.replace('() => {', '() => {\n' + Path(__file__).with_name('usage.js').read_text() + '\n', 1)
if __name__ == '__main__':
demo.queue(max_size=4).launch(css=CSS, theme=THEME, js=APP_JS, head=FORCE_LIGHT_HEAD)
|