Spaces:
Paused
Paused
File size: 3,419 Bytes
a57b67c 53f4c20 a57b67c 9744c13 a57b67c 381de33 53f4c20 a57b67c 53f4c20 381de33 53f4c20 381de33 53f4c20 381de33 a57b67c | 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 | """Run real inference on an explicitly named deployed Space and verify its downloaded GLB/ZIP."""
import argparse
import json
import os
from pathlib import Path
import zipfile
import time
from gradio_client import Client, handle_file
from huggingface_hub import get_token
import trimesh
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--space', required=True, help='Hugging Face owner/space')
parser.add_argument('--image', type=Path)
parser.add_argument('--prompt', default='')
parser.add_argument('--animation-prompt', default='')
parser.add_argument('--animation-seconds', type=float, default=6)
parser.add_argument('--output-dir', type=Path, default=Path('outputs/hf-verification'))
args = parser.parse_args()
if not args.image and not args.prompt.strip():
parser.error('Supply --image, --prompt, or both')
args.output_dir.mkdir(parents=True, exist_ok=True)
client = Client(args.space, token=os.environ.get('HF_TOKEN') or get_token(),
download_files=args.output_dir.resolve())
job = client.submit(handle_file(str(args.image)) if args.image else None,
args.prompt, 8, 0, args.animation_prompt, args.animation_seconds, api_name='/generate')
previous = None
while not job.done():
update = job.status()
current = (update.code.name, tuple(p.desc for p in update.progress_data or []))
if current != previous:
print(json.dumps({'state': current[0], 'progress': current[1]}), flush=True)
previous = current
time.sleep(2)
model, reference, views, bundle, status, manifest, video = job.result()
(args.output_dir / f"{manifest['id']}.json").write_text(json.dumps(manifest, indent=2))
if args.animation_prompt:
import struct
raw = Path(model).read_bytes()
size, kind = struct.unpack_from('<II', raw, 12)
if kind != 0x4e4f534a:
raise RuntimeError('Animated GLB has no JSON chunk')
gltf = json.loads(raw[20:20 + size])
if not gltf.get('skins') or not gltf.get('animations'):
raise RuntimeError('Requested animation returned a static mesh')
if not video or not manifest.get('animation', {}).get('accepted'):
raise RuntimeError('Animation lacks video or failed its technical/visual review')
if manifest['status'] != 'complete':
raise RuntimeError('Space did not complete all stages')
scene = trimesh.load(model, force='scene', process=False)
if len(scene.geometry) != manifest['metrics']['components']:
raise RuntimeError('Downloaded component count differs from manifest')
for mesh in scene.geometry.values():
if not len(mesh.faces) or mesh.visual.kind != 'texture' or mesh.visual.material.baseColorTexture is None:
raise RuntimeError('Downloaded mesh has missing geometry or texture')
with zipfile.ZipFile(bundle) as archive:
embedded = json.loads(archive.read('manifest.json'))
if embedded['id'] != manifest['id'] or 'final.glb' not in archive.namelist():
raise RuntimeError('Download archive does not match the completed run')
print(json.dumps({'verified': True, 'run': manifest['id'], 'model': model, 'bundle': bundle,
'components': len(scene.geometry)}, indent=2))
if __name__ == '__main__':
main()
|