Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -51,6 +51,20 @@ DEFAULT_MODELS = [
|
|
| 51 |
"groq/compound",
|
| 52 |
]
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
# ==================== GROQ API CLIENT ====================
|
| 55 |
class GroqClient:
|
| 56 |
def __init__(self, api_key: str):
|
|
@@ -244,7 +258,7 @@ def refresh_models(api_key: str) -> gr.update:
|
|
| 244 |
|
| 245 |
def process_chat(
|
| 246 |
message: str,
|
| 247 |
-
history: List[List[str]],
|
| 248 |
model: str,
|
| 249 |
temperature: float,
|
| 250 |
max_tokens: int,
|
|
@@ -254,61 +268,62 @@ def process_chat(
|
|
| 254 |
) -> tuple:
|
| 255 |
"""Process chat message with Groq API and auto-fallback"""
|
| 256 |
if not api_key and not GROQ_API_KEY:
|
| 257 |
-
|
|
|
|
| 258 |
|
| 259 |
key = api_key or GROQ_API_KEY
|
| 260 |
client = GroqClient(key)
|
| 261 |
|
| 262 |
-
# Build messages
|
| 263 |
-
|
| 264 |
if system_prompt:
|
| 265 |
-
|
| 266 |
|
| 267 |
for human, assistant in history:
|
| 268 |
-
|
| 269 |
if assistant:
|
| 270 |
-
|
| 271 |
|
| 272 |
-
|
| 273 |
|
| 274 |
-
# Show typing indicator
|
| 275 |
-
|
| 276 |
-
yield
|
| 277 |
|
| 278 |
# Get response with fallback
|
| 279 |
response, model_used = client.chat_completion(
|
| 280 |
-
messages=
|
| 281 |
model=model,
|
| 282 |
temperature=temperature,
|
| 283 |
max_tokens=max_tokens,
|
| 284 |
retry_with_fallback=auto_fallback
|
| 285 |
)
|
| 286 |
|
| 287 |
-
# Update history
|
| 288 |
if "error" in response:
|
| 289 |
error_msg = f"❌ Error: {response['error']}"
|
| 290 |
if "detail" in response:
|
| 291 |
error_msg += f"\n\nDetails: {response['detail']}"
|
| 292 |
-
history[
|
| 293 |
status = f"❌ Error with {model_used}"
|
| 294 |
else:
|
| 295 |
try:
|
| 296 |
content = response["choices"][0]["message"]["content"]
|
| 297 |
usage = response.get("usage", {})
|
| 298 |
|
| 299 |
-
# Add model info footer
|
| 300 |
fallback_notice = ""
|
| 301 |
if model_used != model:
|
| 302 |
fallback_notice = f" (⚠️ Fallback from {model})"
|
| 303 |
|
| 304 |
info = f"\n\n---\n*Model: {model_used}{fallback_notice} | Tokens: {usage.get('total_tokens', 'N/A')}*"
|
| 305 |
-
history[
|
| 306 |
status = f"✅ Success with {model_used}" + (" (fallback)" if model_used != model else "")
|
| 307 |
except Exception as e:
|
| 308 |
-
history[
|
| 309 |
status = f"❌ Parse Error"
|
| 310 |
|
| 311 |
-
|
|
|
|
| 312 |
|
| 313 |
def export_to_github(
|
| 314 |
history: List[List[str]],
|
|
@@ -370,7 +385,7 @@ def format_conversation(history: List[List[str]]) -> str:
|
|
| 370 |
|
| 371 |
def clear_chat():
|
| 372 |
"""Clear chat history"""
|
| 373 |
-
return [],
|
| 374 |
|
| 375 |
def debug_request(
|
| 376 |
message: str,
|
|
@@ -526,7 +541,6 @@ button:hover {
|
|
| 526 |
|
| 527 |
# ==================== GRADIO INTERFACE ====================
|
| 528 |
def create_interface():
|
| 529 |
-
# FIX: Removed css parameter from Blocks constructor
|
| 530 |
with gr.Blocks(title="Groq AI Studio Pro") as demo:
|
| 531 |
|
| 532 |
# Header
|
|
@@ -543,18 +557,17 @@ def create_interface():
|
|
| 543 |
</div>
|
| 544 |
""")
|
| 545 |
|
| 546 |
-
# State
|
| 547 |
state_history = gr.State([])
|
| 548 |
|
| 549 |
with gr.Row():
|
| 550 |
# Left Panel - Chat
|
| 551 |
with gr.Column(scale=3):
|
| 552 |
with gr.Group(elem_classes="glass-panel"):
|
| 553 |
-
# FIX: Removed bubble_full_width and show_copy_button parameters
|
| 554 |
chatbot = gr.Chatbot(
|
| 555 |
label="Conversation",
|
| 556 |
-
elem_classes="chatbot"
|
| 557 |
-
#
|
| 558 |
)
|
| 559 |
|
| 560 |
with gr.Row():
|
|
@@ -658,21 +671,24 @@ def create_interface():
|
|
| 658 |
|
| 659 |
send_event = msg_input.submit(
|
| 660 |
process_chat,
|
| 661 |
-
[msg_input,
|
| 662 |
[chatbot, msg_input, status_text]
|
| 663 |
)
|
| 664 |
|
| 665 |
send_btn.click(
|
| 666 |
process_chat,
|
| 667 |
-
[msg_input,
|
| 668 |
[chatbot, msg_input, status_text]
|
| 669 |
)
|
| 670 |
|
| 671 |
-
clear_btn.click(
|
|
|
|
|
|
|
|
|
|
| 672 |
|
| 673 |
debug_btn.click(
|
| 674 |
debug_request,
|
| 675 |
-
[msg_input,
|
| 676 |
[debug_output]
|
| 677 |
).then(lambda: gr.update(visible=True), outputs=[debug_row])
|
| 678 |
|
|
@@ -706,5 +722,4 @@ def create_interface():
|
|
| 706 |
# Launch
|
| 707 |
if __name__ == "__main__":
|
| 708 |
demo = create_interface()
|
| 709 |
-
# FIX: Moved CSS to launch() method
|
| 710 |
demo.launch(server_name="0.0.0.0", server_port=7860, css=CUSTOM_CSS)
|
|
|
|
| 51 |
"groq/compound",
|
| 52 |
]
|
| 53 |
|
| 54 |
+
# ==================== HELPER: CONVERT HISTORY TO CHATBOT FORMAT ====================
|
| 55 |
+
def to_chatbot_messages(history: List[List[str]]) -> List[Dict[str, str]]:
|
| 56 |
+
"""
|
| 57 |
+
Convert internal history format (list of [user, assistant]) to Gradio Chatbot format.
|
| 58 |
+
Returns a list of dicts with 'role' and 'content'.
|
| 59 |
+
"""
|
| 60 |
+
messages = []
|
| 61 |
+
for user_msg, assistant_msg in history:
|
| 62 |
+
if user_msg:
|
| 63 |
+
messages.append({"role": "user", "content": user_msg})
|
| 64 |
+
if assistant_msg and assistant_msg != "⏳ Thinking...":
|
| 65 |
+
messages.append({"role": "assistant", "content": assistant_msg})
|
| 66 |
+
return messages
|
| 67 |
+
|
| 68 |
# ==================== GROQ API CLIENT ====================
|
| 69 |
class GroqClient:
|
| 70 |
def __init__(self, api_key: str):
|
|
|
|
| 258 |
|
| 259 |
def process_chat(
|
| 260 |
message: str,
|
| 261 |
+
history: List[List[str]], # internal format: list of [user, assistant]
|
| 262 |
model: str,
|
| 263 |
temperature: float,
|
| 264 |
max_tokens: int,
|
|
|
|
| 268 |
) -> tuple:
|
| 269 |
"""Process chat message with Groq API and auto-fallback"""
|
| 270 |
if not api_key and not GROQ_API_KEY:
|
| 271 |
+
new_history = history + [[message, "❌ Error: Please provide a Groq API Key in settings or environment variable."]]
|
| 272 |
+
return to_chatbot_messages(new_history), "", "⚠️ No API Key"
|
| 273 |
|
| 274 |
key = api_key or GROQ_API_KEY
|
| 275 |
client = GroqClient(key)
|
| 276 |
|
| 277 |
+
# Build messages for API
|
| 278 |
+
api_messages = []
|
| 279 |
if system_prompt:
|
| 280 |
+
api_messages.append({"role": "system", "content": system_prompt})
|
| 281 |
|
| 282 |
for human, assistant in history:
|
| 283 |
+
api_messages.append({"role": "user", "content": human})
|
| 284 |
if assistant:
|
| 285 |
+
api_messages.append({"role": "assistant", "content": assistant})
|
| 286 |
|
| 287 |
+
api_messages.append({"role": "user", "content": message})
|
| 288 |
|
| 289 |
+
# Show typing indicator: update chatbot with temporary assistant message
|
| 290 |
+
temp_history = history + [[message, "⏳ Thinking..."]]
|
| 291 |
+
yield to_chatbot_messages(temp_history), "", f"🔄 Using {model}..."
|
| 292 |
|
| 293 |
# Get response with fallback
|
| 294 |
response, model_used = client.chat_completion(
|
| 295 |
+
messages=api_messages,
|
| 296 |
model=model,
|
| 297 |
temperature=temperature,
|
| 298 |
max_tokens=max_tokens,
|
| 299 |
retry_with_fallback=auto_fallback
|
| 300 |
)
|
| 301 |
|
| 302 |
+
# Update internal history
|
| 303 |
if "error" in response:
|
| 304 |
error_msg = f"❌ Error: {response['error']}"
|
| 305 |
if "detail" in response:
|
| 306 |
error_msg += f"\n\nDetails: {response['detail']}"
|
| 307 |
+
history.append([message, error_msg])
|
| 308 |
status = f"❌ Error with {model_used}"
|
| 309 |
else:
|
| 310 |
try:
|
| 311 |
content = response["choices"][0]["message"]["content"]
|
| 312 |
usage = response.get("usage", {})
|
| 313 |
|
|
|
|
| 314 |
fallback_notice = ""
|
| 315 |
if model_used != model:
|
| 316 |
fallback_notice = f" (⚠️ Fallback from {model})"
|
| 317 |
|
| 318 |
info = f"\n\n---\n*Model: {model_used}{fallback_notice} | Tokens: {usage.get('total_tokens', 'N/A')}*"
|
| 319 |
+
history.append([message, content + info])
|
| 320 |
status = f"✅ Success with {model_used}" + (" (fallback)" if model_used != model else "")
|
| 321 |
except Exception as e:
|
| 322 |
+
history.append([message, f"❌ Error parsing response: {str(e)}"])
|
| 323 |
status = f"❌ Parse Error"
|
| 324 |
|
| 325 |
+
# Convert to chatbot format and yield final result
|
| 326 |
+
yield to_chatbot_messages(history), "", status
|
| 327 |
|
| 328 |
def export_to_github(
|
| 329 |
history: List[List[str]],
|
|
|
|
| 385 |
|
| 386 |
def clear_chat():
|
| 387 |
"""Clear chat history"""
|
| 388 |
+
return [], [], "🔄 Ready" # returns (empty chatbot messages, empty internal history, status)
|
| 389 |
|
| 390 |
def debug_request(
|
| 391 |
message: str,
|
|
|
|
| 541 |
|
| 542 |
# ==================== GRADIO INTERFACE ====================
|
| 543 |
def create_interface():
|
|
|
|
| 544 |
with gr.Blocks(title="Groq AI Studio Pro") as demo:
|
| 545 |
|
| 546 |
# Header
|
|
|
|
| 557 |
</div>
|
| 558 |
""")
|
| 559 |
|
| 560 |
+
# State (internal history as list of lists)
|
| 561 |
state_history = gr.State([])
|
| 562 |
|
| 563 |
with gr.Row():
|
| 564 |
# Left Panel - Chat
|
| 565 |
with gr.Column(scale=3):
|
| 566 |
with gr.Group(elem_classes="glass-panel"):
|
|
|
|
| 567 |
chatbot = gr.Chatbot(
|
| 568 |
label="Conversation",
|
| 569 |
+
elem_classes="chatbot",
|
| 570 |
+
type="messages" # Ensure it uses the messages format (default in Gradio 6)
|
| 571 |
)
|
| 572 |
|
| 573 |
with gr.Row():
|
|
|
|
| 671 |
|
| 672 |
send_event = msg_input.submit(
|
| 673 |
process_chat,
|
| 674 |
+
[msg_input, state_history, model_dropdown, temperature, max_tokens, system_prompt, api_key_input, auto_fallback],
|
| 675 |
[chatbot, msg_input, status_text]
|
| 676 |
)
|
| 677 |
|
| 678 |
send_btn.click(
|
| 679 |
process_chat,
|
| 680 |
+
[msg_input, state_history, model_dropdown, temperature, max_tokens, system_prompt, api_key_input, auto_fallback],
|
| 681 |
[chatbot, msg_input, status_text]
|
| 682 |
)
|
| 683 |
|
| 684 |
+
clear_btn.click(
|
| 685 |
+
clear_chat,
|
| 686 |
+
outputs=[chatbot, state_history, status_text]
|
| 687 |
+
)
|
| 688 |
|
| 689 |
debug_btn.click(
|
| 690 |
debug_request,
|
| 691 |
+
[msg_input, state_history, model_dropdown, temperature, max_tokens, system_prompt, api_key_input],
|
| 692 |
[debug_output]
|
| 693 |
).then(lambda: gr.update(visible=True), outputs=[debug_row])
|
| 694 |
|
|
|
|
| 722 |
# Launch
|
| 723 |
if __name__ == "__main__":
|
| 724 |
demo = create_interface()
|
|
|
|
| 725 |
demo.launch(server_name="0.0.0.0", server_port=7860, css=CUSTOM_CSS)
|