### Install Dependencies Source: https://github.com/dwzhu-pku/paperbanana/blob/main/skill/SKILL.md Installs project dependencies using uv. Ensure you are in the repository root directory. ```bash cd uv pip install -r requirements.txt ``` -------------------------------- ### Model Configuration File Example Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Central YAML file for API keys and default model names. Copy from the template and fill in at least one API key. ```yaml # configs/model_config.yaml (copy from model_config.template.yaml) defaults: main_model_name: "gemini-3.1-pro-preview" image_gen_model_name: "gemini-3.1-flash-image-preview" api_keys: google_api_key: "AIza..." # Google Gemini direct access openrouter_api_key: "sk-or-v1-..." # OpenRouter (preferred when set) anthropic_api_key: "" # Optional: Claude models openai_api_key: "" # Optional: GPT / DALL-E models ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Install all required Python packages listed in the requirements.txt file using uv pip. This command should be run after activating the virtual environment. ```bash uv pip install -r requirements.txt ``` -------------------------------- ### Install Dependencies and Create Placeholder Files Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Installs required Python packages and creates placeholder `ref.json` files for diagram and plot tasks. This step is crucial for the PaperBanana pipeline to function correctly. A runtime restart might be necessary after the first run. ```python #@title Step 3: Install dependencies and create required placeholder files import os import sys import subprocess from pathlib import Path os.chdir(REPO_DIR) if str(REPO_DIR) not in sys.path: sys.path.insert(0, str(REPO_DIR)) print('Working directory:', Path.cwd()) print('Python executable:', sys.executable) subprocess.run([sys.executable, '-m', 'pip', 'install', '-q', '--upgrade', 'pip'], check=True) subprocess.run([ sys.executable, '-m', 'pip', 'install', '-q', '-r', str(REPO_DIR / 'requirements.txt'), 'pypdf', 'ipyfilechooser' ], check=True) # PaperBanana planner expects these ref.json files to exist even when retrieval_setting='none'. for task in ['diagram', 'plot']: ref_path = REPO_DIR / 'data' / 'PaperBananaBench' / task / 'ref.json' ref_path.parent.mkdir(parents=True, exist_ok=True) if not ref_path.exists(): ref_path.write_text('[]\n', encoding='utf-8') print('Dependencies installed and placeholder data files are ready.') print() print('If this is your FIRST run on a fresh runtime, restart now:') print(' Runtime -> Restart runtime, then re-run from Step 1.') print('If you already restarted once, ignore this message.') ``` -------------------------------- ### Example: Generate Transformer Architecture Diagram Source: https://github.com/dwzhu-pku/paperbanana/blob/main/skill/SKILL.md An example of generating a diagram for a transformer architecture. It includes detailed method text and a figure caption, saving the output to 'architecture.png'. ```bash python skill/run.py \ --content "We propose a transformer-based encoder-decoder architecture. The encoder consists of 12 self-attention layers with residual connections. The decoder uses cross-attention to attend to encoder outputs and generates the target sequence autoregressively." \ --caption "Figure 1: Overview of the proposed transformer architecture" \ --task diagram \ --output architecture.png ``` -------------------------------- ### Step 4: API Key and Model Setup Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Configure API keys and select model presets for text and image generation. Set `VALIDATE_API_KEY_NOW` to True to perform an initial key check. The `STORE_API_KEY_IN_CONFIG` default is False for security. ```python #@title Step 4: API key and model selection # Paste your Gemini API key in this box. GOOGLE_API_KEY_INPUT = '' # @param {type:"string"} # Optional: for OpenAI-compatible paths (e.g., custom image model like gpt-image-1.5). OPENAI_API_KEY_INPUT = '' # @param {type:"string"} # Optional: loaded to runtime env for compatible custom branches; not used in the default text pipeline. ANTHROPIC_API_KEY_INPUT = '' # @param {type:"string"} # If True, run a tiny test request first so invalid keys fail fast. VALIDATE_API_KEY_NOW = True # @param {type:"boolean"} # Model used only for the key-check request above. VALIDATION_MODEL = 'gemini-2.5-flash' # @param {type:"string"} # Main text-model preset for extraction/planner/critic/stylist text reasoning. TEXT_MODEL_PRESET = 'fast_2_5_flash' # @param ['paper_style_updated', 'balanced_2_5_pro', 'fast_2_5_flash', 'custom'] # Used only when TEXT_MODEL_PRESET='custom'. CUSTOM_TEXT_MODEL = '' # @param {type:"string"} # Main image-model preset for final rendering and optional refinement. IMAGE_MODEL_PRESET = 'nano_banana_2' # @param ['nano_banana_2', 'nano_banana_pro', 'nano_banana', 'custom'] # Used only when IMAGE_MODEL_PRESET='custom'. CUSTOM_IMAGE_MODEL = '' # @param {type:"string"} # Security default: keep API key in runtime env only (not written to Drive config file). STORE_API_KEY_IN_CONFIG = False # @param {type:"boolean"} import os import yaml TEXT_MODEL_MAP = { 'paper_style_updated': 'gemini-3.1-pro-preview', 'balanced_2_5_pro': 'gemini-2.5-pro', 'fast_2_5_flash': 'gemini-2.5-flash', } IMAGE_MODEL_MAP = { 'nano_banana_2': 'gemini-3.1-flash-image-preview', 'nano_banana_pro': 'gemini-3-pro-image-preview', 'nano_banana': 'gemini-2.5-flash-image', } def resolve_model(preset: str, custom: str, mapping: dict) -> str: if preset == 'custom': model = (custom or '').strip() else: model = mapping.get(preset, '').strip() if not model: raise ValueError('Model selection is empty. Choose a preset or provide CUSTOM_*_MODEL.') return model MODEL_NAME = resolve_model(TEXT_MODEL_PRESET, CUSTOM_TEXT_MODEL, TEXT_MODEL_MAP) IMAGE_MODEL_NAME = resolve_model(IMAGE_MODEL_PRESET, CUSTOM_IMAGE_MODEL, IMAGE_MODEL_MAP) if 'gemini' not in MODEL_NAME.lower(): raise ValueError( f'TEXT model "{MODEL_NAME}" is not supported in this notebook flow. ' 'Retriever/Planner/Stylist/Critic are Gemini-based here. ' 'Use a Gemini text model in Step 4. ' 'OPENAI/ANTHROPIC keys are optional for compatible custom branches.' ) # Supports both the box above and `%env GOOGLE_API_KEY=...` in Colab. api_key = (GOOGLE_API_KEY_INPUT or os.environ.get('GOOGLE_API_KEY', '')).strip() if not api_key: raise ValueError( 'API key is empty. Get a key at https://aistudio.google.com/apikey , paste it into GOOGLE_API_KEY_INPUT, and re-run Step 4.' ) # Make key available to repo code. os.environ['GOOGLE_API_KEY'] = api_key ``` -------------------------------- ### Install Python Version with uv Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Install a specific Python version (e.g., 3.12) using uv. Ensure this version is compatible with the project's requirements. ```bash uv python install 3.12 ``` -------------------------------- ### Create and Activate Virtual Environment Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Use uv to create a virtual environment in the current directory and activate it. This is a prerequisite for installing project dependencies. ```bash uv venv # This will create a virtual environment in the current directory, under .venv/ source .venv/bin/activate # or .venv\Scripts\activate on Windows ``` -------------------------------- ### Launch Streamlit Interactive Demo Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Start the Streamlit interactive demo by running the demo.py script. This interface offers two main workflows: generating candidates and refining images. ```bash streamlit run demo.py ``` -------------------------------- ### RetrieverAgent.process() Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Retrieves the top-10 most relevant reference examples from PaperBananaBench using one of four retrieval strategies. It populates `data["top10_references"]` with a list of IDs and optionally `data["retrieved_examples"]` with full objects in manual mode. ```APIDOC ## `RetrieverAgent.process()` ### Description Retrieves the top-10 most relevant reference examples from PaperBananaBench using one of four retrieval strategies. Populates `data["top10_references"]` (list of IDs) and `data["retrieved_examples"]` (full objects in manual mode). ### Parameters #### Query Parameters - **retrieval_setting** (string) - Required - Options: "auto" | "manual" | "random" | "none" ### Request Example ```python import asyncio from pathlib import Path from agents.retriever_agent import RetrieverAgent from utils.config import ExpConfig async def retrieve_refs(): exp_config = ExpConfig( dataset_name="PaperBananaBench", task_name="diagram", work_dir=Path("."), ) agent = RetrieverAgent(exp_config=exp_config) data = { "content": "We propose a multi-layer encoder with self-attention and feed-forward sublayers.", "visual_intent": "Figure 1: Overview of the encoder architecture.", } # retrieval_setting options: "auto" | "manual" | "random" | "none" result = await agent.process(data, retrieval_setting="auto") print(result["top10_references"]) # e.g. ["ref_12", "ref_45", "ref_3", "ref_99", ...] asyncio.run(retrieve_refs()) ``` ``` -------------------------------- ### Launch Gradio Web App Locally Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Starts the Gradio web application locally on port 7860. This provides a user-friendly interface for generating and refining diagrams. ```bash # Launch locally on port 7860 python app.py ``` -------------------------------- ### PlannerAgent.process() Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Generates a detailed textual description of the figure to be created using few-shot in-context learning from retrieved reference examples. For diagrams, it produces `data["target_diagram_desc0"]`; for plots, `data["target_plot_desc0"]`. ```APIDOC ## `PlannerAgent.process()` ### Description Generates a detailed textual description of the figure to be created using few-shot in-context learning from the retrieved reference examples (including their images). For diagrams it produces `data["target_diagram_desc0"]`; for plots, `data["target_plot_desc0"]`. ### Request Body - **content** (string) - Description of the content. - **visual_intent** (string) - Description of the visual intent. - **top10_references** (list[string]) - List of reference IDs. - **retrieved_examples** (list[object]) - List of retrieved example objects. ### Request Example ```python import asyncio from pathlib import Path from agents.planner_agent import PlannerAgent from utils.config import ExpConfig async def plan_diagram(): exp_config = ExpConfig( dataset_name="PaperBananaBench", task_name="diagram", work_dir=Path("."), ) agent = PlannerAgent(exp_config=exp_config) data = { "content": "The model consists of a shared encoder and two task-specific decoder heads.", "visual_intent": "Figure 2: The multi-task architecture.", "top10_references": ["ref_5", "ref_23"], "retrieved_examples": [], # empty → loaded from ref.json by ID } result = await agent.process(data) print(result["target_diagram_desc0"][:300]) # e.g. "A publication-quality architecture diagram on white background. Left side: ..." asyncio.run(plan_diagram()) ``` ``` -------------------------------- ### Retrieve References with RetrieverAgent Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Uses the `RetrieverAgent` to fetch top-10 relevant examples from PaperBananaBench. The `retrieval_setting` parameter controls the strategy ('auto', 'manual', 'random', 'none'). Requires `ExpConfig` with dataset and task names. ```python import asyncio from pathlib import Path from agents.retriever_agent import RetrieverAgent from utils.config import ExpConfig async def retrieve_refs(): exp_config = ExpConfig( dataset_name="PaperBananaBench", task_name="diagram", work_dir=Path("."), ) agent = RetrieverAgent(exp_config=exp_config) data = { "content": "We propose a multi-layer encoder with self-attention and feed-forward sublayers.", "visual_intent": "Figure 1: Overview of the encoder architecture.", } # retrieval_setting options: "auto" | "manual" | "random" | "none" result = await agent.process(data, retrieval_setting="auto") print(result["top10_references"]) # e.g. ["ref_12", "ref_45", "ref_3", "ref_99", ...] asyncio.run(retrieve_refs()) ``` -------------------------------- ### Step 9: Run Generation, Preview, and Save Outputs Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb This code block initializes Step 9, setting up the generation environment and defining helper functions. It configures the save mode (full JSON with base64 or slim JSON) and reloads necessary utilities. Various agents and utility classes are imported for pipeline execution. ```python #@title Step 9: Run generation, preview, and save outputs import base64 import importlib import json import math import re import zipfile from datetime import datetime from io import BytesIO from pathlib import Path import matplotlib.pyplot as plt from PIL import Image from IPython.display import display, Markdown from google.genai import types # If True, JSON files will include base64 image data (much larger files). SAVE_FULL_RESULT_WITH_BASE64 = False # @param {type:"boolean"} if SAVE_FULL_RESULT_WITH_BASE64: print('Step 9 save mode: full JSON with embedded base64 image data (large files).') else: print('Step 9 save mode: slim JSON without embedded images (recommended).') # Reload generation utils after writing config/model settings. import utils.generation_utils as generation_utils importlib.reload(generation_utils) from utils import config from utils.paperviz_processor import PaperVizProcessor from agents.vanilla_agent import VanillaAgent from agents.planner_agent import PlannerAgent from agents.visualizer_agent import VisualizerAgent from agents.stylist_agent import StylistAgent from agents.critic_agent import CriticAgent from agents.retriever_agent import RetrieverAgent from agents.polish_agent import PolishAgent def target_4k_size(aspect_ratio: str) -> tuple[int, int]: if aspect_ratio == '21:9': return (4096, 1755) if aspect_ratio == '3:2': return (3840, 2560) return (3840, 2160) def pick_final_image_key(result_dict, task_name: str, max_rounds: int): task_name = task_name.lower().strip() for round_idx in range(int(max_rounds) - 1, -1, -1): key = f'target_{task_name}_critic_desc{round_idx}_base64_jpg' if result_dict.get(key): return key for key in [ f'target_{task_name}_stylist_desc0_base64_jpg', f'target_{task_name}_desc0_base64_jpg', f'vanilla_{task_name}_base64_jpg', ]: if result_dict.get(key): return key return None def b64_to_image(b64_str: str) -> Image.Image: return Image.open(BytesIO(base64.b64decode(b64_str))).convert('RGB') def strip_base64_fields(payload): if isinstance(payload, dict): return {k: strip_base64_fields(v) for k, v in payload.items() if '_base64_' not in k} if isinstance(payload, list): return [strip_base64_fields(x) for x in payload] return payload PRICING_REFERENCE_URL = 'https://ai.google.dev/gemini-api/docs/pricing' PRICING_LAST_VERIFIED = '2026-02-27' CHARS_PER_TOKEN_EST = 4.0 ``` -------------------------------- ### Initialize ExpConfig for Minimal Run Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Create a minimal ExpConfig instance. Model names are read from configs/model_config.yaml. The result directory is auto-created. ```python from pathlib import Path from utils.config import ExpConfig # Minimal config — reads model names from configs/model_config.yaml exp_config = ExpConfig( dataset_name="PaperBananaBench", task_name="diagram", # "diagram" | "plot" split_name="test", exp_mode="dev_full", # see Experiment Modes below retrieval_setting="auto", # "auto" | "manual" | "random" | "none" max_critic_rounds=3, work_dir=Path("."), ) ``` -------------------------------- ### Validate Task Name and Start Pipeline Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Ensures the TASK_NAME is supported before proceeding with the pipeline. Raises a ValueError for unsupported task names. ```python task_name = str(TASK_NAME).strip().lower() print('Starting Step 9 pipeline... this can take a few minutes.') if task_name not in {'diagram', 'plot'}: raise ValueError(f'Unsupported TASK_NAME: {TASK_NAME}') ``` -------------------------------- ### Initialize Experiment Configuration Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Sets up the experiment configuration object with parameters for dataset, task, pipeline mode, retrieval settings, and model names. ```python exp_config = config.ExpConfig( dataset_name='PaperBananaBench', task_name=task_name, split_name='colab', exp_mode=PIPELINE_MODE, retrieval_setting=RETRIEVAL_SETTING, max_critic_rounds=MAX_CRITIC_ROUNDS, model_name=MODEL_NAME, image_model_name=IMAGE_MODEL_NAME, work_dir=Path(REPO_DIR), ) ``` -------------------------------- ### Initialize PaperVizProcessor Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Instantiates the PaperVizProcessor with various agent components, including vanilla, planner, visualizer, stylist, critic, retriever, and polish agents, all configured with the experiment settings. ```python processor = PaperVizProcessor( exp_config=exp_config, vanilla_agent=VanillaAgent(exp_config=exp_config), planner_agent=PlannerAgent(exp_config=exp_config), visualizer_agent=VisualizerAgent(exp_config=exp_config), stylist_agent=StylistAgent(exp_config=exp_config), critic_agent=CriticAgent(exp_config=exp_config), retriever_agent=RetrieverAgent(exp_config=exp_config), polish_agent=PolishAgent(exp_config=exp_config), ) ``` -------------------------------- ### Get Text Model Rates Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Retrieves the pricing rate for a given text model name from a predefined dictionary. Returns None if the model is not found. ```python def model_rates_or_none(model_name: str): return TEXT_PRICING_USD_PER_MTOK.get(str(model_name or '').strip()) ``` -------------------------------- ### Refine Description with StylistAgent Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Applies a style guide to refine textual descriptions, enriching aesthetic details. Writes the refined description to `data["target_diagram_stylist_desc0"]`. ```python import asyncio from pathlib import Path from agents.stylist_agent import StylistAgent from utils.config import ExpConfig async def style_description(): exp_config = ExpConfig( dataset_name="PaperBananaBench", task_name="diagram", work_dir=Path("."), ) agent = StylistAgent(exp_config=exp_config) data = { "content": "Encoder-decoder architecture with cross-attention layers.", "visual_intent": "Figure 1: Architecture overview.", "target_diagram_desc0": ( "A diagram showing encoder on the left and decoder on the right, " "connected by cross-attention arrows." ), } result = await agent.process(data) print(result["target_diagram_stylist_desc0"][:300]) # Enriched with color HEX codes, font sizes, icon styles, etc. asyncio.run(style_description()) ``` -------------------------------- ### Prepare Source Context and Visual Intent Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Execute Step 8 to prepare the source context, visual intent, and caption. This step is mandatory and should be run even if Step 7 was skipped. It involves importing necessary libraries for PDF processing, generation, and utility functions. ```python #@title Step 8: Prepare source context, visual intent, and caption print('Step 8 is required. Run this even if you skipped Step 7.') import asyncio import importlib import json import os import random import re from pathlib import Path from pypdf import PdfReader from google.genai import types import json_repair import utils.generation_utils as generation_utils importlib.reload(generation_utils) # Concurrency guard: only one Step 8 extraction call in this runtime. if 'STEP8_EXTRACTION_LOCK' not in globals(): globals()['STEP8_EXTRACTION_LOCK'] = globals().get('STEP5C_EXTRACTION_LOCK', asyncio.Lock()) STEP8_EXTRACTION_LOCK = globals()['STEP8_EXTRACTION_LOCK'] ``` -------------------------------- ### Score Candidate Generation Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Initiates the scoring process for a candidate generation, starting by picking the final image key based on task name and max rounds. Returns -1.0 if no final key is found. ```python def score_candidate( result_obj: dict, task_name: str, max_rounds: int, caption_text: str, visual_intent_text: str, required_terms: list[str], strict_required_terms: bool = False, ): final_key = pick_final_image_key(result_obj, task_name, int(max_rounds)) if not final_key: return -1.0, { ``` -------------------------------- ### Configure Experiment with ExpConfig Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Sets up experiment configuration for a 'dev_planner_stylist' mode, focusing on Planner and Stylist agents without a critic loop. This configuration is used for programmatic pipeline execution. ```python # Example: Planner + Stylist only, no critic from utils.config import ExpConfig exp_config = ExpConfig( dataset_name="PaperBananaBench", task_name="diagram", exp_mode="dev_planner_stylist", retrieval_setting="random", work_dir=Path("."), ) ``` -------------------------------- ### Clone PaperBanana Repository Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Clone the PaperBanana repository to your local machine and navigate into the project directory. This is the first step to setting up the project. ```bash git clone https://github.com/dwzhu-pku/PaperBanana.git cd PaperBanana ``` -------------------------------- ### Build Structured Inputs for PaperBanana Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Constructs structured JSON inputs for PaperBanana, including 'source_context', 'visual_intent', and 'figure_caption'. It uses merged summary text and required terms to guide the extraction process, employing resilient API calls. ```python async def build_structured_inputs( merged_summary_text, intent_hint, required_terms, primary_model, fallback_models, max_attempts, base_delay, max_delay, per_attempt_timeout, ): required_terms_text = ', '.join(required_terms) if required_terms else '(none)' pass_b_prompt = f""" You are assisting PaperBanana setup for one publication-quality method figure. From the merged chunk summaries, return STRICT JSON only with exactly keys: - source_context - visual_intent ``` -------------------------------- ### Get Image Output Rate Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Retrieves the pricing rate for a specific image output resolution for a given model name. Falls back to '1K' resolution if the specified resolution is not found. Returns the rate and a boolean indicating if fallback was used. ```python def image_output_rate_or_none(model_name: str, resolution: str = '1K'): rates = IMAGE_OUTPUT_USD_PER_IMAGE.get(str(model_name or '').strip(), {}) if resolution in rates: return rates[resolution], False if '1K' in rates: return rates['1K'], True return None, False ``` -------------------------------- ### Prepare and Run Single Sample Processing Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Prepares input data for a single sample and runs the processing pipeline. This is used for simple, single-image generation tasks. ```python input_sample = { 'id': 'colab_user_input', 'filename': 'colab_user_input', 'caption': figure_caption_text.strip(), 'content': method_text, 'visual_intent': visual_intent_text.strip(), 'additional_info': {'rounded_ratio': ASPECT_RATIO}, 'max_critic_rounds': int(MAX_CRITIC_ROUNDS), } async def run_one(sample): outputs = [] async for result_data in processor.process_queries_batch( [sample], max_concurrent=1, do_eval=False, ): outputs.append(result_data) return outputs[0] print('Running simple mode generation (expected ~2-5 minutes)...') result = await run_one(input_sample) ``` -------------------------------- ### Select Input File Method Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Configures the method for selecting an input file, allowing uploads from a computer, use of an existing Drive path, or browsing Drive with a widget. ```python #@param ['upload_from_computer', 'use_drive_path', 'browse_drive'] from pathlib import Path from IPython.display import display, Markdown FILE_INPUT_METHOD = 'upload_from_computer' # @param ['upload_from_computer', 'use_drive_path', 'browse_drive'] FALLBACK_SELECTED_PATH = str(INPUT_DIR / 'paper.pdf') # @param {type:"string"} BROWSER_ROOT = str(INPUT_DIR) # @param {type:"string"} ``` -------------------------------- ### Run PaperBanana CLI (Basic) Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Execute the PaperBanana command-line interface with default settings. This is the simplest way to run the tool from the terminal. ```bash python main.py ``` -------------------------------- ### CLI: main.py (batch benchmark runner) Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Processes the full PaperBananaBench test split with evaluation. Saves incremental JSON results every 10 samples. Runs 10 samples concurrently by default. ```bash ## CLI: `main.py` (batch benchmark runner) Processes the full PaperBananaBench test split with evaluation. Saves incremental JSON results every 10 samples. Runs 10 samples concurrently by default. ```bash ``` -------------------------------- ### Generate Diagrams via CLI (File Input) Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Use the CLI to generate multiple diagram candidates from a text file. Supports full pipeline execution with options for number of candidates, experiment mode, and retrieval settings. Outputs are saved as PNG files. ```bash # 5 parallel candidates, full pipeline (with Stylist), from a file python skill/run.py \ --content-file method_section.txt \ --caption "Figure 2: Multi-task learning framework" \ --task diagram \ --output results/candidate.png \ --num-candidates 5 \ --exp-mode demo_full \ --retrieval-setting auto # Outputs: results/candidate_0.png, results/candidate_1.png, ..., results/candidate_4.png # Each path printed to stdout on completion. ``` -------------------------------- ### Prepare and Save Resolved Inputs Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Compiles various run parameters and settings into a dictionary, then saves it as a JSON file. This includes task details, selection parameters, and export/refinement settings. ```python resolved_inputs = { 'task_name': task_name, 'ui_mode': UI_MODE, 'input_mode': INPUT_MODE, 'resolved_input_path': resolved_input_path, 'visual_intent_text': visual_intent_text, 'figure_caption_text': figure_caption_text, 'source_context_chars': len(method_text), 'pipeline_mode': PIPELINE_MODE, 'retrieval_setting': RETRIEVAL_SETTING, 'num_candidates': int(NUM_CANDIDATES), 'max_concurrent': int(MAX_CONCURRENT), 'selected_candidate_index': selected_idx, 'selected_final_key': selected_final_key, 'selection_mode': selection_mode, 'auto_select_best': bool(globals().get('AUTO_SELECT_BEST', True)), 'selection_strict_required_terms': bool(globals().get('SELECTION_STRICT_REQUIRED_TERMS', True)), 'image_aware_selection': bool(globals().get('IMAGE_AWARE_SELECTION', False)), 'image_aware_topk': int(globals().get('IMAGE_AWARE_TOPK', 3)), 'image_aware_weight': float(globals().get('IMAGE_AWARE_WEIGHT', 0.35)), 'image_aware_selection_model': str(globals().get('IMAGE_AWARE_SELECTION_MODEL', '')).strip() or MODEL_NAME, 'candidate_scores': score_cards, 'candidate_artifacts': candidate_artifacts, 'candidates_dir': str(candidates_dir), 'context_scope': str(globals().get('STEP8_CONTEXT_SCOPE_USED', globals().get('CONTEXT_SCOPE', 'unknown'))), 'must_include_terms': parse_required_terms(globals().get('MUST_INCLUDE_TERMS', '')), 'step8_coverage_score': float(globals().get('STEP8_COVERAGE_SCORE', 0.0)), 'step8_missing_terms': list(globals().get('STEP8_MISSING_TERMS', [])), 'export_4k': bool(EXPORT_4K), 'run_refinement': bool(RUN_REFINEMENT), 'refine_source': REFINE_SOURCE, 'external_refine_image_path': EXTERNAL_REFINE_IMAGE_PATH, 'refine_resolution': REFINE_RESOLUTION, 'refine_aspect_ratio': REFINE_ASPECT_RATIO, } resolved_inputs_path = run_dir / 'resolved_inputs.json' resolved_inputs_path.write_text(json.dumps(resolved_inputs, ensure_ascii=False, indent=2), encoding='utf-8') ``` -------------------------------- ### Run PaperBanana CLI (Advanced) Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Run the PaperBanana command-line interface with custom settings. This allows for fine-tuning parameters such as dataset, task, experiment mode, and retrieval strategy. ```bash python main.py \ --dataset_name "PaperBananaBench" \ --task_name "diagram" \ --split_name "test" \ --exp_mode "dev_full" \ --retrieval_setting "auto" ``` -------------------------------- ### Initialize Extraction Settings Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Sets up configuration settings for the auto-extraction process, including model names, retry parameters, and chunking configurations. ```python async def auto_extract_inputs_from_paper(full_text: str, intent_hint: str, max_attempts: int, context_scope: str, required_terms: list[str]): async with STEP8_EXTRACTION_LOCK: settings = { 'primary_model': MODEL_NAME, 'fallback_models': parse_fallback_models(MODEL_NAME), 'outer_attempts': int(globals().get('STEP8_OUTER_MAX_ATTEMPTS', globals().get('STEP5C_OUTER_MAX_ATTEMPTS', max(1, int(max_attempts))))), 'base_delay': float(globals().get('STEP8_BASE_DELAY', globals().get('STEP5C_BASE_DELAY', 2.0))), 'max_delay': float(globals().get('STEP8_MAX_DELAY', globals().get('STEP5C_MAX_DELAY', 20.0))), 'per_attempt_timeout': float(globals().get('STEP8_PER_ATTEMPT_TIMEOUT', globals().get('STEP5C_PER_ATTEMPT_TIMEOUT', 60.0))), 'chunk_size': int(globals().get('CHUNK_SIZE_CHARS', 9000)), 'chunk_overlap': int(globals().get('CHUNK_OVERLAP_CHARS', 1200)), 'chunk_summary_max_words': int(globals().get('STEP8_CHUNK_SUMMARY_MAX_WORDS', 150)), ``` -------------------------------- ### Mount Google Drive and Define Paths Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Mounts Google Drive and sets up essential directories for the PaperBanana project. Ensure your Google API key is configured if required by subsequent steps. All project artifacts will be stored within the specified Drive path. ```python #@title Step 1: Mount Google Drive and define project paths from pathlib import Path import os from google.colab import drive # Mount Drive (configurable via PAPERBANANA_DRIVE_MOUNT_POINT) DRIVE_MOUNT_POINT = Path(os.environ.get('PAPERBANANA_DRIVE_MOUNT_POINT', str(Path.home() / 'drive'))) drive.mount(str(DRIVE_MOUNT_POINT)) # All notebook artifacts are stored under this Drive folder DRIVE_ROOT = DRIVE_MOUNT_POINT / 'MyDrive' PB_DRIVE_ROOT = DRIVE_ROOT / 'PaperBanana' REPO_DIR = PB_DRIVE_ROOT / 'PaperBanana' INPUT_DIR = PB_DRIVE_ROOT / 'input' OUTPUT_DIR = PB_DRIVE_ROOT / 'outputs' PB_DRIVE_ROOT.mkdir(parents=True, exist_ok=True) INPUT_DIR.mkdir(parents=True, exist_ok=True) OUTPUT_DIR.mkdir(parents=True, exist_ok=True) print(f'Drive root: {DRIVE_ROOT}') print(f'Project root in Drive: {PB_DRIVE_ROOT}') print(f'Repo path: {REPO_DIR}') print(f'Input path: {INPUT_DIR}') print(f'Output path: {OUTPUT_DIR}') print('Upload your paper to the input folder before Step 5.') ``` -------------------------------- ### Configure Core Settings for Simple Mode Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Set up core parameters for PaperBanana in simple mode. This includes defining the UI mode, task name, input source, and extraction scope. Use this to control how the tool processes input and generates outputs. ```python #@title Step 6: Core settings (simple mode) UI_MODE = 'simple' # @param ['simple', 'advanced'] TASK_NAME = 'diagram' # @param ['diagram', 'plot'] INPUT_MODE = 'drive_pdf_auto' # @param ['drive_pdf_auto', 'paste_text_manual', 'drive_file_manual', 'paste_plot_data_manual'] PDF_PAGE_RANGE = '' # @param {type:"string"} # Extraction scope for drive_pdf_auto: # auto_method_first: try method-only extraction first; auto-fallback to full-paper if coverage is low. # method_only: use method-focused sections only. # full_paper: use full paper with chunked coverage extraction. CONTEXT_SCOPE = 'auto_method_first' # @param ['auto_method_first', 'method_only', 'full_paper'] # Optional comma-separated terms that must be preserved in Step 8 outputs. # Use this for must-keep concepts (example: control group, treatment group, sample transfer). MUST_INCLUDE_TERMS = '' # @param {type:"string"} # Style/pipeline choice from Streamlit app behavior: STYLE_MODE = 'planner_critic_fast' # @param ['planner_critic_fast', 'stylist_enhanced'] # Used in diagram mode. VISUAL_INTENT_HINT = 'Create a clear methodology overview diagram of the main contribution.' # @param {type:"string"} MANUAL_FIGURE_CAPTION = '' # @param {type:"string"} PASTED_METHOD_TEXT = ''' ''' # Used in plot mode. PLOT_VISUAL_INTENT = 'Create a publication-quality plot showing the main result trend with clear axes and legend.' # @param {type:"string"} PLOT_RAW_DATA_FILE_PATH = str(INPUT_DIR / 'raw_data.csv') # @param {type:"string"} PASTED_PLOT_RAW_DATA = ''' ''' # Safe defaults (used unless Step 7 overrides them). USE_WIDGET_SELECTION = True AUTO_EXTRACT_MAX_ATTEMPTS = 3 STEP8_FALLBACK_MODELS = 'gemini-2.5-pro,gemini-3.1-pro-preview' ASPECT_RATIO = '16:9' if STYLE_MODE == 'stylist_enhanced': PIPELINE_MODE = 'demo_full' else: PIPELINE_MODE = 'demo_planner_critic' RETRIEVAL_SETTING = 'none' MAX_CRITIC_ROUNDS = 3 NUM_CANDIDATES = 10 MAX_CONCURRENT = 10 SELECTED_CANDIDATE_INDEX = 0 RUN_REFINEMENT = False REFINE_SOURCE = 'selected_result' EXTERNAL_REFINE_IMAGE_PATH = '' REFINE_PROMPT = 'Keep everything the same but output a cleaner higher-resolution publication-quality figure.' REFINE_RESOLUTION = '2K' REFINE_ASPECT_RATIO = '16:9' EXPORT_4K = True ZIP_EXPORT = True SHOW_STAGE_DESCRIPTIONS = True SHOW_CRITIC_SUGGESTIONS = True STEP8_OUTER_MAX_ATTEMPTS = 4 STEP8_PER_ATTEMPT_TIMEOUT = 60 STEP8_MAX_PAYLOAD_CHARS = 50000 # Step 8 chunk/coverage defaults. CHUNK_SIZE_CHARS = 9000 CHUNK_OVERLAP_CHARS = 1200 STEP8_CHUNK_SUMMARY_MAX_WORDS = 150 MIN_COVERAGE_SCORE = 0.62 STEP8_TERM_REPAIR_MAX_ROUNDS = 2 STEP8_COVERAGE_REPAIR_PASSES = 1 # Step 9 candidate selection default. AUTO_SELECT_BEST = False ``` -------------------------------- ### Define Global Variables and Allowed Patterns Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Sets up global variables for file selection and defines allowed file patterns for filtering. ```python SELECTED_DRIVE_FILE = '' USE_WIDGET_SELECTION = True ALLOWED_PATTERNS = ['*.pdf', '*.txt', '*.md', '*.tex', '*.csv', '*.json', '*.tsv'] ``` -------------------------------- ### Run PaperBanana for Diagram Generation Source: https://github.com/dwzhu-pku/paperbanana/blob/main/skill/SKILL.md Executes the PaperBanana script to generate a diagram. Requires method text and a figure caption. The output is saved to a specified file. ```bash python skill/run.py \ --content "METHOD_TEXT" \ --caption "FIGURE_CAPTION" \ --task diagram \ --output output.png ``` -------------------------------- ### Reinitialize API Clients Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Builds all API client singletons from the current environment variables and model_config.yaml. Call again after setting new API keys at runtime. ```python import os from utils import generation_utils # Inject keys at runtime (e.g. after a user provides them via UI) os.environ["OPENROUTER_API_KEY"] = "sk-or-v1-..." initialized = generation_utils.reinitialize_clients() # Returns: ["OpenRouter"] (list of successfully initialized client names) print(initialized) # ["OpenRouter"] ``` -------------------------------- ### PolishAgent.process() Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt A two-step agent for improving the quality of ground-truth images. It first generates aesthetic improvement suggestions and then applies them to produce a polished version. Stores the result in `data["polished_diagram_base64_jpg"]` or `data["polished_plot_base64_jpg"]`. ```APIDOC ## `PolishAgent.process()` ### Description Two-step quality improvement agent for ground-truth images. Step 1: generates up to 10 specific aesthetic improvement suggestions using the main model. Step 2: applies those suggestions using the image generation model to produce a polished version. Stores result in `data["polished_diagram_base64_jpg"]` or `data["polished_plot_base64_jpg"]`. ### Method `agent.process(data)` ### Parameters #### Request Body - **data** (dict) - Required - A dictionary containing input data for processing. - **path_to_gt_image** (str) - Required - Path to the ground-truth image relative to `data/PaperBananaBench/diagram/`. - **additional_info** (dict) - Optional - Additional information, e.g., `{"rounded_ratio": "16:9"}`. ### Response #### Success Response (dict) - **polished_diagram_base64_jpg** (str) - Base64 encoded JPG image of the polished diagram, if successful. - **polished_plot_base64_jpg** (str) - Base64 encoded JPG image of the polished plot, if successful. ### Request Example ```python data = { "path_to_gt_image": "images/sample_001.jpg", "additional_info": {"rounded_ratio": "16:9"}, } ``` ### Response Example ```json { "polished_diagram_base64_jpg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYE..." } ``` ``` -------------------------------- ### BaseAgent (abstract base class) Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Abstract base class for all agents. Subclasses must implement the `async process(data, **kwargs) -> Dict` method. It is initialized with a model name, system prompt, and an ExpConfig object. ```APIDOC ## `BaseAgent` (abstract base class) ### Description Abstract base for all agents. Subclasses must implement `async process(data, **kwargs) -> Dict`. Initialized with a model name, system prompt, and `ExpConfig`. ### Usage Example ```python from agents.base_agent import BaseAgent from utils.config import ExpConfig from typing import Dict, Any from pathlib import Path class MyCustomAgent(BaseAgent): def __init__(self, **kwargs): super().__init__(**kwargs) self.model_name = self.exp_config.main_model_name self.system_prompt = "You are a custom agent." async def process(self, data: Dict[str, Any], **kwargs) -> Dict[str, Any]: # data["content"] — method text or raw data # data["visual_intent"] — figure caption data["custom_output"] = f"Processed: {data['content'][:50]}" return data exp_config = ExpConfig(dataset_name="Demo", work_dir=Path(".")) agent = MyCustomAgent(exp_config=exp_config) ``` ``` -------------------------------- ### Visualize Pipeline Evolution Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Launch a Streamlit application to visualize the pipeline evolution and intermediate results. This is useful for debugging and understanding the agent interactions. ```bash streamlit run visualize/show_pipeline_evolution.py ``` -------------------------------- ### Print Source Preview Source: https://github.com/dwzhu-pku/paperbanana/blob/main/notebooks/PaperBanana_Colab_End_to_End.ipynb Prints a preview of the source text, limited to the first 900 characters. This is helpful for quickly inspecting the input data. ```python print(' Source preview (first 900 chars): ') print(method_text[:900]) ``` -------------------------------- ### Visualize Evaluation Results Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Launch a Streamlit application to view evaluation results. This helps in assessing the performance of different configurations and models. ```bash streamlit run visualize/show_referenced_eval.py ``` -------------------------------- ### VanillaAgent.process() Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Generates a diagram or plot image directly from raw method text and caption in a single model call. Stores the result in `data["vanilla_diagram_base64_jpg"]` or `data["vanilla_plot_base64_jpg"]`. ```APIDOC ## `VanillaAgent.process()` ### Description Single-call baseline that bypasses the Retriever/Planner/Stylist pipeline. Directly generates a diagram image or matplotlib plot code from the raw method text and caption in one model call. Stores result in `data["vanilla_diagram_base64_jpg"]` or `data["vanilla_plot_base64_jpg"]`. ### Method `agent.process(data)` ### Parameters #### Request Body - **data** (dict) - Required - A dictionary containing input data for processing. - **content** (str) - Required - The raw method text. - **visual_intent** (str) - Required - The caption or description for the visualization. - **additional_info** (dict) - Optional - Additional information, e.g., `{"rounded_ratio": "16:9"}`. ### Response #### Success Response (dict) - **vanilla_diagram_base64_jpg** (str) - Base64 encoded JPG image of the generated diagram, if successful. - **vanilla_plot_base64_jpg** (str) - Base64 encoded JPG image of the generated plot, if successful. ### Request Example ```python data = { "content": "A BERT-style bidirectional transformer with masked language modeling.", "visual_intent": "Figure 1: BERT pre-training architecture.", "additional_info": {"rounded_ratio": "16:9"}, } ``` ### Response Example ```json { "vanilla_diagram_base64_jpg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYE..." } ``` ``` -------------------------------- ### CLI: skill/run.py Source: https://context7.com/dwzhu-pku/paperbanana/llms.txt Standalone command-line entry point for generating diagrams or plots without the benchmark dataset. It accepts method text (inline or from file), auto-downloads PaperBananaBench reference data on first use, runs the full pipeline in parallel for multiple candidates, and saves output PNG files. ```bash ## CLI: `skill/run.py` Standalone command-line entry point for generating diagrams or plots without the benchmark dataset. Accepts method text (inline or from file), auto-downloads the PaperBananaBench reference data on first use, runs the full pipeline in parallel for multiple candidates, and saves output PNG files. ```bash # Install dependencies uv pip install -r requirements.txt export OPENROUTER_API_KEY="sk-or-v1-..." # Single candidate diagram from inline text python skill/run.py \ --content "We propose a transformer encoder-decoder. The encoder uses 12 self-attention layers. The decoder attends to encoder outputs via cross-attention." \ --caption "Figure 1: Overview of the proposed encoder-decoder architecture" \ --task diagram \ --output architecture.png \ --aspect-ratio 16:9 \ --max-critic-rounds 3 \ --num-candidates 1 # 5 parallel candidates, full pipeline (with Stylist), from a file python skill/run.py \ --content-file method_section.txt \ --caption "Figure 2: Multi-task learning framework" \ --task diagram \ --output results/candidate.png \ --num-candidates 5 \ --exp-mode demo_full \ --retrieval-setting auto # Outputs: results/candidate_0.png, results/candidate_1.png, ..., results/candidate_4.png # Each path printed to stdout on completion. ``` ``` -------------------------------- ### Launch Gradio Web App Locally Source: https://github.com/dwzhu-pku/paperbanana/blob/main/README.md Run the Gradio web application locally by executing the app.py script. This provides a user-friendly interface for interacting with PaperBanana. ```bash python app.py ``` -------------------------------- ### Set Google API Key Source: https://github.com/dwzhu-pku/paperbanana/blob/main/skill/SKILL.md Configures the Google API key as an environment variable for direct access to the Gemini API. ```bash export GOOGLE_API_KEY="your-key-here" ```