File size: 9,244 Bytes
dd19186
 
104cf09
 
 
dd19186
 
5629412
104cf09
dd19186
 
104cf09
dd19186
 
0f4d5f6
dd19186
 
 
 
 
 
 
 
 
 
 
 
 
104cf09
0f4d5f6
104cf09
dd19186
104cf09
dd19186
104cf09
54436b0
dd19186
 
 
 
 
 
0f4d5f6
 
104cf09
dd19186
 
0f4d5f6
dd19186
 
0f4d5f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd19186
 
0f4d5f6
 
 
104cf09
dd19186
 
 
 
0f4d5f6
dd19186
 
 
0f4d5f6
dd19186
 
0f4d5f6
 
 
 
dd19186
0f4d5f6
dd19186
0f4d5f6
 
dd19186
0f4d5f6
dd19186
 
0f4d5f6
 
 
 
dd19186
 
104cf09
dd19186
0f4d5f6
5629412
0f4d5f6
dd19186
104cf09
 
dd19186
0f4d5f6
dd19186
0f4d5f6
 
 
 
daa6ac3
dd19186
 
 
 
0f4d5f6
dd19186
 
0f4d5f6
 
dd19186
0f4d5f6
dd19186
 
0f4d5f6
 
dd19186
 
0f4d5f6
dd19186
 
 
 
 
 
0f4d5f6
 
dd19186
 
 
 
 
 
 
0f4d5f6
 
dd19186
 
 
 
 
 
 
0f4d5f6
 
dd19186
 
 
 
 
 
 
0f4d5f6
 
dd19186
 
0f4d5f6
 
 
 
 
 
 
 
 
 
 
 
5629412
dd19186
0f4d5f6
dd19186
0f4d5f6
 
 
dd19186
0f4d5f6
 
47395b1
0f4d5f6
 
 
 
 
dd19186
 
 
 
0f4d5f6
dd19186
 
 
 
 
0f4d5f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104cf09
dd19186
0f4d5f6
 
 
 
 
 
 
 
 
 
 
 
 
 
dd19186
 
 
671d488
5629412
 
0f4d5f6
dd19186
 
0f4d5f6
dd19186
 
0f4d5f6
 
 
 
 
 
104cf09
dd19186
104cf09
dd19186
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
import gradio as gr
import requests
import os
import json

# These will be set as Hugging Face Spaces secrets
API_KEY = os.environ.get("FIREWORKS_API_KEY", "")
SYSTEM_PROMPT = os.environ.get("SYSTEM_PROMPT")

# API endpoint
API_URL = "https://api.fireworks.ai/inference/v1/chat/completions"

def chat_with_model(message, history, temperature, max_tokens, top_p, top_k):
    """
    Stream responses from the API
    """
    # Build conversation history
    messages = [{"role": "system", "content": SYSTEM_PROMPT}]
    
    # Add conversation history
    for human, assistant in history:
        messages.append({"role": "user", "content": human})
        messages.append({"role": "assistant", "content": assistant})
    
    # Add current message
    messages.append({"role": "user", "content": message})
    
    # Prepare the request
    headers = {
        "Accept": "text/event-stream",
        "Content-Type": "application/json",
        "Authorization": f"Bearer {API_KEY}"
    }
    
    payload = {
        "model": "accounts/fireworks/models/kimi-k2-instruct-0905",
        "max_tokens": max_tokens,
        "top_p": top_p,
        "top_k": top_k,
        "presence_penalty": 0,
        "frequency_penalty": 0,
        "temperature": temperature,
        "messages": messages,
        "stream": True
    }
    
    try:
        response = requests.post(API_URL, headers=headers, json=payload, timeout=120, stream=True)
        response.raise_for_status()
        
        assistant_message = ""
        
        for line in response.iter_lines():
            if line:
                line = line.decode('utf-8')
                if line.startswith('data: '):
                    data = line[6:]
                    if data == '[DONE]':
                        break
                    try:
                        json_data = json.loads(data)
                        if 'choices' in json_data and len(json_data['choices']) > 0:
                            delta = json_data['choices'][0].get('delta', {})
                            content = delta.get('content', '')
                            if content:
                                assistant_message += content
                                yield assistant_message
                    except json.JSONDecodeError:
                        continue
        
        if not assistant_message:
            yield "❌ No response received from the model."
        
    except requests.exceptions.RequestException as e:
        yield f"❌ Error: {str(e)}\n\nPlease check your API key in Hugging Face Spaces secrets."
    except Exception as e:
        yield f"❌ Unexpected error: {str(e)}"

# Custom CSS for a modern look
custom_css = """
.gradio-container {
    font-family: 'Inter', sans-serif;
    max-width: 1400px !important;
}
#title {
    text-align: center;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    font-size: 3em;
    font-weight: 800;
    margin-bottom: 0.3em;
    letter-spacing: -0.02em;
}
#subtitle {
    text-align: center;
    font-size: 1.2em;
    color: #888;
    margin-bottom: 2em;
    font-weight: 300;
}
.message-wrap {
    border-radius: 16px !important;
}
footer {
    display: none !important;
}
"""

