Spaces:
Running
Running
Update main.py
Browse files
main.py
CHANGED
|
@@ -239,6 +239,39 @@ def generate_master_blueprint_task(subject, flattened_data, uid, epiphany_id):
|
|
| 239 |
logger.error(f"Master Blueprint Thread Error: {e}")
|
| 240 |
return None
|
| 241 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
# -----------------------------------------------------------------------------
|
| 243 |
# 4. PRIMARY ENDPOINTS: GENERATE & THEIA SWEEP
|
| 244 |
# -----------------------------------------------------------------------------
|
|
@@ -377,7 +410,7 @@ def generate_epiphany():
|
|
| 377 |
|
| 378 |
@app.route('/api/epiphany/theia', methods=['POST'])
|
| 379 |
def theia_sweep():
|
| 380 |
-
"""Standalone Theia Mode: Bounding Box Annotations with
|
| 381 |
logger.info(">>> THEIA SWEEP INITIATED")
|
| 382 |
uid = verify_token(request.headers.get('Authorization'))
|
| 383 |
if not uid: return jsonify({'error': 'Unauthorized'}), 401
|
|
@@ -397,7 +430,16 @@ def theia_sweep():
|
|
| 397 |
if user_data.get('credits', 0) < 4:
|
| 398 |
return jsonify({'error': 'Need 4 Sparks for a Theia Sweep.'}), 402
|
| 399 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
image_file = request.files['image']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 401 |
subject = existing_data.get('subject', 'Complex System')
|
| 402 |
|
| 403 |
sweep_prompt = f"""
|
|
@@ -411,7 +453,7 @@ def theia_sweep():
|
|
| 411 |
"""
|
| 412 |
|
| 413 |
try:
|
| 414 |
-
pil_image = Image.open(io.BytesIO(
|
| 415 |
res = client.models.generate_content(
|
| 416 |
model=ATHENA_FLASH,
|
| 417 |
contents=[sweep_prompt, pil_image],
|
|
@@ -422,8 +464,9 @@ def theia_sweep():
|
|
| 422 |
)
|
| 423 |
|
| 424 |
raw_json = res.text.strip()
|
| 425 |
-
|
| 426 |
-
|
|
|
|
| 427 |
|
| 428 |
annotations = json.loads(raw_json)
|
| 429 |
|
|
|
|
| 239 |
logger.error(f"Master Blueprint Thread Error: {e}")
|
| 240 |
return None
|
| 241 |
|
| 242 |
+
#Prepare hi fidelity images to proper scale
|
| 243 |
+
def prepare_vision_bytes(image_bytes, max_size_mb=9.5):
|
| 244 |
+
"""
|
| 245 |
+
Surgically compresses/resizes image bytes to stay under the 10MB API limit.
|
| 246 |
+
Target: 9.5MB to allow a safe margin for the rest of the request payload.
|
| 247 |
+
"""
|
| 248 |
+
size_mb = len(image_bytes) / (1024 * 1024)
|
| 249 |
+
if size_mb <= max_size_mb:
|
| 250 |
+
return image_bytes
|
| 251 |
+
|
| 252 |
+
logger.info(f"Vision Scaler: Image is {size_mb:.2f}MB. Optimizing for API...")
|
| 253 |
+
try:
|
| 254 |
+
img = Image.open(io.BytesIO(image_bytes))
|
| 255 |
+
|
| 256 |
+
# Target resolution: 2048px on the long side is optimal for Gemini detection
|
| 257 |
+
max_dim = 2048
|
| 258 |
+
w, h = img.size
|
| 259 |
+
if max(w, h) > max_dim:
|
| 260 |
+
scale = max_dim / max(w, h)
|
| 261 |
+
img = img.resize((int(w * scale), int(h * scale)), Image.Resampling.LANCZOS)
|
| 262 |
+
|
| 263 |
+
output = io.BytesIO()
|
| 264 |
+
# Convert to RGB (removes Alpha channel if present to save space)
|
| 265 |
+
# Save as optimized JPEG at 85% quality
|
| 266 |
+
img.convert('RGB').save(output, format="JPEG", quality=85, optimize=True)
|
| 267 |
+
new_bytes = output.getvalue()
|
| 268 |
+
|
| 269 |
+
new_size_mb = len(new_bytes)/(1024*1024)
|
| 270 |
+
logger.info(f"Vision Scaler: Optimization complete. New size: {new_size_mb:.2f}MB")
|
| 271 |
+
return new_bytes
|
| 272 |
+
except Exception as e:
|
| 273 |
+
logger.error(f"Vision Scaler Failure: {e}")
|
| 274 |
+
return image_bytes # Fallback to original and hope for the best
|
| 275 |
# -----------------------------------------------------------------------------
|
| 276 |
# 4. PRIMARY ENDPOINTS: GENERATE & THEIA SWEEP
|
| 277 |
# -----------------------------------------------------------------------------
|
|
|
|
| 410 |
|
| 411 |
@app.route('/api/epiphany/theia', methods=['POST'])
|
| 412 |
def theia_sweep():
|
| 413 |
+
"""Standalone Theia Mode: Bounding Box Annotations with Vision Scaling."""
|
| 414 |
logger.info(">>> THEIA SWEEP INITIATED")
|
| 415 |
uid = verify_token(request.headers.get('Authorization'))
|
| 416 |
if not uid: return jsonify({'error': 'Unauthorized'}), 401
|
|
|
|
| 430 |
if user_data.get('credits', 0) < 4:
|
| 431 |
return jsonify({'error': 'Need 4 Sparks for a Theia Sweep.'}), 402
|
| 432 |
|
| 433 |
+
# --- IMAGE PRE-PROCESSING ---
|
| 434 |
+
if 'image' not in request.files:
|
| 435 |
+
return jsonify({'error': 'image file is required.'}), 400
|
| 436 |
+
|
| 437 |
image_file = request.files['image']
|
| 438 |
+
raw_bytes = image_file.read()
|
| 439 |
+
|
| 440 |
+
# Surgical Fix: Stay under 10MB limit
|
| 441 |
+
image_bytes = prepare_vision_bytes(raw_bytes)
|
| 442 |
+
|
| 443 |
subject = existing_data.get('subject', 'Complex System')
|
| 444 |
|
| 445 |
sweep_prompt = f"""
|
|
|
|
| 453 |
"""
|
| 454 |
|
| 455 |
try:
|
| 456 |
+
pil_image = Image.open(io.BytesIO(image_bytes)).convert('RGB')
|
| 457 |
res = client.models.generate_content(
|
| 458 |
model=ATHENA_FLASH,
|
| 459 |
contents=[sweep_prompt, pil_image],
|
|
|
|
| 464 |
)
|
| 465 |
|
| 466 |
raw_json = res.text.strip()
|
| 467 |
+
# Use helper to strip fences if present
|
| 468 |
+
if "```" in raw_json:
|
| 469 |
+
raw_json = _strip_json_fences(raw_json)
|
| 470 |
|
| 471 |
annotations = json.loads(raw_json)
|
| 472 |
|