martinbowling commited on
Commit
1bc47a2
·
verified ·
1 Parent(s): 4a03aeb

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +226 -0
app.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # /// script
2
+ # requires-python = ">=3.12"
3
+ # dependencies = [
4
+ # "gradio>=4.25.0",
5
+ # "requests>=2.32.2",
6
+ # "groq>=0.5.0",
7
+ # "python-dotenv>=1.0.0",
8
+ # ]
9
+ # ///
10
+
11
+ import gradio as gr
12
+ import requests
13
+ import json
14
+ import os
15
+ from groq import Groq
16
+ from dotenv import load_dotenv
17
+
18
+ # Load environment variables
19
+ load_dotenv()
20
+
21
+ # Initialize global variables
22
+ reasoning_history = []
23
+ ENV_DEEPSEEK_KEY = os.getenv("DEEPSEEK_API_KEY", "")
24
+ ENV_GROQ_KEY = os.getenv("GROQ_API_KEY", "")
25
+
26
+ def validate_keys(deepseek_key, groq_key):
27
+ """Validate API keys and return appropriate message"""
28
+ if not deepseek_key or not groq_key:
29
+ missing = []
30
+ if not deepseek_key:
31
+ missing.append("DeepSeek")
32
+ if not groq_key:
33
+ missing.append("Groq")
34
+ return False, f"Missing API key(s) for: {', '.join(missing)}. Please configure keys."
35
+ return True, "Keys configured successfully!"
36
+
37
+ def process_deepseek(message, api_key):
38
+ if not api_key:
39
+ raise ValueError("DeepSeek API key not configured")
40
+
41
+ headers = {
42
+ "Authorization": f"Bearer {api_key}",
43
+ "Content-Type": "application/json"
44
+ }
45
+ data = {
46
+ "model": "deepseek-reasoner",
47
+ "messages": [
48
+ {"role": "system", "content": "You are a helpful assistant."},
49
+ {"role": "user", "content": message}
50
+ ],
51
+ "stream": True,
52
+ "max_tokens": 1
53
+ }
54
+
55
+ response = requests.post(
56
+ "https://api.deepseek.com/chat/completions",
57
+ headers=headers,
58
+ json=data,
59
+ stream=True
60
+ )
61
+
62
+ reasoning = []
63
+ for line in response.iter_lines():
64
+ if line:
65
+ try:
66
+ cleaned_line = line.decode('utf-8').replace('data: ', '').strip()
67
+ if cleaned_line == '[DONE]':
68
+ continue
69
+ chunk = json.loads(cleaned_line)
70
+ if chunk.get('choices'):
71
+ content = chunk['choices'][0]['delta'].get('reasoning_content', '')
72
+ if content:
73
+ reasoning.append(content)
74
+ except Exception as e:
75
+ continue
76
+
77
+ return ' '.join(reasoning)
78
+
79
+ def chat_fn(message, history, deepseek_key, groq_key):
80
+ # Use environment variables if available, otherwise use UI inputs
81
+ active_deepseek_key = ENV_DEEPSEEK_KEY or deepseek_key
82
+ active_groq_key = ENV_GROQ_KEY or groq_key
83
+
84
+ # Validate keys before processing
85
+ is_valid, validation_message = validate_keys(active_deepseek_key, active_groq_key)
86
+ if not is_valid:
87
+ yield {"role": "assistant", "content": validation_message}
88
+ return
89
+
90
+ try:
91
+ reasoning = process_deepseek(message, active_deepseek_key)
92
+ except Exception as e:
93
+ yield {"role": "assistant", "content": f"DeepSeek API Error: {str(e)}"}
94
+ return
95
+
96
+ reasoning_history.append(reasoning)
97
+
98
+ groq_prompt = f"""You will be given a query and reasoning steps.
99
+ Review the reasoning, thinking through each of the steps and provide a concise answer to the user.
100
+
101
+ <user_query>{message}</user_query>
102
+ <reasoning>{reasoning}</reasoning>"""
103
+
104
+ try:
105
+ client = Groq(api_key=active_groq_key)
106
+ groq_response = client.chat.completions.create(
107
+ model="llama-3.3-70b-specdec",
108
+ messages=[{"role": "user", "content": groq_prompt}],
109
+ temperature=0.7,
110
+ max_tokens=1024,
111
+ top_p=1,
112
+ stream=True,
113
+ )
114
+
115
+ accumulated_response = ""
116
+ for chunk in groq_response:
117
+ part = chunk.choices[0].delta.content or ""
118
+ accumulated_response += part
119
+ yield {"role": "assistant", "content": accumulated_response}
120
+
121
+ except Exception as e:
122
+ yield {"role": "assistant", "content": f"Groq API Error: {str(e)}"}
123
+
124
+ def show_reasoning():
125
+ return reasoning_history[-1] if reasoning_history else "No reasoning available"
126
+
127
+ def toggle_reasoning_visibility(visible):
128
+ return gr.update(visible=visible)
129
+
130
+ def show_settings():
131
+ return gr.update(visible=True)
132
+
133
+ def hide_settings():
134
+ return gr.update(visible=False)
135
+
136
+ # Create the Gradio interface
137
+ with gr.Blocks(theme=gr.themes.Soft(), title="Thoughtful Lightning") as demo:
138
+ # Initialize error banner
139
+ error_banner = gr.Markdown(visible=False)
140
+
141
+ # Main Interface
142
+ gr.Markdown("## ⚡ Thoughtful Lightning")
143
+ gr.Markdown("*Powered by DeepSeek R1 reasoning and Groq's lightning-fast inference*")
144
+
145
+ # Settings Group (Initially Hidden)
146
+ with gr.Group(visible=False) as settings_group:
147
+ gr.Markdown("### ⚙️ Settings")
148
+ gr.Markdown("*Note: Environment variables will be used if available*")
149
+ with gr.Row():
150
+ with gr.Column(scale=1):
151
+ deepseek_key = gr.Textbox(
152
+ label="DeepSeek API Key",
153
+ type="password",
154
+ value="",
155
+ placeholder="Enter DeepSeek API key" if not ENV_DEEPSEEK_KEY else "Using key from environment",
156
+ info="DeepSeek R1 API key for reasoning"
157
+ )
158
+ groq_key = gr.Textbox(
159
+ label="Groq API Key",
160
+ type="password",
161
+ value="",
162
+ placeholder="Enter Groq API key" if not ENV_GROQ_KEY else "Using key from environment",
163
+ info="Groq API key for fast inference"
164
+ )
165
+ with gr.Row():
166
+ close_btn = gr.Button("Close")
167
+ settings_status = gr.Markdown()
168
+
169
+ with gr.Row():
170
+ with gr.Column(scale=1):
171
+ settings_btn = gr.Button("⚙️ Settings")
172
+ reasoning_btn = gr.Button("🧐 Show Reasoning")
173
+
174
+ with gr.Row():
175
+ chat_interface = gr.ChatInterface(
176
+ chat_fn,
177
+ additional_inputs=[deepseek_key, groq_key],
178
+ examples=[
179
+ ["How many r's are in strawberry"],
180
+ ["Which is greater 9.11 or 9.9"],
181
+ ["Best way to learn Rust in 2024?"]
182
+ ]
183
+ )
184
+
185
+ reasoning_output = gr.Textbox(
186
+ label="Reasoning Steps",
187
+ interactive=False,
188
+ visible=False,
189
+ lines=8,
190
+ max_lines=12
191
+ )
192
+
193
+ # Event handlers
194
+ settings_btn.click(
195
+ fn=show_settings,
196
+ outputs=[settings_group]
197
+ )
198
+
199
+ close_btn.click(
200
+ fn=hide_settings,
201
+ outputs=[settings_group]
202
+ )
203
+
204
+ reasoning_btn.click(
205
+ fn=show_reasoning,
206
+ outputs=reasoning_output
207
+ ).then(
208
+ fn=toggle_reasoning_visibility,
209
+ inputs=[gr.State(True)],
210
+ outputs=[reasoning_output]
211
+ )
212
+
213
+ if __name__ == "__main__":
214
+ # Create .env file if it doesn't exist
215
+ if not os.path.exists(".env"):
216
+ with open(".env", "w") as f:
217
+ f.write("DEEPSEEK_API_KEY=\nGROQ_API_KEY=\n")
218
+
219
+ # Show error if no keys are configured
220
+ if not (ENV_DEEPSEEK_KEY or ENV_GROQ_KEY):
221
+ print("\n⚠️ No API keys found in environment variables.")
222
+ print("You can either:")
223
+ print("1. Add them to your .env file")
224
+ print("2. Configure them in the UI settings\n")
225
+
226
+ demo.queue().launch()