File size: 5,066 Bytes
0082045
ced39f2
20d2ac6
ced39f2
 
2a8660c
 
 
 
ced39f2
2a8660c
 
 
0082045
ced39f2
 
 
 
 
0082045
ced39f2
9700024
ced39f2
0082045
7c47949
 
0082045
2a8660c
 
 
 
7c47949
20d2ac6
ced39f2
7c47949
 
 
 
 
 
ced39f2
20d2ac6
 
2a8660c
7c47949
 
9700024
 
20d2ac6
9700024
 
 
20d2ac6
9700024
 
 
ced39f2
 
 
 
 
 
7c47949
 
2a8660c
ced39f2
 
7c47949
2a8660c
ced39f2
9700024
2a8660c
ced39f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9700024
ced39f2
 
 
7c47949
 
ced39f2
 
 
 
 
 
2a8660c
 
ced39f2
2a8660c
 
ced39f2
2a8660c
 
 
 
 
 
ced39f2
2a8660c
20d2ac6
2a8660c
ced39f2
 
0082045
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import gradio as gr
import os
import spaces 
from groq import Groq

# Initialize the Groq client via Hugging Face Secrets
api_key = os.environ.get("GROQ_API_KEY")
if not api_key:
    raise ValueError("GROQ_API_KEY environment variable not found. Please add it as a Secret in your Space Settings.")

client = Groq(api_key=api_key)

# Custom CSS for modern styling
custom_css = """
.gradio-container { background-color: #0b0f19; font-family: 'Inter', sans-serif; }
#title-header { text-align: center; margin-bottom: 20px; }
#title-header h1 { color: #38bdf8; font-weight: 800; font-size: 2.2rem; }
.sidebar-panel { background: #111827 !important; border: 1px solid #1f2937 !important; border-radius: 12px !important; }
.chat-window { border: 1px solid #1f2937 !important; border-radius: 12px !important; background: #111827 !important; }
"""

@spaces.GPU
def chat_stream(message, history, model, system_prompt, temperature, max_tokens):
    """
    Handles streaming responses using the standard tuple-based chat history format.
    history layout: [[user_msg1, bot_msg1], [user_msg2, bot_msg2], ...]
    """
    if not message.strip():
        yield history
        return

    # 1. Initialize message list with system prompt for Groq API
    api_messages = [{"role": "system", "content": system_prompt}]

    # 2. Append existing conversation history seamlessly 
    for user_msg, bot_msg in history:
        if user_msg:
            api_messages.append({"role": "user", "content": user_msg})
        if bot_msg:
            api_messages.append({"role": "assistant", "content": bot_msg})

    # 3. Append the newest user message to the API list
    api_messages.append({"role": "user", "content": message})
    
    # 4. Update the Gradio UI history with an empty slot for the bot's upcoming message
    history.append([message, ""])
    yield history

    # 5. Stream from Groq
    try:
        stream = client.chat.completions.create(
            model=model,
            messages=api_messages,
            temperature=temperature,
            max_tokens=max_tokens,
            stream=True,
        )

        partial_response = ""
        for chunk in stream:
            if chunk.choices[0].delta.content:
                partial_response += chunk.choices[0].delta.content
                # Update the very last bot message slot in history
                history[-1][1] = partial_response
                yield history

    except Exception as e:
        history[-1][1] = f"⚠️ Error connecting to Groq: {str(e)}"
        yield history

# Build the layout manually
with gr.Blocks() as demo:
    gr.Markdown("# 🚀 Personal AI ChatBot", elem_id="title-header")
    gr.Markdown("A fully customizable, hyper-fast LLM workspace.")

    with gr.Row():
        # --- LEFT COLUMN: CONTROL PANEL ---
        with gr.Column(scale=1, elem_classes="sidebar-panel"):
            gr.Markdown("### ⚙️ Engine Configurations")

            model_select = gr.Dropdown(
                choices=["llama-3.3-70b-versatile", "llama-3.1-8b-instant"],
                value="llama-3.3-70b-versatile",
                label="Select AI Model"
            )

            system_input = gr.Textbox(
                value="You are a helpful, brilliant, and concise AI assistant.",
                label="System Prompt / AI Persona",
                lines=3,
                placeholder="Ex: Act as a cynical senior developer..."
            )

            gr.Markdown("---")
            gr.Markdown("### 🧠 Hyperparameters")

            temp_slider = gr.Slider(
                minimum=0.0, maximum=2.0, value=0.7, step=0.1,
                label="Temperature", info="Higher = more creative, Lower = more factual"
            )

            tokens_slider = gr.Slider(
                minimum=128, maximum=4096, value=1024, step=128,
                label="Max Output Tokens"
            )

            gr.Markdown("---")
            gr.Markdown("**Status:** 🟢 Connected via ZeroGPU to Groq")

        # --- RIGHT COLUMN: CHAT INTERFACE ---
        with gr.Column(scale=3):
            # Removed the `type="messages"` keyword argument entirely to prevent the TypeError
            chatbot = gr.Chatbot(elem_classes="chat-window")

            msg_input = gr.Textbox(
                placeholder="Type your message here and press Enter...",
                show_label=False,
                container=False
            )
            
            clear_btn = gr.Button("🗑️ Clear Conversation")

            # Native component wiring
            msg_input.submit(
                fn=chat_stream,
                inputs=[msg_input, chatbot, model_select, system_input, temp_slider, tokens_slider],
                outputs=[chatbot]
            ).then(
                fn=lambda: "", 
                inputs=None, 
                outputs=[msg_input]
            )
            
            # Clear chat utility logic
            clear_btn.click(fn=lambda: [], inputs=None, outputs=[chatbot])

if __name__ == "__main__":
    demo.launch(css=custom_css, theme=gr.themes.Soft())