Fastfill-test / code /fastfill /v2 /serve.py
XXXpilar's picture
FastFill v4 base (step 6552): LoRA adapter, geometry heads, tokenizer, training code, predict.py
e6f80f3 verified
Raw History Blame Contribute Delete
4.41 kB
"""Offline JSON runner for the v2 runtime; no network service or real Host writes.
The demo catalog ranks by category, typed capabilities and target-size distance.
Nuanced natural-language retrieval needs an external semantic Resolver adapter.
"""
import argparse
import json
from pathlib import Path
import sys
from .runtime import Asset, AtomicMemoryHost, BoundedTranslationRepair, CatalogResolver, RuntimeBudget, SupportSurface, run_pipeline
def asset_from_dict(value):
allowed = {"ref", "category", "description", "actual_size_local_m", "canonical_transform",
"semantic_front_local", "capabilities", "support_surfaces", "provenance"}
if not isinstance(value, dict) or set(value) - allowed:
raise ValueError("invalid catalog asset fields")
required = {"ref", "category", "actual_size_local_m"}
if not required.issubset(value):
raise ValueError("asset needs ref, category and actual_size_local_m")
surfaces = tuple(SupportSurface(**surface) for surface in value.get("support_surfaces", ()))
return Asset(**{**value, "support_surfaces": surfaces})
def load_catalog(path):
value = _read(path)
if isinstance(value, dict):
if set(value) != {"assets"}:
raise ValueError("catalog object must contain only assets")
value = value["assets"]
if not isinstance(value, list):
raise ValueError("catalog must be an asset array or {assets: array}")
return CatalogResolver(tuple(asset_from_dict(asset) for asset in value))
def _read(path):
def reject_constant(value):
raise ValueError(f"nonfinite JSON constant {value}")
with Path(path).open() as handle:
return json.load(handle, parse_constant=reject_constant)
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--condition", required=True, type=Path)
parser.add_argument("--prediction", required=True, type=Path)
parser.add_argument("--catalog", required=True, type=Path)
parser.add_argument("--output", type=Path, help="New repository/output JSON path; defaults to stdout")
parser.add_argument("--max-asset-retries", type=int, default=2)
parser.add_argument("--max-repair-calls", type=int, default=0)
parser.add_argument("--repair-step-m", type=float, default=.25)
parser.add_argument("--max-seconds", type=float, default=10.)
parser.add_argument("--required-levels", nargs="+", choices=("bbox", "mesh", "physics", "solver"), default=["bbox"])
parser.add_argument("--commit-in-memory", action="store_true", help="Exercise only the offline atomic Host contract")
parser.add_argument("--idempotency-key", default="offline-request")
args = parser.parse_args(argv)
try:
if args.output is not None:
forbidden = Path("/Volumes/harddisk/3D_Room_Collections").resolve()
if args.output.resolve().is_relative_to(forbidden):
raise ValueError("source datasets are read-only; choose a new output path")
if args.output.exists():
raise ValueError("output already exists; choose a new path")
host = AtomicMemoryHost() if args.commit_in_memory else None
report = run_pipeline(_read(args.condition), _read(args.prediction), load_catalog(args.catalog),
host=host, budget=RuntimeBudget(args.max_asset_retries, args.max_repair_calls, args.max_seconds),
repair=BoundedTranslationRepair(args.repair_step_m) if args.max_repair_calls else None,
required_levels=tuple(args.required_levels), idempotency_key=args.idempotency_key,
expected_world_version=0 if host else None)
if host:
report = {**report, "offline_host_snapshot": host.snapshot()}
output = json.dumps(report, indent=2, allow_nan=False) + "\n"
if args.output:
args.output.parent.mkdir(parents=True, exist_ok=True)
with args.output.open("x") as handle:
handle.write(output)
else:
sys.stdout.write(output)
return 0 if report["ok"] else 2
except (ValueError, TypeError, KeyError, OSError) as exc:
sys.stderr.write(json.dumps({"error": "invalid_runtime_request", "message": str(exc)}) + "\n")
return 2
if __name__ == "__main__":
raise SystemExit(main())