{"id":112955,"date":"2026-08-22T00:41:28","date_gmt":"2026-08-22T00:41:28","guid":{"rendered":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/"},"modified":"2026-08-22T00:41:28","modified_gmt":"2026-08-22T00:41:28","slug":"building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure","status":"publish","type":"post","link":"https:\/\/youzum.net\/zh\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/","title":{"rendered":"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure"},"content":{"rendered":"<p class=\"wp-block-paragraph\">In this tutorial, we explore <a href=\"https:\/\/github.com\/ResearAI\/AutoFigure\"><strong>AutoFigure<\/strong><\/a> as a practical toolkit for generating scientific figures directly from text descriptions, paper-like content, and structured methodological explanations. In this tutorial, we set up the complete AutoFigure environment, fix dependency issues such as Pillow compatibility, and prepare the required rendering tools for SVG and PNG outputs. We then build a custom reference figure, configure an API-backed generation workflow, and use AutoFigure to convert a detailed agentic document intelligence pipeline into a publication-style scientific diagram. Along the way, we also test offline SVG rendering, inspect the generated files, create a sample paper and PDF, and export the final outputs to a reusable gallery and a zip archive.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">import os\nimport sys\nimport json\nimport time\nimport glob\nimport shutil\nimport textwrap\nimport subprocess\nimport importlib\nfrom pathlib import Path\nfrom getpass import getpass\nREPO_URL = \"https:\/\/github.com\/ResearAI\/AutoFigure.git\"\nREPO_DIR = Path(\"\/content\/AutoFigure\")\nOUTPUT_ROOT = Path(\"\/content\/autofigure_colab_outputs\")\nPROVIDER = os.environ.get(\"AUTOFIGURE_PROVIDER\", \"openrouter\")\nDEFAULT_MODELS = {\n   \"openrouter\": \"google\/gemini-3.1-pro-preview\",\n   \"gemini\": \"gemini-3.1-pro-preview\",\n   \"bianxie\": \"gemini-3.1-pro-preview\",\n}\nGENERATION_MODEL = os.environ.get(\n   \"AUTOFIGURE_MODEL\",\n   DEFAULT_MODELS.get(PROVIDER, \"google\/gemini-3.1-pro-preview\")\n)\nMAX_ITERATIONS = int(os.environ.get(\"AUTOFIGURE_MAX_ITERATIONS\", \"1\"))\nQUALITY_THRESHOLD = float(os.environ.get(\"AUTOFIGURE_QUALITY_THRESHOLD\", \"8.5\"))\nRUN_TEXT_TO_FIGURE = True\nRUN_PAPER_TO_FIGURE = False\nRUN_MXGRAPH_DEMO = False\nRUN_IMAGE_ENHANCEMENT = False\nTEXT_OUTPUT_FORMAT = \"svg\"\nMXGRAPH_OUTPUT_FORMAT = \"mxgraphxml\"\nART_STYLE = (\n   \"clean publication-ready scientific illustration, precise alignment, subtle shadows, \"\n   \"clear academic typography, high contrast, minimal clutter\"\n)\nFIGURE_DESCRIPTION = \"\"\"\nCreate a publication-ready scientific method figure for an agentic long-document intelligence system.\nThe figure should explain the following pipeline in a left-to-right architecture:\n1. Long documents enter the system. They may be PDFs, scanned reports, markdown files, tables, or mixed-layout documents.\n2. A document normalization layer extracts raw text, section hierarchy, tables, figures, and metadata.\n3. A routing planner decides whether each section should go to summarization, field extraction, table reconstruction, visual analysis, or citation grounding.\n4. Specialized expert modules process the routed chunks:\n  - Summarizer expert creates hierarchical summaries.\n  - Extraction expert returns JSON fields.\n  - Table expert reconstructs exact tables.\n  - Visual expert describes charts and diagrams.\n  - Citation expert links claims to evidence spans.\n5. A low-cost orchestration layer selects smaller or larger LLMs depending on complexity, confidence, and budget.\n6. A verification layer checks schema validity, source grounding, table consistency, and confidence.\n7. The final output is an analyst-ready workspace containing a summary, extracted fields, exact tables, cited answers, and audit logs.\nDesign requirements:\n- Use a wide 16:9 layout.\n- Use clear module boxes, arrows, and labels.\n- Add small callouts for cost control, confidence scoring, and auditability.\n- Avoid decorative clutter.\n- Make the flow understandable for a finance or enterprise document intelligence audience.\n\"\"\"\nMINI_PAPER_MARKDOWN = \"\"\"\n# Efficient Agentic Document Intelligence for Long Financial Reports\n## Abstract\nWe propose an agentic document intelligence architecture for extracting summaries, facts, tables,\nand grounded answers from long, heterogeneous financial documents.\n## Method\nOur method first normalizes each incoming document into a structured document graph. The graph\ncontains section nodes, paragraph nodes, table nodes, figure nodes, and metadata nodes. A routing\nplanner assigns each node to a specialized expert according to modality, complexity, and required\noutput schema.\nThe system uses five experts. The summarization expert produces hierarchical summaries from\nsection-level chunks. The extraction expert fills strict JSON schemas for entities, dates, risks,\nfinancial metrics, and obligations. The table expert reconstructs exact tables and validates row-column\nalignment. The visual expert describes charts and diagrams. The citation expert maps every generated\nclaim to source spans.\nA budget-aware orchestration layer selects model size dynamically. Simple chunks are processed by\nlow-cost models, while complex chunks are escalated to stronger models. A verification layer then\nchecks schema validity, citation support, numerical consistency, and table integrity. Failed checks are\nrouted back for repair.\n## Experiments\nWe evaluate on financial filings and analyst reports using extraction accuracy, grounding precision,\ntable reconstruction quality, and total inference cost.\n\"\"\"\ndef run(cmd, cwd=None, check=True, quiet=False):\n   print(f\"n$ {cmd}\")\n   process = subprocess.run(\n       cmd,\n       shell=True,\n       cwd=str(cwd) if cwd else None,\n       text=True,\n       stdout=subprocess.PIPE if quiet else None,\n       stderr=subprocess.STDOUT if quiet else None,\n   )\n   if quiet and process.stdout:\n       print(process.stdout[-5000:])\n   if check and process.returncode != 0:\n       raise RuntimeError(f\"Command failed with exit code {process.returncode}: {cmd}\")\n   return process\ndef heading(title):\n   print(\"n\" + \"=\" * 100)\n   print(title)\n   print(\"=\" * 100)\ndef safe_read(path, max_chars=2500):\n   path = Path(path)\n   if not path.exists():\n       return \"\"\n   text = path.read_text(encoding=\"utf-8\", errors=\"ignore\")\n   return text[:max_chars] + (\"n... [truncated]\" if len(text) &gt; max_chars else \"\")\ndef clear_loaded_modules(prefixes):\n   for name in list(sys.modules):\n       if any(name == prefix or name.startswith(prefix + \".\") for prefix in prefixes):\n           del sys.modules[name]\ndef get_colab_secret(names):\n   try:\n       from google.colab import userdata\n       for name in names:\n           try:\n               value = userdata.get(name)\n               if value:\n                   return value\n           except Exception:\n               pass\n   except Exception:\n       pass\n   return None\ndef collect_api_key(provider):\n   env_candidates = [\n       \"AUTOFIGURE_API_KEY\",\n       \"OPENROUTER_API_KEY\",\n       \"GOOGLE_API_KEY\",\n       \"GEMINI_API_KEY\",\n       \"BIANXIE_API_KEY\",\n   ]\n   for key_name in env_candidates:\n       value = os.environ.get(key_name)\n       if value:\n           print(f\"Using API key from environment variable: {key_name}\")\n           return value\n   secret_candidates = {\n       \"openrouter\": [\"AUTOFIGURE_API_KEY\", \"OPENROUTER_API_KEY\"],\n       \"gemini\": [\"AUTOFIGURE_API_KEY\", \"GOOGLE_API_KEY\", \"GEMINI_API_KEY\"],\n       \"bianxie\": [\"AUTOFIGURE_API_KEY\", \"BIANXIE_API_KEY\"],\n   }.get(provider, [\"AUTOFIGURE_API_KEY\"])\n   value = get_colab_secret(secret_candidates)\n   if value:\n       print(\"Using API key from Colab Secrets.\")\n       return value\n   value = getpass(f\"Paste your {provider} API key, or press Enter to skip cloud generation: \").strip()\n   return value\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">We begin by importing and defining the main paths, provider settings, model configuration, and tutorial options. We also prepare the detailed figure description and sample paper content that we use later for AutoFigure generation. We then create helper functions to run commands, print section headings, read files safely, clear loaded modules, and securely collect API keys.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">def display_file_if_possible(path, title=None):\n   path = Path(path) if path else None\n   if not path or not path.exists():\n       print(f&quot;Missing file: {path}&quot;)\n       return\n   try:\n       from IPython.display import display, Image as IPImage, SVG, Markdown\n       if title:\n           display(Markdown(f&quot;### {title}&quot;))\n       suffix = path.suffix.lower()\n       if suffix == &quot;.png&quot;:\n           display(IPImage(filename=str(path)))\n       elif suffix == &quot;.svg&quot;:\n           display(SVG(filename=str(path)))\n       elif suffix in [&quot;.json&quot;, &quot;.md&quot;, &quot;.txt&quot;, &quot;.drawio&quot;]:\n           print(safe_read(path, max_chars=5000))\n       else:\n           print(path)\n   except Exception as exc:\n       print(f&quot;Could not display {path}: {exc}&quot;)\ndef make_output_gallery(output_dir):\n   output_dir = Path(output_dir)\n   gallery_path = output_dir \/ &quot;gallery.html&quot;\n   blocks = []\n   for p in sorted(output_dir.rglob(&quot;*.png&quot;)):\n       rel = p.relative_to(output_dir)\n       blocks.append(f&quot;&quot;&quot;\n       &lt;div class=&quot;card&quot;&gt;\n         &lt;h3&gt;{rel}&lt;\/h3&gt;\n         &lt;img src=&quot;{rel}&quot; \/&gt;\n       &lt;\/div&gt;\n       &quot;&quot;&quot;)\n   for p in sorted(output_dir.rglob(&quot;*.svg&quot;)):\n       rel = p.relative_to(output_dir)\n       svg_text = p.read_text(encoding=&quot;utf-8&quot;, errors=&quot;ignore&quot;)\n       blocks.append(f&quot;&quot;&quot;\n       &lt;div class=&quot;card&quot;&gt;\n         &lt;h3&gt;{rel}&lt;\/h3&gt;\n         &lt;div class=&quot;svgbox&quot;&gt;{svg_text}&lt;\/div&gt;\n       &lt;\/div&gt;\n       &quot;&quot;&quot;)\n   for p in sorted(output_dir.rglob(&quot;*.drawio&quot;)):\n       rel = p.relative_to(output_dir)\n       code = p.read_text(encoding=&quot;utf-8&quot;, errors=&quot;ignore&quot;)[:4000]\n       blocks.append(f&quot;&quot;&quot;\n       &lt;div class=&quot;card&quot;&gt;\n         &lt;h3&gt;{rel}&lt;\/h3&gt;\n         &lt;p&gt;Editable draw.io mxGraph XML file.&lt;\/p&gt;\n         &lt;pre&gt;{code}&lt;\/pre&gt;\n       &lt;\/div&gt;\n       &quot;&quot;&quot;)\n   for p in sorted(output_dir.rglob(&quot;generation_report.json&quot;)):\n       rel = p.relative_to(output_dir)\n       try:\n           report_text = json.dumps(json.loads(p.read_text(encoding=&quot;utf-8&quot;)), indent=2)[:7000]\n       except Exception:\n           report_text = p.read_text(encoding=&quot;utf-8&quot;, errors=&quot;ignore&quot;)[:7000]\n       blocks.append(f&quot;&quot;&quot;\n       &lt;div class=&quot;card&quot;&gt;\n         &lt;h3&gt;{rel}&lt;\/h3&gt;\n         &lt;pre&gt;{report_text}&lt;\/pre&gt;\n       &lt;\/div&gt;\n       &quot;&quot;&quot;)\n   html = f&quot;&quot;&quot;\n   &lt;!doctype html&gt;\n   &lt;html&gt;\n   &lt;head&gt;\n     &lt;meta charset=&quot;utf-8&quot;&gt;\n     &lt;title&gt;AutoFigure Colab Gallery&lt;\/title&gt;\n     &lt;style&gt;\n       body {{\n         font-family: Arial, sans-serif;\n         margin: 24px;\n         background: #f7f7f7;\n       }}\n       h1 {{\n         margin-bottom: 8px;\n       }}\n       .card {{\n         background: white;\n         padding: 18px;\n         margin: 18px 0;\n         border-radius: 14px;\n         box-shadow: 0 2px 16px rgba(0,0,0,0.08);\n       }}\n       img {{\n         max-width: 100%;\n         border: 1px solid #ddd;\n         border-radius: 10px;\n       }}\n       .svgbox {{\n         border: 1px solid #ddd;\n         border-radius: 10px;\n         padding: 8px;\n         overflow: auto;\n       }}\n       pre {{\n         white-space: pre-wrap;\n         word-break: break-word;\n         max-height: 520px;\n         overflow: auto;\n         background: #fafafa;\n         padding: 12px;\n         border-radius: 10px;\n       }}\n     &lt;\/style&gt;\n   &lt;\/head&gt;\n   &lt;body&gt;\n     &lt;h1&gt;AutoFigure Colab Gallery&lt;\/h1&gt;\n     {&#039;&#039;.join(blocks)}\n   &lt;\/body&gt;\n   &lt;\/html&gt;\n   &quot;&quot;&quot;\n   gallery_path.write_text(html, encoding=&quot;utf-8&quot;)\n   return gallery_path\ndef summarize_generation_result(result, label):\n   print(&quot;n&quot; + &quot;-&quot; * 100)\n   print(label)\n   print(&quot;-&quot; * 100)\n   print(f&quot;Success: {result.success}&quot;)\n   print(f&quot;Final score: {result.final_score}&quot;)\n   print(f&quot;Iterations used: {result.iterations_used}&quot;)\n   print(f&quot;SVG path: {result.svg_path}&quot;)\n   print(f&quot;mxGraph path: {result.mxgraph_path}&quot;)\n   print(f&quot;Preview path: {result.preview_path}&quot;)\n   print(f&quot;Enhanced path: {result.enhanced_path}&quot;)\n   print(f&quot;Enhanced paths: {result.enhanced_paths}&quot;)\n   print(f&quot;Error: {result.error}&quot;)\n   if result.logs:\n       print(&quot;nRecent logs:&quot;)\n       for log in result.logs[-20:]:\n           print(f&quot;- {log}&quot;)\n   display_file_if_possible(result.preview_path, f&quot;{label}: PNG Preview&quot;)\n   if result.svg_path:\n       display_file_if_possible(result.svg_path, f&quot;{label}: SVG&quot;)\n   if result.mxgraph_path:\n       display_file_if_possible(result.mxgraph_path, f&quot;{label}: mxGraph XML&quot;)\n   report_candidates = []\n   for candidate in [result.svg_path, result.mxgraph_path, result.preview_path]:\n       if candidate:\n           report_candidates.append(Path(candidate).parent \/ &quot;generation_report.json&quot;)\n   for report_path in report_candidates:\n       if report_path.exists():\n           print(&quot;nGeneration report preview:&quot;)\n           print(safe_read(report_path, max_chars=6000))\n           try:\n               import pandas as pd\n               from IPython.display import display\n               report = json.loads(report_path.read_text(encoding=&quot;utf-8&quot;))\n               rows = []\n               for row in report.get(&quot;iteration_history&quot;, []):\n                   rows.append({\n                       &quot;iteration&quot;: row.get(&quot;iteration&quot;),\n                       &quot;quality_score&quot;: row.get(&quot;quality_score&quot;),\n                       &quot;improvement&quot;: row.get(&quot;improvement&quot;),\n                       &quot;has_critique&quot;: row.get(&quot;critique&quot;) is not None,\n                   })\n               if rows:\n                   display(pd.DataFrame(rows))\n           except Exception as exc:\n               print(f&quot;Could not tabulate report: {exc}&quot;)\n           break\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">We define utility functions that help us display generated files directly inside Colab, including PNG, SVG, JSON, Markdown, text, and draw.io outputs. We also build an HTML gallery generator so that all AutoFigure outputs can be reviewed on a single, organized page. We then add a result-summary function that prints generation metadata, displays previews, and shows the iteration report in a readable format.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">heading(\"1. Installing AutoFigure and Colab dependencies\")\nOUTPUT_ROOT.mkdir(parents=True, exist_ok=True)\nrun(\"apt-get update -qq\", quiet=True)\nrun(\n   \"apt-get install -y -qq \"\n   \"libcairo2 libpango-1.0-0 libpangocairo-1.0-0 \"\n   \"libgdk-pixbuf-2.0-0 libffi-dev shared-mime-info\",\n   quiet=True,\n)\nclear_loaded_modules([\"PIL\", \"autofigure\"])\nrun(f\"{sys.executable} -m pip install -q -U pip 'setuptools&lt;82' wheel jedi\", quiet=True)\nrun(\n   f\"{sys.executable} -m pip install -q --force-reinstall --no-cache-dir \"\n   f\"'Pillow==11.3.0'\",\n   quiet=True,\n)\nif REPO_DIR.exists():\n   print(f\"Repository already exists at {REPO_DIR}. Pulling latest main branch.\")\n   run(\"git fetch origin main\", cwd=REPO_DIR, quiet=True)\n   run(\"git checkout main\", cwd=REPO_DIR, quiet=True)\n   run(\"git pull --ff-only origin main\", cwd=REPO_DIR, check=False, quiet=True)\nelse:\n   run(f\"git clone {REPO_URL} {REPO_DIR}\", quiet=True)\nrun(\n   f\"{sys.executable} -m pip install -q -e '.[pdf,web]' \"\n   f\"reportlab pandas 'Pillow==11.3.0'\",\n   cwd=REPO_DIR,\n   quiet=True,\n)\nrun(\n   f\"{sys.executable} -m pip install -q --force-reinstall --no-cache-dir \"\n   f\"'Pillow==11.3.0'\",\n   quiet=True,\n)\nclear_loaded_modules([\"PIL\", \"autofigure\"])\ntry:\n   from PIL import Image, ImageDraw, ImageFont\n   print(f\"Pillow imported successfully. Version: {Image.__version__}\")\nexcept Exception as exc:\n   print(\"Pillow import still failed after reinstall.\")\n   print(\"Run Runtime -&gt; Restart runtime, then rerun this full cell.\")\n   raise exc\nif RUN_MXGRAPH_DEMO:\n   run(f\"{sys.executable} -m playwright install chromium\", quiet=True)\nsys.path.insert(0, str(REPO_DIR))\nheading(\"2. Importing AutoFigure SDK\")\nfrom autofigure import AutoFigureAgent, Config\nfrom autofigure.generator import (\n   validate_code_syntax,\n   code_to_png,\n   get_initial_prompt_template,\n)\nfrom autofigure.extractor import MethodologyExtractor\nprint(\"AutoFigure imported successfully.\")\nprint(f\"Repository directory: {REPO_DIR}\")\nprint(f\"Output root: {OUTPUT_ROOT}\")\nheading(\"3. Offline SVG preflight: validation and rendering\")\npreflight_dir = OUTPUT_ROOT \/ \"00_offline_preflight\"\npreflight_dir.mkdir(parents=True, exist_ok=True)\nsample_svg = \"\"\"\n&lt;svg width=\"1333\" height=\"750\" viewBox=\"0 0 1333 750\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"&gt;\n &lt;rect x=\"0\" y=\"0\" width=\"1333\" height=\"750\" fill=\"#ffffff\"\/&gt;\n &lt;text x=\"666\" y=\"70\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"36\" font-weight=\"700\" fill=\"#111111\"&gt;\n   AutoFigure Offline Rendering Check\n &lt;\/text&gt;\n &lt;rect x=\"120\" y=\"220\" width=\"250\" height=\"140\" rx=\"18\" fill=\"#f3f3f3\" stroke=\"#111111\" stroke-width=\"3\"\/&gt;\n &lt;text x=\"245\" y=\"285\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"24\" fill=\"#111111\"&gt;Text Prompt&lt;\/text&gt;\n &lt;text x=\"245\" y=\"325\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"17\" fill=\"#444444\"&gt;method description&lt;\/text&gt;\n &lt;line x1=\"390\" y1=\"290\" x2=\"565\" y2=\"290\" stroke=\"#111111\" stroke-width=\"4\" marker-end=\"url(#arrow)\"\/&gt;\n &lt;rect x=\"585\" y=\"220\" width=\"250\" height=\"140\" rx=\"18\" fill=\"#f3f3f3\" stroke=\"#111111\" stroke-width=\"3\"\/&gt;\n &lt;text x=\"710\" y=\"285\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"24\" fill=\"#111111\"&gt;AutoFigure&lt;\/text&gt;\n &lt;text x=\"710\" y=\"325\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"17\" fill=\"#444444\"&gt;generate \u2192 evaluate \u2192 refine&lt;\/text&gt;\n &lt;line x1=\"855\" y1=\"290\" x2=\"1030\" y2=\"290\" stroke=\"#111111\" stroke-width=\"4\" marker-end=\"url(#arrow)\"\/&gt;\n &lt;rect x=\"1050\" y=\"220\" width=\"250\" height=\"140\" rx=\"18\" fill=\"#f3f3f3\" stroke=\"#111111\" stroke-width=\"3\"\/&gt;\n &lt;text x=\"1175\" y=\"285\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"24\" fill=\"#111111\"&gt;Figure&lt;\/text&gt;\n &lt;text x=\"1175\" y=\"325\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"17\" fill=\"#444444\"&gt;SVG + PNG output&lt;\/text&gt;\n &lt;defs&gt;\n   &lt;marker id=\"arrow\" markerWidth=\"12\" markerHeight=\"12\" refX=\"10\" refY=\"6\" orient=\"auto\"&gt;\n     &lt;path d=\"M2,2 L10,6 L2,10 Z\" fill=\"#111111\"\/&gt;\n   &lt;\/marker&gt;\n &lt;\/defs&gt;\n&lt;\/svg&gt;\n\"\"\".strip()\nis_valid, validation_message = validate_code_syntax(sample_svg, \"svg\")\nprint(f\"SVG syntax valid: {is_valid}\")\nprint(f\"Validation message: {validation_message}\")\nsample_svg_path = preflight_dir \/ \"offline_preflight.svg\"\nsample_png_path = preflight_dir \/ \"offline_preflight.png\"\nsample_svg_path.write_text(sample_svg, encoding=\"utf-8\")\nrender_ok, processed_svg = code_to_png(\n   sample_svg,\n   str(sample_png_path),\n   attempt_repair=False,\n   output_format=\"svg\",\n)\nprint(f\"Rendered PNG: {render_ok} -&gt; {sample_png_path}\")\ndisplay_file_if_possible(sample_png_path, \"Offline preflight PNG\")\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">We install the required system packages, resolve Pillow compatibility issues, clone the AutoFigure repository, and install the SDK along with its PDF and web dependencies. We then import AutoFigure\u2019s main classes and generator utilities after confirming that the environment is ready. We also run offline SVG validation and PNG rendering tests to ensure the rendering pipeline works before making any API-based generation calls.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">heading(\"4. Creating a custom reference figure\")\nreference_dir = OUTPUT_ROOT \/ \"01_custom_references\"\nreference_dir.mkdir(parents=True, exist_ok=True)\nreference_path = reference_dir \/ \"reference_architecture_style.png\"\nW, H = 1333, 750\nimg = Image.new(\"RGB\", (W, H), \"white\")\ndraw = ImageDraw.Draw(img)\ntry:\n   title_font = ImageFont.truetype(\"DejaVuSans-Bold.ttf\", 36)\n   box_font = ImageFont.truetype(\"DejaVuSans-Bold.ttf\", 24)\n   small_font = ImageFont.truetype(\"DejaVuSans.ttf\", 18)\nexcept Exception:\n   title_font = None\n   box_font = None\n   small_font = None\ndraw.text(\n   (W \/\/ 2, 55),\n   \"Reference Layout: Modular Scientific Pipeline\",\n   anchor=\"mm\",\n   fill=\"black\",\n   font=title_font,\n)\nboxes = [\n   (90, 215, 290, 120, \"Input\", \"documents\"),\n   (365, 215, 290, 120, \"Planner\", \"route by task\"),\n   (640, 215, 290, 120, \"Experts\", \"summary \/ table \/ vision\"),\n   (915, 215, 290, 120, \"Verifier\", \"grounded output\"),\n]\nfor i, (x, y, bw, bh, title, subtitle) in enumerate(boxes):\n   draw.rounded_rectangle(\n       [x, y, x + bw, y + bh],\n       radius=22,\n       fill=(245, 245, 245),\n       outline=(20, 20, 20),\n       width=3,\n   )\n   draw.text(\n       (x + bw \/ 2, y + 45),\n       title,\n       anchor=\"mm\",\n       fill=\"black\",\n       font=box_font,\n   )\n   draw.text(\n       (x + bw \/ 2, y + 82),\n       subtitle,\n       anchor=\"mm\",\n       fill=(70, 70, 70),\n       font=small_font,\n   )\n   if i &lt; len(boxes) - 1:\n       ax = x + bw + 20\n       ay = y + bh \/ 2\n       bx = boxes[i + 1][0] - 20\n       by = ay\n       draw.line([ax, ay, bx, by], fill=\"black\", width=5)\n       draw.polygon(\n           [(bx, by), (bx - 18, by - 10), (bx - 18, by + 10)],\n           fill=\"black\",\n       )\ndraw.rounded_rectangle(\n   [180, 500, 1150, 585],\n   radius=24,\n   fill=(252, 252, 252),\n   outline=(80, 80, 80),\n   width=2,\n)\ndraw.text(\n   (665, 542),\n   \"Design cue: aligned modules, sparse labels, strong flow direction, clean academic styling\",\n   anchor=\"mm\",\n   fill=(40, 40, 40),\n   font=small_font,\n)\nimg.save(reference_path)\nprint(f\"Custom reference saved: {reference_path}\")\ndisplay_file_if_possible(reference_path, \"Custom reference figure\")\nheading(\"5. Configuring API-backed AutoFigure\")\nAPI_KEY = collect_api_key(PROVIDER)\nif not API_KEY:\n   print(\"No API key provided. Cloud generation sections will be skipped.\")\nelse:\n   print(f\"Provider: {PROVIDER}\")\n   print(f\"Generation model: {GENERATION_MODEL}\")\n   print(\"API key received. The key is not printed.\")\nconfig = None\nagent = None\nif API_KEY:\n   config = Config(\n       generation_api_key=API_KEY,\n       generation_provider=PROVIDER,\n       generation_model=GENERATION_MODEL,\n       methodology_api_key=API_KEY,\n       methodology_provider=PROVIDER,\n       methodology_model=GENERATION_MODEL,\n       enhancement_api_key=API_KEY if RUN_IMAGE_ENHANCEMENT else None,\n       enhancement_provider=PROVIDER,\n       enhancement_model=os.environ.get(\n           \"AUTOFIGURE_ENHANCEMENT_MODEL\",\n           \"google\/gemini-3.1-flash-image-preview\"\n           if PROVIDER == \"openrouter\"\n           else \"gemini-3.1-flash-image-preview\",\n       ),\n       max_iterations=MAX_ITERATIONS,\n       quality_threshold=QUALITY_THRESHOLD,\n       output_dir=str(OUTPUT_ROOT \/ \"02_text_to_figure\"),\n       custom_references=[str(reference_path)],\n       art_style=ART_STYLE,\n   )\n   validation_errors = config.validate()\n   print(f\"Config validation errors: {validation_errors if validation_errors else 'none'}\")\n   print(f\"References found by config: {len(config.get_references())}\")\n   agent = AutoFigureAgent(config)\nheading(\"6. Prompt template preview\")\nprompt_preview = get_initial_prompt_template(\n   topic=\"paper\",\n   content=FIGURE_DESCRIPTION[:2500],\n   output_format=\"svg\",\n)\nprint(prompt_preview[:2500])\nprint(\"n... prompt preview truncated ...\")\nif API_KEY and RUN_TEXT_TO_FIGURE:\n   heading(\"7. Running text-to-figure generation\")\n   text_output_dir = OUTPUT_ROOT \/ \"02_text_to_figure\"\n   text_output_dir.mkdir(parents=True, exist_ok=True)\n   text_result = agent.generate(\n       description=FIGURE_DESCRIPTION,\n       max_iterations=MAX_ITERATIONS,\n       quality_threshold=QUALITY_THRESHOLD,\n       output_format=TEXT_OUTPUT_FORMAT,\n       enable_enhancement=RUN_IMAGE_ENHANCEMENT,\n       art_style=ART_STYLE,\n       enhancement_input_type=\"code2prompt\",\n       enhancement_count=1,\n       custom_references=[str(reference_path)],\n       output_dir=str(text_output_dir),\n       topic=\"paper\",\n   )\n   summarize_generation_result(text_result, \"Text-to-Figure Result\")\nelse:\n   print(\"Skipping text-to-figure generation.\")\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">We create a custom reference image that shows the kind of clean modular scientific layout we want AutoFigure to follow. We then configure AutoFigure with the selected provider, model, API key, output directory, reference image, iteration settings, and visual style. Finally, we preview the internal prompt template and run the main text-to-figure generation workflow to produce a scientific figure from our detailed system description.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">heading(&quot;8. Paper methodology extraction dry check&quot;)\npaper_dir = OUTPUT_ROOT \/ &quot;03_paper_to_figure&quot;\npaper_dir.mkdir(parents=True, exist_ok=True)\npaper_md_path = paper_dir \/ &quot;mini_paper.md&quot;\npaper_md_path.write_text(MINI_PAPER_MARKDOWN, encoding=&quot;utf-8&quot;)\nif API_KEY:\n   if RUN_PAPER_TO_FIGURE:\n       extractor = MethodologyExtractor(config)\n       extracted = extractor.extract_from_file(str(paper_md_path))\n       print(&quot;nExtracted methodology preview:&quot;)\n       print((extracted or &quot;&quot;)[:2500])\n   else:\n       print(f&quot;Created demo paper markdown at: {paper_md_path}&quot;)\n       print(&quot;Set RUN_PAPER_TO_FIGURE = True to run LLM methodology extraction and figure generation.&quot;)\nelse:\n   print(f&quot;Created demo paper markdown at: {paper_md_path}&quot;)\n   print(&quot;No API key available, so LLM methodology extraction is skipped.&quot;)\nif API_KEY and RUN_PAPER_TO_FIGURE:\n   heading(&quot;9. Running paper-to-figure generation&quot;)\n   paper_result = agent.generate_from_paper(\n       paper_path=str(paper_md_path),\n       max_iterations=MAX_ITERATIONS,\n       output_format=&quot;svg&quot;,\n       enable_enhancement=RUN_IMAGE_ENHANCEMENT,\n       art_style=ART_STYLE,\n       enhancement_input_type=&quot;code2prompt&quot;,\n       enhancement_count=1,\n       custom_references=[str(reference_path)],\n       output_dir=str(paper_dir),\n   )\n   summarize_generation_result(paper_result, &quot;Paper-to-Figure Result&quot;)\nheading(&quot;10. Creating a tiny PDF and testing PDF text reading&quot;)\npdf_path = paper_dir \/ &quot;mini_paper.pdf&quot;\ntry:\n   from reportlab.lib.pagesizes import letter\n   from reportlab.pdfgen import canvas\n   c = canvas.Canvas(str(pdf_path), pagesize=letter)\n   width, height = letter\n   y = height - 50\n   for line in MINI_PAPER_MARKDOWN.splitlines():\n       line = line.strip()\n       if not line:\n           y -= 12\n           continue\n       for wrapped in textwrap.wrap(line, width=95):\n           c.drawString(50, y, wrapped)\n           y -= 14\n           if y &lt; 60:\n               c.showPage()\n               y = height - 50\n   c.save()\n   print(f&quot;Created demo PDF: {pdf_path}&quot;)\n   if API_KEY:\n       pdf_text = MethodologyExtractor(config)._read_pdf(pdf_path)\n       print(&quot;PDF text extraction preview:&quot;)\n       print((pdf_text or &quot;&quot;)[:1500])\n   else:\n       print(&quot;PDF created. LLM-based paper-to-figure generation still requires an API key.&quot;)\nexcept Exception as exc:\n   print(f&quot;PDF creation or read test failed: {exc}&quot;)\nif API_KEY and RUN_MXGRAPH_DEMO:\n   heading(&quot;11. Running editable mxGraph XML generation&quot;)\n   mxgraph_dir = OUTPUT_ROOT \/ &quot;04_mxgraph_drawio&quot;\n   mxgraph_dir.mkdir(parents=True, exist_ok=True)\n   mx_result = agent.generate(\n       description=FIGURE_DESCRIPTION,\n       max_iterations=MAX_ITERATIONS,\n       quality_threshold=QUALITY_THRESHOLD,\n       output_format=MXGRAPH_OUTPUT_FORMAT,\n       enable_enhancement=False,\n       custom_references=[str(reference_path)],\n       output_dir=str(mxgraph_dir),\n       topic=&quot;paper&quot;,\n   )\n   summarize_generation_result(mx_result, &quot;mxGraph \/ draw.io Result&quot;)\nelse:\n   heading(&quot;11. mxGraph XML generation skipped&quot;)\n   print(&quot;Set RUN_MXGRAPH_DEMO = True to generate editable draw.io mxGraph XML.&quot;)\n   print(&quot;This path installs Chromium through Playwright and may be slower than SVG generation.&quot;)\nheading(&quot;12. Output inventory and export&quot;)\nall_files = []\nfor path in sorted(OUTPUT_ROOT.rglob(&quot;*&quot;)):\n   if path.is_file():\n       all_files.append(path)\nprint(f&quot;Total files under {OUTPUT_ROOT}: {len(all_files)}&quot;)\nfor path in all_files:\n   rel = path.relative_to(OUTPUT_ROOT)\n   size_kb = path.stat().st_size \/ 1024\n   print(f&quot;{rel}  ({size_kb:.1f} KB)&quot;)\ngallery_path = make_output_gallery(OUTPUT_ROOT)\nprint(f&quot;nGallery HTML: {gallery_path}&quot;)\nzip_base = &quot;\/content\/autofigure_colab_outputs&quot;\nzip_path = shutil.make_archive(zip_base, &quot;zip&quot;, root_dir=str(OUTPUT_ROOT))\nprint(f&quot;Zip archive: {zip_path}&quot;)\ntry:\n   from IPython.display import display, HTML\n   display(\n       HTML(\n           f&quot;&quot;&quot;\n           &lt;h3&gt;AutoFigure tutorial complete&lt;\/h3&gt;\n           &lt;p&gt;&lt;b&gt;Output root:&lt;\/b&gt; {OUTPUT_ROOT}&lt;\/p&gt;\n           &lt;p&gt;&lt;b&gt;Gallery:&lt;\/b&gt; {gallery_path}&lt;\/p&gt;\n           &lt;p&gt;&lt;b&gt;Zip:&lt;\/b&gt; {zip_path}&lt;\/p&gt;\n           &quot;&quot;&quot;\n       )\n   )\nexcept Exception:\n   pass\nprint(&quot;nDone.&quot;)\nprint(&quot;If the model is unavailable or access is denied, change PROVIDER and GENERATION_MODEL near the top of the cell.&quot;)\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p class=\"wp-block-paragraph\">We create a small paper-style Markdown file and optionally use AutoFigure\u2019s methodology extractor to generate a figure from paper content. We also create a simple PDF version of the paper and test whether the PDF text extraction pipeline works correctly. We finish by optionally running the mxGraph draw.io workflow, listing all generated files, building the HTML gallery, and exporting the complete output folder as a zip archive.<\/p>\n<p class=\"wp-block-paragraph\">In conclusion, we completed this tutorial by building a full AutoFigure workflow that moves from environment setup to figure generation, validation, previewing, and export. We saw how AutoFigure helps us transform complex research or system descriptions into structured scientific visuals while still giving us control over references, style, output format, iterations, and optional paper-based extraction. By the end, we have a Colab-ready pipeline that can generate SVG figures and prepare editable drawings. io-style outputs when needed, test PDF extraction, and package all generated assets for later use.<\/p>\n<p class=\"wp-block-paragraph\">\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<\/p><p class=\"wp-block-paragraph\">\n<\/p><p class=\"wp-block-paragraph\">Check out the\u00a0<strong><a href=\"https:\/\/github.com\/MARKTECHPOST-AI-MEDIA-INC\/AI-Agents-Projects-Tutorials\/blob\/main\/LLM%20Projects\/autofigure_scientific_figure_generation_Marktechpost.ipynb\" target=\"_blank\" rel=\"noreferrer noopener\">FULL CODES here<\/a><\/strong><em>.<\/em>\u00a0Also,\u00a0feel free to follow us on\u00a0<strong><a href=\"https:\/\/x.com\/intent\/follow?screen_name=marktechpost\" target=\"_blank\" rel=\"noopener\"><mark>Twitter<\/mark><\/a><\/strong>\u00a0and don\u2019t forget to join our\u00a0<strong><a href=\"https:\/\/www.reddit.com\/r\/machinelearningnews\/\" target=\"_blank\" rel=\"noopener\">150k+ML SubReddit<\/a><\/strong>\u00a0and Subscribe to\u00a0<strong><a href=\"https:\/\/magic.beehiiv.com\/v1\/f5e63dd4-5653-4f09-83e2-321a8b1ba526?email=%7B%7Bemail%7D%7D\" target=\"_blank\" rel=\"noopener\">our Newsletter<\/a><\/strong>. Wait! are you on telegram?\u00a0<strong><a href=\"https:\/\/t.me\/machinelearningresearchnews\" target=\"_blank\" rel=\"noopener\">now you can join us on telegram as well.<\/a><\/strong><\/p>\n<p class=\"wp-block-paragraph\">Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.?\u00a0<strong><a href=\"https:\/\/forms.gle\/wbash1wF6efRj8G58\" target=\"_blank\" rel=\"noopener\"><mark>Connect with us<\/mark><\/a><\/strong><\/p>\n<p>The post <a href=\"https:\/\/www.marktechpost.com\/2026\/08\/21\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\">Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure<\/a> appeared first on <a href=\"https:\/\/www.marktechpost.com\/\">MarkTechPost<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we explore AutoFigure as a practical toolkit for generating scientific figures directly from text descriptions, paper-like content, and structured methodological explanations. In this tutorial, we set up the complete AutoFigure environment, fix dependency issues such as Pillow compatibility, and prepare the required rendering tools for SVG and PNG outputs. We then build a custom reference figure, configure an API-backed generation workflow, and use AutoFigure to convert a detailed agentic document intelligence pipeline into a publication-style scientific diagram. Along the way, we also test offline SVG rendering, inspect the generated files, create a sample paper and PDF, and export the final outputs to a reusable gallery and a zip archive. Copy CodeCopiedUse a different Browser import os import sys import json import time import glob import shutil import textwrap import subprocess import importlib from pathlib import Path from getpass import getpass REPO_URL = &#8220;https:\/\/github.com\/ResearAI\/AutoFigure.git&#8221; REPO_DIR = Path(&#8220;\/content\/AutoFigure&#8221;) OUTPUT_ROOT = Path(&#8220;\/content\/autofigure_colab_outputs&#8221;) PROVIDER = os.environ.get(&#8220;AUTOFIGURE_PROVIDER&#8221;, &#8220;openrouter&#8221;) DEFAULT_MODELS = { &#8220;openrouter&#8221;: &#8220;google\/gemini-3.1-pro-preview&#8221;, &#8220;gemini&#8221;: &#8220;gemini-3.1-pro-preview&#8221;, &#8220;bianxie&#8221;: &#8220;gemini-3.1-pro-preview&#8221;, } GENERATION_MODEL = os.environ.get( &#8220;AUTOFIGURE_MODEL&#8221;, DEFAULT_MODELS.get(PROVIDER, &#8220;google\/gemini-3.1-pro-preview&#8221;) ) MAX_ITERATIONS = int(os.environ.get(&#8220;AUTOFIGURE_MAX_ITERATIONS&#8221;, &#8220;1&#8221;)) QUALITY_THRESHOLD = float(os.environ.get(&#8220;AUTOFIGURE_QUALITY_THRESHOLD&#8221;, &#8220;8.5&#8221;)) RUN_TEXT_TO_FIGURE = True RUN_PAPER_TO_FIGURE = False RUN_MXGRAPH_DEMO = False RUN_IMAGE_ENHANCEMENT = False TEXT_OUTPUT_FORMAT = &#8220;svg&#8221; MXGRAPH_OUTPUT_FORMAT = &#8220;mxgraphxml&#8221; ART_STYLE = ( &#8220;clean publication-ready scientific illustration, precise alignment, subtle shadows, &#8221; &#8220;clear academic typography, high contrast, minimal clutter&#8221; ) FIGURE_DESCRIPTION = &#8220;&#8221;&#8221; Create a publication-ready scientific method figure for an agentic long-document intelligence system. The figure should explain the following pipeline in a left-to-right architecture: 1. Long documents enter the system. They may be PDFs, scanned reports, markdown files, tables, or mixed-layout documents. 2. A document normalization layer extracts raw text, section hierarchy, tables, figures, and metadata. 3. A routing planner decides whether each section should go to summarization, field extraction, table reconstruction, visual analysis, or citation grounding. 4. Specialized expert modules process the routed chunks: &#8211; Summarizer expert creates hierarchical summaries. &#8211; Extraction expert returns JSON fields. &#8211; Table expert reconstructs exact tables. &#8211; Visual expert describes charts and diagrams. &#8211; Citation expert links claims to evidence spans. 5. A low-cost orchestration layer selects smaller or larger LLMs depending on complexity, confidence, and budget. 6. A verification layer checks schema validity, source grounding, table consistency, and confidence. 7. The final output is an analyst-ready workspace containing a summary, extracted fields, exact tables, cited answers, and audit logs. Design requirements: &#8211; Use a wide 16:9 layout. &#8211; Use clear module boxes, arrows, and labels. &#8211; Add small callouts for cost control, confidence scoring, and auditability. &#8211; Avoid decorative clutter. &#8211; Make the flow understandable for a finance or enterprise document intelligence audience. &#8220;&#8221;&#8221; MINI_PAPER_MARKDOWN = &#8220;&#8221;&#8221; # Efficient Agentic Document Intelligence for Long Financial Reports ## Abstract We propose an agentic document intelligence architecture for extracting summaries, facts, tables, and grounded answers from long, heterogeneous financial documents. ## Method Our method first normalizes each incoming document into a structured document graph. The graph contains section nodes, paragraph nodes, table nodes, figure nodes, and metadata nodes. A routing planner assigns each node to a specialized expert according to modality, complexity, and required output schema. The system uses five experts. The summarization expert produces hierarchical summaries from section-level chunks. The extraction expert fills strict JSON schemas for entities, dates, risks, financial metrics, and obligations. The table expert reconstructs exact tables and validates row-column alignment. The visual expert describes charts and diagrams. The citation expert maps every generated claim to source spans. A budget-aware orchestration layer selects model size dynamically. Simple chunks are processed by low-cost models, while complex chunks are escalated to stronger models. A verification layer then checks schema validity, citation support, numerical consistency, and table integrity. Failed checks are routed back for repair. ## Experiments We evaluate on financial filings and analyst reports using extraction accuracy, grounding precision, table reconstruction quality, and total inference cost. &#8220;&#8221;&#8221; def run(cmd, cwd=None, check=True, quiet=False): print(f&#8221;n$ {cmd}&#8221;) process = subprocess.run( cmd, shell=True, cwd=str(cwd) if cwd else None, text=True, stdout=subprocess.PIPE if quiet else None, stderr=subprocess.STDOUT if quiet else None, ) if quiet and process.stdout: print(process.stdout[-5000:]) if check and process.returncode != 0: raise RuntimeError(f&#8221;Command failed with exit code {process.returncode}: {cmd}&#8221;) return process def heading(title): print(&#8220;n&#8221; + &#8220;=&#8221; * 100) print(title) print(&#8220;=&#8221; * 100) def safe_read(path, max_chars=2500): path = Path(path) if not path.exists(): return &#8220;&#8221; text = path.read_text(encoding=&#8221;utf-8&#8243;, errors=&#8221;ignore&#8221;) return text[:max_chars] + (&#8220;n&#8230; [truncated]&#8221; if len(text) &gt; max_chars else &#8220;&#8221;) def clear_loaded_modules(prefixes): for name in list(sys.modules): if any(name == prefix or name.startswith(prefix + &#8220;.&#8221;) for prefix in prefixes): del sys.modules[name] def get_colab_secret(names): try: from google.colab import userdata for name in names: try: value = userdata.get(name) if value: return value except Exception: pass except Exception: pass return None def collect_api_key(provider): env_candidates = [ &#8220;AUTOFIGURE_API_KEY&#8221;, &#8220;OPENROUTER_API_KEY&#8221;, &#8220;GOOGLE_API_KEY&#8221;, &#8220;GEMINI_API_KEY&#8221;, &#8220;BIANXIE_API_KEY&#8221;, ] for key_name in env_candidates: value = os.environ.get(key_name) if value: print(f&#8221;Using API key from environment variable: {key_name}&#8221;) return value secret_candidates = { &#8220;openrouter&#8221;: [&#8220;AUTOFIGURE_API_KEY&#8221;, &#8220;OPENROUTER_API_KEY&#8221;], &#8220;gemini&#8221;: [&#8220;AUTOFIGURE_API_KEY&#8221;, &#8220;GOOGLE_API_KEY&#8221;, &#8220;GEMINI_API_KEY&#8221;], &#8220;bianxie&#8221;: [&#8220;AUTOFIGURE_API_KEY&#8221;, &#8220;BIANXIE_API_KEY&#8221;], }.get(provider, [&#8220;AUTOFIGURE_API_KEY&#8221;]) value = get_colab_secret(secret_candidates) if value: print(&#8220;Using API key from Colab Secrets.&#8221;) return value value = getpass(f&#8221;Paste your {provider} API key, or press Enter to skip cloud generation: &#8220;).strip() return value We begin by importing and defining the main paths, provider settings, model configuration, and tutorial options. We also prepare the detailed figure description and sample paper content that we use later for AutoFigure generation. We then create helper functions to run commands, print section headings, read files safely, clear loaded modules, and securely collect API keys. Copy CodeCopiedUse a different Browser def display_file_if_possible(path, title=None): path = Path(path) if path else None if not path or not path.exists(): print(f&#8221;Missing file: {path}&#8221;) return try: from IPython.display import display, Image as IPImage, SVG, Markdown if title: display(Markdown(f&#8221;### {title}&#8221;)) suffix = path.suffix.lower() if suffix == &#8220;.png&#8221;: display(IPImage(filename=str(path))) elif suffix == &#8220;.svg&#8221;: display(SVG(filename=str(path))) elif suffix in [&#8220;.json&#8221;, &#8220;.md&#8221;, &#8220;.txt&#8221;, &#8220;.drawio&#8221;]: print(safe_read(path, max_chars=5000)) else: print(path) except Exception as exc: print(f&#8221;Could not display {path}: {exc}&#8221;) def make_output_gallery(output_dir): output_dir = Path(output_dir) gallery_path = output_dir \/ &#8220;gallery.html&#8221; blocks = [] for p in sorted(output_dir.rglob(&#8220;*.png&#8221;)): rel = p.relative_to(output_dir) blocks.append(f&#8221;&#8221;&#8221; &lt;div class=&#8221;card&#8221;&gt; &lt;h3&gt;{rel}&lt;\/h3&gt; &lt;img src=&#8221;{rel}&#8221; \/&gt;<\/p>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pmpro_default_level":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_pvb_checkbox_block_on_post":false,"footnotes":""},"categories":[52,5,7,1],"tags":[],"class_list":["post-112955","post","type-post","status-publish","format-standard","hentry","category-ai-club","category-committee","category-news","category-uncategorized","pmpro-has-access"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure - YouZum<\/title>\n<meta name=\"description\" content=\"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/youzum.net\/zh\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure - YouZum\" \/>\n<meta property=\"og:description\" content=\"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19\" \/>\n<meta property=\"og:url\" content=\"https:\/\/youzum.net\/zh\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\" \/>\n<meta property=\"og:site_name\" content=\"YouZum\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/DroneAssociationTH\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-22T00:41:28+00:00\" \/>\n<meta name=\"author\" content=\"admin NU\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin NU\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\"},\"author\":{\"name\":\"admin NU\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c\"},\"headline\":\"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure\",\"datePublished\":\"2026-08-22T00:41:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\"},\"wordCount\":643,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#organization\"},\"articleSection\":[\"AI\",\"Committee\",\"News\",\"Uncategorized\"],\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\",\"url\":\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\",\"name\":\"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure - YouZum\",\"isPartOf\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#website\"},\"datePublished\":\"2026-08-22T00:41:28+00:00\",\"description\":\"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19\",\"breadcrumb\":{\"@id\":\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/youzum.net\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/yousum.gpucore.co\/#website\",\"url\":\"https:\/\/yousum.gpucore.co\/\",\"name\":\"YouSum\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/yousum.gpucore.co\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/yousum.gpucore.co\/#organization\",\"name\":\"Drone Association Thailand\",\"url\":\"https:\/\/yousum.gpucore.co\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png\",\"contentUrl\":\"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png\",\"width\":300,\"height\":300,\"caption\":\"Drone Association Thailand\"},\"image\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/DroneAssociationTH\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c\",\"name\":\"admin NU\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png\",\"contentUrl\":\"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png\",\"caption\":\"admin NU\"},\"url\":\"https:\/\/youzum.net\/zh\/members\/adminnu\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure - YouZum","description":"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/youzum.net\/zh\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/","og_locale":"zh_CN","og_type":"article","og_title":"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure - YouZum","og_description":"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19","og_url":"https:\/\/youzum.net\/zh\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/","og_site_name":"YouZum","article_publisher":"https:\/\/www.facebook.com\/DroneAssociationTH\/","article_published_time":"2026-08-22T00:41:28+00:00","author":"admin NU","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin NU","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"19 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#article","isPartOf":{"@id":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/"},"author":{"name":"admin NU","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c"},"headline":"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure","datePublished":"2026-08-22T00:41:28+00:00","mainEntityOfPage":{"@id":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/"},"wordCount":643,"commentCount":0,"publisher":{"@id":"https:\/\/yousum.gpucore.co\/#organization"},"articleSection":["AI","Committee","News","Uncategorized"],"inLanguage":"zh-Hans","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/","url":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/","name":"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure - YouZum","isPartOf":{"@id":"https:\/\/yousum.gpucore.co\/#website"},"datePublished":"2026-08-22T00:41:28+00:00","description":"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19","breadcrumb":{"@id":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/youzum.net\/building-agentic-document-intelligence-pipelines-creating-scientific-figures-with-autofigure\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/youzum.net\/"},{"@type":"ListItem","position":2,"name":"Building Agentic Document Intelligence Pipelines: Creating Scientific Figures with AutoFigure"}]},{"@type":"WebSite","@id":"https:\/\/yousum.gpucore.co\/#website","url":"https:\/\/yousum.gpucore.co\/","name":"YouSum","description":"","publisher":{"@id":"https:\/\/yousum.gpucore.co\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/yousum.gpucore.co\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"zh-Hans"},{"@type":"Organization","@id":"https:\/\/yousum.gpucore.co\/#organization","name":"Drone Association Thailand","url":"https:\/\/yousum.gpucore.co\/","logo":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/","url":"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png","contentUrl":"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png","width":300,"height":300,"caption":"Drone Association Thailand"},"image":{"@id":"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/DroneAssociationTH\/"]},{"@type":"Person","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c","name":"admin NU","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/person\/image\/","url":"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png","contentUrl":"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png","caption":"admin NU"},"url":"https:\/\/youzum.net\/zh\/members\/adminnu\/"}]}},"rttpg_featured_image_url":null,"rttpg_author":{"display_name":"admin NU","author_link":"https:\/\/youzum.net\/zh\/members\/adminnu\/"},"rttpg_comment":0,"rttpg_category":"<a href=\"https:\/\/youzum.net\/zh\/category\/ai-club\/\" rel=\"category tag\">AI<\/a> <a href=\"https:\/\/youzum.net\/zh\/category\/committee\/\" rel=\"category tag\">Committee<\/a> <a href=\"https:\/\/youzum.net\/zh\/category\/news\/\" rel=\"category tag\">News<\/a> <a href=\"https:\/\/youzum.net\/zh\/category\/uncategorized\/\" rel=\"category tag\">Uncategorized<\/a>","rttpg_excerpt":"In this tutorial, we explore AutoFigure as a practical toolkit for generating scientific figures directly from text descriptions, paper-like content, and structured methodological explanations. In this tutorial, we set up the complete AutoFigure environment, fix dependency issues such as Pillow compatibility, and prepare the required rendering tools for SVG and PNG outputs. We then build&hellip;","_links":{"self":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/posts\/112955","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/comments?post=112955"}],"version-history":[{"count":0,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/posts\/112955\/revisions"}],"wp:attachment":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/media?parent=112955"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/categories?post=112955"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/tags?post=112955"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}