diff --git a/.jules/bolt.md b/.jules/bolt.md index a85f262..a6a99bb 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -1,3 +1,7 @@ ## 2024-05-21 - [Blender Modal Redraws] **Learning:** Blender `modal` operators run frequently (e.g. every 0.3s). Calling `area.tag_redraw()` unconditionally in the loop forces constant viewport rendering, even when no state has changed, causing unnecessary CPU/GPU load. **Action:** Only call `tag_redraw()` when the operator actually processes data or updates the UI state (e.g., via a `refresh_needed` flag). + +## 2024-05-22 - [Google GenAI Client Reuse] +**Learning:** Creating a new `google.genai.Client()` instance takes ~80ms. The original pipeline created 5 instances sequentially, adding ~400ms overhead. Reusing a single client instance saves this overhead and likely benefits from connection pooling. +**Action:** Instantiate API clients once at the start of a pipeline and pass them down to utility functions using dependency injection. diff --git a/operators.py b/operators.py index e202f95..f0de249 100644 --- a/operators.py +++ b/operators.py @@ -90,10 +90,13 @@ def execute(self, context): def _run_pipeline(self, gemini_key, meshy_key, prompt, q): try: + # ⚡ Bolt: Reuse client to avoid overhead (saving ~400ms) + client = utils.get_client(gemini_key) + q.put(("INFO", "Refining prompt...", "")) # Step 1: Refine prompt - refined = utils.refine_prompt(gemini_key, prompt) + refined = utils.refine_prompt(gemini_key, prompt, client=client) q.put(("REFINED", refined, "")) q.put(("INFO", "Prompt refined", "")) @@ -110,7 +113,9 @@ def generate_view(view_name, view_prompt, input_ref=None): # If it's the front view call, input_ref is None usually, # but valid for subsequent calls - res_path = utils.generate_image(gemini_key, view_prompt, out, input_ref) + res_path = utils.generate_image( + gemini_key, view_prompt, out, input_ref, client=client + ) q.put(("IMAGE", f"{view_name} done", res_path)) return res_path diff --git a/utils.py b/utils.py index b12dfd5..e3789f7 100644 --- a/utils.py +++ b/utils.py @@ -16,9 +16,10 @@ def get_client(api_key): return genai.Client(api_key=api_key) -def refine_prompt(api_key, prompt): +def refine_prompt(api_key, prompt, client=None): """Use Gemini to refine a prompt for 3D model generation.""" - client = get_client(api_key) + if client is None: + client = get_client(api_key) instruction = ( f"Refine this prompt for generating a high-quality 3D model reference image. " @@ -36,7 +37,7 @@ def refine_prompt(api_key, prompt): return response.text.strip() -def generate_image(api_key, prompt, output_path, input_image_path=None): +def generate_image(api_key, prompt, output_path, input_image_path=None, client=None): """ Generate an image using Gemini. If input_image_path is provided, use it as reference for the generation. @@ -44,7 +45,8 @@ def generate_image(api_key, prompt, output_path, input_image_path=None): from google.genai import types from PIL import Image - client = get_client(api_key) + if client is None: + client = get_client(api_key) config = types.GenerateContentConfig( response_modalities=["Image"], @@ -117,7 +119,8 @@ def generate_3d_meshy(api_key, image_paths): task_id = resp.json()["result"] # Adaptive polling: Check frequently at first (2s), then back off to 5s - # This reduces waiting time for fast jobs without spamming the API for slow ones. + # This reduces waiting time for fast jobs without spamming the API + # for slow ones. intervals = [2, 2, 2, 5] default_interval = 5