Spaces:
Sleeping
Sleeping
File size: 3,495 Bytes
d3ee9ee 31fa536 d3ee9ee 31fa536 d3ee9ee 31fa536 d3ee9ee 31fa536 d3ee9ee 31fa536 d3ee9ee 31fa536 | 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 81 82 83 84 85 86 87 88 89 90 91 | """Step 6: turn each [IMAGE: ...] marker into a FLUX prompt and render it.
Images are produced entirely by **remote HF Inference Provider calls** (FLUX.1-schnell)
billed to the user's token — this Space has no GPU, so nothing is generated locally.
The render tries auto provider routing first, then falls back across the providers that
serve the model, so a single provider being unavailable for the user's token doesn't
break the run.
"""
from __future__ import annotations
from pathlib import Path
from typing import List, Optional, Tuple
from huggingface_hub import InferenceClient
from . import config, llm
_PROMPT_SYSTEM = (
"You are a prompt engineer for the FLUX text-to-image model. Given a short scene "
"description for a blog illustration and the article topic, write ONE vivid, concrete "
"image prompt (single line, <60 words). Describe subject, setting, composition, "
"lighting and style. Prefer clean, editorial, photographic or tasteful illustrative "
"styles suitable for a professional blog. No text/words in the image. Return only the prompt."
)
def _flux_prompt(client: InferenceClient, topic: str, scene: str) -> str:
try:
p = llm.chat(
client,
config.MODEL_REASONING,
_PROMPT_SYSTEM,
f"Article topic: {topic}\nScene: {scene}\nWrite the FLUX prompt.",
max_tokens=150,
temperature=0.8,
)
p = p.strip().strip('"')
return p or scene
except Exception:
return f"{scene}, editorial photography, clean composition, natural lighting"
def _render(hf_token: str, prompt: str) -> Tuple[Optional[object], Optional[str]]:
"""Generate one image via Inference Providers, trying auto then explicit providers.
Returns (PIL image, None) on success or (None, error message) if every provider fails.
"""
# None => let the router auto-select; then try each known provider explicitly.
attempts: List[Optional[str]] = [None] + config.IMAGE_PROVIDERS
errors: List[str] = []
for provider in attempts:
try:
client = (
InferenceClient(token=hf_token, provider=provider)
if provider
else InferenceClient(token=hf_token)
)
image = client.text_to_image(prompt=prompt, model=config.MODEL_IMAGE)
return image, None
except Exception as e: # noqa: BLE001 - try the next provider
errors.append(f"{provider or 'auto'}: {e}")
continue
return None, " | ".join(errors[-3:])
def generate_images(
client: InferenceClient,
hf_token: str,
topic: str,
scenes: List[str],
run_dir: Path,
) -> List[dict]:
"""Render one image per scene via inference calls. Returns [{scene, prompt, path|None, error?}]."""
run_dir.mkdir(parents=True, exist_ok=True)
out: List[dict] = []
for i, scene in enumerate(scenes):
prompt = _flux_prompt(client, topic, scene)
item = {"scene": scene, "prompt": prompt, "path": None}
image, err = _render(hf_token, prompt)
if image is not None:
try:
path = run_dir / f"image_{i + 1}.png"
image.save(path)
item["path"] = str(path)
except Exception as e: # noqa: BLE001
item["error"] = f"save failed: {e}"
else:
item["error"] = err or "image generation failed"
out.append(item)
return out
|