Instructions to use litert-community/clef-flash-LiteRT with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use litert-community/clef-flash-LiteRT with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Download conversion/clef_cpu_check.py from litert-community/clef-flash-LiteRT: direct link, hf CLI and curl.
- Browser
- Download file 11.3 kB
-
https://huggingface.co/litert-community/clef-flash-LiteRT/resolve/main/conversion/clef_cpu_check.py
- Command line
-
hf download hf://litert-community/clef-flash-LiteRT/conversion/clef_cpu_check.py
-
curl -L -o clef_cpu_check.py https://huggingface.co/litert-community/clef-flash-LiteRT/resolve/main/conversion/clef_cpu_check.py
11.3 kB
| #!/usr/bin/env python3 | |
| """Round 1 step 9: the exported row graph on the Mac CPU (ai-edge-litert 2.2.0 CompiledModel, XNNPACK, 8 threads, no | |
| weight cache file) on every reference text run that fits L, plus the red arms; the hidden states go to the author's | |
| head in venv-ref (scripts/clef_score.py --hidden-dir cache/r1/cpu --tag cpu_L1024). | |
| ~/venvs/lt094dev/bin/python scripts/clef_cpu_check.py --tflite out/r1/clef_rowprefill_L1024_fp32.tflite \ | |
| [--threads 8] [--deadline-s 1440] | |
| -> cache/r1/cpu/<id>__text.npy (hidden at the real positions, float32 [T, 4096]), one per run | |
| results/cpu_check_L1024_part<k>.json per invocation (k = 1, 2, ...); when every run has its file: | |
| results/cpu_check_L1024.json (the parts merged) | |
| Resumable: a run whose .npy exists is skipped (each .npy is written to a temp name and renamed); no new run starts | |
| after --deadline-s seconds. Inputs by signature name: embeds / valid / cos / sin from the NumPy host | |
| (scripts/clef_host.py, the reference's ids); `hidden` read back [1, L, 4096]. Recorded: compile seconds, | |
| is_fully_accelerated, the runtime's delegation lines (VERBOSE log on, this process's fd 2 -> logs/cpu_check_L<L>_part<k> | |
| .runtime.log: XNNPACK's `Replacing N out of M node(s)` = delegated / total nodes and partitions), per run write / run / | |
| read ms and non-finite counts, the hidden max |diff| against the reference's last_hidden and against the torch check's | |
| hidden where it exists, memory (phys_footprint) after compile and at the end, and the files next to the model and in | |
| TMPDIR before / after (a weight cache file would show there; the CpuOptions weight-cache path is left empty).""" | |
| import argparse | |
| import importlib.metadata | |
| import json | |
| import os | |
| import sys | |
| import time | |
| from pathlib import Path | |
| import numpy as np | |
| K = Path(__file__).resolve().parents[1] | |
| sys.path.insert(0, str(K / "scripts")) | |
| import clef_host as H # noqa: E402 | |
| from clef_export import memory # noqa: E402 | |
| from clef_rt import LINE_KEYS, PARTITIONED, REPLACING, runtime_log_verbose # noqa: E402 | |
| SNAP = K / "hf/hub/models--Cloudflare--clef-flash/snapshots/f0b7d3cd65296abfe459e6c228b618f5d8b26d2f" | |
| SIG = "serving_default" | |
| def listing(d: Path) -> list: | |
| return sorted(f"{p.name} {p.stat().st_size}" for p in d.iterdir()) if d.is_dir() else [] | |
| def main() -> int: | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--tflite", required=True) | |
| ap.add_argument("--threads", type=int, default=8) | |
| ap.add_argument("--deadline-s", type=float, default=None) | |
| a = ap.parse_args() | |
| t_start = time.monotonic() | |
| path = K / a.tflite | |
| cache = K / "cache/r1/cpu" | |
| cache.mkdir(parents=True, exist_ok=True) | |
| k = 1 | |
| while (K / f"results/cpu_check_L1024_part{k}.json").exists(): | |
| k += 1 | |
| ref = json.loads((K / "ref/records_ref.json").read_text()) | |
| red = json.loads((K / "ref/records_ref_red.json").read_text()) | |
| runs_all = [r for r in ref["rows"] if r["arm"] == "text"] + list(red["rows"]) | |
| log = K / f"logs/cpu_check_part{k}.runtime.log" | |
| log_f = open(log, "w") | |
| saved = os.dup(2) | |
| os.dup2(log_f.fileno(), 2) | |
| doc = {"what": "round 1 step 9: CompiledModel CPU (XNNPACK) on the fp32 row graph", "tflite": a.tflite, | |
| "tflite_bytes": path.stat().st_size, "part": k, "started_at": time.strftime("%Y-%m-%dT%H:%M:%S%z"), | |
| "ai_edge_litert": importlib.metadata.version("ai-edge-litert"), "threads": a.threads, | |
| "runtime_log": str(log.relative_to(K)), "files_next_to_model_before": listing(path.parent), | |
| "tmpdir": os.environ.get("TMPDIR"), "tmpdir_before": listing(Path(os.environ.get("TMPDIR", "/nonexistent")))} | |
| rows, stopped = [], False | |
| try: | |
| doc["logger"] = runtime_log_verbose() | |
| from ai_edge_litert.compiled_model import CompiledModel, CpuOptions, HardwareAccelerator, Options | |
| cpu = CpuOptions(num_threads=a.threads) | |
| doc["cpu_options"] = cpu._as_flat_kwargs() | |
| opts = Options(hardware_accelerators=HardwareAccelerator.CPU, cpu_options=cpu) | |
| doc["memory_before_compile"] = memory() | |
| t0 = time.perf_counter() | |
| model = CompiledModel.from_file(str(path), options=opts) | |
| doc["compile_seconds"] = round(time.perf_counter() - t0, 2) | |
| doc["memory_after_compile"] = memory() | |
| try: | |
| doc["is_fully_accelerated"] = bool(model.is_fully_accelerated()) | |
| except Exception as e: # informational | |
| doc["is_fully_accelerated"] = f"unavailable: {type(e).__name__}: {e}" | |
| sigs = model.get_signature_list() | |
| assert list(sigs) == [SIG], sigs | |
| in_det, out_det = model.get_input_tensor_details(SIG), model.get_output_tensor_details(SIG) | |
| doc["inputs"] = {n: {kk: str(v) for kk, v in d.items()} for n, d in in_det.items()} | |
| doc["outputs"] = {n: {kk: str(v) for kk, v in d.items()} for n, d in out_det.items()} | |
| L, D = (int(x) for x in list(out_det["hidden"]["shape"])[1:]) | |
| assert sorted(in_det) == ["cos", "embeds", "sin", "valid"], sorted(in_det) | |
| doc["L"] = L | |
| runs = [r for r in runs_all if r["tokens"] <= L] | |
| doc["runs_total"] = len(runs) | |
| doc["runs_skipped_longer_than_L"] = [f"{r['id']}/{r['arm']} {r['tokens']}" for r in runs_all if r["tokens"] > L] | |
| ins = {n: model.create_input_buffer_by_name(SIG, n) for n in in_det} | |
| outs = {n: model.create_output_buffer_by_name(SIG, n) for n in out_det} | |
| table = H.EmbedTable(SNAP) | |
| for r in runs: | |
| name = f"{r['id']}__{r['arm']}.npy" | |
| if (cache / name).exists(): | |
| continue | |
| if a.deadline_s is not None and time.monotonic() - t_start > a.deadline_s: | |
| stopped = True | |
| break | |
| T = r["tokens"] | |
| embeds, valid, cos, sin = H.row_inputs(r["ids"], L, table) | |
| t = time.perf_counter() | |
| ins["embeds"].write(embeds) | |
| ins["valid"].write(valid) | |
| ins["cos"].write(cos) | |
| ins["sin"].write(sin) | |
| tr = time.perf_counter() | |
| model.run_by_name(SIG, ins, outs) | |
| run_ms = (time.perf_counter() - tr) * 1000 | |
| h = np.asarray(outs["hidden"].read(L * D, np.float32), dtype=np.float32).reshape(L, D) | |
| all_ms = (time.perf_counter() - t) * 1000 | |
| hr = h[:T].copy() | |
| tmp = cache / (name + ".tmp.npy") | |
| np.save(tmp, hr) | |
| os.replace(tmp, cache / name) | |
| z = np.load(K / f"ref/npz/{r['id']}__{r['arm']}.npz") | |
| row = {"id": r["id"], "arm": r["arm"], "source": r["source"], "tokens": T, "ms_write_run_read": round(all_ms, 1), | |
| "ms_run": round(run_ms, 1), "nonfinite_real": int((~np.isfinite(hr)).sum()), | |
| "nonfinite_all": int((~np.isfinite(h)).sum()), | |
| "hidden_max_abs_vs_reference": float(np.abs(hr - z["last_hidden"]).max())} | |
| tc = K / f"cache/r1/torch/{name}" | |
| if tc.exists(): | |
| row["hidden_max_abs_vs_torch_check"] = float(np.abs(hr - np.load(tc)).max()) | |
| rows.append(row) | |
| print(f"{len(rows)} {r['id']} T={T} run {run_ms:.0f} ms max|dh| ref {row['hidden_max_abs_vs_reference']:.3e}", | |
| file=sys.stdout, flush=True) | |
| doc["memory_end"] = memory() | |
| for b in list(ins.values()) + list(outs.values()): | |
| try: | |
| b.destroy() | |
| except Exception: | |
| pass | |
| model.close() | |
| doc["status"] = "OK" | |
| except BaseException as e: | |
| doc["status"] = "FAIL" | |
| doc["error"] = f"{type(e).__name__}: {e}" | |
| import traceback | |
| traceback.print_exc() | |
| finally: | |
| sys.stderr.flush() | |
| os.dup2(saved, 2) | |
| log_f.close() | |
| lines = log.read_text(errors="replace").splitlines() | |
| doc["runtime_log_lines"] = len(lines) | |
| doc["runtime_log_key_lines"] = [ln for ln in lines if LINE_KEYS.search(ln)][:80] | |
| doc["delegation"] = { | |
| "replacing": [{"delegated": int(m[0]), "total": int(m[1]), "delegate": m[2], "partitions": int(m[3])} | |
| for m in REPLACING.findall("\n".join(lines))], | |
| "partitioned": [{"subgraph": int(m[0]), "selected": int(m[1]), "total": int(m[2]), "partitions": int(m[3])} | |
| for m in PARTITIONED.findall("\n".join(lines))]} | |
| doc["files_next_to_model_after"] = listing(path.parent) | |
| doc["tmpdir_after"] = listing(Path(os.environ.get("TMPDIR", "/nonexistent"))) | |
| doc["new_files_next_to_model"] = sorted(set(doc["files_next_to_model_after"]) - set(doc["files_next_to_model_before"])) | |
| doc.update(rows=rows, runs_this_part=len(rows), stopped_at_deadline=stopped, | |
| seconds_wall=round(time.monotonic() - t_start, 1), finished_at=time.strftime("%Y-%m-%dT%H:%M:%S%z")) | |
| if rows: | |
| ms = np.asarray([r["ms_run"] for r in rows]) | |
| doc["ms_run_this_part"] = {"median": float(np.median(ms)), "min": float(ms.min()), "max": float(ms.max()), | |
| "note": "per-run times of the gate loop (a correctness run, not the ladder row)"} | |
| (K / f"results/cpu_check_L1024_part{k}.json").write_text(json.dumps(doc, indent=1) + "\n") | |
| print(json.dumps({kk: doc.get(kk) for kk in ("status", "error", "part", "compile_seconds", "is_fully_accelerated", | |
| "runs_this_part", "stopped_at_deadline", "delegation", | |
| "new_files_next_to_model", "seconds_wall")}, indent=1), flush=True) | |
| done = doc["status"] == "OK" and all((cache / f"{r['id']}__{r['arm']}.npy").exists() for r in runs_all if r["tokens"] <= 1024) | |
| if done and not (K / "results/cpu_check_L1024.json").exists(): | |
| parts = [json.loads((K / f"results/cpu_check_L1024_part{i}.json").read_text()) for i in range(1, k + 1)] | |
| allrows = [x for p in parts for x in p["rows"]] | |
| merged = {"what": doc["what"], "tflite": a.tflite, "tflite_bytes": doc["tflite_bytes"], "parts": len(parts), | |
| "runs": len(allrows), "rows": allrows, | |
| "all_finite": all(x["nonfinite_real"] == 0 for x in allrows), | |
| "hidden_max_abs_vs_reference": max(x["hidden_max_abs_vs_reference"] for x in allrows), | |
| "hidden_max_abs_vs_torch_check": max((x["hidden_max_abs_vs_torch_check"] for x in allrows | |
| if "hidden_max_abs_vs_torch_check" in x), default=None), | |
| "compile_seconds": [p.get("compile_seconds") for p in parts], | |
| "delegation": [p["delegation"] for p in parts], "is_fully_accelerated": [p.get("is_fully_accelerated") for p in parts], | |
| "memory_after_compile": [p.get("memory_after_compile") for p in parts], | |
| "new_files_next_to_model": sorted({f for p in parts for f in p["new_files_next_to_model"]}), | |
| "cpu_options": doc.get("cpu_options"), "ai_edge_litert": doc["ai_edge_litert"]} | |
| (K / "results/cpu_check_L1024.json").write_text(json.dumps(merged, indent=1) + "\n") | |
| print("MERGED results/cpu_check_L1024.json", flush=True) | |
| return 0 if doc["status"] == "OK" else 1 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |