aaron1141 commited on
Commit
09fc1b5
ยท
1 Parent(s): 14c5323

feat: embed extracted images as base64 data URIs in preview cards

Browse files
Files changed (1) hide show
  1. app.py +44 -17
app.py CHANGED
@@ -6,28 +6,52 @@ import shutil
6
  import tempfile
7
  import traceback
8
  import zipfile
 
9
 
10
  import gradio as gr
11
 
 
 
12
  try:
13
  import markdown as _md
14
- def _md2html(text: str) -> str:
15
- """Markdown โ†’ HTML. Local image refs become styled badges (post-process)."""
 
 
 
 
16
  html = _md.markdown(text, extensions=["nl2br", "tables"])
17
- # After markdown conversion ![alt](path) becomes <img โ€ฆ alt="alt">.
18
- # Replace every <img> tag with a grey badge so nothing tries to load local paths.
19
- def _img_badge(m):
20
- alt_m = re.search(r'alt="([^"]*)"', m.group(0))
21
- alt = alt_m.group(1) if alt_m else "image"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  return (
23
  '<span style="display:inline-flex;align-items:center;gap:4px;'
24
  'background:#f3f4f6;border:1px solid #d1d5db;border-radius:4px;'
25
- 'padding:1px 7px;font-size:12px;color:#6b7280">'
26
- f'๐Ÿ“ท {alt}</span>'
27
  )
28
- return re.sub(r'<img\b[^>]*/?>', _img_badge, html)
 
 
29
  except ImportError:
30
- def _md2html(text: str) -> str:
31
  return text.replace("\n", "<br>")
32
 
33
  _REPO_ROOT = os.path.dirname(os.path.abspath(__file__))
