Instructions to use litert-community/Idol with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use litert-community/Idol 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
File size: 3,542 Bytes
74728e5 | 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 | """The state lever's graph form (round 2): one graph for the denoiser's 22 middle joint blocks, each block's weights as
runtime inputs, so the phone compiles it once per photo instead of once per block (the S26 compiled the joint blocks
96 times per photo, 0.39 s each, because only one or two fit in memory at a time).
Writes <out>/den_joint_mid.tflite (no weights; inputs h, t_mod, gate, then the 30 weight inputs of
idol_graphs.SHARED_WEIGHT_NAMES) and <out>/den_joint_w.f32 (little-endian float32, blocks 1..22 one after another,
each block's inputs in that order, flattened), and checks the shared module against every block's own module in
PyTorch on one random input.
IDOL_SDK=<idol-sdk> python export_shared_joint.py --out models/state
"""
import argparse
import json
import os
import sys
import time
import numpy as np
import torch
from safetensors.torch import load_file
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import f0_export as F0 # noqa: E402
import idol_graphs as IG # noqa: E402
def main():
ap = argparse.ArgumentParser()
ap.add_argument('--out', required=True)
ap.add_argument('--chunk', type=int, default=512)
a = ap.parse_args()
os.makedirs(a.out, exist_ok=True)
torch.set_grad_enabled(False)
den, _ = F0.load_denoiser()
den = den.float()
lora = load_file(F0.snap('speridlabs/idol-turbo', 'idol_turbo_lora.safetensors'))
blocks = list(range(1, len(den.blocks) - 1))
mids = [IG.DenJoint(den, k, lora, a.chunk).eval() for k in blocks]
shared = IG.DenJointShared(mids[0]).eval()
ref = mids[0].block
shapes = [list(t.shape) for t in IG.shared_block_weights(mids[0])]
L = IG.DEN_TOKENS + IG.COND_TOKENS + 1
torch.manual_seed(0)
h = torch.randn(1, L, 1024)
t_mod = torch.randn(1, 6144) * 0.1
gate = IG.lora_gate('slow')
worst = 0.0
wpath = os.path.join(a.out, 'den_joint_w.f32')
with open(wpath, 'wb') as f:
for k, jb in zip(blocks, mids):
b = jb.block
assert b.modulation and (b.c, b.h, b.d, b.eps1, b.eps2, b.repo.eps) == \
(ref.c, ref.h, ref.d, ref.eps1, ref.eps2, ref.repo.eps), k
w = IG.shared_block_weights(jb)
assert [list(t.shape) for t in w] == shapes, k
got, want = shared(h, t_mod, gate, *w), jb(h, t_mod, gate)
rel = float((got - want).norm() / want.norm())
worst = max(worst, rel)
print(f'block {k:2d}: shared vs own module rel L2 {rel:.2e}', flush=True)
for t in w:
f.write(t.numpy().astype('<f4').tobytes())
assert worst < 1e-5, worst
per_block = sum(int(np.prod(s)) for s in shapes)
assert os.path.getsize(wpath) == per_block * len(blocks) * 4
t0 = time.time()
import litert_torch
path = os.path.join(a.out, 'den_joint_mid.tflite')
litert_torch.convert(shared, (h, t_mod, gate, *IG.shared_block_weights(mids[0]))).export(path)
info = F0.scan_tflite(path)
json.dump({'blocks': blocks, 'names': IG.SHARED_WEIGHT_NAMES, 'shapes': shapes, 'per_block_floats': per_block,
'worst_rel_l2': worst, 'export_s': round(time.time() - t0, 1), 'scan': info},
open(os.path.join(a.out, 'shared_joint.json'), 'w'), indent=1, default=str)
print(f'den_joint_mid.tflite {os.path.getsize(path):,} B; den_joint_w.f32 {os.path.getsize(wpath):,} B '
f'({len(blocks)} blocks x {per_block:,} floats); worst rel L2 {worst:.2e}', flush=True)
if __name__ == '__main__':
main()
|