import base64, io, os, json import gradio as gr from huggingface_hub import InferenceClient from PIL import Image # --- HF Inference Client ----------------------------------------------------- client = InferenceClient( provider="nebius", api_key=os.environ.get("HF_TOKEN", ""), ) SYSTEM_PROMPT = ( "Return ONLY a minified JSON object with keys: " "name, title, email, link — in that order." ) # --- Utility helpers --------------------------------------------------------- def pil_to_data_url(pil_img: Image.Image) -> str: """Convert PIL image to a base‑64 data‑URL readable by the vision model.""" buf = io.BytesIO() pil_img.convert("RGB").save(buf, format="PNG") b64 = base64.b64encode(buf.getvalue()).decode() return f"data:image/png;base64,{b64}" def make_html_card(json_str: str) -> str: """Generate a colourful HTML business‑card preview from JSON.""" try: data = json.loads(json_str) except json.JSONDecodeError: return "
🤔 Hmm, the model did not return valid JSON.
" name = data.get("name", "") title = data.get("title", "") email = data.get("email", "") link = data.get("link", "") return f""" """ # --- Core generation fn ------------------------------------------------------ def generate_business_card(pil_img: Image.Image | None): """Return both raw JSON & a pretty HTML preview.""" if pil_img is None: return "// Upload a selfie first 🙂", "" data_url = pil_to_data_url(pil_img) resp = client.chat.completions.create( model="google/gemma-3-27b-it", max_tokens=200, temperature=0.9, messages=[ {"role": "system", "content": SYSTEM_PROMPT}, { "role": "user", "content": [ {"type": "text", "text": "Generate my JSON business card:"}, {"type": "image_url", "image_url": {"url": data_url}}, ], }, ], ) json_str = resp.choices[0].message.content.strip().strip("`") card_html = make_html_card(json_str) return json_str, card_html # --- Theme ------------------------------------------------------------------- theme = ( gr.themes.Default(primary_hue="indigo", secondary_hue="purple") .set(body_background_fill="linear-gradient(120deg,#f6d365 0%,#fda085 100%)") ) # --- UI ---------------------------------------------------------------------- with gr.Blocks(title="Business‑Card Agent", theme=theme, css=".gradio-container {font-family:'Inter',sans-serif;}") as demo: gr.Markdown( """Upload a selfie & get a business_card.json draft — plus a live preview!