editppt-vision-validator-lora / inference_example.py
EditPPT's picture
Initial release
da0be07
Raw History Blame Contribute Delete
1.84 kB
"""Minimal inference with the EditPPT vision-validator LoRA on Qwen3.5-9B.
Input order matters: [image BEFORE the edit, image AFTER the edit, prompt]. Render slides at 960x540
(1 slide pt = 1 px for a standard 16:9 deck). Fill prompt_template.txt with str.replace, not str.format
(the template contains literal JSON braces).
"""
import json
import torch
from peft import PeftModel
from PIL import Image
from transformers import AutoModelForImageTextToText, AutoProcessor
BASE, ADAPTER = "Qwen/Qwen3.5-9B", "EditPPT/editppt-vision-validator-lora"
PIXELS = 960 * 540
processor = AutoProcessor.from_pretrained(BASE, min_pixels=PIXELS, max_pixels=PIXELS)
model = AutoModelForImageTextToText.from_pretrained(BASE, dtype=torch.bfloat16, device_map="cuda:0")
model = PeftModel.from_pretrained(model, ADAPTER).eval()
def validate(before_png, after_png, instruction, tools_used, slide_json):
prompt = (open("prompt_template.txt").read()
.replace("{instruction}", instruction)
.replace("{tools_used}", str(tools_used)) # python-repr list of {'name', 'arguments'}
.replace("{slide_json}", str(slide_json))) # python-repr dict: slide_w, slide_h, current_slide, objects
msgs = [{"role": "user", "content": [{"type": "image"}, {"type": "image"}, {"type": "text", "text": prompt}]}]
text = processor.apply_chat_template(msgs, add_generation_prompt=True, tokenize=False)
imgs = [Image.open(p).convert("RGB") for p in (before_png, after_png)]
enc = processor(text=[text], images=imgs, return_tensors="pt").to(model.device)
with torch.no_grad():
out = model.generate(**enc, max_new_tokens=1024, do_sample=False)
raw = processor.tokenizer.decode(out[0, enc["input_ids"].shape[1]:], skip_special_tokens=True)
return json.loads(raw[raw.index("{"): raw.rindex("}") + 1])