Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -5,7 +5,6 @@ import datetime
|
|
5 |
import streamlit.components.v1 as components
|
6 |
|
7 |
# --- CONFIG ---
|
8 |
-
# Place your API keys here
|
9 |
GROQ_API_KEY = st.secrets.get('GROQ_API_KEY', 'YOUR_GROQ_API_KEY')
|
10 |
BLACKBOX_API_KEY = st.secrets.get('BLACKBOX_API_KEY', 'YOUR_BLACKBOX_API_KEY')
|
11 |
|
@@ -22,9 +21,8 @@ EXAMPLE_QUESTIONS = [
|
|
22 |
"How can I make this code more readable?"
|
23 |
]
|
24 |
|
25 |
-
# --- API
|
26 |
def call_groq_api(prompt, model="llama3-70b-8192"):
|
27 |
-
# Replace with actual Groq API call
|
28 |
headers = {"Authorization": f"Bearer {GROQ_API_KEY}", "Content-Type": "application/json"}
|
29 |
data = {"model": model, "messages": [{"role": "user", "content": prompt}]}
|
30 |
response = requests.post("https://api.groq.com/openai/v1/chat/completions", json=data, headers=headers)
|
@@ -47,18 +45,15 @@ def call_blackbox_agent(messages):
|
|
47 |
if response.status_code == 200:
|
48 |
return response.json()["choices"][0]["message"]["content"]
|
49 |
else:
|
50 |
-
# fallback to Groq if Blackbox fails
|
51 |
return call_groq_api(messages[-1]["content"])
|
52 |
|
53 |
# --- UTILS ---
|
54 |
def code_matches_language(code, language):
|
55 |
-
# Simple heuristic, can be improved
|
56 |
if language.lower() in code.lower():
|
57 |
return True
|
58 |
-
return True
|
59 |
|
60 |
def calculate_code_complexity(code):
|
61 |
-
# Dummy complexity metric
|
62 |
lines = code.count('\n') + 1
|
63 |
return f"{lines} lines"
|
64 |
|
@@ -73,10 +68,6 @@ def get_inline_diff(original, modified):
|
|
73 |
return '\n'.join(diff)
|
74 |
|
75 |
def is_coding_question(question):
|
76 |
-
"""
|
77 |
-
Uses Blackbox AI agent to check if the question is about programming/code.
|
78 |
-
Returns True if yes, False otherwise.
|
79 |
-
"""
|
80 |
messages = [
|
81 |
{"role": "system", "content": "You are a helpful coding assistant."},
|
82 |
{"role": "user", "content": f"Is the following question about programming or code? Answer only 'yes' or 'no'. Question: {question}"}
|
@@ -127,7 +118,6 @@ elif page == "AI Workflow":
|
|
127 |
st.error(f"Language mismatch. Please check your code and language selection.")
|
128 |
else:
|
129 |
with st.spinner("Running AI Workflow..."):
|
130 |
-
# Simulate workflow steps
|
131 |
steps = [
|
132 |
("Explain", call_groq_api(f"Explain this {programming_language} code for a {skill_level} {user_role} in {explanation_language}:\n{code_input}")),
|
133 |
("Refactor", call_blackbox_agent([
|
@@ -145,11 +135,9 @@ elif page == "AI Workflow":
|
|
145 |
for t in timeline:
|
146 |
st.subheader(t["step"])
|
147 |
st.write(t["output"])
|
148 |
-
# Show code diff (Original vs Refactored)
|
149 |
st.subheader("Code Diff (Original vs Refactored)")
|
150 |
-
refactored_code = steps[1][1]
|
151 |
st.code(get_inline_diff(code_input, refactored_code), language=programming_language.lower())
|
152 |
-
# Download report
|
153 |
report = f"AI Workflow Report\nGenerated on: {datetime.datetime.now()}\nLanguage: {programming_language}\nSkill Level: {skill_level}\nRole: {user_role}\n\n"
|
154 |
for t in timeline:
|
155 |
report += f"## {t['step']}\n{t['output']}\n\n---\n\n"
|
@@ -175,72 +163,99 @@ elif page == "Semantic Search":
|
|
175 |
st.caption("Example questions:")
|
176 |
st.write(", ".join(EXAMPLE_QUESTIONS))
|
177 |
|
178 |
-
# Session state for question and trigger
|
179 |
if 'voice_question' not in st.session_state:
|
180 |
st.session_state['voice_question'] = ''
|
181 |
if 'run_semantic_search' not in st.session_state:
|
182 |
st.session_state['run_semantic_search'] = False
|
183 |
|
184 |
-
#
|
185 |
-
|
186 |
-
<
|
187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
<script>
|
189 |
-
const
|
190 |
-
const
|
191 |
let recognition;
|
192 |
if ('webkitSpeechRecognition' in window) {
|
193 |
recognition = new webkitSpeechRecognition();
|
194 |
recognition.lang = 'en-US';
|
195 |
recognition.continuous = false;
|
196 |
recognition.interimResults = false;
|
197 |
-
|
|
|
198 |
recognition.start();
|
199 |
-
|
200 |
};
|
201 |
recognition.onresult = function(event) {
|
202 |
const transcript = event.results[0][0].transcript;
|
|
|
203 |
window.parent.postMessage({isStreamlitMessage: true, type: 'streamlit:setComponentValue', value: transcript}, '*');
|
204 |
-
|
205 |
};
|
206 |
recognition.onerror = function() {
|
207 |
-
|
208 |
};
|
209 |
recognition.onend = function() {
|
210 |
-
|
211 |
};
|
212 |
} else {
|
213 |
-
|
214 |
-
|
|
|
|
|
|
|
|
|
215 |
}
|
216 |
</script>
|
217 |
-
''
|
218 |
|
219 |
-
#
|
220 |
-
|
221 |
|
222 |
-
#
|
223 |
-
#
|
224 |
-
|
225 |
-
# Here, we simulate the process using session_state for demonstration.
|
226 |
-
# You may need to use streamlit_js_eval or a similar package for real-time JS->Python value passing.
|
227 |
|
228 |
-
#
|
229 |
-
if
|
230 |
-
|
231 |
-
|
232 |
st.session_state['run_semantic_search'] = True
|
233 |
-
st.success(f"Question recognized: {
|
234 |
else:
|
235 |
st.warning("Please ask a relevant question.")
|
236 |
-
st.session_state['voice_question'] = ''
|
237 |
|
238 |
-
# Run Semantic Search button
|
239 |
run_btn = st.button("Run Semantic Search")
|
240 |
-
# If triggered by voice or button
|
241 |
run_search = run_btn or st.session_state.get('run_semantic_search', False)
|
242 |
if run_search:
|
243 |
-
st.session_state['run_semantic_search'] = False
|
244 |
if not code_input.strip() or not question.strip():
|
245 |
st.error("Both code and question are required.")
|
246 |
elif not code_matches_language(code_input, programming_language):
|
|
|
5 |
import streamlit.components.v1 as components
|
6 |
|
7 |
# --- CONFIG ---
|
|
|
8 |
GROQ_API_KEY = st.secrets.get('GROQ_API_KEY', 'YOUR_GROQ_API_KEY')
|
9 |
BLACKBOX_API_KEY = st.secrets.get('BLACKBOX_API_KEY', 'YOUR_BLACKBOX_API_KEY')
|
10 |
|
|
|
21 |
"How can I make this code more readable?"
|
22 |
]
|
23 |
|
24 |
+
# --- API CALLS ---
|
25 |
def call_groq_api(prompt, model="llama3-70b-8192"):
|
|
|
26 |
headers = {"Authorization": f"Bearer {GROQ_API_KEY}", "Content-Type": "application/json"}
|
27 |
data = {"model": model, "messages": [{"role": "user", "content": prompt}]}
|
28 |
response = requests.post("https://api.groq.com/openai/v1/chat/completions", json=data, headers=headers)
|
|
|
45 |
if response.status_code == 200:
|
46 |
return response.json()["choices"][0]["message"]["content"]
|
47 |
else:
|
|
|
48 |
return call_groq_api(messages[-1]["content"])
|
49 |
|
50 |
# --- UTILS ---
|
51 |
def code_matches_language(code, language):
|
|
|
52 |
if language.lower() in code.lower():
|
53 |
return True
|
54 |
+
return True
|
55 |
|
56 |
def calculate_code_complexity(code):
|
|
|
57 |
lines = code.count('\n') + 1
|
58 |
return f"{lines} lines"
|
59 |
|
|
|
68 |
return '\n'.join(diff)
|
69 |
|
70 |
def is_coding_question(question):
|
|
|
|
|
|
|
|
|
71 |
messages = [
|
72 |
{"role": "system", "content": "You are a helpful coding assistant."},
|
73 |
{"role": "user", "content": f"Is the following question about programming or code? Answer only 'yes' or 'no'. Question: {question}"}
|
|
|
118 |
st.error(f"Language mismatch. Please check your code and language selection.")
|
119 |
else:
|
120 |
with st.spinner("Running AI Workflow..."):
|
|
|
121 |
steps = [
|
122 |
("Explain", call_groq_api(f"Explain this {programming_language} code for a {skill_level} {user_role} in {explanation_language}:\n{code_input}")),
|
123 |
("Refactor", call_blackbox_agent([
|
|
|
135 |
for t in timeline:
|
136 |
st.subheader(t["step"])
|
137 |
st.write(t["output"])
|
|
|
138 |
st.subheader("Code Diff (Original vs Refactored)")
|
139 |
+
refactored_code = steps[1][1]
|
140 |
st.code(get_inline_diff(code_input, refactored_code), language=programming_language.lower())
|
|
|
141 |
report = f"AI Workflow Report\nGenerated on: {datetime.datetime.now()}\nLanguage: {programming_language}\nSkill Level: {skill_level}\nRole: {user_role}\n\n"
|
142 |
for t in timeline:
|
143 |
report += f"## {t['step']}\n{t['output']}\n\n---\n\n"
|
|
|
163 |
st.caption("Example questions:")
|
164 |
st.write(", ".join(EXAMPLE_QUESTIONS))
|
165 |
|
|
|
166 |
if 'voice_question' not in st.session_state:
|
167 |
st.session_state['voice_question'] = ''
|
168 |
if 'run_semantic_search' not in st.session_state:
|
169 |
st.session_state['run_semantic_search'] = False
|
170 |
|
171 |
+
# Custom input with mic button (HTML/JS)
|
172 |
+
question_html = """
|
173 |
+
<style>
|
174 |
+
.input-mic-container {
|
175 |
+
position: relative;
|
176 |
+
width: 100%;
|
177 |
+
max-width: 500px;
|
178 |
+
}
|
179 |
+
.input-mic {
|
180 |
+
width: 100%;
|
181 |
+
padding-right: 40px;
|
182 |
+
height: 38px;
|
183 |
+
font-size: 16px;
|
184 |
+
box-sizing: border-box;
|
185 |
+
}
|
186 |
+
.mic-btn {
|
187 |
+
position: absolute;
|
188 |
+
right: 5px;
|
189 |
+
top: 4px;
|
190 |
+
border: none;
|
191 |
+
background: none;
|
192 |
+
font-size: 22px;
|
193 |
+
cursor: pointer;
|
194 |
+
outline: none;
|
195 |
+
}
|
196 |
+
</style>
|
197 |
+
<div class="input-mic-container">
|
198 |
+
<input id="questionInput" class="input-mic" type="text" placeholder="Ask a question about your code" value="{value}" />
|
199 |
+
<button class="mic-btn" id="micBtn" title="Speak your question">π€</button>
|
200 |
+
</div>
|
201 |
<script>
|
202 |
+
const input = document.getElementById('questionInput');
|
203 |
+
const micBtn = document.getElementById('micBtn');
|
204 |
let recognition;
|
205 |
if ('webkitSpeechRecognition' in window) {
|
206 |
recognition = new webkitSpeechRecognition();
|
207 |
recognition.lang = 'en-US';
|
208 |
recognition.continuous = false;
|
209 |
recognition.interimResults = false;
|
210 |
+
micBtn.onclick = function(e) {
|
211 |
+
e.preventDefault();
|
212 |
recognition.start();
|
213 |
+
micBtn.textContent = 'ποΈ';
|
214 |
};
|
215 |
recognition.onresult = function(event) {
|
216 |
const transcript = event.results[0][0].transcript;
|
217 |
+
input.value = transcript;
|
218 |
window.parent.postMessage({isStreamlitMessage: true, type: 'streamlit:setComponentValue', value: transcript}, '*');
|
219 |
+
micBtn.textContent = 'π€';
|
220 |
};
|
221 |
recognition.onerror = function() {
|
222 |
+
micBtn.textContent = 'π€';
|
223 |
};
|
224 |
recognition.onend = function() {
|
225 |
+
micBtn.textContent = 'π€';
|
226 |
};
|
227 |
} else {
|
228 |
+
micBtn.disabled = true;
|
229 |
+
micBtn.title = 'Voice not supported';
|
230 |
+
}
|
231 |
+
// Send value on input change
|
232 |
+
input.onchange = function() {
|
233 |
+
window.parent.postMessage({isStreamlitMessage: true, type: 'streamlit:setComponentValue', value: input.value}, '*');
|
234 |
}
|
235 |
</script>
|
236 |
+
""".replace("{value}", st.session_state.get('voice_question', ''))
|
237 |
|
238 |
+
# Render the custom input+mic
|
239 |
+
question_value = components.html(question_html, height=60)
|
240 |
|
241 |
+
# Fallback for Streamlit's JS->Python communication
|
242 |
+
# For demo, use a text_input to allow manual typing as well
|
243 |
+
question = st.text_input("Ask a question about your code", value=st.session_state.get('voice_question', ''), key="sem_question")
|
|
|
|
|
244 |
|
245 |
+
# If the value is updated, validate and set
|
246 |
+
if question and question != st.session_state.get('voice_question', ''):
|
247 |
+
if is_coding_question(question):
|
248 |
+
st.session_state['voice_question'] = question
|
249 |
st.session_state['run_semantic_search'] = True
|
250 |
+
st.success(f"Question recognized: {question}")
|
251 |
else:
|
252 |
st.warning("Please ask a relevant question.")
|
253 |
+
st.session_state['voice_question'] = ''
|
254 |
|
|
|
255 |
run_btn = st.button("Run Semantic Search")
|
|
|
256 |
run_search = run_btn or st.session_state.get('run_semantic_search', False)
|
257 |
if run_search:
|
258 |
+
st.session_state['run_semantic_search'] = False
|
259 |
if not code_input.strip() or not question.strip():
|
260 |
st.error("Both code and question are required.")
|
261 |
elif not code_matches_language(code_input, programming_language):
|