Spaces:
Running on Zero
Running on Zero
File size: 1,731 Bytes
36cdb93 | 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 | """Prompt encoding with a content-addressed cache.
The T5 encoder (umt5-xxl) runs on CPU here to keep the GPU free, which costs
~40 s per prompt -- worth caching. The original cache key in run_streaming.py was
`abs(hash(prompt)) % 10**8`; Python salts `hash()` for str per process
(PYTHONHASHSEED), so the key changed on every invocation and the cache never hit.
That is why diag/ accumulated 19 ctx_*.pt files for ~3 distinct prompts. sha1 of
the text is stable across processes.
"""
import gc
import hashlib
import os
import torch
def prompt_key(prompt):
return hashlib.sha1(prompt.encode('utf-8')).hexdigest()[:16]
def encode_prompt(prompt, neg_prompt, ckpt_dir, cfg, cache_dir, text_len=512):
"""Return (pos, neg) embeddings [1, text_len, dim], cached on disk."""
os.makedirs(cache_dir, exist_ok=True)
path = os.path.join(cache_dir, f'ctx_{prompt_key(prompt)}.pt')
if os.path.exists(path):
return torch.load(path, map_location='cpu')
from wan.modules.t5 import T5EncoderModel
print(f'Loading T5 (CPU) to encode prompt -> {os.path.basename(path)} ...')
t5 = T5EncoderModel(text_len=text_len, dtype=cfg.t5_dtype,
device=torch.device('cpu'),
checkpoint_path=f'{ckpt_dir}/{cfg.t5_checkpoint}',
tokenizer_path=f'{ckpt_dir}/google/umt5-xxl')
def enc(p):
x = t5([p], torch.device('cpu'))[0].float()
if x.shape[0] < text_len:
x = torch.cat([x, torch.zeros(text_len - x.shape[0], x.shape[1])], 0)
return x[:text_len].unsqueeze(0)
blob = {'pos': enc(prompt), 'neg': enc(neg_prompt), 'prompt': prompt}
del t5
gc.collect()
torch.save(blob, path)
return blob
|