ChartPipeline / scripts /improve_generated_infographics.py
Ray1ee01's picture
Upload folder using huggingface_hub
58e6885 verified
Raw
History Blame Contribute Delete
5.11 kB
import argparse
import base64
import json
import os
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path
from openai import OpenAI
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
os.chdir(ROOT)
from config import api_key, base_url
DEFAULT_PROMPT = "improve this infographics to make it look more visual coherent and appealing."
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--input-root",
default=None,
help="chart_template_samples 下某次任务目录;默认取最新时间戳目录",
)
parser.add_argument(
"--output-dir",
default=None,
help="输出目录;默认 <input-root>/gpt_image_2_improved",
)
parser.add_argument("--model", default="gpt-image-2")
parser.add_argument("--prompt", default=DEFAULT_PROMPT)
parser.add_argument("--limit", type=int, default=0)
parser.add_argument("--workers", type=int, default=1)
parser.add_argument("--size", default="auto")
parser.add_argument("--quality", default="auto")
parser.add_argument("--overwrite", action="store_true")
return parser.parse_args()
def latest_sample_run(root: Path):
runs = [
p
for p in root.iterdir()
if p.is_dir() and (p / "run_config.json").is_file() and p.name[:8].isdigit()
]
if not runs:
raise SystemExit(f"no timestamp run found under {root}")
return sorted(runs, key=lambda p: p.name)[-1]
def collect_pngs(input_root: Path, output_dir: Path, limit: int):
pngs = [
p
for p in input_root.rglob("*.png")
if output_dir not in p.parents
]
pngs = sorted(pngs)
if limit > 0:
pngs = pngs[:limit]
return pngs
def output_path_for(input_root: Path, output_dir: Path, image_path: Path):
rel = image_path.relative_to(input_root)
return output_dir / rel.parent / f"{image_path.stem}_gpt_image_2.png"
def write_jsonl(path: Path, record: dict):
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, "a", encoding="utf-8") as f:
f.write(json.dumps(record, ensure_ascii=False) + "\n")
def improve_one(client, image_path: Path, out_path: Path, args):
out_path.parent.mkdir(parents=True, exist_ok=True)
with open(image_path, "rb") as image_file:
result = client.images.edit(
model=args.model,
image=image_file,
prompt=args.prompt,
size=args.size,
quality=args.quality,
n=1,
)
image_bytes = base64.b64decode(result.data[0].b64_json)
with open(out_path, "wb") as f:
f.write(image_bytes)
return {
"input": str(image_path),
"output": str(out_path),
"model": args.model,
"prompt": args.prompt,
}
def improve_job(job):
args, image_path, out_path = job
client = OpenAI(api_key=api_key, base_url=base_url)
return improve_one(client, image_path, out_path, args)
def main():
args = parse_args()
input_root = Path(args.input_root) if args.input_root else latest_sample_run(
ROOT / "output" / "chart_template_samples"
)
output_dir = Path(args.output_dir) if args.output_dir else input_root / "gpt_image_2_improved"
output_dir.mkdir(parents=True, exist_ok=True)
images = collect_pngs(input_root, output_dir, args.limit)
manifest = output_dir / "manifest.jsonl"
if manifest.exists() and args.overwrite:
manifest.unlink()
jobs = []
for image_path in images:
out_path = output_path_for(input_root, output_dir, image_path)
if out_path.exists() and not args.overwrite:
continue
jobs.append((args, image_path, out_path))
print(f"input_root={input_root}", flush=True)
print(f"output_dir={output_dir}", flush=True)
print(f"images={len(images)} pending={len(jobs)} workers={args.workers}", flush=True)
if args.workers > 1:
with ThreadPoolExecutor(max_workers=args.workers) as executor:
futures = [executor.submit(improve_job, job) for job in jobs]
for index, future in enumerate(as_completed(futures), 1):
record = future.result()
write_jsonl(manifest, record)
print(f"[{index}/{len(jobs)}] {record['output']}", flush=True)
else:
client = OpenAI(api_key=api_key, base_url=base_url)
for index, (_args, image_path, out_path) in enumerate(jobs, 1):
record = improve_one(client, image_path, out_path, args)
write_jsonl(manifest, record)
print(f"[{index}/{len(jobs)}] {record['output']}", flush=True)
summary = {
"input_root": str(input_root),
"output_dir": str(output_dir),
"model": args.model,
"prompt": args.prompt,
"total_images": len(images),
"submitted_images": len(jobs),
}
with open(output_dir / "summary.json", "w", encoding="utf-8") as f:
json.dump(summary, f, indent=2, ensure_ascii=False)
if __name__ == "__main__":
main()