SeFi-Image / sefi /io.py
WaveCut's picture
Add SeFi Image ZeroGPU app
f085bc2 verified
Raw
History Blame Contribute Delete
2.65 kB
"""Prompt and output helpers for SEFI inference."""
from __future__ import annotations
import json
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Iterable
from PIL import Image
@dataclass(frozen=True)
class GenerationItem:
index: int
prompt_index: int
repeat_index: int
prompt: str
@property
def file_stem(self) -> str:
if self.repeat_index == 0:
return f"{self.prompt_index:06d}"
return f"{self.prompt_index:06d}_{self.repeat_index:02d}"
def load_prompts(*, prompt: str | None, prompt_file: str | None) -> list[str]:
prompts: list[str] = []
if prompt:
prompts.append(prompt)
if prompt_file:
with open(prompt_file, "r", encoding="utf-8") as handle:
prompts.extend(line.strip() for line in handle if line.strip())
if not prompts:
raise ValueError("Provide --prompt or --prompt-file.")
return prompts
def expand_prompts(prompts: Iterable[str], num_images_per_prompt: int) -> list[GenerationItem]:
if num_images_per_prompt <= 0:
raise ValueError("num_images_per_prompt must be > 0.")
items: list[GenerationItem] = []
index = 0
for prompt_index, prompt in enumerate(prompts):
for repeat_index in range(num_images_per_prompt):
items.append(
GenerationItem(
index=index,
prompt_index=prompt_index,
repeat_index=repeat_index,
prompt=prompt,
)
)
index += 1
return items
def save_images(
*,
output_dir: str | Path,
items: list[GenerationItem],
images: list[Image.Image],
rank: int = 0,
) -> None:
if len(items) != len(images):
raise ValueError(f"items/images length mismatch: {len(items)} != {len(images)}")
out = Path(output_dir)
out.mkdir(parents=True, exist_ok=True)
metadata_path = out / f"metadata_rank{rank:03d}.jsonl"
with metadata_path.open("a", encoding="utf-8") as meta:
for item, image in zip(items, images):
image_path = out / f"{item.file_stem}.png"
image.save(image_path)
row = asdict(item)
row["image"] = image_path.name
meta.write(json.dumps(row, ensure_ascii=False) + "\n")
def write_manifest(output_dir: str | Path, payload: dict) -> None:
out = Path(output_dir)
out.mkdir(parents=True, exist_ok=True)
with (out / "inference_manifest.json").open("w", encoding="utf-8") as handle:
json.dump(payload, handle, ensure_ascii=False, indent=2, sort_keys=True)