{"slug": "gemini-business-card-merge-my-ai-workflow", "title": "Gemini Business Card Merge: My AI Workflow", "summary": "A developer built a workflow using Google's Gemini 1.5 Flash model to merge front and back images of bilingual business cards into a single JSON record, replacing fragile regex rules with a prompt that instructs the LLM to combine fields like name and company into unified strings. The system holds the first image in a user_states dictionary with a 5-minute timeout while waiting for the second side, then sends both images simultaneously to Gemini for semantic merging.", "body_md": "# Gemini Business Card Merge: My AI Workflow\n\nInstead of writing a thousand fragile regex rules to guess if two names are the same, I just let the user tell me. I implemented a \"waiting room\" state. When the first side hits, the bot asks, \"Is there a back side?\" If the user says yes, the bot holds onto that image in a `user_states`\n\ndictionary with a 5-minute timeout (because users have the attention span of a goldfish).\n\nThe real magic happens when both images are fed into [Gemini](/en/tags/gemini/) simultaneously. Trying to merge \"Wang Daming\" and \"David Wang\" via code is a recipe for a headache. Sending both images in one prompt and letting the LLM handle the semantic merge is the only sane way to do this.\n\nHere is the prompt logic I used to force Gemini to combine the data into a single clean JSON object:\n\n```\nYou are an expert OCR and data extraction agent. I am providing you with two images: the front and back of a single business card. \n\nYour task:\n1. Extract all professional information from both images.\n2. Merge the data into a single unified record.\n3. If a field (like Name or Company) appears in both languages, combine them into a single string (e.g., \"Chinese Name / English Name\").\n4. Ensure the output strictly follows the provided JSON schema.\n5. Ignore any background noise or irrelevant text.\n\nReturn only the final merged JSON.\n```\n\nFor the implementation, I used `gemini-1.5-flash`\n\nbecause it's fast enough that the user doesn't forget why they're waiting. I just wrap both image parts into the `generate_content`\n\ncall.\n\n``` python\ndef generate_json_from_two_images(\n front_img: PIL.Image.Image,\n back_img: PIL.Image.Image,\n prompt: str) -> object:\n model = GenerativeModel(\n \"gemini-1.5-flash\",\n generation_config={\n \"response_mime_type\": \"application/json\",\n \"response_schema\": NAMECARD_SCHEMA\n },\n )\n front_part = Part.from_data(\n data=pil_to_bytes(front_img), mime_type=\"image/jpeg\")\n back_part = Part.from_data(\n data=pil_to_bytes(back_img), mime_type=\"image/jpeg\")\n response = model.generate_content(\n [prompt, front_part, back_part],\n stream=False,\n labels={\"client_id\": \"namecard\"}\n )\n return response\n```\n\nThis approach turns a messy data-cleaning chore into a simple prompt engineering task. No more duplicate entries, no more manual deleting—just a clean, consolidated record.\n\n[Next Understanding LLM Context and Hallucinations →](/en/threads/2244/)", "url": "https://wpnews.pro/news/gemini-business-card-merge-my-ai-workflow", "canonical_source": "https://promptcube3.com/en/threads/2256/", "published_at": "2026-07-23 11:11:45+00:00", "updated_at": "2026-07-23 19:42:19.753665+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "generative-ai", "ai-tools", "developer-tools"], "entities": ["Gemini", "Google", "Gemini 1.5 Flash"], "alternates": {"html": "https://wpnews.pro/news/gemini-business-card-merge-my-ai-workflow", "markdown": "https://wpnews.pro/news/gemini-business-card-merge-my-ai-workflow.md", "text": "https://wpnews.pro/news/gemini-business-card-merge-my-ai-workflow.txt", "jsonld": "https://wpnews.pro/news/gemini-business-card-merge-my-ai-workflow.jsonld"}}