Spaces:
Running
Running
Commit
·
0b78b24
1
Parent(s):
5c7c72c
fix: Handle MCP cost estimator markdown response properly
Browse filesThe MCP server returns AI-generated markdown analysis (via Gemini 2.5 Pro),
not a structured dictionary. Updated the cost estimation to:
- Parse markdown text to extract cost and duration values
- Display full MCP markdown analysis in a scrollable container
- Add better error logging and type checking
- Handle cases where markdown parsing is unavailable
Now models not in the leaderboard will get proper cost estimates
from the MCP server with full AI-powered analysis displayed.
app.py
CHANGED
|
@@ -2431,6 +2431,7 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
|
|
| 2431 |
print(f"[INFO] No historical data for {model}, using MCP cost estimator")
|
| 2432 |
try:
|
| 2433 |
from gradio_client import Client
|
|
|
|
| 2434 |
|
| 2435 |
mcp_client = Client("https://mcp-1st-birthday-tracemind-mcp-server.hf.space/")
|
| 2436 |
result = mcp_client.predict(
|
|
@@ -2441,30 +2442,42 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
|
|
| 2441 |
api_name="/run_estimate_cost"
|
| 2442 |
)
|
| 2443 |
|
| 2444 |
-
|
| 2445 |
-
print(f"[INFO] MCP result: {result}")
|
| 2446 |
|
| 2447 |
-
#
|
| 2448 |
-
|
| 2449 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2450 |
return {
|
| 2451 |
'source': 'mcp',
|
| 2452 |
'total_cost_usd': 'N/A',
|
| 2453 |
'estimated_duration_minutes': 'N/A',
|
| 2454 |
'historical_runs': 0,
|
| 2455 |
'has_cost_data': False,
|
| 2456 |
-
'error': 'MCP
|
| 2457 |
}
|
| 2458 |
-
|
| 2459 |
-
return {
|
| 2460 |
-
'source': 'mcp',
|
| 2461 |
-
'total_cost_usd': result.get('estimated_cost', 'N/A'),
|
| 2462 |
-
'estimated_duration_minutes': result.get('estimated_duration', 'N/A'),
|
| 2463 |
-
'historical_runs': 0,
|
| 2464 |
-
'has_cost_data': True
|
| 2465 |
-
}
|
| 2466 |
except Exception as mcp_error:
|
| 2467 |
print(f"[ERROR] MCP cost estimation failed: {mcp_error}")
|
|
|
|
|
|
|
| 2468 |
# Return a result indicating MCP is unavailable
|
| 2469 |
return {
|
| 2470 |
'source': 'mcp',
|
|
@@ -2518,36 +2531,61 @@ with gr.Blocks(title="TraceMind-AI", theme=theme) as app:
|
|
| 2518 |
if cost_est['source'] == 'historical':
|
| 2519 |
source_label = f"📊 Historical Data ({cost_est['historical_runs']} past runs)"
|
| 2520 |
cost_display = f"${cost_est['total_cost_usd']}" if cost_est['has_cost_data'] else "N/A (cost tracking not enabled)"
|
| 2521 |
-
|
| 2522 |
-
|
| 2523 |
-
|
| 2524 |
-
|
| 2525 |
-
|
| 2526 |
-
|
| 2527 |
-
|
| 2528 |
-
|
| 2529 |
-
|
| 2530 |
-
|
| 2531 |
-
|
| 2532 |
-
<div
|
| 2533 |
-
|
| 2534 |
-
|
| 2535 |
-
|
| 2536 |
-
<div
|
| 2537 |
-
|
|
|
|
|
|
|
| 2538 |
</div>
|
| 2539 |
-
<div>
|
| 2540 |
-
<div style="font-size: 0.9em;
|
| 2541 |
-
|
|
|
|
| 2542 |
</div>
|
| 2543 |
</div>
|
| 2544 |
-
|
| 2545 |
-
|
| 2546 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2547 |
</div>
|
| 2548 |
</div>
|
| 2549 |
-
|
| 2550 |
-
|
| 2551 |
return info_html
|
| 2552 |
|
| 2553 |
def on_submit_evaluation_comprehensive(
|
|
|
|
| 2431 |
print(f"[INFO] No historical data for {model}, using MCP cost estimator")
|
| 2432 |
try:
|
| 2433 |
from gradio_client import Client
|
| 2434 |
+
import re
|
| 2435 |
|
| 2436 |
mcp_client = Client("https://mcp-1st-birthday-tracemind-mcp-server.hf.space/")
|
| 2437 |
result = mcp_client.predict(
|
|
|
|
| 2442 |
api_name="/run_estimate_cost"
|
| 2443 |
)
|
| 2444 |
|
| 2445 |
+
print(f"[INFO] MCP result type: {type(result)}")
|
| 2446 |
+
print(f"[INFO] MCP result: {result[:200] if isinstance(result, str) else result}")
|
| 2447 |
|
| 2448 |
+
# MCP returns markdown text, not a dict
|
| 2449 |
+
# Parse the markdown to extract cost and duration
|
| 2450 |
+
if isinstance(result, str):
|
| 2451 |
+
# Try to extract cost values from markdown
|
| 2452 |
+
cost_match = re.search(r'\$(\d+\.?\d*)', result)
|
| 2453 |
+
duration_match = re.search(r'(\d+\.?\d+)\s*(minutes?|hours?)', result, re.IGNORECASE)
|
| 2454 |
+
|
| 2455 |
+
extracted_cost = cost_match.group(1) if cost_match else 'See details below'
|
| 2456 |
+
extracted_duration = duration_match.group(0) if duration_match else 'See details below'
|
| 2457 |
+
|
| 2458 |
+
# Return with markdown content
|
| 2459 |
+
return {
|
| 2460 |
+
'source': 'mcp',
|
| 2461 |
+
'total_cost_usd': extracted_cost,
|
| 2462 |
+
'estimated_duration_minutes': extracted_duration,
|
| 2463 |
+
'historical_runs': 0,
|
| 2464 |
+
'has_cost_data': True,
|
| 2465 |
+
'markdown_details': result # Include full markdown response
|
| 2466 |
+
}
|
| 2467 |
+
else:
|
| 2468 |
+
# Unexpected response type
|
| 2469 |
return {
|
| 2470 |
'source': 'mcp',
|
| 2471 |
'total_cost_usd': 'N/A',
|
| 2472 |
'estimated_duration_minutes': 'N/A',
|
| 2473 |
'historical_runs': 0,
|
| 2474 |
'has_cost_data': False,
|
| 2475 |
+
'error': f'MCP returned unexpected type: {type(result)}'
|
| 2476 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2477 |
except Exception as mcp_error:
|
| 2478 |
print(f"[ERROR] MCP cost estimation failed: {mcp_error}")
|
| 2479 |
+
import traceback
|
| 2480 |
+
traceback.print_exc()
|
| 2481 |
# Return a result indicating MCP is unavailable
|
| 2482 |
return {
|
| 2483 |
'source': 'mcp',
|
|
|
|
| 2531 |
if cost_est['source'] == 'historical':
|
| 2532 |
source_label = f"📊 Historical Data ({cost_est['historical_runs']} past runs)"
|
| 2533 |
cost_display = f"${cost_est['total_cost_usd']}" if cost_est['has_cost_data'] else "N/A (cost tracking not enabled)"
|
| 2534 |
+
|
| 2535 |
+
info_html = f"""
|
| 2536 |
+
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 2537 |
+
padding: 20px; border-radius: 10px; color: white; margin: 10px 0;">
|
| 2538 |
+
<h3 style="margin-top: 0;">💰 Cost Estimate</h3>
|
| 2539 |
+
<div style="font-size: 0.9em; opacity: 0.9; margin-bottom: 5px;">{source_label}</div>
|
| 2540 |
+
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-top: 15px;">
|
| 2541 |
+
<div>
|
| 2542 |
+
<div style="font-size: 0.9em; opacity: 0.9;">Model</div>
|
| 2543 |
+
<div style="font-weight: bold;">{model}</div>
|
| 2544 |
+
</div>
|
| 2545 |
+
<div>
|
| 2546 |
+
<div style="font-size: 0.9em; opacity: 0.9;">Hardware</div>
|
| 2547 |
+
<div style="font-weight: bold;">{hardware.upper()}</div>
|
| 2548 |
+
</div>
|
| 2549 |
+
<div>
|
| 2550 |
+
<div style="font-size: 0.9em; opacity: 0.9;">Estimated Cost</div>
|
| 2551 |
+
<div style="font-weight: bold;">{cost_display}</div>
|
| 2552 |
+
</div>
|
| 2553 |
</div>
|
| 2554 |
+
<div style="margin-top: 15px; padding: 10px; background: rgba(255,255,255,0.15); border-radius: 5px;">
|
| 2555 |
+
<div style="font-size: 0.9em;">
|
| 2556 |
+
⏱️ Estimated completion: {cost_est['estimated_duration_minutes']} minutes
|
| 2557 |
+
</div>
|
| 2558 |
</div>
|
| 2559 |
</div>
|
| 2560 |
+
"""
|
| 2561 |
+
else:
|
| 2562 |
+
# MCP Cost Estimator - show full markdown analysis
|
| 2563 |
+
source_label = "🤖 MCP Cost Estimator (AI-powered by Gemini 2.5 Pro)"
|
| 2564 |
+
markdown_details = cost_est.get('markdown_details', '')
|
| 2565 |
+
|
| 2566 |
+
# Convert markdown to HTML for better display
|
| 2567 |
+
import markdown
|
| 2568 |
+
try:
|
| 2569 |
+
html_content = markdown.markdown(markdown_details)
|
| 2570 |
+
except:
|
| 2571 |
+
# Fallback if markdown library not available
|
| 2572 |
+
html_content = f"<pre style='white-space: pre-wrap;'>{markdown_details}</pre>"
|
| 2573 |
+
|
| 2574 |
+
info_html = f"""
|
| 2575 |
+
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 2576 |
+
padding: 20px; border-radius: 10px; color: white; margin: 10px 0;">
|
| 2577 |
+
<h3 style="margin-top: 0;">💰 Cost Estimate - MCP Analysis</h3>
|
| 2578 |
+
<div style="font-size: 0.9em; opacity: 0.9; margin-bottom: 15px;">{source_label}</div>
|
| 2579 |
+
<div style="background: rgba(255,255,255,0.95); color: #333; padding: 15px; border-radius: 8px;
|
| 2580 |
+
max-height: 400px; overflow-y: auto;">
|
| 2581 |
+
{html_content}
|
| 2582 |
+
</div>
|
| 2583 |
+
<div style="margin-top: 10px; font-size: 0.85em; opacity: 0.9;">
|
| 2584 |
+
ℹ️ This estimate was generated by AI analysis since no historical data is available for this model.
|
| 2585 |
</div>
|
| 2586 |
</div>
|
| 2587 |
+
"""
|
| 2588 |
+
|
| 2589 |
return info_html
|
| 2590 |
|
| 2591 |
def on_submit_evaluation_comprehensive(
|