Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -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.
9 changes: 7 additions & 2 deletions operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -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", ""))

Expand All @@ -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

Expand Down
13 changes: 8 additions & 5 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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. "
Expand All @@ -36,15 +37,16 @@ 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.
"""
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"],
Expand Down Expand Up @@ -117,7 +119,8 @@ def generate_3d_meshy(api_key, image_paths):
task_id = resp.json()["result"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟒 Good readability improvement by splitting the long comment into two lines.


# 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

Expand Down
Loading