Kai Izumoto
Update app.py
872296d verified
"""
SuperCoder - Hugging Face Spaces Frontend (FIXED)
Connects to your local API server via tunnel
"""
import gradio as gr
import requests
from typing import List, Tuple
import os
# ============================================================================
# Configuration - YOUR TUNNEL URL
# ============================================================================
# The API_URL is pulled from a Space Secret for better security
API_URL = os.getenv("API_URL", "https://your-tunnel-url.ngrok-free.dev")
API_URL = API_URL.rstrip('/')
# ============================================================================
# API Client Functions
# ============================================================================
def call_api(message: str, temperature: float = 0.1, max_tokens: int = 512) -> str:
"""Call the remote API with error handling"""
if not message or not message.strip():
return "⚠️ Please enter a message"
try:
response = requests.post(
f"{API_URL}/api/chat",
json={
"messages": [{"role": "user", "content": message}],
"temperature": temperature,
"max_tokens": max_tokens
},
timeout=90,
headers={
"Content-Type": "application/json",
"ngrok-skip-browser-warning": "true"
}
)
if response.status_code == 200:
result = response.json()
return result.get("response", "No response from API")
elif response.status_code == 503:
return "πŸ”§ Backend service unavailable. Please ensure your local server is running."
else:
return f"❌ API Error ({response.status_code}): {response.text[:200]}"
except requests.exceptions.Timeout:
return "⏱️ Request timed out. The model might be processing a complex request or the server is down."
except requests.exceptions.ConnectionError:
return f"πŸ”Œ Cannot connect to API at {API_URL}. Please verify:\n1. Local server is running\n2. Tunnel (ngrok/cloudflare) is active\n3. API_URL is correct"
except Exception as e:
return f"⚠️ Unexpected error: {str(e)}"
def check_api_status() -> str:
"""Check if the API is reachable and healthy"""
try:
response = requests.get(
f"{API_URL}/health",
timeout=10, # Increased timeout slightly for cold starts
headers={"ngrok-skip-browser-warning": "true"}
)
if response.status_code == 200:
data = response.json()
status = data.get("status", "unknown")
if status == "ok":
return "βœ… Connected - Backend Ready"
else:
return f"⚠️ Connected but status: {status}"
else:
return f"❌ API returned status {response.status_code}"
except requests.exceptions.ConnectionError:
return f"πŸ”΄ Cannot reach {API_URL} - Check tunnel status"
except requests.exceptions.Timeout:
return "⏱️ Health check timed out"
except Exception as e:
return f"❌ Error: {str(e)}"
# ============================================================================
# Gradio Interface
# ============================================================================
def respond(message: str, history: List[Tuple[str, str]], temperature: float, max_tokens: int):
"""Handle chat responses"""
history.append((message, None))
yield history # Show user message immediately
bot_response = call_api(message, temperature, max_tokens)
history[-1] = (message, bot_response)
yield history
def apply_template(template: str, history: List[Tuple[str, str]]) -> tuple:
"""Apply a code template"""
templates = {
"Explain Code": "Please explain the following code in detail:\n```python\n# Paste your code here\n```",
"Debug Code": "I have a bug in my code. Can you help me debug it?\n```python\n# Paste your buggy code here\n```",
"Write Function": "Please write a Python function that: [describe what you need]",
"Optimize Code": "Can you optimize this code for better performance?\n```python\n# Paste your code here\n```",
"Add Comments": "Please add clear comments to this code:\n```python\n# Paste your code here\n```"
}
return templates.get(template, ""), history
# Create the Gradio interface
with gr.Blocks(
title="SuperCoder Pro",
theme=gr.themes.Soft(primary_hue="indigo"),
css=".gradio-container {max-width: 1200px !important}"
) as demo:
gr.Markdown(
"""
# πŸ€– SuperCoder Pro
### AI-Powered Coding Assistant
> **Note:** This interface connects to a local backend via a secure tunnel.
> Ensure your local server and tunnel are running.
"""
)
# Status bar
with gr.Row():
with gr.Column(scale=4):
# --- FIX ---: Set a static default value here
status_display = gr.Textbox(
value="⏳ Initializing...",
label="πŸ”Œ Backend Status",
interactive=False,
show_copy_button=True
)
with gr.Column(scale=1):
refresh_btn = gr.Button("πŸ”„ Refresh Status", size="sm")
# Main chat interface
with gr.Row():
with gr.Column(scale=3):
chatbot = gr.Chatbot(
label="πŸ’¬ Conversation",
height=500,
show_copy_button=True,
avatar_images=(None, "πŸ€–"),
bubble_full_width=False
)
with gr.Row():
msg_input = gr.Textbox(
placeholder="Ask me to write, explain, debug, or review code...",
scale=5,
lines=2,
show_label=False,
autofocus=True,
container=False
)
send_btn = gr.Button("Send πŸš€", scale=1, variant="primary")
# Settings sidebar
with gr.Column(scale=1):
gr.Markdown("### βš™οΈ Model Settings")
temperature = gr.Slider(0.0, 1.0, value=0.1, step=0.05, label="🌑️ Temperature")
max_tokens = gr.Slider(128, 4096, value=1024, step=128, label="πŸ“ Max Tokens")
gr.Markdown("---")
gr.Markdown("### 🎯 Quick Templates")
template_dropdown = gr.Dropdown(
choices=["Explain Code", "Debug Code", "Write Function", "Optimize Code", "Add Comments"],
label="Select Template",
value="Explain Code"
)
use_template_btn = gr.Button("πŸ“ Use Template", size="sm")
clear_btn = gr.Button("πŸ—‘οΈ Clear Chat", variant="stop", size="sm")
gr.Markdown("---")
gr.Markdown(f"""### πŸ“‘ Connection Info\n**API Endpoint:**\n`{API_URL}`""")
# Event handlers
# --- FIX ---: Use the demo.load() event to check status after UI is ready
demo.load(check_api_status, outputs=[status_display])
refresh_btn.click(check_api_status, outputs=[status_display])
msg_submit_event = msg_input.submit(
respond,
inputs=[msg_input, chatbot, temperature, max_tokens],
outputs=[chatbot]
)
msg_submit_event.then(lambda: gr.update(value=""), outputs=[msg_input])
send_btn.click(
respond,
inputs=[msg_input, chatbot, temperature, max_tokens],
outputs=[chatbot]
).then(lambda: gr.update(value=""), outputs=[msg_input])
use_template_btn.click(apply_template, inputs=[template_dropdown, chatbot], outputs=[msg_input, chatbot])
clear_btn.click(lambda: [], outputs=[chatbot])
# ============================================================================
# Launch Configuration for HF Spaces
# ============================================================================
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
show_error=True
)