@@ -116,7 +140,8 @@ EXAMPLES = [
116
  # โ”€โ”€ Helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
117
 
118
 
119
- def _render_preview(jsonl_path: str, lang: str = "en") -> str:
 
120
  if not jsonl_path or not os.path.exists(jsonl_path):
121
  return ""
122
  items = []
@@ -142,14 +167,16 @@ def _render_preview(jsonl_path: str, lang: str = "en") -> str:
142
 
143
  cards = []
144
  for i, item in enumerate(items):
145
- q_html = _md2html(str(item.get("question", "")))
146
- a_html = _md2html(str(item.get("answer", "")))
147
- sol_raw = str(item.get("solution", ""))
148
  name = item.get("name", "")
 
 
 
 
 
149
 
150
  # Truncate solution before converting (avoids cutting mid-tag)
151
  sol_short = (sol_raw[:400] + "\n\nโ€ฆ") if len(sol_raw) > 400 else sol_raw
152
- sol_html = _md2html(sol_short)
153
  sol_block = (
154
  f'<div style="margin-top:12px;padding-top:10px;border-top:1px solid #e5e7eb">'
155
  f'<span style="font-weight:600;color:#374151">{label_s}:</span>'
@@ -358,7 +385,7 @@ def run_vqa_extraction(
358
  if lang == "en" else
359
  f"โœ… ๅฎŒๆˆ๏ผๅ…ฑๆๅ– {count} ๆก QA ๅฏน{img_note}ใ€‚ไธ‹่ฝฝ zip ๅฏ่Žทๅพ— JSONL ๅ’Œๅ›พ็‰‡ใ€‚"
360
  )
361
- yield zip_path, done, _render_preview(jsonl_path, lang)
362
 
363
  except Exception:
364
  yield None, f"โŒ Unexpected error:\n{traceback.format_exc()}", ""
 
6
  import tempfile
7
  import traceback
8
  import zipfile
9
+ import base64
10
 
11
  import gradio as gr
12
 
13
+ _MIME = {"png": "png", "jpg": "jpeg", "jpeg": "jpeg", "gif": "gif", "webp": "webp"}
14
+
15
  try:
16
  import markdown as _md
17
+ def _md2html(text: str, img_dir: str = None) -> str:
18
+ """Markdown โ†’ HTML.
19
+ If img_dir is given, <img src="vqa_images/x.png"> tags are replaced with
20
+ base64 data URIs so the browser renders the actual image.
21
+ Otherwise a grey badge placeholder is shown.
22
+ """
23
  html = _md.markdown(text, extensions=["nl2br", "tables"])
24
+
25
+ def _img_handler(m):
26
+ tag = m.group(0)
27
+ src_m = re.search(r'src="([^"]*)"', tag)
28
+ alt_m = re.search(r'alt="([^"]*)"', tag)
29
+ src = src_m.group(1) if src_m else ""
30
+ alt = alt_m.group(1) if alt_m else "image"
31
+
32
+ if img_dir and src:
33
+ img_name = os.path.basename(src)
34
+ img_path = os.path.join(img_dir, img_name)
35
+ if os.path.exists(img_path):
36
+ ext = img_name.rsplit(".", 1)[-1].lower()
37
+ mime = _MIME.get(ext, "png")
38
+ with open(img_path, "rb") as f:
39
+ b64 = base64.b64encode(f.read()).decode()
40
+ return (
41
+ f'<img src="data:image/{mime};base64,{b64}" alt="{alt}" '
42
+ f'style="max-width:100%;border-radius:6px;margin:6px 0;display:block;">'
43
+ )
44
+ # Fallback badge when image file is not found
45
  return (
46
  '<span style="display:inline-flex;align-items:center;gap:4px;'
47
  'background:#f3f4f6;border:1px solid #d1d5db;border-radius:4px;'
48
+ f'padding:1px 7px;font-size:12px;color:#6b7280">๐Ÿ“ท {alt}</span>'
 
49
  )
50
+
51
+ return re.sub(r'<img\b[^>]*/?>', _img_handler, html)
52
+
53
  except ImportError:
54
+ def _md2html(text: str, img_dir: str = None) -> str:
55
  return text.replace("\n", "<br>")
56
 
57
  _REPO_ROOT = os.path.dirname(os.path.abspath(__file__))
 
140
  # โ”€โ”€ Helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
141
 
142
 
143
+ def _render_preview(jsonl_path: str, lang: str = "en", output_dir: str = None) -> str:
144
+ """Render up to 3 QA items as styled HTML cards with real image rendering."""
145
  if not jsonl_path or not os.path.exists(jsonl_path):
146
  return ""
147
  items = []
 
167
 
168
  cards = []
169
  for i, item in enumerate(items):
 
 
 
170
  name = item.get("name", "")
171
+ # Images live at output_dir/{name}/vqa_images/
172
+ img_dir = os.path.join(output_dir, name, "vqa_images") if output_dir else None
173
+ q_html = _md2html(str(item.get("question", "")), img_dir)
174
+ a_html = _md2html(str(item.get("answer", "")), img_dir)
175
+ sol_raw = str(item.get("solution", ""))
176
 
177
  # Truncate solution before converting (avoids cutting mid-tag)
178
  sol_short = (sol_raw[:400] + "\n\nโ€ฆ") if len(sol_raw) > 400 else sol_raw
179
+ sol_html = _md2html(sol_short, img_dir)
180
  sol_block = (
181
  f'<div style="margin-top:12px;padding-top:10px;border-top:1px solid #e5e7eb">'
182
  f'<span style="font-weight:600;color:#374151">{label_s}:</span>'
 
385
  if lang == "en" else
386
  f"โœ… ๅฎŒๆˆ๏ผๅ…ฑๆๅ– {count} ๆก QA ๅฏน{img_note}ใ€‚ไธ‹่ฝฝ zip ๅฏ่Žทๅพ— JSONL ๅ’Œๅ›พ็‰‡ใ€‚"
387
  )
388
+ yield zip_path, done, _render_preview(jsonl_path, lang, output_dir)
389
 
390
  except Exception:
391
  yield None, f"โŒ Unexpected error:\n{traceback.format_exc()}", ""