# Create Gradio interface
with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue="purple", secondary_hue="pink")) as demo:
    gr.HTML("<h1 id='title'>Palmyra-Sec Playground</h1>")
    gr.HTML("<p id='subtitle'>Intelligent conversations powered by advanced language models</p>")
    
    with gr.Row():
        with gr.Column(scale=3):
            chatbot = gr.Chatbot(
                height=550,
                bubble_full_width=False,
                avatar_images=(
                    "https://api.dicebear.com/7.x/avataaars/svg?seed=user",
                    "https://api.dicebear.com/7.x/bottts-neutral/svg?seed=ai&backgroundColor=b6e3f4"
                ),
                show_copy_button=True
            )
            
            with gr.Row():
                msg = gr.Textbox(
                    placeholder="Ask me anything...",
                    show_label=False,
                    scale=4,
                    container=False,
                    lines=2
                )
                submit_btn = gr.Button("Send πŸ’¬", scale=1, variant="primary", size="lg")
            
            with gr.Row():
                clear_btn = gr.ClearButton([msg, chatbot], value="πŸ—‘οΈ Clear", size="sm")
                retry_btn = gr.Button("πŸ”„ Retry", size="sm", variant="secondary")
        
        with gr.Column(scale=1):
            gr.Markdown("### βš™οΈ Model Settings")
            
            temperature = gr.Slider(
                minimum=0,
                maximum=2,
                value=0.6,
                step=0.1,
                label="🌑️ Temperature",
                info="Creativity level"
            )
            
            max_tokens = gr.Slider(
                minimum=100,
                maximum=4000,
                value=2000,
                step=100,
                label="πŸ“ Max Tokens",
                info="Response length"
            )
            
            top_p = gr.Slider(
                minimum=0,
                maximum=1,
                value=1,
                step=0.05,
                label="🎯 Top P",
                info="Diversity control"
            )
            
            top_k = gr.Slider(
                minimum=1,
                maximum=100,
                value=40,
                step=1,
                label="πŸ”’ Top K",
                info="Token selection"
            )
            
            with gr.Accordion("πŸ“š Quick Presets", open=False):
                gr.Markdown("""
                **Creative** β†’ Temp: 0.9, Top P: 0.95  
                **Balanced** β†’ Temp: 0.6, Top P: 1.0  
                **Precise** β†’ Temp: 0.3, Top P: 0.9
                """)
                
                with gr.Row():
                    creative_btn = gr.Button("🎨 Creative", size="sm")
                    balanced_btn = gr.Button("βš–οΈ Balanced", size="sm")
                    precise_btn = gr.Button("🎯 Precise", size="sm")
            
        
    
    # Handle message submission with streaming
    def respond(message, chat_history, temp, max_tok, top_p_val, top_k_val):
        if not message.strip():
            return chat_history, ""
            
        if not API_KEY:
            chat_history.append((message, "⚠️ Please configure API key in Space secrets!"))
            return chat_history, ""
        
        chat_history.append((message, ""))
        
        for partial_response in chat_with_model(message, chat_history[:-1], temp, max_tok, top_p_val, top_k_val):
            chat_history[-1] = (message, partial_response)
            yield chat_history, ""
    
    msg.submit(
        respond,
        [msg, chatbot, temperature, max_tokens, top_p, top_k],
        [chatbot, msg]
    )
    
    submit_btn.click(
        respond,
        [msg, chatbot, temperature, max_tokens, top_p, top_k],
        [chatbot, msg]
    )
    
    # Retry last message
    def retry_last(chat_history, temp, max_tok, top_p_val, top_k_val):
        if not chat_history:
            return chat_history
        
        last_message = chat_history[-1][0]
        chat_history = chat_history[:-1]
        
        for updated_history, _ in respond(last_message, chat_history, temp, max_tok, top_p_val, top_k_val):
            yield updated_history
    
    retry_btn.click(
        retry_last,
        [chatbot, temperature, max_tokens, top_p, top_k],
        [chatbot]
    )
    
    # Preset buttons
    def set_creative():
        return 0.9, 0.95
    
    def set_balanced():
        return 0.6, 1.0
    
    def set_precise():
        return 0.3, 0.9
    
    creative_btn.click(set_creative, None, [temperature, top_p])
    balanced_btn.click(set_balanced, None, [temperature, top_p])
    precise_btn.click(set_precise, None, [temperature, top_p])
    
    # Add examples
    gr.Examples(
        examples=[
            ["Give me defensive actions. Also map the mitigations to NIST and ISO 27001 controls."],
            ["A financial services company detected unusual outbound traffic from an internal SQL server at 2am. Provide an executive summary of what might be happening, a technical analysis, likely MITRE ATT&CK techniques, and immediate incident response steps the SOC should take."],
            ["We are preparing for a SOC-2 audit. Draft a short security policy on how our engineering team should handle secrets (API keys, SSH keys, environment variables) in source code and CI/CD pipelines. Include recommended tools and preventive controls."],
            ["What are the best practices for Python code?"],
        ],
        inputs=msg,
        label="πŸ’‘ Example Prompts"
    )
    
    gr.Markdown("""
    ---
    <div style='text-align: center; color: #888; font-size: 0.9em;'>
    πŸ”’ <b>Privacy First</b> β€’ All credentials stored securely β€’ Conversations are ephemeral
    </div>
    """)

# Launch the app
if __name__ == "__main__":
    demo.launch()